• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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