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