• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-2025 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 #define HST_LOG_TAG "FfmpegDemuxerPlugin"
18 #include <unistd.h>
19 #include <algorithm>
20 #include <malloc.h>
21 #include <string>
22 #include <sstream>
23 #include <iomanip>
24 #include <map>
25 #include <fstream>
26 #include <chrono>
27 #include <limits>
28 #include "avcodec_trace.h"
29 #include "securec.h"
30 #include "ffmpeg_format_helper.h"
31 #include "ffmpeg_utils.h"
32 #include "buffer/avbuffer.h"
33 #include "plugin/plugin_buffer.h"
34 #include "plugin/plugin_definition.h"
35 #include "common/log.h"
36 #include "meta/video_types.h"
37 #include "demuxer_log_compressor.h"
38 #include "ffmpeg_demuxer_plugin.h"
39 #include "meta/format.h"
40 #include "syspara/parameters.h"
41 
42 namespace {
43 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_DEMUXER, "FfmpegDemuxerPlugin" };
44 }
45 
46 namespace OHOS {
47 namespace Media {
48 namespace Plugins {
49 namespace Ffmpeg {
50 const uint32_t DEFAULT_READ_SIZE = 4096;
51 const uint32_t DEFAULT_SNIFF_SIZE = 4096 * 4;
52 const int32_t MP3_PROBE_SCORE_LIMIT = 5;
53 const int32_t DEF_PROBE_SCORE_LIMIT = 50;
54 const uint32_t RANK_MAX = 100;
55 const int32_t NAL_START_CODE_SIZE = 4;
56 const uint32_t INIT_DOWNLOADS_DATA_SIZE_THRESHOLD = 2 * 1024 * 1024;
57 const int64_t LIVE_FLV_PROBE_SIZE = 100 * 1024 * 2;
58 const uint32_t DEFAULT_CACHE_LIMIT = 50 * 1024 * 1024; // 50M
59 const int64_t INIT_TIME_THRESHOLD = 1000;
60 const uint32_t ID3V2_HEADER_SIZE = 10;
61 const int32_t MS_TO_US = 1000;
62 const int32_t MS_TO_NS = 1000 * 1000;
63 const uint32_t REFERENCE_PARSER_PTS_LIST_UPPER_LIMIT = 200000;
64 const int DEFAULT_CHANNEL_CNT = 3;
65 const int FLV_READ_SIZE_LIMIT_FACTOR = 2;
66 const int FLV_READ_SIZE_LIMIT_DEFAULT = 4096 * 2160 * 3 * 2;
67 const char* PLUGIN_NAME_PREFIX = "avdemux_";
68 const char* PLUGIN_NAME_MP3 = "mp3";
69 const char* PLUGIN_NAME_MPEGPS = "mpeg";
70 const uint8_t START_CODE[] = {0x00, 0x00, 0x01};
71 const int32_t MPEGPS_START_CODE_SIZE = 4;
72 const uint8_t MPEGPS_START_CODE[] = {0x00, 0x00, 0x01, 0xBA};
73 
74 // id3v2 tag position
75 const int32_t POS_0 = 0;
76 const int32_t POS_1 = 1;
77 const int32_t POS_2 = 2;
78 const int32_t POS_3 = 3;
79 const int32_t POS_4 = 4;
80 const int32_t POS_5 = 5;
81 const int32_t POS_6 = 6;
82 const int32_t POS_7 = 7;
83 const int32_t POS_8 = 8;
84 const int32_t POS_9 = 9;
85 const int32_t POS_14 = 14;
86 const int32_t POS_16 = 16;
87 const int32_t POS_21 = 21;
88 const int32_t POS_24 = 24;
89 const int32_t POS_FF = 0xff;
90 const int32_t LEN_MASK = 0x7f;
91 const int32_t TAG_MASK = 0x80;
92 const int32_t TAG_VERSION_MASK = 0x10;
93 
94 const std::vector<AVCodecID> g_streamContainedXPS = {
95     AV_CODEC_ID_H264,
96     AV_CODEC_ID_HEVC,
97     AV_CODEC_ID_VVC
98 };
99 namespace {
100 std::map<std::string, std::shared_ptr<AVInputFormat>> g_pluginInputFormat;
101 std::mutex g_mtx;
102 
103 int Sniff(const std::string& pluginName, std::shared_ptr<DataSource> dataSource);
104 int SniffWithSize(const std::string& pluginName, std::shared_ptr<DataSource> dataSource, int probSize);
105 int SniffMPEGPS(const std::string& pluginName, std::shared_ptr<DataSource> dataSource);
106 
107 Status RegisterPlugins(const std::shared_ptr<Register>& reg);
108 
109 void ReplaceDelimiter(const std::string &delmiters, char newDelimiter, std::string &str);
110 
FreeAVPacket(AVPacket * pkt)111 void FreeAVPacket(AVPacket* pkt)
112 {
113     av_packet_free(&pkt);
114     pkt = nullptr;
115 }
116 
117 static const std::map<SeekMode, int32_t>  g_seekModeToFFmpegSeekFlags = {
118     { SeekMode::SEEK_PREVIOUS_SYNC, AVSEEK_FLAG_BACKWARD },
119     { SeekMode::SEEK_NEXT_SYNC, AVSEEK_FLAG_FRAME },
120     { SeekMode::SEEK_CLOSEST_SYNC, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD }
121 };
122 
123 static const std::map<AVCodecID, std::string> g_bitstreamFilterMap = {
124     { AV_CODEC_ID_H264, "h264_mp4toannexb" },
125 };
126 
127 static const std::map<AVCodecID, VideoStreamType> g_streamParserMap = {
128     { AV_CODEC_ID_HEVC, VideoStreamType::HEVC },
129     { AV_CODEC_ID_VVC,  VideoStreamType::VVC },
130 };
131 
132 static const std::vector<AVMediaType> g_streamMediaTypeVec = {
133     AVMEDIA_TYPE_AUDIO,
134     AVMEDIA_TYPE_VIDEO,
135     AVMEDIA_TYPE_SUBTITLE,
136     AVMEDIA_TYPE_TIMEDMETA,
137     AVMEDIA_TYPE_AUXILIARY
138 };
139 
140 static const std::unordered_map<std::string, PluginSnifferFunc> g_pluginSnifferMap = {
141     {std::string(PLUGIN_NAME_MPEGPS), SniffMPEGPS},
142 };
143 
HaveValidParser(const AVCodecID codecId)144 bool HaveValidParser(const AVCodecID codecId)
145 {
146     return g_streamParserMap.count(codecId) != 0;
147 }
148 
GetFileDuration(const AVFormatContext & avFormatContext)149 int64_t GetFileDuration(const AVFormatContext& avFormatContext)
150 {
151     int64_t duration = 0;
152     const AVDictionaryEntry *metaDuration = av_dict_get(avFormatContext.metadata, "DURATION", NULL, 0);
153     int64_t us;
154     if (metaDuration != nullptr && (av_parse_time(&us, metaDuration->value, 1) == 0)) {
155         if (us > duration) {
156             MEDIA_LOG_D("Get duration from file");
157             duration = us;
158         }
159     }
160 
161     if (duration <= 0) {
162         for (uint32_t i = 0; i < avFormatContext.nb_streams; ++i) {
163             auto streamDuration = (ConvertTimeFromFFmpeg(avFormatContext.streams[i]->duration,
164                 avFormatContext.streams[i]->time_base)) / 1000; // us
165             if (streamDuration > duration) {
166                 MEDIA_LOG_D("Get duration from stream " PUBLIC_LOG_U32, i);
167                 duration = streamDuration;
168             }
169         }
170     }
171     return duration;
172 }
173 
GetStreamDuration(const AVStream & avStream)174 int64_t GetStreamDuration(const AVStream& avStream)
175 {
176     int64_t duration = 0;
177     const AVDictionaryEntry *metaDuration = av_dict_get(avStream.metadata, "DURATION", NULL, 0);
178     int64_t us;
179     if (metaDuration != nullptr && (av_parse_time(&us, metaDuration->value, 1) == 0)) {
180         if (us > duration) {
181             MEDIA_LOG_D("Get duration from stream");
182             duration = us;
183         }
184     }
185     return duration;
186 }
187 
CheckStartTime(const AVFormatContext * formatContext,const AVStream * stream,int64_t & timeStamp,int64_t seekTime)188 bool CheckStartTime(const AVFormatContext *formatContext, const AVStream *stream, int64_t &timeStamp, int64_t seekTime)
189 {
190     int64_t startTime = 0;
191     int64_t num = 1000; // ms convert us
192     FALSE_RETURN_V_MSG_E(stream != nullptr, false, "String is nullptr");
193     if (stream->start_time != AV_NOPTS_VALUE) {
194         startTime = stream->start_time;
195         if (timeStamp > 0 && startTime > INT64_MAX - timeStamp) {
196             MEDIA_LOG_E("Seek value overflow with start time: " PUBLIC_LOG_D64 " timeStamp: " PUBLIC_LOG_D64,
197                 startTime, timeStamp);
198             return false;
199         }
200     }
201     MEDIA_LOG_D("StartTime: " PUBLIC_LOG_D64, startTime);
202     int64_t fileDuration = formatContext->duration;
203     int64_t streamDuration = stream->duration;
204     if (fileDuration == AV_NOPTS_VALUE || fileDuration <= 0) {
205         fileDuration = GetFileDuration(*formatContext);
206     }
207     if (streamDuration == AV_NOPTS_VALUE || streamDuration <= 0) {
208         streamDuration = GetStreamDuration(*stream);
209     }
210     MEDIA_LOG_D("File duration=" PUBLIC_LOG_D64 ", stream duration=" PUBLIC_LOG_D64, fileDuration, streamDuration);
211     // when timestemp out of file duration, return error
212     if (fileDuration > 0 && seekTime > fileDuration / num) { // fileDuration us
213         MEDIA_LOG_E("Seek to timestamp=" PUBLIC_LOG_D64 " failed, max=" PUBLIC_LOG_D64, timeStamp, fileDuration);
214         return false;
215     }
216     // when timestemp out of stream duration, seek to end of stream
217     if (streamDuration > 0 && timeStamp > streamDuration) {
218         MEDIA_LOG_W("Out of stream, seek to " PUBLIC_LOG_D64, timeStamp);
219         timeStamp = streamDuration;
220     }
221     if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ||
222         stream->codecpar->codec_type == AVMEDIA_TYPE_AUXILIARY) {
223         MEDIA_LOG_D("Reset timeStamp by start time [" PUBLIC_LOG_D64 "/" PUBLIC_LOG_D64 "]",
224             timeStamp, timeStamp + startTime);
225         timeStamp += startTime;
226     }
227     return true;
228 }
229 
ConvertFlagsToFFmpeg(AVStream * avStream,int64_t ffTime,SeekMode mode,int64_t seekTime)230 int ConvertFlagsToFFmpeg(AVStream *avStream, int64_t ffTime, SeekMode mode, int64_t seekTime)
231 {
232     FALSE_RETURN_V_MSG_E(avStream != nullptr && avStream->codecpar != nullptr, -1, "AVStream is nullptr");
233     if (avStream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE && ffTime == 0) {
234         return AVSEEK_FLAG_FRAME;
235     }
236     if (FFmpegFormatHelper::IsAudioType(*avStream) && seekTime != 0) {
237         int64_t streamDuration = avStream->duration;
238         if (streamDuration == AV_NOPTS_VALUE || streamDuration <= 0) {
239             streamDuration = GetStreamDuration(*avStream);
240         }
241         // When the seekTime is within the last 0.5s, still use BACKWARD mode to ensure consistent func behavior.
242         int64_t buffering = ConvertTimeToFFmpeg(500 * MS_TO_NS, avStream->time_base); // 0.5s
243         if (streamDuration > 0  && (streamDuration < buffering || ffTime >= streamDuration - buffering)) {
244             return AVSEEK_FLAG_BACKWARD;
245         }
246         return g_seekModeToFFmpegSeekFlags.at(mode);
247     }
248     if (!FFmpegFormatHelper::IsVideoType(*avStream) || seekTime == 0) {
249         return AVSEEK_FLAG_BACKWARD;
250     }
251     if (mode == SeekMode::SEEK_NEXT_SYNC || mode == SeekMode::SEEK_PREVIOUS_SYNC) {
252         return g_seekModeToFFmpegSeekFlags.at(mode);
253     }
254     // find closest time in next and prev
255     int keyFrameNext = av_index_search_timestamp(avStream, ffTime, AVSEEK_FLAG_FRAME);
256     FALSE_RETURN_V_MSG_E(keyFrameNext >= 0, AVSEEK_FLAG_BACKWARD, "Not next key frame");
257 
258     int keyFramePrev = av_index_search_timestamp(avStream, ffTime, AVSEEK_FLAG_BACKWARD);
259     FALSE_RETURN_V_MSG_E(keyFramePrev >= 0, AVSEEK_FLAG_FRAME, "Not pre key frame");
260 
261     int64_t ffTimePrev = CalculateTimeByFrameIndex(avStream, keyFramePrev);
262     int64_t ffTimeNext = CalculateTimeByFrameIndex(avStream, keyFrameNext);
263     MEDIA_LOG_D("FfTime=" PUBLIC_LOG_D64 ", ffTimePrev=" PUBLIC_LOG_D64 ", ffTimeNext=" PUBLIC_LOG_D64,
264         ffTime, ffTimePrev, ffTimeNext);
265     if (ffTimePrev == ffTimeNext || (ffTimeNext - ffTime < ffTime - ffTimePrev)) {
266         return AVSEEK_FLAG_FRAME;
267     } else {
268         return AVSEEK_FLAG_BACKWARD;
269     }
270 }
271 
IsSupportedTrackType(const AVStream & avStream)272 bool IsSupportedTrackType(const AVStream& avStream)
273 {
274     return (std::find(g_streamMediaTypeVec.cbegin(), g_streamMediaTypeVec.cend(),
275         avStream.codecpar->codec_type) != g_streamMediaTypeVec.cend());
276 }
277 
IsSupportedTrack(const AVStream & avStream)278 bool IsSupportedTrack(const AVStream& avStream)
279 {
280     FALSE_RETURN_V_MSG_E(avStream.codecpar != nullptr, false, "Codecpar is nullptr");
281     if (!IsSupportedTrackType(avStream)) {
282         MEDIA_LOG_E("Unsupport track type: " PUBLIC_LOG_D32, avStream.codecpar->codec_type);
283         return false;
284     }
285     if (avStream.codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
286         if (avStream.codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) {
287             MEDIA_LOG_E("Unsupport raw video track");
288             return false;
289         }
290         if (FFmpegFormatHelper::IsImageTrack(avStream)) {
291             MEDIA_LOG_E("Unsupport image track");
292             return false;
293         }
294     }
295     return true;
296 }
297 
IsBeginAsAnnexb(const uint8_t * sample,int32_t size)298 bool IsBeginAsAnnexb(const uint8_t *sample, int32_t size)
299 {
300     if (size < NAL_START_CODE_SIZE) {
301         return false;
302     }
303     bool hasShortStartCode = (sample[0] == 0 && sample[1] == 0 && sample[2] == 1); // 001
304     bool hasLongStartCode = (sample[0] == 0 && sample[1] == 0 && sample[2] == 0 && sample[3] == 1); // 0001
305     return hasShortStartCode || hasLongStartCode;
306 }
307 
GetNaluSize(const uint8_t * nalStart)308 int32_t GetNaluSize(const uint8_t *nalStart)
309 {
310     return static_cast<int32_t>(
311         (nalStart[POS_3]) | (nalStart[POS_2] << POS_8) | (nalStart[POS_1] << POS_16) | (nalStart[POS_0] << POS_24));
312 }
313 
IsHvccSyncFrame(const uint8_t * sample,int32_t size)314 bool IsHvccSyncFrame(const uint8_t *sample, int32_t size)
315 {
316     const uint8_t* nalStart = sample;
317     const uint8_t* end = nalStart + size;
318     int32_t sizeLen = NAL_START_CODE_SIZE;
319     int32_t naluSize = 0;
320     naluSize = GetNaluSize(nalStart);
321     if (naluSize <= 0 || nalStart > end - sizeLen) {
322         return false;
323     }
324     nalStart = nalStart + sizeLen;
325     while (nalStart < end) {
326         uint8_t naluType = static_cast<uint8_t>((nalStart[0] & 0x7E) >> 1);
327         if (naluType > 0x10 && naluType <= 0x17) {
328             return true;
329         }
330         if (nalStart > end - naluSize) {
331             return false;
332         }
333         nalStart = nalStart + naluSize;
334         if (nalStart > end - sizeLen) {
335             return false;
336         }
337         naluSize = GetNaluSize(nalStart);
338         if (naluSize < 0) {
339             return false;
340         }
341         nalStart = nalStart + sizeLen;
342     }
343     return false;
344 }
345 
FindNalStartCode(const uint8_t * start,const uint8_t * end,int32_t & startCodeLen)346 const uint8_t* FindNalStartCode(const uint8_t *start, const uint8_t *end, int32_t &startCodeLen)
347 {
348     startCodeLen = sizeof(START_CODE);
349     auto *iter = std::search(start, end, START_CODE, START_CODE + startCodeLen);
350     if (iter != end && (iter > start && *(iter - 1) == 0x00)) {
351         ++startCodeLen;
352         return iter - 1;
353     }
354     return iter;
355 }
356 
IsAnnexbSyncFrame(const uint8_t * sample,int32_t size)357 bool IsAnnexbSyncFrame(const uint8_t *sample, int32_t size)
358 {
359     const uint8_t* nalStart = sample;
360     const uint8_t* end = nalStart + size;
361     const uint8_t* nalEnd = nullptr;
362     int32_t startCodeLen = 0;
363     nalStart = FindNalStartCode(nalStart, end, startCodeLen);
364     if (nalStart > end - startCodeLen) {
365         return false;
366     }
367     nalStart = nalStart + startCodeLen;
368     while (nalStart < end) {
369         nalEnd = FindNalStartCode(nalStart, end, startCodeLen);
370         uint8_t naluType = static_cast<uint8_t>((nalStart[0] & 0x7E) >> 1);
371         if (naluType > 0x10 && naluType <= 0x17) {
372             return true;
373         }
374         if (nalEnd > end - startCodeLen) {
375             return false;
376         }
377         nalStart = nalEnd + startCodeLen;
378     }
379     return false;
380 }
381 
IsHevcSyncFrame(const uint8_t * sample,int32_t size)382 bool IsHevcSyncFrame(const uint8_t *sample, int32_t size)
383 {
384     if (size < NAL_START_CODE_SIZE) {
385         return false;
386     }
387     if (IsBeginAsAnnexb(sample, size)) {
388         return IsAnnexbSyncFrame(sample, size);
389     } else {
390         return IsHvccSyncFrame(sample, size);
391     }
392 }
393 
FfmpegLogPrint(void * avcl,int level,const char * fmt,va_list vl)394 void FfmpegLogPrint(void* avcl, int level, const char* fmt, va_list vl)
395 {
396     (void)avcl;
397     char buf[500] = {0}; // 500
398     int ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, vl);
399     if (ret < 0) {
400         return;
401     }
402     switch (level) {
403         case AV_LOG_WARNING:
404             MEDIA_LOG_D("[FFLogW] " PUBLIC_LOG_S, buf);
405             break;
406         case AV_LOG_ERROR:
407             MEDIA_LOG_E("[FFLogE] " PUBLIC_LOG_S, buf);
408             break;
409         case AV_LOG_FATAL:
410             MEDIA_LOG_E("[FFLogF] " PUBLIC_LOG_S, buf);
411             break;
412         case AV_LOG_PANIC:
413             MEDIA_LOG_E("[FFLogP] " PUBLIC_LOG_S, buf);
414             break;
415         case AV_LOG_INFO:
416             MEDIA_LOG_D("[FFLogI] " PUBLIC_LOG_S, buf);
417             break;
418         case AV_LOG_DEBUG:
419             MEDIA_LOG_D("[FFLogD] " PUBLIC_LOG_S, buf);
420             break;
421         default:
422             break;
423     }
424 }
425 } // namespace
426 
427 std::atomic<int> FFmpegDemuxerPlugin::readatIndex_ = 0;
FFmpegDemuxerPlugin(std::string name)428 FFmpegDemuxerPlugin::FFmpegDemuxerPlugin(std::string name)
429     : DemuxerPlugin(std::move(name)),
430       seekable_(Seekable::SEEKABLE),
431       ioContext_(),
432       selectedTrackIds_(),
433       cacheQueue_("cacheQueue"),
434       parserRefIoContext_()
435 {
436     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
437     MEDIA_LOG_D("In");
438 #ifndef _WIN32
439     (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
440     (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
441 #endif
442     av_log_set_callback(FfmpegLogPrint);
443 #ifdef BUILD_ENG_VERSION
444     std::string dumpModeStr = OHOS::system::GetParameter("FFmpegDemuxerPlugin.dump", "0");
445     dumpMode_ = static_cast<DumpMode>(strtoul(dumpModeStr.c_str(), nullptr, 2)); // 2 is binary
446     MEDIA_LOG_D("Dump mode = %s(%lu)", dumpModeStr.c_str(), dumpMode_);
447 #endif
448     MEDIA_LOG_D("Out");
449 }
450 
~FFmpegDemuxerPlugin()451 FFmpegDemuxerPlugin::~FFmpegDemuxerPlugin()
452 {
453     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
454     MEDIA_LOG_D("In");
455     ReleaseFFmpegReadLoop();
456 #ifndef _WIN32
457     (void)mallopt(M_FLUSH_THREAD_CACHE, 0);
458 #endif
459     formatContext_ = nullptr;
460     pluginImpl_ = nullptr;
461     for (auto &item : avbsfContexts_) {
462         if (item.second != nullptr) {
463             item.second = nullptr;
464         }
465     }
466     streamParsers_ = nullptr;
467     referenceParser_ = nullptr;
468     parserRefCtx_ = nullptr;
469     selectedTrackIds_.clear();
470     for (auto item : videoFirstFrameMap_) {
471         if (item.second != nullptr) {
472             FreeAVPacket(item.second);
473         }
474     }
475     MEDIA_LOG_D("Out");
476 }
477 
Dump(const DumpParam & dumpParam)478 void FFmpegDemuxerPlugin::Dump(const DumpParam &dumpParam)
479 {
480     std::string path;
481     switch (dumpParam.mode) {
482         case DUMP_READAT_INPUT:
483             path = "Readat_index." + std::to_string(dumpParam.index) + "_offset." + std::to_string(dumpParam.offset) +
484                 "_size." + std::to_string(dumpParam.size);
485             break;
486         case DUMP_AVPACKET_OUTPUT:
487             path = "AVPacket_index." + std::to_string(dumpParam.index) + "_track." +
488                 std::to_string(dumpParam.trackId) + "_pts." + std::to_string(dumpParam.pts) + "_pos." +
489                 std::to_string(dumpParam.pos);
490             break;
491         case DUMP_AVBUFFER_OUTPUT:
492             path = "AVBuffer_track." + std::to_string(dumpParam.trackId) + "_index." +
493                 std::to_string(dumpParam.index) + "_pts." + std::to_string(dumpParam.pts);
494             break;
495         default:
496             return;
497     }
498     std::ofstream ofs;
499     path = "/data/ff_dump/" + path;
500     ofs.open(path, std::ios::out); //  | std::ios::app
501     if (ofs.is_open()) {
502         ofs.write(reinterpret_cast<char*>(dumpParam.buf), dumpParam.size);
503         ofs.close();
504     }
505     MEDIA_LOG_D("Dump path:" PUBLIC_LOG_S, path.c_str());
506 }
507 
GetProbeSize(int32_t & offset,int32_t & size)508 bool FFmpegDemuxerPlugin::GetProbeSize(int32_t &offset, int32_t &size)
509 {
510     offset = 0;
511     size = 5000000; // 5000000 ff init probe size
512     return true;
513 }
514 
ResetParam()515 void FFmpegDemuxerPlugin::ResetParam()
516 {
517     readatIndex_ = 0;
518     avpacketIndex_ = 0;
519     ioContext_.offset = 0;
520     ioContext_.retry = false;
521     ioContext_.eos = false;
522     ioContext_.initDownloadDataSize = 0;
523     mediaInfo_ = MediaInfo();
524     for (size_t i = 0; i < selectedTrackIds_.size(); ++i) {
525         cacheQueue_.RemoveTrackQueue(selectedTrackIds_[i]);
526     }
527     selectedTrackIds_.clear();
528     checkedTrackIds_.clear();
529     pluginImpl_.reset();
530     formatContext_.reset();
531 
532     streamParsers_.reset();
533     for (auto item : avbsfContexts_) {
534         item.second.reset();
535     }
536     trackMtx_.clear();
537     trackDfxInfoMap_.clear();
538 }
539 
Reset()540 Status FFmpegDemuxerPlugin::Reset()
541 {
542     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
543     MEDIA_LOG_D("In");
544     ReleaseFFmpegReadLoop();
545     ResetParam();
546     return Status::OK;
547 }
548 
InitBitStreamContext(const AVStream & avStream)549 void FFmpegDemuxerPlugin::InitBitStreamContext(const AVStream& avStream)
550 {
551     FALSE_RETURN_MSG(avStream.codecpar != nullptr, "Codecpar is nullptr");
552     AVCodecID codecID = avStream.codecpar->codec_id;
553     MEDIA_LOG_D("For track " PUBLIC_LOG_D32, avStream.index);
554     FALSE_RETURN_MSG(g_bitstreamFilterMap.count(codecID) != 0, "Can not match any BitStreamContext");
555     const AVBitStreamFilter* avBitStreamFilter = av_bsf_get_by_name(g_bitstreamFilterMap.at(codecID).c_str());
556 
557     FALSE_RETURN_MSG((avBitStreamFilter != nullptr), "Call av_bsf_get_by_name failed for" PUBLIC_LOG_S,
558             g_bitstreamFilterMap.at(codecID).c_str());
559 
560     if (avbsfContexts_.count(avStream.index) <= 0 || !avbsfContexts_[avStream.index]) {
561         AVBSFContext* avbsfContext {nullptr};
562         int ret = av_bsf_alloc(avBitStreamFilter, &avbsfContext);
563         FALSE_RETURN_MSG((ret >= 0 && avbsfContext != nullptr),
564             "Call av_bsf_alloc failed, err:" PUBLIC_LOG_S, AVStrError(ret).c_str());
565 
566         ret = avcodec_parameters_copy(avbsfContext->par_in, avStream.codecpar);
567         FALSE_RETURN_MSG((ret >= 0), "Call avcodec_parameters_copy failed, err:" PUBLIC_LOG_S, AVStrError(ret).c_str());
568 
569         ret = av_bsf_init(avbsfContext);
570         FALSE_RETURN_MSG((ret >= 0), "Call av_bsf_init failed, err:" PUBLIC_LOG_S, AVStrError(ret).c_str());
571 
572         avbsfContexts_[avStream.index] = std::shared_ptr<AVBSFContext>(avbsfContext, [](AVBSFContext* ptr) {
573             if (ptr) {
574                 av_bsf_free(&ptr);
575             }
576         });
577     }
578     FALSE_RETURN_MSG(avbsfContexts_[avStream.index] != nullptr,
579         "Stream " PUBLIC_LOG_S " will not be converted to annexb", g_bitstreamFilterMap.at(codecID).c_str());
580     MEDIA_LOG_D("Track " PUBLIC_LOG_D32 " will convert to annexb", avStream.index);
581 }
582 
ConvertAvcToAnnexb(AVPacket & pkt)583 Status FFmpegDemuxerPlugin::ConvertAvcToAnnexb(AVPacket& pkt)
584 {
585     int32_t trackId = pkt.stream_index;
586     int ret = av_bsf_send_packet(avbsfContexts_[trackId].get(), &pkt);
587     FALSE_RETURN_V_MSG_E(ret >= 0, Status::ERROR_UNKNOWN,
588         "Call av_bsf_send_packet failed, err:" PUBLIC_LOG_S, AVStrError(ret).c_str());
589     av_packet_unref(&pkt);
590 
591     ret = av_bsf_receive_packet(avbsfContexts_[trackId].get(), &pkt);
592     FALSE_RETURN_V_MSG_E(ret >= 0, Status::ERROR_PACKET_CONVERT_FAILED,
593         "Call av_bsf_receive_packet failed, err:" PUBLIC_LOG_S, AVStrError(ret).c_str());
594     return Status::OK;
595 }
596 
ConvertHevcToAnnexb(AVPacket & pkt,std::shared_ptr<SamplePacket> samplePacket)597 Status FFmpegDemuxerPlugin::ConvertHevcToAnnexb(AVPacket& pkt, std::shared_ptr<SamplePacket> samplePacket)
598 {
599     size_t cencInfoSize = 0;
600     uint8_t *cencInfo = av_packet_get_side_data(samplePacket->pkts[0], AV_PKT_DATA_ENCRYPTION_INFO, &cencInfoSize);
601     streamParsers_->ConvertPacketToAnnexb(pkt.stream_index, &(pkt.data), pkt.size, cencInfo, cencInfoSize, false);
602     if (NeedCombineFrame(samplePacket->pkts[0]->stream_index) &&
603         streamParsers_->IsSyncFrame(pkt.stream_index, pkt.data, pkt.size)) {
604         pkt.flags = static_cast<int32_t>(static_cast<uint32_t>(pkt.flags) | static_cast<uint32_t>(AV_PKT_FLAG_KEY));
605     }
606     return Status::OK;
607 }
608 
ConvertVvcToAnnexb(AVPacket & pkt,std::shared_ptr<SamplePacket> samplePacket)609 Status FFmpegDemuxerPlugin::ConvertVvcToAnnexb(AVPacket& pkt, std::shared_ptr<SamplePacket> samplePacket)
610 {
611     streamParsers_->ConvertPacketToAnnexb(pkt.stream_index, &(pkt.data), pkt.size, nullptr, 0, false);
612     return Status::OK;
613 }
614 
WriteBuffer(std::shared_ptr<AVBuffer> outBuffer,const uint8_t * writeData,uint32_t writeSize)615 Status FFmpegDemuxerPlugin::WriteBuffer(
616     std::shared_ptr<AVBuffer> outBuffer, const uint8_t *writeData, uint32_t writeSize)
617 {
618     FALSE_RETURN_V_MSG_E(outBuffer != nullptr, Status::ERROR_NULL_POINTER, "Buffer is nullptr");
619     if (writeData != nullptr && writeSize > 0) {
620         FALSE_RETURN_V_MSG_E(outBuffer->memory_ != nullptr, Status::ERROR_NULL_POINTER, "Memory is nullptr");
621         int32_t ret = outBuffer->memory_->Write(writeData, writeSize, 0);
622         FALSE_RETURN_V_MSG_E(ret >= 0, Status::ERROR_INVALID_OPERATION, "Memory write failed");
623     }
624 
625     MEDIA_LOG_D("CurrentBuffer: [" PUBLIC_LOG_D64 "/" PUBLIC_LOG_D64 "/" PUBLIC_LOG_U32 "]",
626         outBuffer->pts_, outBuffer->duration_, outBuffer->flag_);
627     return Status::OK;
628 }
629 
SetDrmCencInfo(std::shared_ptr<AVBuffer> sample,std::shared_ptr<SamplePacket> samplePacket)630 Status FFmpegDemuxerPlugin::SetDrmCencInfo(
631     std::shared_ptr<AVBuffer> sample, std::shared_ptr<SamplePacket> samplePacket)
632 {
633     FALSE_RETURN_V_MSG_E(sample != nullptr && sample->memory_ != nullptr, Status::ERROR_INVALID_OPERATION,
634         "Sample is nullptr");
635     FALSE_RETURN_V_MSG_E((samplePacket != nullptr && samplePacket->pkts.size() > 0), Status::ERROR_INVALID_OPERATION,
636         "Packet is nullptr");
637     FALSE_RETURN_V_MSG_E((samplePacket->pkts[0] != nullptr && samplePacket->pkts[0]->size >= 0),
638         Status::ERROR_INVALID_OPERATION, "Packet empty");
639 
640     size_t cencInfoSize = 0;
641     MetaDrmCencInfo *cencInfo = (MetaDrmCencInfo *)av_packet_get_side_data(samplePacket->pkts[0],
642         AV_PKT_DATA_ENCRYPTION_INFO, &cencInfoSize);
643     if ((cencInfo != nullptr) && (cencInfoSize != 0)) {
644         std::vector<uint8_t> drmCencVec(reinterpret_cast<uint8_t *>(cencInfo),
645             (reinterpret_cast<uint8_t *>(cencInfo)) + sizeof(MetaDrmCencInfo));
646         sample->meta_->SetData(Media::Tag::DRM_CENC_INFO, std::move(drmCencVec));
647     }
648     return Status::OK;
649 }
650 
NeedCombineFrame(uint32_t trackId)651 bool FFmpegDemuxerPlugin::NeedCombineFrame(uint32_t trackId)
652 {
653     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, false, "AVFormatContext is nullptr");
654     return (fileType_ == FileType::MPEGTS && formatContext_->streams[trackId]->codecpar->codec_id == AV_CODEC_ID_HEVC);
655 }
656 
CombinePackets(std::shared_ptr<SamplePacket> samplePacket)657 AVPacket* FFmpegDemuxerPlugin::CombinePackets(std::shared_ptr<SamplePacket> samplePacket)
658 {
659     AVPacket *tempPkt = nullptr;
660     if (NeedCombineFrame(samplePacket->pkts[0]->stream_index) && samplePacket->pkts.size() > 1) {
661         int totalSize = 0;
662         for (auto pkt : samplePacket->pkts) {
663             FALSE_RETURN_V_MSG_E(pkt != nullptr, nullptr, "AVPacket is nullptr");
664             totalSize += pkt->size;
665         }
666         tempPkt = av_packet_alloc();
667         FALSE_RETURN_V_MSG_E(tempPkt != nullptr, nullptr, "Temp packet is nullptr");
668         int ret = av_new_packet(tempPkt, totalSize);
669         FALSE_RETURN_V_MSG_E(ret >= 0, nullptr, "Call av_new_packet failed");
670         av_packet_copy_props(tempPkt, samplePacket->pkts[0]);
671         int offset = 0;
672         bool copySuccess = true;
673         for (auto pkt : samplePacket->pkts) {
674             if (pkt == nullptr || tempPkt == nullptr || tempPkt->data == nullptr || pkt->data == nullptr) {
675                 copySuccess = false;
676                 MEDIA_LOG_E("Cache packet or data is nullptr");
677                 break;
678             }
679             if (offset < 0 || pkt->size < 0 || offset > INT_MAX - pkt->size || offset + pkt->size > totalSize) {
680                 copySuccess = false;
681                 MEDIA_LOG_E("Memcpy param invalid: totalSize=" PUBLIC_LOG_D32 ", offset=" PUBLIC_LOG_D32 ", pkt->size="
682                     PUBLIC_LOG_D32, totalSize, offset, pkt->size);
683                 break;
684             }
685             ret = memcpy_s(tempPkt->data + offset, tempPkt->size - offset, pkt->data, pkt->size);
686             if (ret != EOK) {
687                 copySuccess = false;
688                 MEDIA_LOG_E("Memcpy failed, ret:" PUBLIC_LOG_D32, ret);
689                 break;
690             }
691             offset += pkt->size;
692         }
693         if (!copySuccess) {
694             FreeAVPacket(tempPkt);
695             return nullptr;
696         }
697         tempPkt->size = totalSize;
698         MEDIA_LOG_D("Combine " PUBLIC_LOG_ZU " packets, total size=" PUBLIC_LOG_D32,
699             samplePacket->pkts.size(), totalSize);
700     } else {
701         tempPkt = samplePacket->pkts[0];
702     }
703     return tempPkt;
704 }
705 
ConvertPacketToAnnexb(std::shared_ptr<AVBuffer> sample,AVPacket * srcAVPacket,std::shared_ptr<SamplePacket> dstSamplePacket)706 Status FFmpegDemuxerPlugin::ConvertPacketToAnnexb(std::shared_ptr<AVBuffer> sample, AVPacket* srcAVPacket,
707     std::shared_ptr<SamplePacket> dstSamplePacket)
708 {
709     Status ret = Status::OK;
710     if (dstSamplePacket->isAnnexb) {
711         MEDIA_LOG_D("Has converted");
712         return ret;
713     }
714     auto codecId = formatContext_->streams[srcAVPacket->stream_index]->codecpar->codec_id;
715     if (codecId == AV_CODEC_ID_HEVC && streamParsers_ != nullptr &&
716         streamParsers_->ParserIsInited(srcAVPacket->stream_index)) {
717         ret = ConvertHevcToAnnexb(*srcAVPacket, dstSamplePacket);
718         SetDropTag(*srcAVPacket, sample, AV_CODEC_ID_HEVC);
719     } else if (codecId == AV_CODEC_ID_VVC && streamParsers_ != nullptr &&
720         streamParsers_->ParserIsInited(srcAVPacket->stream_index)) {
721         ret = ConvertVvcToAnnexb(*srcAVPacket, dstSamplePacket);
722     } else if (codecId == AV_CODEC_ID_H264 &&
723         avbsfContexts_.count(srcAVPacket->stream_index) > 0 && avbsfContexts_[srcAVPacket->stream_index] != nullptr) {
724         ret = ConvertAvcToAnnexb(*srcAVPacket);
725         SetDropTag(*srcAVPacket, sample, AV_CODEC_ID_H264);
726     }
727     if (ret != Status::OK) {
728         cacheQueue_.Pop(dstSamplePacket->pkts[0]->stream_index);
729         if (ioContext_.retry) {
730             ioContext_.retry = false;
731             formatContext_->pb->eof_reached = 0;
732             formatContext_->pb->error = 0;
733             return Status::ERROR_AGAIN;
734         }
735     }
736     dstSamplePacket->isAnnexb = true;
737     return ret;
738 }
739 
VideoFirstFrameValid(uint32_t trackIndex)740 bool FFmpegDemuxerPlugin::VideoFirstFrameValid(uint32_t trackIndex)
741 {
742     return videoFirstFrameMap_.count(trackIndex) > 0 && videoFirstFrameMap_[trackIndex] != nullptr;
743 }
744 
WriteBufferAttr(std::shared_ptr<AVBuffer> sample,std::shared_ptr<SamplePacket> samplePacket)745 void FFmpegDemuxerPlugin::WriteBufferAttr(std::shared_ptr<AVBuffer> sample, std::shared_ptr<SamplePacket> samplePacket)
746 {
747     AVStream *avStream = formatContext_->streams[samplePacket->pkts[0]->stream_index];
748     if (samplePacket->pkts[0]->pts != AV_NOPTS_VALUE) {
749         sample->pts_ = AvTime2Us(ConvertTimeFromFFmpeg(samplePacket->pkts[0]->pts, avStream->time_base));
750     }
751     // durantion dts
752     if (samplePacket->pkts[0]->duration != AV_NOPTS_VALUE) {
753         int64_t duration = AvTime2Us(ConvertTimeFromFFmpeg(samplePacket->pkts[0]->duration, avStream->time_base));
754         sample->duration_ = duration;
755         sample->meta_->SetData(Media::Tag::BUFFER_DURATION, duration);
756     }
757     if (samplePacket->pkts[0]->dts != AV_NOPTS_VALUE) {
758         int64_t dts = AvTime2Us(ConvertTimeFromFFmpeg(samplePacket->pkts[0]->dts, avStream->time_base));
759         sample->dts_ = dts;
760         sample->meta_->SetData(Media::Tag::BUFFER_DECODING_TIMESTAMP, dts);
761     }
762 
763     if (FFmpegFormatHelper::IsVideoType(*avStream) && avStream->codecpar->codec_id != AV_CODEC_ID_H264 &&
764         VideoFirstFrameValid(avStream->index) &&
765         samplePacket->pkts[0]->dts == videoFirstFrameMap_[avStream->index]->dts) {
766         if (streamParsers_ != nullptr) {
767             streamParsers_->ResetXPSSendStatus(avStream->index);
768         }
769     }
770 }
771 
BufferIsValid(std::shared_ptr<AVBuffer> sample,std::shared_ptr<SamplePacket> samplePacket)772 Status FFmpegDemuxerPlugin::BufferIsValid(std::shared_ptr<AVBuffer> sample, std::shared_ptr<SamplePacket> samplePacket)
773 {
774     FALSE_RETURN_V_MSG_E(samplePacket != nullptr && samplePacket->pkts.size() > 0 &&
775         samplePacket->pkts[0] != nullptr && samplePacket->pkts[0]->size >= 0,
776         Status::ERROR_INVALID_OPERATION, "Input packet is nullptr or empty");
777     FALSE_RETURN_V_MSG_E(static_cast<uint32_t>(samplePacket->pkts[0]->stream_index) < formatContext_->nb_streams,
778         Status::ERROR_INVALID_OPERATION, "FormatContext state error");
779     FALSE_RETURN_V_MSG_E(formatContext_->streams[samplePacket->pkts[0]->stream_index] != nullptr,
780         Status::ERROR_INVALID_OPERATION, "Stream state error");
781     MEDIA_LOG_D("Convert packet info for track " PUBLIC_LOG_D32, samplePacket->pkts[0]->stream_index);
782     FALSE_RETURN_V_MSG_E(sample != nullptr && sample->memory_ != nullptr && sample->meta_ != nullptr,
783         Status::ERROR_INVALID_OPERATION, "Input sample is nullptr");
784     FALSE_RETURN_V_MSG_E(sample->memory_->GetCapacity() >= 0, Status::ERROR_INVALID_DATA,
785         "Invalid capability[%{public}d]", sample->memory_->GetCapacity());
786     return Status::OK;
787 }
788 
UpdateLastPacketInfo(int32_t trackId,int64_t pts,int64_t pos,int64_t duration)789 void FFmpegDemuxerPlugin::UpdateLastPacketInfo(int32_t trackId, int64_t pts, int64_t pos, int64_t duration)
790 {
791     trackDfxInfoMap_[trackId].lastPts = pts;
792     trackDfxInfoMap_[trackId].lastDuration = duration;
793     trackDfxInfoMap_[trackId].lastPos = pos;
794 }
795 
ConvertAVPacketToSample(std::shared_ptr<AVBuffer> sample,std::shared_ptr<SamplePacket> samplePacket)796 Status FFmpegDemuxerPlugin::ConvertAVPacketToSample(
797     std::shared_ptr<AVBuffer> sample, std::shared_ptr<SamplePacket> samplePacket)
798 {
799     Status bufferIsValid = BufferIsValid(sample, samplePacket);
800     FALSE_RETURN_V_MSG_E(bufferIsValid == Status::OK, bufferIsValid, "AVBuffer or packet is invalid");
801     WriteBufferAttr(sample, samplePacket);
802 
803     // convert
804     AVPacket *tempPkt = CombinePackets(samplePacket);
805     FALSE_RETURN_V_MSG_E(tempPkt != nullptr, Status::ERROR_INVALID_OPERATION, "Temp packet is empty");
806     if (cacheQueue_.ResetInfo(samplePacket) == false) {
807         MEDIA_LOG_D("Reset info failed");
808     }
809     Status ret = ConvertPacketToAnnexb(sample, tempPkt, samplePacket);
810     if (ret != Status::OK && tempPkt->size != samplePacket->pkts[0]->size) {
811         FreeAVPacket(tempPkt);
812     }
813     FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Convert annexb failed");
814     if (cacheQueue_.SetInfo(samplePacket) == false) {
815         MEDIA_LOG_D("Set info failed");
816     }
817 
818     // flag\copy
819     FALSE_RETURN_V_MSG_E(tempPkt->size >= 0 && static_cast<uint32_t>(tempPkt->size) >= samplePacket->offset,
820         Status::ERROR_INVALID_DATA, "Invalid size[%{public}d] offset[%{public}u]", tempPkt->size, samplePacket->offset);
821     uint32_t remainSize = static_cast<uint32_t>(tempPkt->size) - samplePacket->offset;
822     uint32_t capability = static_cast<uint32_t>(sample->memory_->GetCapacity());
823     uint32_t copySize = remainSize < capability ? remainSize : capability;
824     MEDIA_LOG_D("Convert size [" PUBLIC_LOG_D32 "/" PUBLIC_LOG_U32 "/" PUBLIC_LOG_U32 "/" PUBLIC_LOG_U32 "]",
825         tempPkt->size, remainSize, copySize, samplePacket->offset);
826     SetDrmCencInfo(sample, samplePacket);
827 
828     sample->flag_ = ConvertFlagsFromFFmpeg(*tempPkt, (copySize != static_cast<uint32_t>(tempPkt->size)));
829     ret = WriteBuffer(sample, tempPkt->data + samplePacket->offset, copySize);
830     if (ret != Status::OK && tempPkt->size != samplePacket->pkts[0]->size) {
831         FreeAVPacket(tempPkt);
832     }
833     FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Write buffer failed");
834 
835     if (!samplePacket->isEOS) {
836         UpdateLastPacketInfo(tempPkt->stream_index, sample->pts_, tempPkt->pos, sample->duration_);
837     }
838 #ifdef BUILD_ENG_VERSION
839     DumpParam dumpParam {DumpMode(DUMP_AVBUFFER_OUTPUT & dumpMode_), tempPkt->data + samplePacket->offset,
840         tempPkt->stream_index, -1, copySize, trackDfxInfoMap_[tempPkt->stream_index].frameIndex++, tempPkt->pts, -1};
841     Dump(dumpParam);
842 #endif
843     if (tempPkt != nullptr && tempPkt->size != samplePacket->pkts[0]->size) {
844         FreeAVPacket(tempPkt);
845     }
846 
847     if (copySize < remainSize) {
848         FALSE_RETURN_V_MSG_E(samplePacket->offset <= UINT32_MAX - copySize, Status::ERROR_INVALID_DATA,
849             "Invalid offset[%{public}u] copySize[%{public}u]", samplePacket->offset, copySize);
850         samplePacket->offset += copySize;
851         MEDIA_LOG_D("Buffer is not enough, next buffer to copy remain data");
852         return Status::ERROR_NOT_ENOUGH_DATA;
853     }
854     return Status::OK;
855 }
856 
PushEOSToAllCache()857 Status FFmpegDemuxerPlugin::PushEOSToAllCache()
858 {
859     Status ret = Status::OK;
860     for (size_t i = 0; i < selectedTrackIds_.size(); ++i) {
861         auto streamIndex = selectedTrackIds_[i];
862         MEDIA_LOG_I("Track " PUBLIC_LOG_D32, streamIndex);
863         std::shared_ptr<SamplePacket> eosSample = std::make_shared<SamplePacket>();
864         eosSample->isEOS = true;
865         cacheQueue_.Push(streamIndex, eosSample);
866         ret = CheckCacheDataLimit(streamIndex);
867     }
868     return ret;
869 }
870 
WebvttPktProcess(AVPacket * pkt)871 bool FFmpegDemuxerPlugin::WebvttPktProcess(AVPacket *pkt)
872 {
873     auto trackId = pkt->stream_index;
874     if (pkt->size > 0) {    // vttc
875         return false;
876     } else {    // vtte
877         if (cacheQueue_.HasCache(trackId)) {
878             std::shared_ptr<SamplePacket> cacheSamplePacket = cacheQueue_.Back(static_cast<uint32_t>(trackId));
879             if (cacheSamplePacket != nullptr && cacheSamplePacket->pkts.size() > 0 &&
880                 cacheSamplePacket->pkts[0] != nullptr && cacheSamplePacket->pkts[0]->duration == 0 &&
881                 pkt->pts != AV_NOPTS_VALUE && cacheSamplePacket->pkts[0]->pts != AV_NOPTS_VALUE) {
882                 cacheSamplePacket->pkts[0]->duration = pkt->pts - cacheSamplePacket->pkts[0]->pts;
883             }
884         }
885     }
886     FreeAVPacket(pkt);
887     return true;
888 }
889 
IsWebvttMP4(const AVStream * avStream)890 bool FFmpegDemuxerPlugin::IsWebvttMP4(const AVStream *avStream)
891 {
892     return (avStream->codecpar->codec_id == AV_CODEC_ID_WEBVTT && FFmpegFormatHelper::IsMpeg4File(fileType_));
893 }
894 
WebvttMP4EOSProcess(const AVPacket * pkt)895 void FFmpegDemuxerPlugin::WebvttMP4EOSProcess(const AVPacket *pkt)
896 {
897     if (pkt != nullptr) {
898         auto trackId = pkt->stream_index;
899         AVStream *avStream = formatContext_->streams[trackId];
900         if (IsWebvttMP4(avStream) && pkt->size == 0 && cacheQueue_.HasCache(trackId)) {
901             std::shared_ptr<SamplePacket> cacheSamplePacket = cacheQueue_.Back(static_cast<uint32_t>(trackId));
902             if (cacheSamplePacket != nullptr && cacheSamplePacket->pkts.size() > 0 &&
903                 cacheSamplePacket->pkts[0] != nullptr && cacheSamplePacket->pkts[0]->duration == 0) {
904                 cacheSamplePacket->pkts[0]->duration =
905                     formatContext_->streams[pkt->stream_index]->duration - cacheSamplePacket->pkts[0]->pts;
906             }
907         }
908     }
909 }
910 
ResetContext()911 void FFmpegDemuxerPlugin::ResetContext()
912 {
913     formatContext_->pb->eof_reached = 0;
914     formatContext_->pb->error = 0;
915     ioContext_.retry = false;
916 }
917 
SelectedVideo()918 bool FFmpegDemuxerPlugin::SelectedVideo()
919 {
920     for (uint32_t index : selectedTrackIds_) {
921         FALSE_RETURN_V_NOLOG(
922             formatContext_ != nullptr &&
923             index < formatContext_->nb_streams &&
924             formatContext_->streams[index] != nullptr &&
925             formatContext_->streams[index]->codecpar != nullptr, false);
926 
927         if (formatContext_->streams[index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
928             return true;
929         }
930     }
931     return false;
932 }
933 
NeedDropAfterSeek(uint32_t trackId,int64_t pts)934 bool FFmpegDemuxerPlugin::NeedDropAfterSeek(uint32_t trackId, int64_t pts)
935 {
936     FALSE_RETURN_V_NOLOG(seekTime_ != AV_NOPTS_VALUE && seekMode_ == SeekMode::SEEK_NEXT_SYNC, false);
937     FALSE_RETURN_V_NOLOG(formatContext_ != nullptr && trackId < formatContext_->nb_streams, false);
938     FALSE_RETURN_V_NOLOG(fileType_ != FileType::OGG && fileType_ != FileType::UNKNOW, false);
939     AVStream *avStream = formatContext_->streams[trackId];
940     FALSE_RETURN_V_NOLOG(avStream != nullptr && avStream->codecpar != nullptr, false);
941     FALSE_RETURN_V_NOLOG(avStream->start_time != AV_NOPTS_VALUE, false);
942     if (avStream->start_time < 0) {
943         FALSE_RETURN_V_NOLOG(pts <= INT64_MAX + avStream->start_time, false);
944     } else if (avStream->start_time > 0) {
945         FALSE_RETURN_V_NOLOG(pts >= INT64_MIN + avStream->start_time, false);
946     }
947     if (!SelectedVideo() && FFmpegFormatHelper::IsAudioType(*avStream) && // audio seek
948         AvTime2Us(ConvertTimeFromFFmpeg(pts - avStream->start_time, avStream->time_base)) < seekTime_ * MS_TO_US) {
949         MEDIA_LOG_W("Seek frame behind time, drop");
950         return true;
951     }
952     seekTime_ = AV_NOPTS_VALUE;
953     return false;
954 }
955 
AVReadFrameLimit(AVPacket * pkt)956 int FFmpegDemuxerPlugin::AVReadFrameLimit(AVPacket *pkt)
957 {
958     if (!ioContext_.isLimitType) {
959         return av_read_frame(formatContext_.get(), pkt);
960     }
961 
962     ioContext_.isLimit = true;
963     int ffmpegRet = av_read_frame(formatContext_.get(), pkt);
964     ioContext_.isLimit = false;
965     ioContext_.readSizeCnt = 0;
966     return ffmpegRet;
967 }
968 
ReadPacketToCacheQueue(const uint32_t readId)969 Status FFmpegDemuxerPlugin::ReadPacketToCacheQueue(const uint32_t readId)
970 {
971     std::lock_guard<std::mutex> lock(mutex_);
972     AVPacket *pkt = nullptr;
973     bool continueRead = true;
974     Status ret = Status::OK;
975     while (continueRead) {
976         FALSE_RETURN_V(!isInterruptNeeded_.load(), Status::ERROR_WRONG_STATE);
977         if (pkt == nullptr) {
978             pkt = av_packet_alloc();
979             FALSE_RETURN_V_MSG_E(pkt != nullptr, Status::ERROR_NULL_POINTER, "Call av_packet_alloc failed");
980         }
981         std::unique_lock<std::mutex> sLock(syncMutex_);
982         int ffmpegRet = AVReadFrameLimit(pkt);
983         sLock.unlock();
984         if (ffmpegRet == AVERROR_EOF) { // eos
985             WebvttMP4EOSProcess(pkt);
986             FreeAVPacket(pkt);
987             ret = PushEOSToAllCache();
988             FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Push eos failed");
989             return Status::END_OF_STREAM;
990         }
991         if (ffmpegRet < 0) { // fail
992             FreeAVPacket(pkt);
993             MEDIA_LOG_E("Call av_read_frame failed:" PUBLIC_LOG_S ", retry: " PUBLIC_LOG_D32,
994                 AVStrError(ffmpegRet).c_str(), int(ioContext_.retry));
995             if (ioContext_.retry) {
996                 ResetContext();
997                 return Status::ERROR_AGAIN;
998             }
999             return Status::ERROR_UNKNOWN;
1000         }
1001         auto trackId = pkt->stream_index;
1002         if (!TrackIsSelected(trackId) || NeedDropAfterSeek(trackId, pkt->pts)) {
1003             av_packet_unref(pkt);
1004             continue;
1005         }
1006         AVStream *avStream = formatContext_->streams[trackId];
1007         if (IsWebvttMP4(avStream) && WebvttPktProcess(pkt)) {
1008             break;
1009         } else if (!IsWebvttMP4(avStream) && (!NeedCombineFrame(readId) ||
1010             (cacheQueue_.HasCache(static_cast<uint32_t>(trackId)) && IsBeginAsAnnexb(pkt->data, pkt->size)))) {
1011             continueRead = false;
1012         }
1013         ret = AddPacketToCacheQueue(pkt);
1014         FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Add cache failed");
1015         pkt = nullptr;
1016     }
1017     return ret;
1018 }
1019 
SetEosSample(std::shared_ptr<AVBuffer> sample)1020 Status FFmpegDemuxerPlugin::SetEosSample(std::shared_ptr<AVBuffer> sample)
1021 {
1022     MEDIA_LOG_D("In");
1023     sample->pts_ = 0;
1024     sample->flag_ =  (uint32_t)(AVBufferFlag::EOS);
1025     Status ret = WriteBuffer(sample, nullptr, 0);
1026     FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Write buffer failed");
1027     MEDIA_LOG_I("Out");
1028     return Status::OK;
1029 }
1030 
Start()1031 Status FFmpegDemuxerPlugin::Start()
1032 {
1033     return Status::OK;
1034 }
1035 
Stop()1036 Status FFmpegDemuxerPlugin::Stop()
1037 {
1038     return Status::OK;
1039 }
1040 
1041 // Write packet unimplemented, return 0
AVWritePacket(void * opaque,uint8_t * buf,int bufSize)1042 int FFmpegDemuxerPlugin::AVWritePacket(void* opaque, uint8_t* buf, int bufSize)
1043 {
1044     (void)opaque;
1045     (void)buf;
1046     (void)bufSize;
1047     return 0;
1048 }
1049 
CheckContextIsValid(void * opaque,int & bufSize)1050 int FFmpegDemuxerPlugin::CheckContextIsValid(void* opaque, int &bufSize)
1051 {
1052     int ret = -1;
1053     auto ioContext = static_cast<IOContext*>(opaque);
1054     FALSE_RETURN_V_MSG_E(ioContext != nullptr, ret, "IOContext is nullptr");
1055     FALSE_RETURN_V_MSG_E(ioContext->dataSource != nullptr, ret, "DataSource is nullptr");
1056     FALSE_RETURN_V_MSG_E(ioContext->offset <= INT64_MAX - static_cast<int64_t>(bufSize), ret, "Offset invalid");
1057 
1058     if (ioContext->dataSource->IsDash() && ioContext->eos == true) {
1059         MEDIA_LOG_I("Read eos");
1060         return AVERROR_EOF;
1061     }
1062 
1063     MEDIA_LOG_D("Offset: " PUBLIC_LOG_D64 ", totalSize: " PUBLIC_LOG_U64, ioContext->offset, ioContext->fileSize);
1064     if (ioContext->fileSize > 0) {
1065         FALSE_RETURN_V_MSG_E(static_cast<uint64_t>(ioContext->offset) <= ioContext->fileSize, ret, "Out of file size");
1066         if (static_cast<size_t>(ioContext->offset + bufSize) > ioContext->fileSize) {
1067             bufSize = static_cast<int64_t>(ioContext->fileSize) - ioContext->offset;
1068         }
1069     }
1070 
1071     if (ioContext->isLimit) {
1072         if (bufSize > ioContext->sizeLimit - ioContext->readSizeCnt) {
1073             MEDIA_LOG_E("Read limit cur: " PUBLIC_LOG_D32 ", limit: " PUBLIC_LOG_D32 ", read: " PUBLIC_LOG_D32,
1074                 ioContext->readSizeCnt, ioContext->sizeLimit, bufSize);
1075             return ret;
1076         }
1077         ioContext->readSizeCnt += bufSize;
1078     }
1079     return 0;
1080 }
1081 
AVSeek(void * opaque,int64_t offset,int whence)1082 int64_t FFmpegDemuxerPlugin::AVSeek(void* opaque, int64_t offset, int whence)
1083 {
1084     auto ioContext = static_cast<IOContext*>(opaque);
1085     uint64_t newPos = 0;
1086     FALSE_RETURN_V_MSG_E(ioContext != nullptr, newPos, "IOContext is nullptr");
1087     switch (whence) {
1088         case SEEK_SET:
1089             newPos = static_cast<uint64_t>(offset);
1090             ioContext->offset = newPos;
1091             MEDIA_LOG_D("Whence: " PUBLIC_LOG_D32 ", pos = " PUBLIC_LOG_D64 ", newPos = " PUBLIC_LOG_U64,
1092                 whence, offset, newPos);
1093             break;
1094         case SEEK_CUR:
1095             newPos = ioContext->offset + offset;
1096             MEDIA_LOG_D("Whence: " PUBLIC_LOG_D32 ", pos = " PUBLIC_LOG_D64 ", newPos = " PUBLIC_LOG_U64,
1097                 whence, offset, newPos);
1098             break;
1099         case SEEK_END:
1100         case AVSEEK_SIZE: {
1101             FALSE_RETURN_V_MSG_E(ioContext->dataSource != nullptr, newPos, "DataSource is nullptr");
1102             if (ioContext->dataSource->IsDash()) {
1103                 return -1;
1104             }
1105             uint64_t mediaDataSize = 0;
1106             if (ioContext->dataSource->GetSize(mediaDataSize) == Status::OK && (mediaDataSize > 0)) {
1107                 newPos = mediaDataSize + offset;
1108                 MEDIA_LOG_D("Whence: " PUBLIC_LOG_D32 ", pos = " PUBLIC_LOG_D64 ", newPos = " PUBLIC_LOG_U64,
1109                     whence, offset, newPos);
1110             }
1111             break;
1112         }
1113         default:
1114             MEDIA_LOG_E("Unexpected whence " PUBLIC_LOG_D32, whence);
1115             break;
1116     }
1117     if (whence != AVSEEK_SIZE) {
1118         ioContext->offset = newPos;
1119     }
1120     MEDIA_LOG_D("Current offset: " PUBLIC_LOG_D64 ", new pos: " PUBLIC_LOG_U64, ioContext->offset, newPos);
1121     return newPos;
1122 }
1123 
AllocAVIOContext(int flags,IOContext * ioContext)1124 AVIOContext* FFmpegDemuxerPlugin::AllocAVIOContext(int flags, IOContext *ioContext)
1125 {
1126     auto buffer = static_cast<unsigned char*>(av_malloc(DEFAULT_READ_SIZE));
1127     FALSE_RETURN_V_MSG_E(buffer != nullptr, nullptr, "Call av_malloc failed");
1128 
1129     AVIOContext* avioContext = avio_alloc_context(
1130         buffer, DEFAULT_READ_SIZE,
1131         static_cast<int>(static_cast<uint32_t>(flags) & static_cast<uint32_t>(AVIO_FLAG_WRITE)),
1132         static_cast<void*>(ioContext),
1133         AVReadPacket, AVWritePacket, AVSeek);
1134     if (avioContext == nullptr) {
1135         MEDIA_LOG_E("Call avio_alloc_context failed");
1136         av_free(buffer);
1137         return nullptr;
1138     }
1139     avioContext->seekable = (seekable_ == Seekable::SEEKABLE) ? AVIO_SEEKABLE_NORMAL : 0;
1140     if (!(static_cast<uint32_t>(flags) & static_cast<uint32_t>(AVIO_FLAG_WRITE))) {
1141         avioContext->buf_ptr = avioContext->buf_end;
1142         avioContext->write_flag = 0;
1143     }
1144     return avioContext;
1145 }
1146 
FreeContext(AVFormatContext * formatContext,AVIOContext * avioContext)1147 void FreeContext(AVFormatContext* formatContext, AVIOContext* avioContext)
1148 {
1149     if (formatContext) {
1150         avformat_close_input(&formatContext);
1151     }
1152     if (avioContext) {
1153         if (avioContext->buffer) {
1154             av_freep(&(avioContext->buffer));
1155         }
1156         avio_context_free(&avioContext);
1157     }
1158 }
1159 
ParseHeader(AVFormatContext * formatContext,std::shared_ptr<AVInputFormat> pluginImpl,AVDictionary ** options)1160 int32_t ParseHeader(AVFormatContext* formatContext, std::shared_ptr<AVInputFormat> pluginImpl, AVDictionary **options)
1161 {
1162     FALSE_RETURN_V_MSG_E(formatContext && pluginImpl, -1, "AVFormatContext is nullptr");
1163     MediaAVCodec::AVCodecTrace trace("ffmpeg_init");
1164 
1165     AVIOContext* avioContext = formatContext->pb;
1166     auto begin = std::chrono::steady_clock::now();
1167     int ret = avformat_open_input(&formatContext, nullptr, pluginImpl.get(), options);
1168     if (ret < 0) {
1169         FreeContext(formatContext, avioContext);
1170         MEDIA_LOG_E("Call avformat_open_input failed by " PUBLIC_LOG_S ", err:" PUBLIC_LOG_S,
1171             pluginImpl->name, AVStrError(ret).c_str());
1172         return ret;
1173     }
1174 
1175     auto open = std::chrono::steady_clock::now();
1176     if (FFmpegFormatHelper::GetFileTypeByName(*formatContext) == FileType::FLV) { // Fix init live-flv-source too slow
1177         formatContext->probesize = LIVE_FLV_PROBE_SIZE;
1178     }
1179 
1180     ret = avformat_find_stream_info(formatContext, NULL);
1181     auto parse = std::chrono::steady_clock::now();
1182     int64_t openSpend = static_cast<int64_t>(
1183             std::chrono::duration_cast<std::chrono::milliseconds>(open - begin).count());
1184     int64_t parseSpend = static_cast<int64_t>(
1185             std::chrono::duration_cast<std::chrono::milliseconds>(parse - open).count());
1186     if ((parseSpend < 0) || (openSpend > INT64_MAX - parseSpend) || (openSpend + parseSpend > INIT_TIME_THRESHOLD)) {
1187         MEDIA_LOG_W("Spend [" PUBLIC_LOG_D64 "/" PUBLIC_LOG_D64 "]", openSpend, parseSpend);
1188     }
1189     if (ret < 0) {
1190         FreeContext(formatContext, avioContext);
1191         MEDIA_LOG_E("Parse stream info failed by " PUBLIC_LOG_S ", err:" PUBLIC_LOG_S,
1192             pluginImpl->name, AVStrError(ret).c_str());
1193         return ret;
1194     }
1195     return 0;
1196 }
1197 
InitAVFormatContext(IOContext * ioContext)1198 std::shared_ptr<AVFormatContext> FFmpegDemuxerPlugin::InitAVFormatContext(IOContext *ioContext)
1199 {
1200     AVFormatContext* formatContext = avformat_alloc_context();
1201     FALSE_RETURN_V_MSG_E(formatContext != nullptr, nullptr, "AVFormatContext is nullptr");
1202 
1203     formatContext->pb = AllocAVIOContext(AVIO_FLAG_READ, ioContext);
1204     if (formatContext->pb == nullptr) {
1205         FreeContext(formatContext, nullptr);
1206         return nullptr;
1207     }
1208 
1209     formatContext->flags = static_cast<uint32_t>(formatContext->flags) | static_cast<uint32_t>(AVFMT_FLAG_CUSTOM_IO);
1210     if (std::string(pluginImpl_->name) == PLUGIN_NAME_MP3) {
1211         formatContext->flags =
1212             static_cast<uint32_t>(formatContext->flags) | static_cast<uint32_t>(AVFMT_FLAG_FAST_SEEK);
1213     }
1214     AVDictionary *options = nullptr;
1215     if (ioContext_.dataSource->IsDash()) {
1216         av_dict_set(&options, "use_tfdt", "true", 0);
1217     }
1218 
1219     int ret = ParseHeader(formatContext, pluginImpl_, &options);
1220     av_dict_free(&options);
1221     FALSE_RETURN_V_MSG_E(ret >= 0, nullptr, "ParseHeader failed");
1222 
1223     std::shared_ptr<AVFormatContext> retFormatContext =
1224         std::shared_ptr<AVFormatContext>(formatContext, [](AVFormatContext *ptr) {
1225             if (ptr) {
1226                 auto ctx = ptr->pb;
1227                 avformat_close_input(&ptr);
1228                 if (ctx) {
1229                     ctx->opaque = nullptr;
1230                     av_freep(&(ctx->buffer));
1231                     av_opt_free(ctx);
1232                     avio_context_free(&ctx);
1233                     ctx = nullptr;
1234                 }
1235             }
1236         });
1237     return retFormatContext;
1238 }
1239 
NotifyInitializationCompleted()1240 void FFmpegDemuxerPlugin::NotifyInitializationCompleted()
1241 {
1242     ioContext_.initCompleted = true;
1243     if (ioContext_.initDownloadDataSize >= INIT_DOWNLOADS_DATA_SIZE_THRESHOLD) {
1244         MEDIA_LOG_I("Large init size %{public}u", ioContext_.initDownloadDataSize);
1245     }
1246 }
1247 
InitIoContextInDemuxer(const std::shared_ptr<DataSource> & source)1248 void FFmpegDemuxerPlugin::InitIoContextInDemuxer(const std::shared_ptr<DataSource>& source)
1249 {
1250     ioContext_.dataSource = source;
1251     ioContext_.offset = 0;
1252     ioContext_.eos = false;
1253     ioContext_.dumpMode = dumpMode_;
1254     seekable_ = ioContext_.dataSource->IsDash() ? Plugins::Seekable::UNSEEKABLE : source->GetSeekable();
1255     if (seekable_ == Plugins::Seekable::SEEKABLE) {
1256         ioContext_.dataSource->GetSize(ioContext_.fileSize);
1257     } else {
1258         ioContext_.fileSize = -1;
1259     }
1260     MEDIA_LOG_I("FileSize: " PUBLIC_LOG_U64 ", seekable: " PUBLIC_LOG_D32, ioContext_.fileSize, seekable_);
1261 }
1262 
SetDataSource(const std::shared_ptr<DataSource> & source)1263 Status FFmpegDemuxerPlugin::SetDataSource(const std::shared_ptr<DataSource>& source)
1264 {
1265     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
1266     FALSE_RETURN_V_MSG_E(formatContext_ == nullptr, Status::ERROR_WRONG_STATE,
1267         "AVFormatContext has been initialized");
1268     FALSE_RETURN_V_MSG_E(source != nullptr, Status::ERROR_INVALID_PARAMETER, "DataSource is nullptr");
1269     if (ioContext_.invokerType != InvokerType::INIT) {
1270         std::lock_guard<std::mutex> initLock(ioContext_.invokerTypeMutex);
1271         ioContext_.invokerType = InvokerType::INIT;
1272     }
1273     InitIoContextInDemuxer(source);
1274     {
1275         std::lock_guard<std::mutex> glock(g_mtx);
1276         pluginImpl_ = g_pluginInputFormat[pluginName_];
1277     }
1278     FALSE_RETURN_V_MSG_E(pluginImpl_ != nullptr, Status::ERROR_UNSUPPORTED_FORMAT, "No match inputformat");
1279     formatContext_ = InitAVFormatContext(&ioContext_);
1280     if (formatContext_ == nullptr) {
1281         if (ioContext_.retry) {
1282             MEDIA_LOG_E("SetDataSource failed cause not enough data");
1283             return Status::ERROR_NOT_ENOUGH_DATA;
1284         }
1285         MEDIA_LOG_E("AVFormatContext is nullptr");
1286         return Status::ERROR_UNKNOWN;
1287     }
1288     fileType_ = FFmpegFormatHelper::GetFileTypeByName(*formatContext_);
1289     InitParser();
1290 
1291     // parse media info
1292     GetMediaInfo();
1293 
1294     SetAVReadFrameLimit();
1295 
1296     // check param
1297     if (ioContext_.retry && !HasCodecParameters()) {
1298         ResetParam();
1299         MEDIA_LOG_E("SetDataSource failed cause not enough data");
1300         return Status::ERROR_NOT_ENOUGH_DATA;
1301     }
1302     NotifyInitializationCompleted();
1303     MEDIA_LOG_I("Out");
1304     cachelimitSize_ = DEFAULT_CACHE_LIMIT;
1305     if (ioContext_.initErrorAgain == true && formatContext_->pb->error == -1) { // -1 means error_again during init
1306         MEDIA_LOG_E("Initialization error_again occurred");
1307         ResetContext();
1308         ioContext_.initErrorAgain = false;
1309     }
1310     return Status::OK;
1311 }
1312 
CheckProbScore(const std::string & pluginName,const int32_t probScore)1313 static bool CheckProbScore(const std::string& pluginName, const int32_t probScore)
1314 {
1315     if (probScore >= DEF_PROBE_SCORE_LIMIT) {
1316         return true;
1317     }
1318 
1319     std::string pluginType = pluginName.substr(std::string(PLUGIN_NAME_PREFIX).size());
1320     if (StartWith(pluginType.c_str(), PLUGIN_NAME_MP3) && probScore > MP3_PROBE_SCORE_LIMIT) {
1321         return true;
1322     }
1323 
1324     return false;
1325 }
1326 
SetDataSourceWithProbSize(const std::shared_ptr<DataSource> & source,const int32_t probSize)1327 Status FFmpegDemuxerPlugin::SetDataSourceWithProbSize(const std::shared_ptr<DataSource>& source,
1328     const int32_t probSize)
1329 {
1330     std::unique_lock<std::shared_mutex> lock(sharedMutex_);
1331     FALSE_RETURN_V_MSG_E(formatContext_ == nullptr, Status::ERROR_WRONG_STATE,
1332         "AVFormatContext has been initialized");
1333     FALSE_RETURN_V_MSG_E(source != nullptr, Status::ERROR_INVALID_PARAMETER, "DataSource is nullptr");
1334     FALSE_RETURN_V_MSG_E(probSize >= 0, Status::ERROR_INVALID_PARAMETER, "probSize is invalid");
1335 
1336     int32_t probScore = SniffWithSize(pluginName_, source, probSize);
1337     FALSE_RETURN_V_MSG_E(CheckProbScore(pluginName_, probScore), Status::ERROR_INVALID_PARAMETER,
1338         "source and inputformat mismatch");
1339     lock.unlock();
1340 
1341     return SetDataSource(source);
1342 }
1343 
HasCodecParameters()1344 bool FFmpegDemuxerPlugin::HasCodecParameters()
1345 {
1346     int32_t param;
1347     FALSE_RETURN_V_MSG_E(static_cast<size_t>(formatContext_->nb_streams) == mediaInfo_.tracks.size(), false,
1348         "mediaInfo is error");
1349     for (uint32_t i = 0; i < formatContext_->nb_streams; i++) {
1350         auto avStream = formatContext_->streams[i];
1351         FALSE_RETURN_V_MSG_E(avStream != nullptr && avStream->codecpar != nullptr, false, "AVStream is nullptr");
1352         Meta &format = mediaInfo_.tracks[i];
1353         bool flag = !HaveValidParser(avStream->codecpar->codec_id) ||
1354             (HaveValidParser(avStream->codecpar->codec_id) && streamParsers_ != nullptr);
1355         if (FFmpegFormatHelper::IsAudioType(*avStream)) {
1356             FALSE_RETURN_V_MSG_E(format.GetData(Tag::AUDIO_CHANNEL_COUNT, param), false,
1357                 "unspecified channel_count");
1358             FALSE_RETURN_V_MSG_E(format.GetData(Tag::AUDIO_SAMPLE_RATE, param), false, "unspecified sample_rate");
1359         } else if (FFmpegFormatHelper::IsVideoType(*avStream)) {
1360             FALSE_RETURN_V_MSG_E(flag && format.GetData(Tag::VIDEO_WIDTH, param), false, "unspecified width");
1361             FALSE_RETURN_V_MSG_E(flag && format.GetData(Tag::VIDEO_HEIGHT, param), false, "unspecified height");
1362         }
1363     }
1364     return true;
1365 }
1366 
InitParser()1367 void FFmpegDemuxerPlugin::InitParser()
1368 {
1369     FALSE_RETURN_MSG(formatContext_ != nullptr, "AVFormatContext is nullptr");
1370     ParserBoxInfo();
1371     streamParsers_ = std::make_shared<MultiStreamParserManager>();
1372     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
1373         if (g_bitstreamFilterMap.count(formatContext_->streams[trackIndex]->codecpar->codec_id) != 0) {
1374             InitBitStreamContext(*(formatContext_->streams[trackIndex]));
1375             continue;
1376         }
1377         if (HaveValidParser(formatContext_->streams[trackIndex]->codecpar->codec_id) && streamParsers_ != nullptr) {
1378             Status ret = streamParsers_->Create(
1379                 trackIndex, g_streamParserMap.at(formatContext_->streams[trackIndex]->codecpar->codec_id));
1380             if (ret != Status::OK) {
1381                 MEDIA_LOG_W("Init failed");
1382             } else {
1383                 MEDIA_LOG_D("Track " PUBLIC_LOG_D32 " will be converted", trackIndex);
1384             }
1385         }
1386     }
1387 }
1388 
GetMediaInfo(MediaInfo & mediaInfo)1389 Status FFmpegDemuxerPlugin::GetMediaInfo(MediaInfo& mediaInfo)
1390 {
1391     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
1392     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1393     mediaInfo = mediaInfo_;
1394     return Status::OK;
1395 }
1396 
SetAVReadFrameLimit()1397 Status FFmpegDemuxerPlugin::SetAVReadFrameLimit()
1398 {
1399     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1400     if (fileType_ != FileType::FLV) {
1401         return Status::OK;
1402     }
1403 
1404     ioContext_.isLimitType = true;
1405     ioContext_.sizeLimit = FLV_READ_SIZE_LIMIT_DEFAULT;
1406     FALSE_RETURN_V_MSG_E(static_cast<size_t>(formatContext_->nb_streams) == mediaInfo_.tracks.size(), Status::OK,
1407         "mediaInfo size is error");
1408     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
1409         if (formatContext_->streams[trackIndex] == nullptr) {
1410             MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " info is nullptr", trackIndex);
1411             continue;
1412         }
1413         if (FFmpegFormatHelper::IsVideoType(*(formatContext_->streams[trackIndex]))) {
1414             int width = 0;
1415             int height = 0;
1416             Meta &format = mediaInfo_.tracks[trackIndex];
1417             format.GetData(Tag::VIDEO_WIDTH, width);
1418             format.GetData(Tag::VIDEO_HEIGHT, height);
1419             if (width * height > 0) {
1420                 int32_t limitSize = width * height * DEFAULT_CHANNEL_CNT * FLV_READ_SIZE_LIMIT_FACTOR;
1421                 ioContext_.sizeLimit = std::max(ioContext_.sizeLimit, limitSize);
1422                 MEDIA_LOG_D("Track " PUBLIC_LOG_U32 " hei:" PUBLIC_LOG_D32 ", wid:" PUBLIC_LOG_D32
1423                     " limit " PUBLIC_LOG_D32, trackIndex, height, width, limitSize);
1424             }
1425         }
1426     }
1427     return Status::OK;
1428 }
1429 
UpdateReferenceIds()1430 void FFmpegDemuxerPlugin::UpdateReferenceIds()
1431 {
1432     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
1433         if (trackIndex >= mediaInfo_.tracks.size()) {
1434             break;
1435         }
1436         Meta meta = mediaInfo_.tracks[trackIndex];
1437         std::vector<int32_t> referenceIds;
1438         meta.Get<Tag::REFERENCE_TRACK_IDS>(referenceIds);
1439         for (auto id : referenceIds) {
1440             if (referenceIdsMap_.count(id) == 0) {
1441                 referenceIdsMap_[id] = std::vector<int32_t>();
1442             }
1443             if (!std::any_of(referenceIdsMap_[id].begin(), referenceIdsMap_[id].end(),
1444                 [trackIndex](int32_t i) { return static_cast<uint32_t>(i) == trackIndex; })) {
1445                 referenceIdsMap_[id].push_back(trackIndex);
1446             }
1447 
1448             if (referenceIdsMap_.count(trackIndex) == 0) {
1449                 referenceIdsMap_[trackIndex] = std::vector<int32_t>();
1450             }
1451             if (!std::any_of(referenceIdsMap_[trackIndex].begin(), referenceIdsMap_[trackIndex].end(),
1452                 [id](int32_t i) { return i == id; })) {
1453                 referenceIdsMap_[trackIndex].push_back(id);
1454             }
1455         }
1456     }
1457     for (auto item : referenceIdsMap_) {
1458         if (item.second.size() == 0 || static_cast<size_t>(item.first) >= mediaInfo_.tracks.size()) {
1459             continue;
1460         }
1461         for (auto id : item.second) {
1462             MEDIA_LOG_D("Track " PUBLIC_LOG_D32 " ref " PUBLIC_LOG_D32, item.first, id);
1463         }
1464         mediaInfo_.tracks[item.first].Set<Tag::REFERENCE_TRACK_IDS>(item.second);
1465     }
1466 }
1467 
GetStreamInitialParams()1468 void FFmpegDemuxerPlugin::GetStreamInitialParams()
1469 {
1470     FALSE_RETURN_MSG_W(formatContext_ != nullptr, "AVFormatContext is nullptr");
1471     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
1472         auto stream = formatContext_->streams[trackIndex];
1473         if (stream == nullptr) {
1474             continue;
1475         }
1476         Meta format;
1477         int64_t bitRate = static_cast<int64_t>(stream->codecpar->bit_rate);
1478         if (bitRate > 0) {
1479             format.Set<Tag::MEDIA_BITRATE>(bitRate);
1480         } else {
1481             MEDIA_LOG_D("Track " PUBLIC_LOG_D32 " bitrate parse failed", trackIndex);
1482         }
1483         streamInitialParam_[trackIndex] = format;
1484     }
1485 }
1486 
SetStreamInitialParams(uint32_t trackId,Meta & format)1487 void FFmpegDemuxerPlugin::SetStreamInitialParams(uint32_t trackId, Meta &format)
1488 {
1489     FALSE_RETURN_MSG_W(streamInitialParam_.count(trackId) > 0, "TrackId is invalid");
1490     int64_t bitRate = 0;
1491     bool ret = streamInitialParam_[trackId].GetData(Tag::MEDIA_BITRATE, bitRate);
1492     if (!ret || bitRate <= 0) {
1493         MEDIA_LOG_W("Track " PUBLIC_LOG_D32 " has no bitrate", trackId);
1494     } else {
1495         format.Set<Tag::MEDIA_BITRATE>(bitRate);
1496     }
1497 }
1498 
GetMediaInfo()1499 Status FFmpegDemuxerPlugin::GetMediaInfo()
1500 {
1501     MediaAVCodec::AVCodecTrace trace("FFmpegDemuxerPlugin::GetMediaInfo");
1502     GetStreamInitialParams();
1503     Status ret = ParseVideoFirstFrames();
1504     FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Parse video info failed");
1505 
1506     FFmpegFormatHelper::ParseMediaInfo(*formatContext_, mediaInfo_.general);
1507     DemuxerLogCompressor::StringifyMeta(mediaInfo_.general, -1); // source meta
1508     for (uint32_t trackId = 0; trackId < formatContext_->nb_streams; ++trackId) {
1509         Meta meta;
1510         auto avStream = formatContext_->streams[trackId];
1511         if (avStream == nullptr) {
1512             MEDIA_LOG_W("Track " PUBLIC_LOG_D32 " info is nullptr", trackId);
1513             mediaInfo_.tracks.push_back(meta);
1514             continue;
1515         }
1516         FFmpegFormatHelper::ParseTrackInfo(*avStream, meta, *formatContext_);
1517         if (avStream->codecpar->codec_id == AV_CODEC_ID_HEVC) {
1518             if (streamParsers_ != nullptr && streamParsers_->ParserIsInited(trackId) && VideoFirstFrameValid(trackId)) {
1519                 auto firstFrame = videoFirstFrameMap_[trackId];
1520                 streamParsers_->ConvertPacketToAnnexb(
1521                     trackId, &(firstFrame->data), firstFrame->size, nullptr, 0, false);
1522                 streamParsers_->ParseAnnexbExtraData(trackId, firstFrame->data, firstFrame->size);
1523                 // Parser only sends xps info when first call ConvertPacketToAnnexb
1524                 // readSample will call ConvertPacketToAnnexb again, so rest here
1525                 streamParsers_->ResetXPSSendStatus(trackId);
1526                 ParseHEVCMetadataInfo(*avStream, meta);
1527             } else {
1528                 MEDIA_LOG_W("Parse hevc info failed");
1529             }
1530         }
1531         if (avStream->codecpar->codec_id == AV_CODEC_ID_HEVC ||
1532             avStream->codecpar->codec_id == AV_CODEC_ID_H264 ||
1533             avStream->codecpar->codec_id == AV_CODEC_ID_VVC) {
1534             ConvertCsdToAnnexb(*avStream, meta);
1535         }
1536         SetStreamInitialParams(trackId, meta);
1537         mediaInfo_.tracks.push_back(meta);
1538         DemuxerLogCompressor::StringifyMeta(meta, trackId);
1539     }
1540     UpdateReferenceIds();
1541     return Status::OK;
1542 }
1543 
GetUserMeta(std::shared_ptr<Meta> meta)1544 Status FFmpegDemuxerPlugin::GetUserMeta(std::shared_ptr<Meta> meta)
1545 {
1546     MediaAVCodec::AVCodecTrace trace("FFmpegDemuxerPlugin::GetUserMeta");
1547     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
1548     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1549     FALSE_RETURN_V_MSG_E(meta != nullptr, Status::ERROR_NULL_POINTER, "Meta is nullptr");
1550 
1551     FFmpegFormatHelper::ParseUserMeta(*formatContext_, meta);
1552     return Status::OK;
1553 }
1554 
ParseDrmInfo(const MetaDrmInfo * const metaDrmInfo,size_t drmInfoSize,std::multimap<std::string,std::vector<uint8_t>> & drmInfo)1555 void FFmpegDemuxerPlugin::ParseDrmInfo(const MetaDrmInfo *const metaDrmInfo, size_t drmInfoSize,
1556     std::multimap<std::string, std::vector<uint8_t>>& drmInfo)
1557 {
1558     MEDIA_LOG_D("In");
1559     size_t infoCount = drmInfoSize / sizeof(MetaDrmInfo);
1560     for (size_t index = 0; index < infoCount; index++) {
1561         std::stringstream ssConverter;
1562         std::string uuid;
1563         for (uint32_t i = 0; i < metaDrmInfo[index].uuidLen; i++) {
1564             int32_t singleUuid = static_cast<int32_t>(metaDrmInfo[index].uuid[i]);
1565             ssConverter << std::hex << std::setfill('0') << std::setw(2) << singleUuid; // 2:w
1566             uuid = ssConverter.str();
1567         }
1568         drmInfo.insert({ uuid, std::vector<uint8_t>(metaDrmInfo[index].pssh,
1569             metaDrmInfo[index].pssh + metaDrmInfo[index].psshLen) });
1570     }
1571 }
1572 
GetDrmInfo(std::multimap<std::string,std::vector<uint8_t>> & drmInfo)1573 Status FFmpegDemuxerPlugin::GetDrmInfo(std::multimap<std::string, std::vector<uint8_t>>& drmInfo)
1574 {
1575     MEDIA_LOG_D("In");
1576     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
1577     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1578 
1579     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
1580         Meta meta;
1581         AVStream *avStream = formatContext_->streams[trackIndex];
1582         if (avStream == nullptr) {
1583             MEDIA_LOG_W("Track " PUBLIC_LOG_D32 " is nullptr", trackIndex);
1584             continue;
1585         }
1586         MEDIA_LOG_D("GetDrmInfo by stream side data");
1587         size_t drmInfoSize = 0;
1588         MetaDrmInfo *tmpDrmInfo = (MetaDrmInfo *)av_stream_get_side_data(avStream,
1589             AV_PKT_DATA_ENCRYPTION_INIT_INFO, &drmInfoSize);
1590         if (tmpDrmInfo != nullptr && drmInfoSize != 0) {
1591             ParseDrmInfo(tmpDrmInfo, drmInfoSize, drmInfo);
1592         }
1593     }
1594     return Status::OK;
1595 }
1596 
ConvertCsdToAnnexb(const AVStream & avStream,Meta & format)1597 void FFmpegDemuxerPlugin::ConvertCsdToAnnexb(const AVStream& avStream, Meta &format)
1598 {
1599     uint8_t *extradata = avStream.codecpar->extradata;
1600     int32_t extradataSize = avStream.codecpar->extradata_size;
1601     if (HaveValidParser(avStream.codecpar->codec_id) && streamParsers_ != nullptr &&
1602         streamParsers_->ParserIsInited(avStream.index)) {
1603         streamParsers_->ConvertPacketToAnnexb(avStream.index, &(extradata), extradataSize, nullptr, 0, true);
1604     } else if (avStream.codecpar->codec_id == AV_CODEC_ID_H264 &&
1605         avbsfContexts_.count(avStream.index) > 0 && avbsfContexts_[avStream.index] != nullptr &&
1606         avbsfContexts_[avStream.index]->par_out->extradata != nullptr &&
1607         avbsfContexts_[avStream.index]->par_out->extradata_size > 0) {
1608             extradata = avbsfContexts_[avStream.index]->par_out->extradata;
1609             extradataSize = avbsfContexts_[avStream.index]->par_out->extradata_size;
1610     }
1611     if (extradata != nullptr && extradataSize > 0) {
1612         std::vector<uint8_t> extra(extradataSize);
1613         extra.assign(extradata, extradata + extradataSize);
1614         format.Set<Tag::MEDIA_CODEC_CONFIG>(extra);
1615     }
1616 }
1617 
AddPacketToCacheQueue(AVPacket * pkt)1618 Status FFmpegDemuxerPlugin::AddPacketToCacheQueue(AVPacket *pkt)
1619 {
1620     FALSE_RETURN_V_MSG_E(pkt != nullptr, Status::ERROR_NULL_POINTER, "Pkt is nullptr");
1621 #ifdef BUILD_ENG_VERSION
1622     DumpParam dumpParam {DumpMode(DUMP_AVPACKET_OUTPUT & dumpMode_), pkt->data, pkt->stream_index, -1, pkt->size,
1623         avpacketIndex_++, pkt->pts, pkt->pos};
1624     Dump(dumpParam);
1625 #endif
1626     auto trackId = pkt->stream_index;
1627     Status ret = Status::OK;
1628     if (NeedCombineFrame(trackId) && !IsBeginAsAnnexb(pkt->data, pkt->size) && cacheQueue_.HasCache(trackId)) {
1629         std::shared_ptr<SamplePacket> cacheSamplePacket = cacheQueue_.Back(static_cast<uint32_t>(trackId));
1630         if (cacheSamplePacket != nullptr) {
1631             cacheSamplePacket->pkts.push_back(pkt);
1632         }
1633     } else {
1634         std::shared_ptr<SamplePacket> cacheSamplePacket = std::make_shared<SamplePacket>();
1635         if (cacheSamplePacket != nullptr) {
1636             cacheSamplePacket->pkts.push_back(pkt);
1637             cacheSamplePacket->offset = 0;
1638             cacheQueue_.Push(static_cast<uint32_t>(trackId), cacheSamplePacket);
1639             ret = CheckCacheDataLimit(static_cast<uint32_t>(trackId));
1640         }
1641     }
1642     return ret;
1643 }
1644 
SetVideoFirstFrame(AVPacket * pkt,bool isConvert)1645 Status FFmpegDemuxerPlugin::SetVideoFirstFrame(AVPacket* pkt, bool isConvert)
1646 {
1647     auto firstFrame = av_packet_alloc();
1648     FALSE_RETURN_V_MSG_E(firstFrame != nullptr, Status::ERROR_NULL_POINTER, "Call av_packet_alloc failed");
1649     int32_t avRet = av_new_packet(firstFrame, pkt->size);
1650     if (avRet < 0) {
1651         MEDIA_LOG_E("Call av_new_packet failed");
1652         FreeAVPacket(firstFrame);
1653         return Status::ERROR_INVALID_DATA;
1654     }
1655     avRet = av_packet_copy_props(firstFrame, pkt);
1656     if (avRet < 0) {
1657         MEDIA_LOG_E("Call av_packet_copy_props failed");
1658         FreeAVPacket(firstFrame);
1659         return Status::ERROR_INVALID_DATA;
1660     }
1661     auto ret = memcpy_s(firstFrame->data, firstFrame->size, pkt->data, pkt->size);
1662     if (ret != EOK) {
1663         MEDIA_LOG_E("Memcpy failed, ret:" PUBLIC_LOG_D32, ret);
1664         FreeAVPacket(firstFrame);
1665         return Status::ERROR_INVALID_DATA;
1666     }
1667     if (firstFrame->data == nullptr) {
1668         MEDIA_LOG_E("Get first frame failed");
1669         FreeAVPacket(firstFrame);
1670         return Status::ERROR_WRONG_STATE;
1671     }
1672     if (isConvert) {
1673         bool convertRet = streamParsers_->ConvertExtraDataToAnnexb(pkt->stream_index,
1674             formatContext_->streams[pkt->stream_index]->codecpar->extradata,
1675             formatContext_->streams[pkt->stream_index]->codecpar->extradata_size);
1676         if (!convertRet) {
1677             MEDIA_LOG_E("ConvertExtraDataToAnnexb failed:" PUBLIC_LOG_D32, pkt->stream_index);
1678             FreeAVPacket(firstFrame);
1679             return Status::ERROR_INVALID_DATA;
1680         }
1681     }
1682     videoFirstFrameMap_[pkt->stream_index] = firstFrame;
1683     if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->pts >= 0 && pkt->dts >= 0) {
1684         seekCalibMap_[pkt->stream_index] = pkt->pts - pkt->dts;
1685     }
1686     return Status::OK;
1687 }
1688 
IsSyncFrameCheckNeeded(std::shared_ptr<AVFormatContext> formatContext)1689 static bool IsSyncFrameCheckNeeded(std::shared_ptr<AVFormatContext> formatContext)
1690 {
1691     FALSE_RETURN_V_MSG_E(formatContext != nullptr, false, "AVFormatContext is nullptr");
1692     FileType fileType = FFmpegFormatHelper::GetFileTypeByName(*formatContext);
1693     if (fileType == FileType::MPEGTS || fileType == FileType::MPEGPS) {
1694         return false;
1695     }
1696     return true;
1697 }
1698 
AllSupportTrackFramesReady()1699 bool FFmpegDemuxerPlugin::AllSupportTrackFramesReady()
1700 {
1701     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
1702         AVStream* stream = formatContext_->streams[trackIndex];
1703         if (stream == nullptr || stream->codecpar == nullptr || !IsSupportedTrackType(*stream)) {
1704             continue;
1705         }
1706         if (!TrackIsChecked(trackIndex)) {
1707             return false;
1708         }
1709     }
1710     return true;
1711 }
1712 
AllVideoFirstFramesReady()1713 bool FFmpegDemuxerPlugin::AllVideoFirstFramesReady()
1714 {
1715     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
1716         AVStream* stream = formatContext_->streams[trackIndex];
1717         if (stream == nullptr || stream->codecpar == nullptr || !FFmpegFormatHelper::IsVideoType(*stream)) {
1718             continue;
1719         }
1720         if (!TrackIsChecked(trackIndex)) {
1721             return false;
1722         }
1723     }
1724     return true;
1725 }
1726 
1727 /*
1728 return true:
1729   unsupport track
1730   support track:
1731     packet with key FLAG
1732     packet without key FLAG:
1733       HEVC + TS/PS file
1734       HEVC + IsHevcSyncFrame pass
1735 return false:
1736   support track + without key FLAG + not hevc track
1737   support track + without key FLAG + hevc track + not ts/ps + IsHevcSyncFrame fail
1738 */
IsSyncFrame(AVStream * stream,AVPacket * pkt,std::shared_ptr<AVFormatContext> formatContext)1739 static bool IsSyncFrame(AVStream *stream, AVPacket *pkt, std::shared_ptr<AVFormatContext> formatContext)
1740 {
1741     FALSE_RETURN_V_MSG_E(stream != nullptr && stream->codecpar != nullptr, false, "stream is nullptr");
1742     FALSE_RETURN_V_MSG_E(pkt != nullptr, false, "pkt is nullptr");
1743     FALSE_RETURN_V_MSG_E(formatContext != nullptr, false, "AVFormatContext is nullptr");
1744     if (!FFmpegFormatHelper::IsValidCodecId(stream->codecpar->codec_id)) {
1745         return true;
1746     }
1747     return (static_cast<uint32_t>(pkt->flags) & static_cast<uint32_t>(AV_PKT_FLAG_KEY) ||
1748             (stream->codecpar->codec_id == AV_CODEC_ID_HEVC &&
1749                 (!IsSyncFrameCheckNeeded(formatContext) || IsHevcSyncFrame(pkt->data, pkt->size))));
1750 }
1751 
ParseVideoFirstFrames()1752 Status FFmpegDemuxerPlugin::ParseVideoFirstFrames()
1753 {
1754     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1755     FALSE_RETURN_V_MSG_E(streamParsers_ != nullptr, Status::ERROR_NULL_POINTER, "StreamParser is nullptr");
1756     AVPacket *pkt = nullptr;
1757     Status ret = Status::OK;
1758     bool extraType = false;
1759     if (fileType_ == FileType::MPEGTS || FFmpegFormatHelper::IsMpeg4File(fileType_) || fileType_ == FileType::FLV) {
1760         extraType = true;
1761     }
1762     // Finish for extraType: get all support stream
1763     // Finish: read all video or init all parser
1764     while ((extraType && !AllSupportTrackFramesReady()) ||
1765            (!extraType && !AllVideoFirstFramesReady() && !streamParsers_->AllParserInited())) {
1766         FALSE_RETURN_V_MSG_E(!isInterruptNeeded_.load(), Status::ERROR_WRONG_STATE, "ParseVideoFirstFrames interrupt");
1767         if (pkt == nullptr) {
1768             pkt = av_packet_alloc();
1769             FALSE_RETURN_V_MSG_E(pkt != nullptr, Status::ERROR_NULL_POINTER, "Call av_packet_alloc failed");
1770         }
1771         std::unique_lock<std::mutex> sLock(syncMutex_);
1772         int ffmpegRet = av_read_frame(formatContext_.get(), pkt);
1773         sLock.unlock();
1774         if (ffmpegRet < 0) {
1775             MEDIA_LOG_E("Call av_read_frame failed, ret:" PUBLIC_LOG_D32, ffmpegRet);
1776             FreeAVPacket(pkt);
1777             break;
1778         }
1779         int32_t trackId = pkt->stream_index;
1780         auto stream = formatContext_->streams[trackId];
1781         FALSE_RETURN_V_MSG_E(stream != nullptr && stream->codecpar != nullptr, Status::ERROR_NULL_POINTER,
1782             "Stream " PUBLIC_LOG_D32 " is invalid", trackId);
1783         ret = AddPacketToCacheQueue(pkt);
1784         FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "Add to cache failed");
1785         bool isSpecialStreamType = (stream->codecpar->codec_id == AV_CODEC_ID_VVC);
1786         if (!isSpecialStreamType && (TrackIsChecked(trackId) || !IsSyncFrame(stream, pkt, formatContext_))) {
1787             pkt = nullptr;
1788             continue;
1789         }
1790         checkedTrackIds_.push_back(trackId);
1791         if (streamParsers_->ParserIsCreated(trackId) && !streamParsers_->ParserIsInited(trackId)) {
1792             ret = SetVideoFirstFrame(pkt);
1793         } else if (extraType && FFmpegFormatHelper::IsVideoType(*stream)) {
1794             ret = SetVideoFirstFrame(pkt, false);
1795         }
1796         if (ret != Status::OK) {
1797             pkt = nullptr;
1798             MEDIA_LOG_E("Set first frame failed, track " PUBLIC_LOG_D32, trackId);
1799             return ret;
1800         }
1801         pkt = nullptr;
1802     }
1803     return ret;
1804 }
1805 
ParseHEVCMetadataInfo(const AVStream & avStream,Meta & format)1806 void FFmpegDemuxerPlugin::ParseHEVCMetadataInfo(const AVStream& avStream, Meta& format)
1807 {
1808     HevcParseFormat parse;
1809     parse.isHdrVivid = streamParsers_->IsHdrVivid(avStream.index);
1810     parse.colorRange = streamParsers_->GetColorRange(avStream.index);
1811     parse.colorPrimaries = streamParsers_->GetColorPrimaries(avStream.index);
1812     parse.colorTransfer = streamParsers_->GetColorTransfer(avStream.index);
1813     parse.colorMatrixCoeff = streamParsers_->GetColorMatrixCoeff(avStream.index);
1814     parse.profile = streamParsers_->GetProfileIdc(avStream.index);
1815     parse.level = streamParsers_->GetLevelIdc(avStream.index);
1816     parse.chromaLocation = streamParsers_->GetChromaLocation(avStream.index);
1817     parse.picWidInLumaSamples = streamParsers_->GetPicWidInLumaSamples(avStream.index);
1818     parse.picHetInLumaSamples = streamParsers_->GetPicHetInLumaSamples(avStream.index);
1819 
1820     FFmpegFormatHelper::ParseHevcInfo(*formatContext_, parse, format);
1821 }
1822 
TrackIsSelected(const uint32_t trackId)1823 bool FFmpegDemuxerPlugin::TrackIsSelected(const uint32_t trackId)
1824 {
1825     return std::any_of(selectedTrackIds_.begin(), selectedTrackIds_.end(),
1826                        [trackId](uint32_t id) { return id == trackId; });
1827 }
1828 
TrackIsChecked(const uint32_t trackId)1829 bool FFmpegDemuxerPlugin::TrackIsChecked(const uint32_t trackId)
1830 {
1831     return std::any_of(checkedTrackIds_.begin(), checkedTrackIds_.end(),
1832                        [trackId](uint32_t id) { return id == trackId; });
1833 }
1834 
SelectTrack(uint32_t trackId)1835 Status FFmpegDemuxerPlugin::SelectTrack(uint32_t trackId)
1836 {
1837     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
1838     MEDIA_LOG_I("Select " PUBLIC_LOG_D32, trackId);
1839     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1840     if (trackId >= static_cast<uint32_t>(formatContext_.get()->nb_streams)) {
1841         MEDIA_LOG_E("Track is invalid, just have " PUBLIC_LOG_D32 " tracks in file", formatContext_.get()->nb_streams);
1842         return Status::ERROR_INVALID_PARAMETER;
1843     }
1844 
1845     AVStream* avStream = formatContext_->streams[trackId];
1846     FALSE_RETURN_V_MSG_E(avStream != nullptr, Status::ERROR_NULL_POINTER, "AVStream is nullptr");
1847     if (!IsSupportedTrack(*avStream)) {
1848         MEDIA_LOG_E("Track type is unsupport");
1849         return Status::ERROR_INVALID_PARAMETER;
1850     }
1851 
1852     if (!TrackIsSelected(trackId)) {
1853         selectedTrackIds_.push_back(trackId);
1854         trackMtx_[trackId] = std::make_shared<std::mutex>();
1855         trackDfxInfoMap_[trackId] = {0, -1, -1, -1, false};
1856         return cacheQueue_.AddTrackQueue(trackId);
1857     } else {
1858         MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " has been selected", trackId);
1859     }
1860     return Status::OK;
1861 }
1862 
UnselectTrack(uint32_t trackId)1863 Status FFmpegDemuxerPlugin::UnselectTrack(uint32_t trackId)
1864 {
1865     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
1866     MEDIA_LOG_I("Unselect " PUBLIC_LOG_D32, trackId);
1867     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1868     auto index = std::find_if(selectedTrackIds_.begin(), selectedTrackIds_.end(),
1869                               [trackId](uint32_t selectedId) {return trackId == selectedId; });
1870     if (index != selectedTrackIds_.end()) {
1871         selectedTrackIds_.erase(index);
1872         trackMtx_.erase(trackId);
1873         trackDfxInfoMap_.erase(trackId);
1874         return cacheQueue_.RemoveTrackQueue(trackId);
1875     } else {
1876         MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " is not in selected list", trackId);
1877     }
1878     return Status::OK;
1879 }
1880 
SelectSeekTrack() const1881 int FFmpegDemuxerPlugin::SelectSeekTrack() const
1882 {
1883     int trackIndex = static_cast<int>(selectedTrackIds_[0]);
1884     for (size_t i = 1; i < selectedTrackIds_.size(); i++) {
1885         int idx = static_cast<int>(selectedTrackIds_[i]);
1886         if (formatContext_->streams[idx]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
1887             return idx;
1888         }
1889     }
1890     return trackIndex;
1891 }
1892 
CheckSeekParams(int64_t seekTime,SeekMode mode) const1893 Status FFmpegDemuxerPlugin::CheckSeekParams(int64_t seekTime, SeekMode mode) const
1894 {
1895     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
1896     FALSE_RETURN_V_MSG_E(!selectedTrackIds_.empty(), Status::ERROR_INVALID_OPERATION, "No track has been selected");
1897     FALSE_RETURN_V_MSG_E(seekTime >= 0 && seekTime <= INT64_MAX / MS_TO_NS, Status::ERROR_INVALID_PARAMETER,
1898         "Seek time " PUBLIC_LOG_D64 " is not supported", seekTime);
1899     FALSE_RETURN_V_MSG_E(g_seekModeToFFmpegSeekFlags.count(mode) != 0, Status::ERROR_INVALID_PARAMETER,
1900         "Seek mode " PUBLIC_LOG_U32 " is not supported", static_cast<uint32_t>(mode));
1901     return Status::OK;
1902 }
1903 
SyncSeekThread()1904 void FFmpegDemuxerPlugin::SyncSeekThread()
1905 {
1906     if (ioContext_.invokerType != InvokerType::SEEK) {
1907         std::lock_guard<std::mutex> seekLock(ioContext_.invokerTypeMutex);
1908         ioContext_.invokerType = InvokerType::SEEK;
1909     }
1910     if (readThread_ != nullptr && threadState_ == READING) {
1911         MEDIA_LOG_I("Seek notify read thread to stop");
1912         std::unique_lock<std::mutex> waitLock(seekWaitMutex_);
1913         ioContext_.readCbReady = true;
1914         readCbCv_.notify_all();
1915         seekWaitCv_.wait(waitLock, [this] { return threadState_ == WAITING || threadState_ == NOT_STARTED; });
1916     }
1917 }
1918 
IsUseFirstFrameDts(int trackIndex,int64_t seekTime)1919 bool FFmpegDemuxerPlugin::IsUseFirstFrameDts(int trackIndex, int64_t seekTime)
1920 {
1921     if (seekTime == 0 &&
1922         (fileType_ == FileType::MPEGTS || FFmpegFormatHelper::IsMpeg4File(fileType_)) &&
1923         FFmpegFormatHelper::IsVideoType(*(formatContext_->streams[trackIndex])) &&
1924         VideoFirstFrameValid(trackIndex)) {
1925             return true;
1926     }
1927     return false;
1928 }
1929 
DoSeekInternal(int trackIndex,int64_t seekTime,int64_t ffTime,SeekMode mode,int64_t & realSeekTime)1930 Status FFmpegDemuxerPlugin::DoSeekInternal(int trackIndex, int64_t seekTime, int64_t ffTime,
1931     SeekMode mode, int64_t& realSeekTime)
1932 {
1933     auto avStream = formatContext_->streams[trackIndex];
1934     FALSE_RETURN_V_MSG_E(avStream != nullptr, Status::ERROR_NULL_POINTER, "AVStream is nullptr");
1935     realSeekTime = ConvertTimeFromFFmpeg(ffTime, avStream->time_base);
1936     int flag = ConvertFlagsToFFmpeg(avStream, ffTime, mode, seekTime);
1937     MEDIA_LOG_I("Time [" PUBLIC_LOG_U64 "/" PUBLIC_LOG_U64 "/" PUBLIC_LOG_D64 "] flag ["
1938                 PUBLIC_LOG_D32 "/" PUBLIC_LOG_D32 "]",
1939                 seekTime, ffTime, realSeekTime, static_cast<int32_t>(mode), flag);
1940     if (flag == AVSEEK_FLAG_FRAME && FFmpegFormatHelper::IsMpeg4File(fileType_)) {
1941         int keyFrameNext = av_index_search_timestamp(avStream, ffTime, AVSEEK_FLAG_FRAME);
1942         FALSE_RETURN_V_MSG_E(keyFrameNext >= 0, Status::ERROR_OUT_OF_RANGE,
1943             "Seek failed, err: Not next key frame");
1944     }
1945     std::unique_lock<std::mutex> sLock(syncMutex_);
1946     auto ret = av_seek_frame(formatContext_.get(), trackIndex, ffTime, flag);
1947     sLock.unlock();
1948     formatContext_->pb->error = 0;
1949     FALSE_RETURN_V_MSG_E(ret >= 0, Status::ERROR_UNKNOWN,
1950         "Call av_seek_frame failed, err: " PUBLIC_LOG_S, AVStrError(ret).c_str());
1951     if (readLoopStatus_ != Status::OK) {
1952         MEDIA_LOG_E("Read loop status is not OK, release thread");
1953         ReleaseFFmpegReadLoop();
1954     }
1955     for (size_t i = 0; i < selectedTrackIds_.size(); ++i) {
1956         cacheQueue_.RemoveTrackQueue(selectedTrackIds_[i]);
1957         cacheQueue_.AddTrackQueue(selectedTrackIds_[i]);
1958     }
1959     seekTime_ = seekTime;
1960     seekMode_ = flag == AVSEEK_FLAG_BACKWARD ? SeekMode::SEEK_PREVIOUS_SYNC : mode;
1961     return Status::OK;
1962 }
1963 
IsEnableSeekTimeCalib(const std::shared_ptr<AVFormatContext> & formatContext)1964 static bool IsEnableSeekTimeCalib(const std::shared_ptr<AVFormatContext> &formatContext)
1965 {
1966     FALSE_RETURN_V_MSG_E(formatContext != nullptr, false, "AVFormatContext is nullptr");
1967     if (FileType::FLV == FFmpegFormatHelper::GetFileTypeByName(*formatContext)) {
1968         return true;
1969     }
1970     return false;
1971 }
1972 
SeekTo(int32_t trackId,int64_t seekTime,SeekMode mode,int64_t & realSeekTime)1973 Status FFmpegDemuxerPlugin::SeekTo(int32_t trackId, int64_t seekTime, SeekMode mode, int64_t& realSeekTime)
1974 {
1975     (void) trackId;
1976     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
1977     MediaAVCodec::AVCodecTrace trace("SeekTo");
1978 
1979     Status check = CheckSeekParams(seekTime, mode);
1980     FALSE_RETURN_V_MSG_E(check == Status::OK, check, "CheckSeekParams failed");
1981     if (readThread_ != nullptr) {
1982         SyncSeekThread();
1983     }
1984     int trackIndex = SelectSeekTrack();
1985     MEDIA_LOG_D("Seek based on track " PUBLIC_LOG_D32, trackIndex);
1986 
1987     auto avStream = formatContext_->streams[trackIndex];
1988     FALSE_RETURN_V_MSG_E(avStream != nullptr, Status::ERROR_NULL_POINTER, "AVStream is nullptr");
1989     int64_t ffTime = ConvertTimeToFFmpeg(seekTime * MS_TO_NS, avStream->time_base);
1990     if (!CheckStartTime(formatContext_.get(), avStream, ffTime, seekTime)) {
1991         MEDIA_LOG_E("Get start time from track " PUBLIC_LOG_D32 " failed", trackIndex);
1992         return Status::ERROR_INVALID_OPERATION;
1993     }
1994 
1995     if (IsEnableSeekTimeCalib(formatContext_) && seekCalibMap_.count(trackIndex) > 0) {
1996         int64_t calibTime = ffTime - seekCalibMap_[trackIndex];
1997         auto ret = DoSeekInternal(trackIndex, seekTime, calibTime, mode, realSeekTime);
1998         if (ret == Status::OK) {
1999             return ret;
2000         }
2001         MEDIA_LOG_E("Seek using calibTime " PUBLIC_LOG_D64 " failed", calibTime);
2002     }
2003 
2004     if (IsUseFirstFrameDts(trackIndex, seekTime)) {
2005         ffTime = videoFirstFrameMap_[trackIndex]->dts;
2006     }
2007 
2008     return DoSeekInternal(trackIndex, seekTime, ffTime, mode, realSeekTime);
2009 }
2010 
Flush()2011 Status FFmpegDemuxerPlugin::Flush()
2012 {
2013     Status ret = Status::OK;
2014     std::lock_guard<std::shared_mutex> lock(sharedMutex_);
2015     MEDIA_LOG_I("In");
2016     if (ioContext_.invokerType != InvokerType::FLUSH) {
2017         std::lock_guard<std::mutex> seekLock(ioContext_.invokerTypeMutex);
2018         ioContext_.invokerType = InvokerType::FLUSH;
2019     }
2020     for (size_t i = 0; i < selectedTrackIds_.size(); ++i) {
2021         ret = cacheQueue_.RemoveTrackQueue(selectedTrackIds_[i]);
2022         ret = cacheQueue_.AddTrackQueue(selectedTrackIds_[i]);
2023     }
2024     if (formatContext_) {
2025         std::unique_lock<std::mutex> sLock(syncMutex_);
2026         avio_flush(formatContext_.get()->pb);
2027         avformat_flush(formatContext_.get());
2028         sLock.unlock();
2029     }
2030     return ret;
2031 }
2032 
ResetEosStatus()2033 void FFmpegDemuxerPlugin::ResetEosStatus()
2034 {
2035     MEDIA_LOG_I("In");
2036     if (formatContext_ != nullptr && formatContext_->pb != nullptr) {
2037         formatContext_->pb->eof_reached = 0;
2038         formatContext_->pb->error = 0;
2039     }
2040 }
2041 
DumpPacketInfo(int32_t trackId,Stage stage)2042 void FFmpegDemuxerPlugin::DumpPacketInfo(int32_t trackId, Stage stage)
2043 {
2044     if (trackDfxInfoMap_.count(trackId) <= 0) {
2045         return;
2046     }
2047     if (stage == Stage::FIRST_READ && !trackDfxInfoMap_[trackId].dumpFirstInfo) {
2048         MEDIA_LOG_I("Info Track[" PUBLIC_LOG_D32 "] [first] [" PUBLIC_LOG_D64 "/" PUBLIC_LOG_D64 "/" PUBLIC_LOG_D64 "]",
2049             trackId, trackDfxInfoMap_[trackId].lastPts,
2050             trackDfxInfoMap_[trackId].lastDuration, trackDfxInfoMap_[trackId].lastPos);
2051         trackDfxInfoMap_[trackId].dumpFirstInfo = true;
2052     } else if (stage == Stage::FILE_END) {
2053         MEDIA_LOG_I("Info Track[" PUBLIC_LOG_D32 "] [eos] [" PUBLIC_LOG_D64 "/" PUBLIC_LOG_D64 "/" PUBLIC_LOG_D64 "]",
2054             trackId, trackDfxInfoMap_[trackId].lastPts,
2055             trackDfxInfoMap_[trackId].lastDuration, trackDfxInfoMap_[trackId].lastPos);
2056     }
2057 }
2058 
ClearUnselectTrackCache()2059 void FFmpegDemuxerPlugin::ClearUnselectTrackCache()
2060 {
2061     for (uint32_t trackIndex = 0; trackIndex < formatContext_->nb_streams; ++trackIndex) {
2062         if (TrackIsSelected(trackIndex)) {
2063             continue;
2064         }
2065         trackMtx_.erase(trackIndex);
2066         trackDfxInfoMap_.erase(trackIndex);
2067         if (cacheQueue_.RemoveTrackQueue(trackIndex) != Status::OK) {
2068             MEDIA_LOG_W("Reset track cache failed: " PUBLIC_LOG_U32, trackIndex);
2069         }
2070     }
2071 }
2072 
FrameReady(Status ret)2073 bool FFmpegDemuxerPlugin::FrameReady(Status ret)
2074 {
2075     if (ret == Status::END_OF_STREAM) {
2076         MEDIA_LOG_D("Read to end");
2077         return true;
2078     }
2079     FALSE_RETURN_V_MSG_E(ret != Status::ERROR_UNKNOWN, false, "Read from ffmpeg failed");
2080     FALSE_RETURN_V_MSG_E(ret != Status::ERROR_AGAIN, false, "Read from ffmpeg failed, retry");
2081     FALSE_RETURN_V_MSG_E(ret != Status::ERROR_NO_MEMORY, false, "Cache size out of limit");
2082     FALSE_RETURN_V_MSG_E(ret != Status::ERROR_WRONG_STATE, false, "Read from ffmpeg failed interrupt");
2083     return true;
2084 }
2085 
ReadSample(uint32_t trackId,std::shared_ptr<AVBuffer> sample)2086 Status FFmpegDemuxerPlugin::ReadSample(uint32_t trackId, std::shared_ptr<AVBuffer> sample)
2087 {
2088     std::shared_lock<std::shared_mutex> lock(sharedMutex_);
2089     MediaAVCodec::AVCodecTrace trace("ReadSample");
2090     MEDIA_LOG_D("In");
2091     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
2092     FALSE_RETURN_V_MSG_E(!selectedTrackIds_.empty(), Status::ERROR_INVALID_OPERATION, "No track has been selected");
2093     FALSE_RETURN_V_MSG_E(TrackIsSelected(trackId), Status::ERROR_INVALID_PARAMETER, "Track has not been selected");
2094     FALSE_RETURN_V_MSG_E(sample != nullptr && sample->memory_ != nullptr, Status::ERROR_INVALID_PARAMETER,
2095         "AVBuffer or memory is nullptr");
2096     FALSE_RETURN_V_MSG_E(readModeMap_.find(1) == readModeMap_.end(), Status::ERROR_INVALID_OPERATION,
2097         "Cannot use sync and async Read together");
2098     if (needClear_) {
2099         ClearUnselectTrackCache();
2100         needClear_ = false;
2101     }
2102     readModeMap_[0] = 1;
2103     Status ret;
2104     if (NeedCombineFrame(trackId) && cacheQueue_.GetCacheSize(trackId) == 1) {
2105         ret = ReadPacketToCacheQueue(trackId);
2106     }
2107     while (!cacheQueue_.HasCache(trackId)) {
2108         FALSE_RETURN_V_MSG_E(!isInterruptNeeded_.load(), Status::ERROR_WRONG_STATE, " ReadSample interrupt");
2109         ret = ReadPacketToCacheQueue(trackId);
2110         bool frameReady = FrameReady(ret);
2111         FALSE_RETURN_V_MSG_E(frameReady, ret, "Read from ffmpeg failed");
2112     }
2113     std::lock_guard<std::mutex> lockTrack(*trackMtx_[trackId].get());
2114     auto samplePacket = cacheQueue_.Front(trackId);
2115     FALSE_RETURN_V_MSG_E(samplePacket != nullptr, Status::ERROR_NULL_POINTER, "Cache packet is nullptr");
2116     if (samplePacket->isEOS) {
2117         ret = SetEosSample(sample);
2118         if (ret == Status::OK) {
2119             DumpPacketInfo(trackId, Stage::FILE_END);
2120             cacheQueue_.Pop(trackId);
2121         }
2122         return ret;
2123     }
2124     ret = ConvertAVPacketToSample(sample, samplePacket);
2125     DumpPacketInfo(trackId, Stage::FIRST_READ);
2126     if (ret == Status::ERROR_NOT_ENOUGH_DATA) {
2127         return Status::OK;
2128     } else if (ret == Status::OK) {
2129         MEDIA_LOG_D("All partial sample has been copied");
2130         cacheQueue_.Pop(trackId);
2131     }
2132     return ret;
2133 }
2134 
GetNextSampleSize(uint32_t trackId,int32_t & size)2135 Status FFmpegDemuxerPlugin::GetNextSampleSize(uint32_t trackId, int32_t& size)
2136 {
2137     std::shared_lock<std::shared_mutex> lock(sharedMutex_);
2138     MediaAVCodec::AVCodecTrace trace("GetNextSampleSize");
2139     MEDIA_LOG_D("In, track " PUBLIC_LOG_D32, trackId);
2140     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_UNKNOWN, "AVFormatContext is nullptr");
2141     FALSE_RETURN_V_MSG_E(TrackIsSelected(trackId), Status::ERROR_UNKNOWN, "Track has not been selected");
2142     FALSE_RETURN_V_MSG_E(readModeMap_.find(1) == readModeMap_.end(), Status::ERROR_INVALID_OPERATION,
2143         "Cannot use sync and async Read together");
2144     readModeMap_[0] = 1;
2145     Status ret;
2146     if (NeedCombineFrame(trackId) && cacheQueue_.GetCacheSize(trackId) == 1) {
2147         ret = ReadPacketToCacheQueue(trackId);
2148     }
2149     while (!cacheQueue_.HasCache(trackId)) {
2150         ret = ReadPacketToCacheQueue(trackId);
2151         bool frameReady = FrameReady(ret);
2152         FALSE_RETURN_V_MSG_E(frameReady, ret, "Read from ffmpeg failed");
2153     }
2154     std::shared_ptr<SamplePacket> samplePacket = cacheQueue_.Front(trackId);
2155     FALSE_RETURN_V_MSG_E(samplePacket != nullptr, Status::ERROR_UNKNOWN, "Cache sample is nullptr");
2156     if (samplePacket->isEOS) {
2157         MEDIA_LOG_I("Track " PUBLIC_LOG_D32 " eos", trackId);
2158         return Status::END_OF_STREAM;
2159     }
2160     FALSE_RETURN_V_MSG_E(samplePacket->pkts.size() > 0, Status::ERROR_UNKNOWN, "Cache sample is empty");
2161     int totalSize = 0;
2162     for (auto pkt : samplePacket->pkts) {
2163         FALSE_RETURN_V_MSG_E(pkt != nullptr, Status::ERROR_UNKNOWN, "Packet in sample is nullptr");
2164         totalSize += pkt->size;
2165     }
2166 
2167     FALSE_RETURN_V_MSG_E(trackId < formatContext_->nb_streams, Status::ERROR_UNKNOWN, "Track is out of range");
2168     AVStream* avStream = formatContext_->streams[trackId];
2169     FALSE_RETURN_V_MSG_E(avStream != nullptr && avStream->codecpar != nullptr,
2170         Status::ERROR_UNKNOWN, "AVStream is nullptr");
2171     if ((std::count(g_streamContainedXPS.begin(), g_streamContainedXPS.end(), avStream->codecpar->codec_id) > 0) &&
2172         static_cast<uint32_t>(samplePacket->pkts[0]->flags) & static_cast<uint32_t>(AV_PKT_FLAG_KEY)) {
2173         totalSize += avStream->codecpar->extradata_size;
2174     }
2175     size = totalSize;
2176     return Status::OK;
2177 }
2178 
InitPTSandIndexConvert()2179 void FFmpegDemuxerPlugin::InitPTSandIndexConvert()
2180 {
2181     indexToRelativePTSFrameCount_ = 0; // init IndexToRelativePTSFrameCount_
2182     relativePTSToIndexPosition_ = 0; // init RelativePTSToIndexPosition_
2183     indexToRelativePTSMaxHeap_ = std::priority_queue<int64_t>(); // init IndexToRelativePTSMaxHeap_
2184     relativePTSToIndexPTSMin_ = INT64_MAX;
2185     relativePTSToIndexPTSMax_ = INT64_MIN;
2186     relativePTSToIndexRightDiff_ = INT64_MAX;
2187     relativePTSToIndexLeftDiff_ = INT64_MAX;
2188     relativePTSToIndexTempDiff_ = INT64_MAX;
2189 }
2190 
GetIndexByRelativePresentationTimeUs(const uint32_t trackIndex,const uint64_t relativePresentationTimeUs,uint32_t & index)2191 Status FFmpegDemuxerPlugin::GetIndexByRelativePresentationTimeUs(const uint32_t trackIndex,
2192     const uint64_t relativePresentationTimeUs, uint32_t &index)
2193 {
2194     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
2195 
2196     FALSE_RETURN_V_MSG_E(FFmpegFormatHelper::IsMpeg4File(fileType_),
2197         Status::ERROR_MISMATCHED_TYPE, "FileType is not MP4");
2198 
2199     FALSE_RETURN_V_MSG_E(trackIndex < formatContext_->nb_streams, Status::ERROR_INVALID_DATA, "Track is out of range");
2200     bool frameCheck = IsLessMaxReferenceParserFrames(trackIndex);
2201     FALSE_RETURN_V_MSG_E(frameCheck, Status::ERROR_INVALID_DATA, "Frame count exceeds limit");
2202 
2203     InitPTSandIndexConvert();
2204 
2205     auto avStream = formatContext_->streams[trackIndex];
2206     FALSE_RETURN_V_MSG_E(avStream != nullptr, Status::ERROR_NULL_POINTER, "AVStream is nullptr");
2207 
2208     Status ret = GetPresentationTimeUsFromFfmpegMOV(GET_FIRST_PTS, trackIndex,
2209         static_cast<int64_t>(relativePresentationTimeUs), index);
2210     FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "Get pts failed");
2211 
2212     int64_t absolutePTS = static_cast<int64_t>(relativePresentationTimeUs) + absolutePTSIndexZero_;
2213 
2214     ret = GetPresentationTimeUsFromFfmpegMOV(RELATIVEPTS_TO_INDEX, trackIndex,
2215         absolutePTS, index);
2216     FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "Get pts failed");
2217 
2218     if (absolutePTS < relativePTSToIndexPTSMin_ || absolutePTS > relativePTSToIndexPTSMax_) {
2219         MEDIA_LOG_E("Pts is out of range");
2220         return Status::ERROR_INVALID_DATA;
2221     }
2222 
2223     if (relativePTSToIndexLeftDiff_ == 0 || relativePTSToIndexRightDiff_ == 0) {
2224         index = relativePTSToIndexPosition_;
2225     } else {
2226         index = relativePTSToIndexLeftDiff_ < relativePTSToIndexRightDiff_ ?
2227         relativePTSToIndexPosition_ - 1 : relativePTSToIndexPosition_;
2228     }
2229     return Status::OK;
2230 }
2231 
GetRelativePresentationTimeUsByIndex(const uint32_t trackIndex,const uint32_t index,uint64_t & relativePresentationTimeUs)2232 Status FFmpegDemuxerPlugin::GetRelativePresentationTimeUsByIndex(const uint32_t trackIndex,
2233     const uint32_t index, uint64_t &relativePresentationTimeUs)
2234 {
2235     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
2236     FALSE_RETURN_V_MSG_E(index < UINT32_MAX, Status::ERROR_INVALID_DATA, "Index is out of range");
2237     FALSE_RETURN_V_MSG_E(FFmpegFormatHelper::IsMpeg4File(fileType_),
2238         Status::ERROR_MISMATCHED_TYPE, "FileType is not MP4");
2239 
2240     FALSE_RETURN_V_MSG_E(trackIndex < formatContext_->nb_streams, Status::ERROR_INVALID_DATA, "Track is out of range");
2241     bool frameCheck = IsLessMaxReferenceParserFrames(trackIndex);
2242     FALSE_RETURN_V_MSG_E(frameCheck, Status::ERROR_INVALID_DATA, "Frame count exceeds limit");
2243 
2244     InitPTSandIndexConvert();
2245 
2246     auto avStream = formatContext_->streams[trackIndex];
2247     FALSE_RETURN_V_MSG_E(avStream != nullptr, Status::ERROR_NULL_POINTER, "AVStream is nullptr");
2248 
2249     Status ret = GetPresentationTimeUsFromFfmpegMOV(GET_FIRST_PTS, trackIndex,
2250         static_cast<int64_t>(relativePresentationTimeUs), index);
2251     FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "Get pts failed");
2252 
2253     ret = GetPresentationTimeUsFromFfmpegMOV(INDEX_TO_RELATIVEPTS, trackIndex,
2254         static_cast<int64_t>(relativePresentationTimeUs), index);
2255     FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "Get pts failed");
2256 
2257     if (index + 1 > indexToRelativePTSFrameCount_) {
2258         MEDIA_LOG_E("Index is out of range");
2259         return Status::ERROR_INVALID_DATA;
2260     }
2261 
2262     int64_t relativepts = indexToRelativePTSMaxHeap_.top() - absolutePTSIndexZero_;
2263     FALSE_RETURN_V_MSG_E(relativepts >= 0, Status::ERROR_INVALID_DATA, "Existence of calculation results less than 0");
2264     relativePresentationTimeUs = static_cast<uint64_t>(relativepts);
2265 
2266     return Status::OK;
2267 }
2268 
PTSAndIndexConvertSttsAndCttsProcess(IndexAndPTSConvertMode mode,const AVStream * avStream,int64_t absolutePTS,uint32_t index)2269 Status FFmpegDemuxerPlugin::PTSAndIndexConvertSttsAndCttsProcess(IndexAndPTSConvertMode mode,
2270     const AVStream* avStream, int64_t absolutePTS, uint32_t index)
2271 {
2272     uint32_t sttsIndex = 0;
2273     uint32_t cttsIndex = 0;
2274     int64_t pts = 0; // init pts
2275     int64_t dts = 0; // init dts
2276     ptsCnt_ = 0;
2277     int32_t sttsCurNum = static_cast<int32_t>(avStream->stts_data[sttsIndex].count);
2278     int32_t cttsCurNum = static_cast<int32_t>(avStream->ctts_data[cttsIndex].count);
2279     while (sttsIndex < avStream->stts_count && cttsIndex < avStream->ctts_count &&
2280             cttsCurNum >= 0 && sttsCurNum >= 0) {
2281         if (cttsCurNum == 0) {
2282             cttsIndex++;
2283             if (cttsIndex >= avStream->ctts_count) {
2284                 break;
2285             }
2286             cttsCurNum = static_cast<int32_t>(avStream->ctts_data[cttsIndex].count);
2287         }
2288         cttsCurNum--;
2289         if ((INT64_MAX / 1000 / 1000) < // 1000 is used for converting pts to us
2290             ((dts + static_cast<int64_t>(avStream->ctts_data[cttsIndex].duration)) /
2291             static_cast<int64_t>(avStream->time_scale))) {
2292                 MEDIA_LOG_E("pts overflow");
2293                 return Status::ERROR_INVALID_DATA;
2294         }
2295         double timeScaleRate = static_cast<double>(MS_TO_NS) / static_cast<double>(avStream->time_scale);
2296         double ptsTemp = static_cast<double>(dts) + static_cast<double>(avStream->ctts_data[cttsIndex].duration);
2297         pts = static_cast<int64_t>(ptsTemp * timeScaleRate);
2298         if (mode == GET_ALL_FRAME_PTS) {
2299             if (ptsCnt_ >= REFERENCE_PARSER_PTS_LIST_UPPER_LIMIT) {
2300                 MEDIA_LOG_I("PTS cnt has reached the maximum limit");
2301                 break;
2302             }
2303             ptsCnt_++;
2304         }
2305         PTSAndIndexConvertSwitchProcess(mode, pts, absolutePTS, index, static_cast<int64_t>(dts * timeScaleRate));
2306         sttsCurNum--;
2307         if ((INT64_MAX - dts) < (static_cast<int64_t>(avStream->stts_data[sttsIndex].duration))) {
2308             MEDIA_LOG_E("dts overflow");
2309             return Status::ERROR_INVALID_DATA;
2310         }
2311         dts += static_cast<int64_t>(avStream->stts_data[sttsIndex].duration);
2312         if (sttsCurNum == 0) {
2313             sttsIndex++;
2314             sttsCurNum = sttsIndex < avStream->stts_count ?
2315                          static_cast<int32_t>(avStream->stts_data[sttsIndex].count) : 0;
2316         }
2317     }
2318     return Status::OK;
2319 }
2320 
PTSAndIndexConvertOnlySttsProcess(IndexAndPTSConvertMode mode,const AVStream * avStream,int64_t absolutePTS,uint32_t index)2321 Status FFmpegDemuxerPlugin::PTSAndIndexConvertOnlySttsProcess(IndexAndPTSConvertMode mode,
2322     const AVStream* avStream, int64_t absolutePTS, uint32_t index)
2323 {
2324     uint32_t sttsIndex = 0;
2325     int64_t pts = 0; // init pts
2326     int64_t dts = 0; // init dts
2327     ptsCnt_ = 0;
2328     int32_t sttsCurNum = static_cast<int32_t>(avStream->stts_data[sttsIndex].count);
2329     while (sttsIndex < avStream->stts_count && sttsCurNum >= 0) {
2330         if ((INT64_MAX / 1000 / 1000) < // 1000 is used for converting pts to us
2331             (dts / static_cast<int64_t>(avStream->time_scale))) {
2332                 MEDIA_LOG_E("pts overflow");
2333                 return Status::ERROR_INVALID_DATA;
2334         }
2335         double timeScaleRate = static_cast<double>(MS_TO_NS) / static_cast<double>(avStream->time_scale);
2336         double ptsTemp = static_cast<double>(dts);
2337         pts = static_cast<int64_t>(ptsTemp * timeScaleRate);
2338         if (mode == GET_ALL_FRAME_PTS) {
2339             if (ptsCnt_ >= REFERENCE_PARSER_PTS_LIST_UPPER_LIMIT) {
2340                 MEDIA_LOG_I("PTS cnt has reached the maximum limit");
2341                 break;
2342             }
2343             ptsCnt_++;
2344         }
2345         PTSAndIndexConvertSwitchProcess(mode, pts, absolutePTS, index, pts);
2346         sttsCurNum--;
2347         if ((INT64_MAX - dts) < (static_cast<int64_t>(avStream->stts_data[sttsIndex].duration))) {
2348             MEDIA_LOG_E("dts overflow");
2349             return Status::ERROR_INVALID_DATA;
2350         }
2351         dts += static_cast<int64_t>(avStream->stts_data[sttsIndex].duration);
2352         if (sttsCurNum == 0) {
2353             sttsIndex++;
2354             sttsCurNum = sttsIndex < avStream->stts_count ?
2355                          static_cast<int32_t>(avStream->stts_data[sttsIndex].count) : 0;
2356         }
2357     }
2358     return Status::OK;
2359 }
2360 
GetPresentationTimeUsFromFfmpegMOV(IndexAndPTSConvertMode mode,uint32_t trackIndex,int64_t absolutePTS,uint32_t index)2361 Status FFmpegDemuxerPlugin::GetPresentationTimeUsFromFfmpegMOV(IndexAndPTSConvertMode mode,
2362     uint32_t trackIndex, int64_t absolutePTS, uint32_t index)
2363 {
2364     auto avStream = formatContext_->streams[trackIndex];
2365     FALSE_RETURN_V_MSG_E(avStream != nullptr, Status::ERROR_NULL_POINTER, "AVStream is nullptr");
2366     FALSE_RETURN_V_MSG_E(avStream->stts_data != nullptr && avStream->stts_count != 0,
2367         Status::ERROR_NULL_POINTER, "AVStream->stts_data is empty");
2368     FALSE_RETURN_V_MSG_E(avStream->time_scale != 0, Status::ERROR_INVALID_DATA, "AVStream->time_scale is zero");
2369     return avStream->ctts_data == nullptr ?
2370         PTSAndIndexConvertOnlySttsProcess(mode, avStream, absolutePTS, index) :
2371         PTSAndIndexConvertSttsAndCttsProcess(mode, avStream, absolutePTS, index);
2372 }
2373 
PTSAndIndexConvertSwitchProcess(IndexAndPTSConvertMode mode,int64_t pts,int64_t absolutePTS,uint32_t index,int64_t dts)2374 void FFmpegDemuxerPlugin::PTSAndIndexConvertSwitchProcess(IndexAndPTSConvertMode mode,
2375     int64_t pts, int64_t absolutePTS, uint32_t index, int64_t dts)
2376 {
2377     switch (mode) {
2378         case GET_FIRST_PTS:
2379             absolutePTSIndexZero_ = pts < absolutePTSIndexZero_ ? pts : absolutePTSIndexZero_;
2380             break;
2381         case INDEX_TO_RELATIVEPTS:
2382             IndexToRelativePTSProcess(pts, index);
2383             break;
2384         case RELATIVEPTS_TO_INDEX:
2385             RelativePTSToIndexProcess(pts, absolutePTS);
2386             break;
2387         case GET_ALL_FRAME_PTS:
2388             if (dts == 0L) {
2389                 minPts_ = pts;
2390                 MEDIA_LOG_I("minPts=" PUBLIC_LOG_D64, minPts_);
2391             }
2392             MEDIA_LOG_D("dts " PUBLIC_LOG_D64 ", pts " PUBLIC_LOG_D64 ", frameId " PUBLIC_LOG_ZU,
2393                 dts - minPts_, pts - minPts_, pts2DtsMap_.size());
2394             pts2DtsMap_.emplace(pts - minPts_, dts - minPts_);
2395             break;
2396         default:
2397             MEDIA_LOG_E("Wrong mode");
2398             break;
2399     }
2400 }
2401 
IndexToRelativePTSProcess(int64_t pts,uint32_t index)2402 void FFmpegDemuxerPlugin::IndexToRelativePTSProcess(int64_t pts, uint32_t index)
2403 {
2404     if (indexToRelativePTSMaxHeap_.size() < index + 1) {
2405         indexToRelativePTSMaxHeap_.push(pts);
2406     } else {
2407         if (pts < indexToRelativePTSMaxHeap_.top()) {
2408             indexToRelativePTSMaxHeap_.pop();
2409             indexToRelativePTSMaxHeap_.push(pts);
2410         }
2411     }
2412     indexToRelativePTSFrameCount_++;
2413 }
2414 
RelativePTSToIndexProcess(int64_t pts,int64_t absolutePTS)2415 void FFmpegDemuxerPlugin::RelativePTSToIndexProcess(int64_t pts, int64_t absolutePTS)
2416 {
2417     if (relativePTSToIndexPTSMin_ > pts) {
2418         relativePTSToIndexPTSMin_ = pts;
2419     }
2420     if (relativePTSToIndexPTSMax_ < pts) {
2421         relativePTSToIndexPTSMax_ = pts;
2422     }
2423     relativePTSToIndexTempDiff_ = abs(pts - absolutePTS);
2424     if (pts < absolutePTS && relativePTSToIndexTempDiff_ < relativePTSToIndexLeftDiff_) {
2425         relativePTSToIndexLeftDiff_ = relativePTSToIndexTempDiff_;
2426     }
2427     if (pts >= absolutePTS && relativePTSToIndexTempDiff_ < relativePTSToIndexRightDiff_) {
2428         relativePTSToIndexRightDiff_ = relativePTSToIndexTempDiff_;
2429     }
2430     if (pts < absolutePTS) {
2431         relativePTSToIndexPosition_++;
2432     }
2433 }
2434 
CheckCacheDataLimit(uint32_t trackId)2435 Status FFmpegDemuxerPlugin::CheckCacheDataLimit(uint32_t trackId)
2436 {
2437     if (!outOfLimit_) {
2438         auto cacheDataSize = cacheQueue_.GetCacheDataSize(trackId);
2439         if (cacheDataSize > cachelimitSize_) {
2440             MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " cache out of limit: " PUBLIC_LOG_U32 "/" PUBLIC_LOG_U32 ", by user "
2441                 PUBLIC_LOG_D32, trackId, cacheDataSize, cachelimitSize_, static_cast<int32_t>(setLimitByUser));
2442             outOfLimit_ = true;
2443         }
2444     }
2445     return Status::OK;
2446 }
2447 
SetCacheLimit(uint32_t limitSize)2448 void FFmpegDemuxerPlugin::SetCacheLimit(uint32_t limitSize)
2449 {
2450     setLimitByUser = true;
2451     cachelimitSize_ = limitSize;
2452 }
2453 
GetCurrentCacheSize(uint32_t trackId,uint32_t & size)2454 Status FFmpegDemuxerPlugin::GetCurrentCacheSize(uint32_t trackId, uint32_t& size)
2455 {
2456     MEDIA_LOG_D("TrackId " PUBLIC_LOG_U32, trackId);
2457     FALSE_RETURN_V_MSG_E(formatContext_ != nullptr, Status::ERROR_NULL_POINTER, "AVFormatContext is nullptr");
2458     FALSE_RETURN_V_MSG_E(!selectedTrackIds_.empty(), Status::ERROR_INVALID_OPERATION, "No track has been selected");
2459     FALSE_RETURN_V_MSG_E(TrackIsSelected(trackId), Status::ERROR_INVALID_PARAMETER, "Track has not been selected");
2460     uint32_t dataSize = cacheQueue_.GetCacheDataSize(trackId);
2461     FALSE_RETURN_V_MSG_E(dataSize < UINT32_MAX, Status::ERROR_WRONG_STATE, "CacheSize is invalid");
2462     size = dataSize;
2463     return Status::OK;
2464 }
2465 
SetInterruptState(bool isInterruptNeeded)2466 void FFmpegDemuxerPlugin::SetInterruptState(bool isInterruptNeeded)
2467 {
2468     MEDIA_LOG_I("SetInterruptState %{public}d", isInterruptNeeded);
2469     isInterruptNeeded_ = isInterruptNeeded;
2470 }
2471 
2472 namespace { // plugin set
2473 
IsStartWithID3(const uint8_t * buf,const char * tagName)2474 int IsStartWithID3(const uint8_t *buf, const char *tagName)
2475 {
2476     return buf[POS_0] == tagName[POS_0] &&
2477            buf[POS_1] == tagName[POS_1] &&
2478            buf[POS_2] == tagName[POS_2] &&
2479            buf[POS_3] != POS_FF &&
2480            buf[POS_4] != POS_FF &&
2481            (buf[POS_6] & TAG_MASK) == 0 &&
2482            (buf[POS_7] & TAG_MASK) == 0 &&
2483            (buf[POS_8] & TAG_MASK) == 0 &&
2484            (buf[POS_9] & TAG_MASK) == 0;
2485 }
2486 
GetID3TagLen(const uint8_t * buf)2487 int GetID3TagLen(const uint8_t *buf)
2488 {
2489     int32_t len = ((buf[POS_6] & LEN_MASK) << POS_21) + ((buf[POS_7] & LEN_MASK) << POS_14) +
2490                   ((buf[POS_8] & LEN_MASK) << POS_7) + (buf[POS_9] & LEN_MASK) +
2491                   static_cast<int32_t>(ID3V2_HEADER_SIZE);
2492     if (buf[POS_5] & TAG_VERSION_MASK) {
2493         len += static_cast<int32_t>(ID3V2_HEADER_SIZE);
2494     }
2495     return len;
2496 }
2497 
GetConfidence(std::shared_ptr<AVInputFormat> plugin,const std::string & pluginName,std::shared_ptr<DataSource> dataSource,size_t & getData,size_t bufferSize)2498 int32_t GetConfidence(std::shared_ptr<AVInputFormat> plugin, const std::string& pluginName,
2499     std::shared_ptr<DataSource> dataSource, size_t &getData, size_t bufferSize)
2500 {
2501     uint64_t fileSize = 0;
2502     Status getFileSize = dataSource->GetSize(fileSize);
2503     if (getFileSize == Status::OK) {
2504         bufferSize = (bufferSize < fileSize) ? bufferSize : fileSize;
2505     }
2506     std::vector<uint8_t> buff(bufferSize + AVPROBE_PADDING_SIZE); // fix ffmpeg probe crash, refer to tools/probetest.c
2507     auto bufferInfo = std::make_shared<Buffer>();
2508     auto bufData = bufferInfo->WrapMemory(buff.data(), bufferSize, bufferSize);
2509     FALSE_RETURN_V_MSG_E(bufferInfo->GetMemory() != nullptr, -1,
2510         "Alloc buffer failed for " PUBLIC_LOG_S, pluginName.c_str());
2511     Status ret = Status::OK;
2512     {
2513         std::string traceName = "Sniff_" + pluginName + "_Readat";
2514         MediaAVCodec::AVCodecTrace trace(traceName.c_str());
2515         ret = dataSource->ReadAt(0, bufferInfo, bufferSize);
2516     }
2517     FALSE_RETURN_V_MSG_E(ret == Status::OK, -1, "Read probe data failed for " PUBLIC_LOG_S, pluginName.c_str());
2518     getData = bufferInfo->GetMemory()->GetSize();
2519     FALSE_RETURN_V_MSG_E(getData > 0, -1, "No data for sniff " PUBLIC_LOG_S, pluginName.c_str());
2520     if (getFileSize == Status::OK && getData > ID3V2_HEADER_SIZE && IsStartWithID3(buff.data(), "ID3")) {
2521         int32_t id3Len = GetID3TagLen(buff.data());
2522         // id3 tag length is out of file, or file just contains id3 tag, no valid data.
2523         FALSE_RETURN_V_MSG_E(id3Len >= 0 && static_cast<uint64_t>(id3Len) < fileSize, -1,
2524             "File data error for " PUBLIC_LOG_S, pluginName.c_str());
2525         if (id3Len > 0) {
2526             uint64_t remainSize = fileSize - static_cast<uint64_t>(id3Len);
2527             bufferSize = (bufferSize < remainSize) ? bufferSize : remainSize;
2528             int resetRet = memset_s(buff.data(), bufferSize, 0, bufferSize);
2529             FALSE_RETURN_V_MSG_E(resetRet == EOK, -1, "Reset buff failed for " PUBLIC_LOG_S, pluginName.c_str());
2530             ret = dataSource->ReadAt(id3Len, bufferInfo, bufferSize);
2531             FALSE_RETURN_V_MSG_E(ret == Status::OK, -1, "Read probe data failed for " PUBLIC_LOG_S, pluginName.c_str());
2532             getData = bufferInfo->GetMemory()->GetSize();
2533             FALSE_RETURN_V_MSG_E(getData > 0, -1, "No data for sniff " PUBLIC_LOG_S, pluginName.c_str());
2534         }
2535     }
2536     AVProbeData probeData{"", buff.data(), static_cast<int32_t>(getData), ""};
2537     return plugin->read_probe(&probeData);
2538 }
2539 
Sniff(const std::string & pluginName,std::shared_ptr<DataSource> dataSource)2540 int Sniff(const std::string& pluginName, std::shared_ptr<DataSource> dataSource)
2541 {
2542     FALSE_RETURN_V_MSG_E(!pluginName.empty(), 0, "Plugin name is empty");
2543     FALSE_RETURN_V_MSG_E(dataSource != nullptr, 0, "DataSource is nullptr");
2544     return SniffWithSize(pluginName, dataSource, DEFAULT_SNIFF_SIZE);
2545 }
2546 
SniffWithSize(const std::string & pluginName,std::shared_ptr<DataSource> dataSource,int probSize)2547 int SniffWithSize(const std::string& pluginName, std::shared_ptr<DataSource> dataSource, int probSize)
2548 {
2549     FALSE_RETURN_V_MSG_E(!pluginName.empty(), 0, "Plugin name is empty");
2550     FALSE_RETURN_V_MSG_E(dataSource != nullptr, 0, "DataSource is nullptr");
2551     std::shared_ptr<AVInputFormat> plugin;
2552     {
2553         std::lock_guard<std::mutex> lock(g_mtx);
2554         plugin = g_pluginInputFormat[pluginName];
2555     }
2556     FALSE_RETURN_V_MSG_E((plugin != nullptr && plugin->read_probe), 0,
2557         "Get plugin for " PUBLIC_LOG_S " failed", pluginName.c_str());
2558     size_t getData = 0;
2559     int confidence = GetConfidence(plugin, pluginName, dataSource, getData, probSize);
2560     if (confidence < 0) {
2561         return 0;
2562     }
2563     if (StartWith(plugin->name, PLUGIN_NAME_MP3) && confidence > 0 && confidence <= MP3_PROBE_SCORE_LIMIT) {
2564         MEDIA_LOG_W("Score " PUBLIC_LOG_D32 " is too low", confidence);
2565         confidence = 0;
2566     }
2567     if (getData < DEFAULT_SNIFF_SIZE || confidence > 0) {
2568         MEDIA_LOG_I("Sniff:" PUBLIC_LOG_S "[" PUBLIC_LOG_ZU "/" PUBLIC_LOG_D32 "]", plugin->name, getData, confidence);
2569     }
2570     return confidence;
2571 }
2572 
CheckMPEGPSStartCode(std::shared_ptr<DataSource> & dataSource)2573 bool CheckMPEGPSStartCode(std::shared_ptr<DataSource> &dataSource)
2574 {
2575     FALSE_RETURN_V_MSG_E(dataSource != nullptr, false, "DataSource is nullptr");
2576     std::vector<uint8_t> buff(MPEGPS_START_CODE_SIZE);
2577     auto bufferInfo = std::make_shared<Buffer>();
2578     auto bufData = bufferInfo->WrapMemory(buff.data(), MPEGPS_START_CODE_SIZE, MPEGPS_START_CODE_SIZE);
2579     FALSE_RETURN_V_MSG_E(bufferInfo->GetMemory() != nullptr, false, "Alloc buffer failed");
2580 
2581     auto ret = dataSource->ReadAt(0, bufferInfo, MPEGPS_START_CODE_SIZE);
2582     FALSE_RETURN_V_MSG_E(ret == Status::OK, false, "Read data failed");
2583     for (int32_t i = 0; i < MPEGPS_START_CODE_SIZE; i++) {
2584         if (buff[i] != MPEGPS_START_CODE[i]) {
2585             return false;
2586         }
2587     }
2588     return true;
2589 }
2590 
SniffMPEGPS(const std::string & pluginName,std::shared_ptr<DataSource> dataSource)2591 int SniffMPEGPS(const std::string& pluginName, std::shared_ptr<DataSource> dataSource)
2592 {
2593     FALSE_RETURN_V_MSG_E(!pluginName.empty(), 0, "Plugin name is empty");
2594     FALSE_RETURN_V_MSG_E(dataSource != nullptr, 0, "DataSource is nullptr");
2595     int32_t psScore = SniffWithSize(pluginName, dataSource, DEFAULT_SNIFF_SIZE);
2596     if (psScore >= DEF_PROBE_SCORE_LIMIT) {
2597         std::string mp3PluginName = std::string(PLUGIN_NAME_PREFIX) + std::string(PLUGIN_NAME_MP3);
2598         int32_t mp3Score = SniffWithSize(mp3PluginName, dataSource, DEFAULT_SNIFF_SIZE);
2599         if (mp3Score >= DEF_PROBE_SCORE_LIMIT && !CheckMPEGPSStartCode(dataSource)) {
2600             return 0;
2601         }
2602     }
2603     return psScore;
2604 }
2605 
FindSniffer(const std::string & pluginName)2606 static PluginSnifferFunc FindSniffer(const std::string& pluginName)
2607 {
2608     if (g_pluginSnifferMap.find(pluginName) != g_pluginSnifferMap.end()) {
2609         return g_pluginSnifferMap.at(pluginName);
2610     }
2611 
2612     return Sniff;
2613 }
2614 
ReplaceDelimiter(const std::string & delmiters,char newDelimiter,std::string & str)2615 void ReplaceDelimiter(const std::string& delmiters, char newDelimiter, std::string& str)
2616 {
2617     MEDIA_LOG_D("Reset from [" PUBLIC_LOG_S "]", str.c_str());
2618     for (auto it = str.begin(); it != str.end(); ++it) {
2619         if (delmiters.find(newDelimiter) != std::string::npos) {
2620             *it = newDelimiter;
2621         }
2622     }
2623     MEDIA_LOG_D("Reset to [" PUBLIC_LOG_S "]", str.c_str());
2624 };
2625 
RegisterPlugins(const std::shared_ptr<Register> & reg)2626 Status RegisterPlugins(const std::shared_ptr<Register>& reg)
2627 {
2628     MEDIA_LOG_I("In");
2629     FALSE_RETURN_V_MSG_E(reg != nullptr, Status::ERROR_INVALID_PARAMETER, "Register is nullptr");
2630     std::lock_guard<std::mutex> lock(g_mtx);
2631     const AVInputFormat* plugin = nullptr;
2632     void* i = nullptr;
2633     while ((plugin = av_demuxer_iterate(&i))) {
2634         if (plugin == nullptr) {
2635             continue;
2636         }
2637         MEDIA_LOG_D("Check ffmpeg demuxer " PUBLIC_LOG_S "[" PUBLIC_LOG_S "]", plugin->name, plugin->long_name);
2638         std::string pluginName = "avdemux_" + std::string(plugin->name);
2639         ReplaceDelimiter(".,|-<> ", '_', pluginName);
2640 
2641         DemuxerPluginDef regInfo;
2642         regInfo.name = pluginName;
2643         regInfo.description = "ffmpeg demuxer plugin";
2644         regInfo.rank = RANK_MAX;
2645         regInfo.AddExtensions(SplitString(plugin->extensions, ','));
2646         g_pluginInputFormat[pluginName] =
2647             std::shared_ptr<AVInputFormat>(const_cast<AVInputFormat*>(plugin), [](void*) {});
2648         auto func = [](const std::string& name) -> std::shared_ptr<DemuxerPlugin> {
2649             return std::make_shared<FFmpegDemuxerPlugin>(name);
2650         };
2651         regInfo.SetCreator(func);
2652         regInfo.SetSniffer(FindSniffer(plugin->name));
2653         auto ret = reg->AddPlugin(regInfo);
2654         if (ret != Status::OK) {
2655             MEDIA_LOG_E("Add plugin failed, err=" PUBLIC_LOG_D32, static_cast<int>(ret));
2656         } else {
2657             MEDIA_LOG_D("Add plugin " PUBLIC_LOG_S, pluginName.c_str());
2658         }
2659     }
2660     FALSE_RETURN_V_MSG_E(!g_pluginInputFormat.empty(), Status::ERROR_UNKNOWN, "Can not load any ffmpeg demuxer");
2661     return Status::OK;
2662 }
2663 } // namespace
__anon8e4663700e02null2664 PLUGIN_DEFINITION(FFmpegDemuxer, LicenseType::LGPL, RegisterPlugins, [] {});
2665 } // namespace Ffmpeg
2666 } // namespace Plugins
2667 } // namespace Media
2668 } // namespace OHOS
2669