1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define MEDIA_PLUGIN
17 #include <unistd.h>
18 #include <algorithm>
19 #include <malloc.h>
20 #include <string>
21 #include <sstream>
22 #include <map>
23 #include <fstream>
24 #include <chrono>
25 #include <limits>
26 #include "avcodec_trace.h"
27 #include "securec.h"
28 #include "ffmpeg_format_helper.h"
29 #include "ffmpeg_utils.h"
30 #include "buffer/avbuffer.h"
31 #include "plugin/plugin_buffer.h"
32 #include "plugin/plugin_definition.h"
33 #include "common/log.h"
34 #include "meta/video_types.h"
35 #include "avcodec_sysevent.h"
36 #include "ffmpeg_demuxer_plugin.h"
37 #include "meta/format.h"
38 #include "syspara/parameters.h"
39
40 namespace {
41 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_DEMUXER, "FfmpegReferenceParser" };
42 constexpr int64_t REFERENCE_PARSER_TIMEOUT_MS = 10000;
43 }
44
45 namespace OHOS {
46 namespace Media {
47 namespace Plugins {
48 namespace Ffmpeg {
49
ParserBoxInfo()50 void FFmpegDemuxerPlugin::ParserBoxInfo()
51 {
52 std::string formatName(formatContext_.get()->iformat->name);
53 if (formatName.find("mp4") == std::string::npos) {
54 MEDIA_LOG_D("Do not support " PUBLIC_LOG_S, formatName.c_str());
55 return;
56 }
57 int videoStreamIdx = av_find_best_stream(formatContext_.get(), AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
58 FALSE_RETURN_MSG(videoStreamIdx >= 0, "Can not find video stream");
59 AVStream *videoStream = formatContext_->streams[videoStreamIdx];
60 FALSE_RETURN_MSG(videoStream != nullptr, "Video stream is nullptr");
61 parserRefVideoStreamIdx_ = videoStreamIdx;
62 if (videoStream->avg_frame_rate.den == 0 || videoStream->avg_frame_rate.num == 0) {
63 fps_ = videoStream->r_frame_rate.num / (double)videoStream->r_frame_rate.den;
64 } else {
65 fps_ = videoStream->avg_frame_rate.num / (double)videoStream->avg_frame_rate.den;
66 }
67 struct KeyFrameNode *keyFramePosInfo = nullptr;
68 if (av_get_key_frame_pos_from_stream(videoStream, &keyFramePosInfo) == 0) {
69 struct KeyFrameNode *cur = keyFramePosInfo;
70 while (cur != nullptr) {
71 IFramePos_.emplace_back(cur->pos);
72 cur = cur->next;
73 }
74 av_destory_key_frame_pos_list(keyFramePosInfo);
75 }
76 FALSE_RETURN_MSG(GetPresentationTimeUsFromFfmpegMOV(GET_ALL_FRAME_PTS, videoStreamIdx, 0, 0) == Status::OK,
77 "get all frame pts failed.");
78 ptsListFromZero_.clear();
79 for (size_t ptsIdx = 0; ptsIdx < ptsListOrg_.size(); ptsIdx++) {
80 ptsListFromZero_.emplace_back(ptsListOrg_[ptsIdx] - absolutePTSIndexZero_);
81 }
82 if (ptsListFromZero_.size() > 0) {
83 sort(ptsListFromZero_.begin(), ptsListFromZero_.end());
84 }
85 MEDIA_LOG_I("Success parse, fps: " PUBLIC_LOG_F ", IFramePos size: " PUBLIC_LOG_ZU, fps_, IFramePos_.size());
86 }
87
ParserRefUpdatePos(int64_t timeStampMs,bool isForward)88 Status FFmpegDemuxerPlugin::ParserRefUpdatePos(int64_t timeStampMs, bool isForward)
89 {
90 FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_UNKNOWN, "AVFormatContext is nullptr");
91 std::string formatName(formatContext_.get()->iformat->name);
92 FALSE_RETURN_V_MSG_E(formatName.find("mp4") != std::string::npos, Status::ERROR_UNSUPPORTED_FORMAT,
93 "Only support mp4");
94 int64_t clipTimeStampMs = std::max(timeStampMs, static_cast<int64_t>(0));
95 if (IFramePos_.size() == 0 || referenceParser_ == nullptr) {
96 MEDIA_LOG_W("Parse failed, size: " PUBLIC_LOG_ZU, IFramePos_.size());
97 pendingSeekMsTime_ = clipTimeStampMs;
98 updatePosIsForward_ = isForward;
99 return Status::OK;
100 }
101 int32_t gopId = 0;
102 FALSE_RETURN_V_MSG_E(GetGopIdFromSeekPos(clipTimeStampMs, gopId) == Status::OK,
103 Status::ERROR_UNKNOWN, "GetGopIdFromSeekPos failed.");
104 GopLayerInfo gopLayerInfo;
105 Status ret = GetGopLayerInfo(gopId, gopLayerInfo);
106 if (ret == Status::ERROR_AGAIN && gopId != parserCurGopId_) {
107 pendingSeekMsTime_ = clipTimeStampMs;
108 parserState_ = false;
109 MEDIA_LOG_I("Pending time: " PUBLIC_LOG_D64, pendingSeekMsTime_);
110 }
111 updatePosIsForward_ = isForward;
112 return Status::OK;
113 }
114
ParserFirstDts()115 void FFmpegDemuxerPlugin::ParserFirstDts()
116 {
117 AVPacket *pkt = av_packet_alloc();
118 bool isEnd = false;
119 bool isFirst = true;
120 while (!isEnd) {
121 std::unique_lock<std::mutex> sLock(syncMutex_);
122 int ffmpegRet = av_read_frame(parserRefFormatContext_.get(), pkt);
123 sLock.unlock();
124 if (ffmpegRet < 0) {
125 av_packet_unref(pkt);
126 av_packet_free(&pkt);
127 return;
128 }
129 if (pkt->stream_index != parserRefVideoStreamIdx_) {
130 continue;
131 }
132 if (isFirst) {
133 firstDts_ = AvTime2Us(
134 ConvertTimeFromFFmpeg(pkt->dts, parserRefFormatContext_->streams[parserRefVideoStreamIdx_]->time_base));
135 MEDIA_LOG_I("Success parse, first dts: " PUBLIC_LOG_D64, firstDts_);
136 isFirst = false;
137 }
138 if (pkt->dts < 0) {
139 dtsOffset_++;
140 } else {
141 isEnd = true;
142 }
143 av_packet_unref(pkt);
144 }
145 av_packet_unref(pkt);
146 av_packet_free(&pkt);
147 }
148
InitIoContext()149 Status FFmpegDemuxerPlugin::InitIoContext()
150 {
151 parserRefIoContext_.dataSource = ioContext_.dataSource;
152 parserRefIoContext_.offset = 0;
153 parserRefIoContext_.eos = false;
154 parserRefIoContext_.initCompleted = true;
155 FALSE_RETURN_V_MSG_E(parserRefIoContext_.dataSource != nullptr, Status::ERROR_UNKNOWN, "Data source is nullptr");
156 if (parserRefIoContext_.dataSource->GetSeekable() == Plugins::Seekable::SEEKABLE) {
157 parserRefIoContext_.dataSource->GetSize(parserRefIoContext_.fileSize);
158 } else {
159 parserRefIoContext_.fileSize = -1;
160 MEDIA_LOG_E("Not support online video");
161 return Status::ERROR_INVALID_OPERATION;
162 }
163 return Status::OK;
164 }
165
ParserRefCheckVideoValid(const AVStream * videoStream)166 Status FFmpegDemuxerPlugin::ParserRefCheckVideoValid(const AVStream *videoStream)
167 {
168 if (videoStream == nullptr) {
169 MEDIA_LOG_E("videoStream is nullptr: video track id %{public}d, trackNums %{public}u",
170 parserRefVideoStreamIdx_, parserRefFormatContext_->nb_streams);
171 return Status::ERROR_UNKNOWN;
172 }
173 if (videoStream->codecpar == nullptr) {
174 MEDIA_LOG_E("videoStream->codecpar is nullptr: video track id %{public}d, trackNums %{public}u",
175 parserRefVideoStreamIdx_, parserRefFormatContext_->nb_streams);
176 return Status::ERROR_UNKNOWN;
177 }
178 FALSE_RETURN_V_MSG_E(
179 videoStream->codecpar->codec_id == AV_CODEC_ID_HEVC || videoStream->codecpar->codec_id == AV_CODEC_ID_H264,
180 Status::ERROR_UNSUPPORTED_FORMAT, "Codec type not support " PUBLIC_LOG_D32, videoStream->codecpar->codec_id);
181 return Status::OK;
182 }
183
ParserRefInit()184 Status FFmpegDemuxerPlugin::ParserRefInit()
185 {
186 parserRefStartTime_ = std::chrono::duration_cast<std::chrono::milliseconds>(
187 std::chrono::system_clock::now().time_since_epoch()).count();
188 std::string suffix = std::to_string(parserRefStartTime_) + "_" + std::to_string(IFramePos_.size());
189 MediaAVCodec::AVCodecTrace trace("ParserRefCost_1_" + suffix);
190 MEDIA_LOG_I("Parser ref start time: " PUBLIC_LOG_D64, parserRefStartTime_);
191 FALSE_RETURN_V_MSG_E(IFramePos_.size() > 0 && fps_ > 0, Status::ERROR_UNKNOWN,
192 "Init failed, IFramePos size:" PUBLIC_LOG_ZU ", fps:" PUBLIC_LOG_F, IFramePos_.size(), fps_);
193 FALSE_RETURN_V_MSG_E(InitIoContext() == Status::OK, Status::ERROR_UNKNOWN, "Init IOContext failed");
194 parserRefFormatContext_ = InitAVFormatContext(&parserRefIoContext_);
195 FALSE_RETURN_V_MSG_E(parserRefFormatContext_ != nullptr, Status::ERROR_UNKNOWN, "AVFormatContext is nullptr");
196 std::string formatName(parserRefFormatContext_.get()->iformat->name);
197 FALSE_RETURN_V_MSG_E(formatName.find("mp4") != std::string::npos, Status::ERROR_UNSUPPORTED_FORMAT, "Mp4 only");
198 for (uint32_t trackIndex = 0; trackIndex < parserRefFormatContext_->nb_streams; trackIndex++) {
199 AVStream *stream = parserRefFormatContext_->streams[trackIndex];
200 FALSE_RETURN_V_MSG_E(stream != nullptr && stream->codecpar != nullptr, Status::ERROR_UNKNOWN,
201 "AVStream or codecpar is nullptr, track " PUBLIC_LOG_U32, trackIndex);
202 if (stream->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
203 stream->discard = AVDISCARD_ALL;
204 } else {
205 parserRefVideoStreamIdx_ = static_cast<int32_t>(trackIndex);
206 }
207 }
208 FALSE_RETURN_V_MSG_E(parserRefVideoStreamIdx_ >= 0, Status::ERROR_UNKNOWN, "Can not find video stream");
209 AVStream *videoStream = parserRefFormatContext_->streams[parserRefVideoStreamIdx_];
210 FALSE_RETURN_V_MSG_E(ParserRefCheckVideoValid(videoStream) == Status::OK, Status::ERROR_UNKNOWN,
211 "ParserRefCheckVideoValid failed");
212 processingIFrame_.assign(IFramePos_.begin(), IFramePos_.end());
213 ParserFirstDts();
214 CodecType codecType = videoStream->codecpar->codec_id == AV_CODEC_ID_HEVC ? CodecType::H265 : CodecType::H264;
215 referenceParser_ = ReferenceParserManager::Create(codecType, IFramePos_);
216 FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference is nullptr");
217 ParserSdtpInfo *sc = (ParserSdtpInfo *)videoStream->priv_data;
218 if (sc->sdtpCount > 0 && sc->sdtpData != nullptr) {
219 MEDIA_LOG_E("Sdtp exist: " PUBLIC_LOG_D32, sc->sdtpCount);
220 if (referenceParser_->ParserSdtpData(sc->sdtpData, sc->sdtpCount) == Status::OK) {
221 isSdtpExist_ = true;
222 return Status::END_OF_STREAM;
223 }
224 }
225 return referenceParser_->ParserExtraData(videoStream->codecpar->extradata, videoStream->codecpar->extradata_size);
226 }
227
InsertIframePtsMap(AVPacket * pkt,int32_t gopId,int32_t trackIdx,std::unordered_map<int32_t,int64_t> & iFramePtsMap)228 static void InsertIframePtsMap(AVPacket *pkt, int32_t gopId, int32_t trackIdx,
229 std::unordered_map<int32_t, int64_t> &iFramePtsMap)
230 {
231 bool validCheck = (pkt != nullptr) && (pkt->stream_index == trackIdx) &&
232 (pkt->flags == AV_PKT_FLAG_KEY) && (gopId != -1); // -1 disable
233 if (validCheck && (iFramePtsMap.find(gopId) == iFramePtsMap.end())) {
234 iFramePtsMap.insert(std::pair<int32_t, int64_t>(gopId, pkt->pts));
235 }
236 }
237
ParserRefInfoLoop(AVPacket * pkt,uint32_t curStreamId)238 Status FFmpegDemuxerPlugin::ParserRefInfoLoop(AVPacket *pkt, uint32_t curStreamId)
239 {
240 std::unique_lock<std::mutex> sLock(syncMutex_);
241 int ffmpegRet = av_read_frame(parserRefFormatContext_.get(), pkt);
242 sLock.unlock();
243 if (ffmpegRet < 0 && ffmpegRet != AVERROR_EOF) {
244 MEDIA_LOG_E("Call av_read_frame failed:" PUBLIC_LOG_S ", retry:" PUBLIC_LOG_D32,
245 AVStrError(ffmpegRet).c_str(), int(parserRefIoContext_.retry));
246 if (parserRefIoContext_.retry) {
247 parserRefFormatContext_->pb->eof_reached = 0;
248 parserRefFormatContext_->pb->error = 0;
249 parserRefIoContext_.retry = false;
250 return Status::ERROR_AGAIN;
251 }
252 return Status::ERROR_UNKNOWN;
253 }
254 InsertIframePtsMap(pkt, parserCurGopId_, parserRefVideoStreamIdx_, iFramePtsMap_);
255 FALSE_RETURN_V_MSG_D(pkt->stream_index == parserRefVideoStreamIdx_ || ffmpegRet == AVERROR_EOF, Status::OK,
256 "eos or not video");
257 int64_t dts = AvTime2Us(
258 ConvertTimeFromFFmpeg(pkt->dts, parserRefFormatContext_->streams[parserRefVideoStreamIdx_]->time_base));
259 Status result = referenceParser_->ParserNalUnits(pkt->data, pkt->size, curStreamId, dts);
260 FALSE_RETURN_V_MSG_E(result == Status::OK, Status::ERROR_UNKNOWN, "parse nal units error!");
261 int32_t iFramePosSize = static_cast<int32_t>(IFramePos_.size());
262 if (ffmpegRet == AVERROR_EOF || result != Status::OK ||
263 (parserCurGopId_ + 1 < iFramePosSize && curStreamId == IFramePos_[parserCurGopId_ + 1] - 1)) { // 处理完一个GOP
264 MEDIA_LOG_I("IFramePos: " PUBLIC_LOG_ZU ", processingIFrame: " PUBLIC_LOG_ZU ", curStreamId: " PUBLIC_LOG_U32
265 ", curGopId: " PUBLIC_LOG_U32, IFramePos_.size(), processingIFrame_.size(), curStreamId, parserCurGopId_);
266 processingIFrame_.remove(IFramePos_[parserCurGopId_]);
267 if (processingIFrame_.size() == 0) {
268 parserCurGopId_ = -1;
269 return Status::OK;
270 }
271 int32_t tmpGopId = parserCurGopId_;
272 int32_t searchCnt = 0;
273 while (formatContext_ != nullptr && std::find(processingIFrame_.begin(), processingIFrame_.end(),
274 IFramePos_[parserCurGopId_]) == processingIFrame_.end()) {
275 if (updatePosIsForward_) {
276 parserCurGopId_ = (parserCurGopId_ + 1) % iFramePosSize;
277 } else {
278 parserCurGopId_ = parserCurGopId_ == 0 ? iFramePosSize - 1 : parserCurGopId_ - 1;
279 }
280 searchCnt++;
281 FALSE_RETURN_V_MSG_E(searchCnt < iFramePosSize, Status::ERROR_UNKNOWN, "Cannot find gop");
282 }
283 if (formatContext_ == nullptr || tmpGopId + 1 != parserCurGopId_ || !updatePosIsForward_) {
284 return Status::END_OF_STREAM;
285 }
286 }
287 return Status::OK;
288 }
289
GetGopIdFromSeekPos(int64_t seekMs,int32_t & gopId)290 Status FFmpegDemuxerPlugin::GetGopIdFromSeekPos(int64_t seekMs, int32_t &gopId)
291 {
292 AVStream *st = parserRefFormatContext_->streams[parserRefVideoStreamIdx_];
293 FALSE_RETURN_V_MSG_E(st != nullptr, Status::ERROR_UNKNOWN, "AVStream is nullptr");
294 if (seekMs < 0) {
295 seekMs = 0;
296 }
297 int32_t iFrameIdx;
298 if (ptsListFromZero_.size() > 0) {
299 iFrameIdx = std::upper_bound(ptsListFromZero_.begin(), ptsListFromZero_.end(),
300 seekMs * MS_TO_SEC) - ptsListFromZero_.begin() - 1;
301 if (iFrameIdx < 0) {
302 iFrameIdx = static_cast<int32_t>(ptsListFromZero_.size()) - 1;
303 }
304 MEDIA_LOG_D("get I frame iFrameIdx from box parser");
305 } else {
306 int64_t orgPts = ConvertTimeToFFmpegByUs(seekMs * MS_TO_SEC, st->time_base);
307 FALSE_RETURN_V_MSG_E(orgPts >= 0, Status::ERROR_UNKNOWN,
308 "ffmpegTime is negative to seek " PUBLIC_LOG_D64, seekMs);
309 iFrameIdx = av_index_search_timestamp(st, orgPts + CalculateTimeByFrameIndex(st, 0), AVSEEK_FLAG_BACKWARD);
310 FALSE_RETURN_V_MSG_E(iFrameIdx >= 0, Status::ERROR_UNKNOWN,
311 "iFrameIdx is negative to seek " PUBLIC_LOG_D64, seekMs);
312 MEDIA_LOG_D("get I frame iFrameIdx from simulated dts");
313 }
314 gopId = std::upper_bound(IFramePos_.begin(), IFramePos_.end(), iFrameIdx) - IFramePos_.begin() - 1;
315 if (gopId < 0) {
316 gopId = static_cast<int32_t>(IFramePos_.size()) - 1;
317 }
318 return Status::OK;
319 }
320
SelectProGopId()321 Status FFmpegDemuxerPlugin::SelectProGopId()
322 {
323 AVStream *st = parserRefFormatContext_->streams[parserRefVideoStreamIdx_];
324 FALSE_RETURN_V_MSG_E(st != nullptr, Status::ERROR_UNKNOWN, "AVStream is nullptr");
325 if (pendingSeekMsTime_ >= 0) {
326 FALSE_RETURN_V_MSG_E(GetGopIdFromSeekPos(pendingSeekMsTime_, parserCurGopId_) == Status::OK,
327 Status::ERROR_UNKNOWN, "GetGopIdFromSeekPos failed");
328 pendingSeekMsTime_ = -1;
329 }
330 int64_t ptsSeek;
331 if (iFramePtsMap_.find(parserCurGopId_) != iFramePtsMap_.end()) { // if I frame pts had got before decoding
332 ptsSeek = iFramePtsMap_[parserCurGopId_];
333 MEDIA_LOG_D("get I frame pts from which had been decoded");
334 } else {
335 int32_t iFramePosSize = static_cast<int32_t>(IFramePos_.size());
336 int64_t dtsCur = CalculateTimeByFrameIndex(st, IFramePos_[parserCurGopId_]);
337 if (parserCurGopId_ + 1 < iFramePosSize) {
338 int64_t dtsNext = CalculateTimeByFrameIndex(st, IFramePos_[parserCurGopId_ + 1]);
339 ptsSeek = dtsCur + (dtsNext - dtsCur) / 2; // 2 middle between cur gop and next gop
340 } else {
341 ptsSeek = INT64_MAX; // seek last gop
342 }
343 MEDIA_LOG_D("get I frame pts from simulated dts");
344 }
345 auto ret = av_seek_frame(parserRefFormatContext_.get(), parserRefVideoStreamIdx_, ptsSeek, AVSEEK_FLAG_BACKWARD);
346 FALSE_RETURN_V_MSG_E(ret >= 0, Status::ERROR_UNKNOWN,
347 "Call av_seek_frame failed, err: " PUBLIC_LOG_S, AVStrError(ret).c_str());
348 return Status::OK;
349 }
350
ParserRefInfo()351 Status FFmpegDemuxerPlugin::ParserRefInfo()
352 {
353 FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::OK, "AVFormatContext is nullptr");
354 if (!isInit_) {
355 isInit_ = true;
356 Status ret = ParserRefInit();
357 if (ret == Status::END_OF_STREAM) {
358 return Status::OK;
359 }
360 if (ret != Status::OK) {
361 return Status::ERROR_UNKNOWN;
362 }
363 }
364 int64_t duration = std::chrono::duration_cast<std::chrono::milliseconds>(
365 std::chrono::system_clock::now().time_since_epoch()).count() - parserRefStartTime_;
366 std::string suffix = std::to_string(duration) + "_" + std::to_string(parserCurGopId_);
367 MediaAVCodec::AVCodecTrace trace("ParserRefCost_2_" + suffix);
368 FALSE_RETURN_V_MSG_W(duration < REFERENCE_PARSER_TIMEOUT_MS, Status::ERROR_UNKNOWN, "Reference parser timeout");
369 FALSE_RETURN_V_MSG(parserCurGopId_ != -1, Status::OK, "Reference parser end"); // 参考关系解析完毕
370 FALSE_RETURN_V_MSG_E(SelectProGopId() == Status::OK, Status::ERROR_UNKNOWN, "Call selectProGopId failed");
371 uint32_t curStreamId = IFramePos_[parserCurGopId_];
372 MEDIA_LOG_I("curStreamId: " PUBLIC_LOG_U32 ", parserCurGopId: " PUBLIC_LOG_D32 ", IFramePos size: " PUBLIC_LOG_ZU
373 ", processingIFrame_ size: " PUBLIC_LOG_ZU ", duration: " PUBLIC_LOG_D64, curStreamId, parserCurGopId_,
374 IFramePos_.size(), processingIFrame_.size(), duration);
375 AVPacket *pkt = av_packet_alloc();
376 while (formatContext_ != nullptr && parserState_ && parserCurGopId_ != -1) {
377 Status rlt = ParserRefInfoLoop(pkt, curStreamId);
378 duration = std::chrono::duration_cast<std::chrono::milliseconds>(
379 std::chrono::system_clock::now().time_since_epoch()).count() - parserRefStartTime_;
380 suffix = std::to_string(duration) + "_" + std::to_string(parserCurGopId_) + "_" + std::to_string(curStreamId);
381 MediaAVCodec::AVCodecTrace traceInLoop("ParserRefCost_3_" + suffix);
382 FALSE_RETURN_V_MSG_W(duration < REFERENCE_PARSER_TIMEOUT_MS, Status::ERROR_UNKNOWN, "Reference parser timeout");
383 if (rlt != Status::OK) {
384 av_packet_unref(pkt);
385 av_packet_free(&pkt);
386 parserState_ = true;
387 return rlt;
388 }
389 if (pkt->stream_index == parserRefVideoStreamIdx_) {
390 curStreamId++;
391 }
392 av_packet_unref(pkt);
393 }
394
395 av_packet_free(&pkt);
396 parserState_ = true;
397 return Status::ERROR_AGAIN;
398 }
399
GetFrameLayerInfo(std::shared_ptr<AVBuffer> videoSample,FrameLayerInfo & frameLayerInfo)400 Status FFmpegDemuxerPlugin::GetFrameLayerInfo(std::shared_ptr<AVBuffer> videoSample, FrameLayerInfo &frameLayerInfo)
401 {
402 FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference is nullptr");
403 MEDIA_LOG_D("In, dts: " PUBLIC_LOG_D64, videoSample->dts_);
404 if (isSdtpExist_) {
405 int64_t ffmpegDts = ConvertTimeToFFmpegByUs(
406 videoSample->dts_, parserRefFormatContext_->streams[parserRefVideoStreamIdx_]->time_base);
407 int32_t frameId = av_index_search_timestamp(
408 parserRefFormatContext_->streams[parserRefVideoStreamIdx_], ffmpegDts, AVSEEK_FLAG_ANY);
409 FALSE_RETURN_V_MSG_E(frameId >= 0, Status::ERROR_UNKNOWN, "Can not find frameId");
410 MEDIA_LOG_D("Get frameId: " PUBLIC_LOG_U32, frameId);
411 return referenceParser_->GetFrameLayerInfo(static_cast<uint32_t>(frameId), frameLayerInfo);
412 }
413 return referenceParser_->GetFrameLayerInfo(videoSample->dts_, frameLayerInfo);
414 }
415
GetFrameLayerInfo(uint32_t frameId,FrameLayerInfo & frameLayerInfo)416 Status FFmpegDemuxerPlugin::GetFrameLayerInfo(uint32_t frameId, FrameLayerInfo &frameLayerInfo)
417 {
418 FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference is nullptr");
419 MEDIA_LOG_D("In, dts: " PUBLIC_LOG_U32, frameId);
420 return referenceParser_->GetFrameLayerInfo(frameId, frameLayerInfo);
421 }
422
GetGopLayerInfo(uint32_t gopId,GopLayerInfo & gopLayerInfo)423 Status FFmpegDemuxerPlugin::GetGopLayerInfo(uint32_t gopId, GopLayerInfo &gopLayerInfo)
424 {
425 FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference is nullptr");
426 MEDIA_LOG_D("In, gopId: " PUBLIC_LOG_U32, gopId);
427 return referenceParser_->GetGopLayerInfo(gopId, gopLayerInfo);
428 }
429
GetIFramePos(std::vector<uint32_t> & IFramePos)430 Status FFmpegDemuxerPlugin::GetIFramePos(std::vector<uint32_t> &IFramePos)
431 {
432 FALSE_RETURN_V_MSG_E(IFramePos_.size() > 0, Status::ERROR_UNKNOWN, "IFramePos size is 0");
433 IFramePos = IFramePos_;
434 return Status::OK;
435 }
436
Dts2FrameId(int64_t dts,uint32_t & frameId,bool offset)437 Status FFmpegDemuxerPlugin::Dts2FrameId(int64_t dts, uint32_t &frameId, bool offset)
438 {
439 FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::OK, "AVFormatContext is nullptr");
440 int64_t ffmpegDts = ConvertTimeToFFmpegByUs(dts, formatContext_->streams[parserRefVideoStreamIdx_]->time_base);
441 int32_t tmpFrameId = av_index_search_timestamp(
442 formatContext_->streams[parserRefVideoStreamIdx_], ffmpegDts, AVSEEK_FLAG_ANY);
443 if (tmpFrameId >= 0) {
444 frameId = static_cast<uint32_t>(tmpFrameId);
445 if (!offset) {
446 frameId += dtsOffset_;
447 }
448 } else if (dts >= firstDts_) {
449 if (formatContext_->streams[parserRefVideoStreamIdx_]->nb_frames < 1) {
450 MEDIA_LOG_E("FrameId sub overflow");
451 return Status::ERROR_UNKNOWN;
452 }
453 frameId = static_cast<uint32_t>(formatContext_->streams[parserRefVideoStreamIdx_]->nb_frames) - 1;
454 } else {
455 frameId = 0;
456 }
457
458 MEDIA_LOG_D("Out, frameId: " PUBLIC_LOG_D32 ", dts: " PUBLIC_LOG_D64, frameId, dts);
459 return Status::OK;
460 }
461
462 } // namespace Ffmpeg
463 } // namespace Plugins
464 } // namespace Media
465 } // namespace OHOS