• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 HST_LOG_TAG "FfmpegFormatHelper"
17 
18 #include <algorithm>
19 #include <regex>
20 #include <iconv.h>
21 #include <sstream>
22 #include "ffmpeg_converter.h"
23 #include "meta/meta_key.h"
24 #include "meta/media_types.h"
25 #include "meta/mime_type.h"
26 #include "meta/video_types.h"
27 #include "meta/audio_types.h"
28 #include "common/log.h"
29 #include "ffmpeg_format_helper.h"
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 #include "libavutil/avutil.h"
35 #include "libavutil/display.h"
36 #ifdef __cplusplus
37 }
38 #endif
39 
40 #define DISPLAY_MATRIX_SIZE (static_cast<size_t>(9))
41 #define CONVERT_MATRIX_SIZE (static_cast<size_t>(4))
42 #define CUVA_VERSION_MAP (static_cast<uint16_t>(1))
43 #define TERMINAL_PROVIDE_CODE (static_cast<uint16_t>(4))
44 #define TERMINAL_PROVIDE_ORIENTED_CODE (static_cast<uint16_t>(5))
45 
46 namespace {
47 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_DEMUXER, "FfmpegFormatHelper" };
48 }
49 
50 namespace OHOS {
51 namespace Media {
52 namespace Plugins {
53 namespace Ffmpeg {
54 const uint32_t DOUBLE_BYTES = 2;
55 const uint32_t KEY_PREFIX_LEN = 20;
56 const uint32_t VALUE_PREFIX_LEN = 8;
57 const uint32_t VALID_LOCATION_LEN = 2;
58 const int32_t VIDEO_ROTATION_360 = 360;
59 const int32_t AV3A_SAMPLE_8BITS = 8;
60 const int32_t AV3A_SAMPLE_16BITS = 16;
61 const int32_t AV3A_SAMPLE_24BITS = 24;
62 
63 const unsigned char MASK_80 = 0x80;
64 const unsigned char MASK_C0 = 0xC0;
65 const int32_t MIN_BYTES = 2;
66 const int32_t MAX_BYTES = 6;
67 
68 static std::map<AVMediaType, MediaType> g_convertFfmpegTrackType = {
69     {AVMEDIA_TYPE_VIDEO, MediaType::VIDEO},
70     {AVMEDIA_TYPE_AUDIO, MediaType::AUDIO},
71     {AVMEDIA_TYPE_SUBTITLE, MediaType::SUBTITLE},
72     {AVMEDIA_TYPE_TIMEDMETA, MediaType::TIMEDMETA}
73 };
74 
75 static std::map<AVCodecID, std::string_view> g_codecIdToMime = {
76     {AV_CODEC_ID_MP1, MimeType::AUDIO_MPEG},
77     {AV_CODEC_ID_MP2, MimeType::AUDIO_MPEG},
78     {AV_CODEC_ID_MP3, MimeType::AUDIO_MPEG},
79     {AV_CODEC_ID_FLAC, MimeType::AUDIO_FLAC},
80     {AV_CODEC_ID_AAC, MimeType::AUDIO_AAC},
81     {AV_CODEC_ID_VORBIS, MimeType::AUDIO_VORBIS},
82     {AV_CODEC_ID_OPUS, MimeType::AUDIO_OPUS},
83     {AV_CODEC_ID_AMR_NB, MimeType::AUDIO_AMR_NB},
84     {AV_CODEC_ID_AMR_WB, MimeType::AUDIO_AMR_WB},
85     {AV_CODEC_ID_H264, MimeType::VIDEO_AVC},
86     {AV_CODEC_ID_MPEG4, MimeType::VIDEO_MPEG4},
87 #ifdef SUPPORT_CODEC_RV
88     {AV_CODEC_ID_RV30, MimeType::VIDEO_RV30},
89     {AV_CODEC_ID_RV40, MimeType::VIDEO_RV40},
90 #endif
91     {AV_CODEC_ID_MJPEG, MimeType::IMAGE_JPG},
92     {AV_CODEC_ID_PNG, MimeType::IMAGE_PNG},
93     {AV_CODEC_ID_BMP, MimeType::IMAGE_BMP},
94     {AV_CODEC_ID_H263, MimeType::VIDEO_H263},
95     {AV_CODEC_ID_MPEG2TS, MimeType::VIDEO_MPEG2},
96     {AV_CODEC_ID_MPEG2VIDEO, MimeType::VIDEO_MPEG2},
97     {AV_CODEC_ID_HEVC, MimeType::VIDEO_HEVC},
98     {AV_CODEC_ID_VVC, MimeType::VIDEO_VVC},
99     {AV_CODEC_ID_VP8, MimeType::VIDEO_VP8},
100     {AV_CODEC_ID_VP9, MimeType::VIDEO_VP9},
101     {AV_CODEC_ID_AVS3DA, MimeType::AUDIO_AVS3DA},
102     {AV_CODEC_ID_APE, MimeType::AUDIO_APE},
103     {AV_CODEC_ID_PCM_MULAW, MimeType::AUDIO_G711MU},
104 #ifdef SUPPORT_CODEC_COOK
105     {AV_CODEC_ID_COOK, MimeType::AUDIO_COOK},
106 #endif
107 #ifdef SUPPORT_CODEC_AC3
108     {AV_CODEC_ID_AC3, MimeType::AUDIO_AC3},
109 #endif
110     {AV_CODEC_ID_SUBRIP, MimeType::TEXT_SUBRIP},
111     {AV_CODEC_ID_WEBVTT, MimeType::TEXT_WEBVTT},
112     {AV_CODEC_ID_FFMETADATA, MimeType::TIMED_METADATA}
113 };
114 
115 static std::map<std::string, FileType> g_convertFfmpegFileType = {
116     {"mpegts", FileType::MPEGTS},
117     {"matroska,webm", FileType::MKV},
118     {"amr", FileType::AMR},
119     {"amrnb", FileType::AMR},
120     {"amrwb", FileType::AMR},
121     {"aac", FileType::AAC},
122     {"mp3", FileType::MP3},
123     {"flac", FileType::FLAC},
124     {"ogg", FileType::OGG},
125     {"wav", FileType::WAV},
126     {"flv", FileType::FLV},
127     {"avi", FileType::AVI},
128     {"mpeg", FileType::MPEGPS},
129     {"rm", FileType::RM},
130     {"ac3", FileType::AC3},
131     {"ape", FileType::APE},
132     {"srt", FileType::SRT},
133     {"webvtt", FileType::VTT},
134 };
135 
136 static std::map<std::string, TagType> g_formatToString = {
137     {"title",         Tag::MEDIA_TITLE},
138     {"artist",        Tag::MEDIA_ARTIST},
139     {"album",         Tag::MEDIA_ALBUM},
140     {"album_artist",  Tag::MEDIA_ALBUM_ARTIST},
141     {"date",          Tag::MEDIA_DATE},
142     {"comment",       Tag::MEDIA_COMMENT},
143     {"genre",         Tag::MEDIA_GENRE},
144     {"copyright",     Tag::MEDIA_COPYRIGHT},
145     {"language",      Tag::MEDIA_LANGUAGE},
146     {"description",   Tag::MEDIA_DESCRIPTION},
147     {"lyrics",        Tag::MEDIA_LYRICS},
148     {"author",        Tag::MEDIA_AUTHOR},
149     {"composer",      Tag::MEDIA_COMPOSER},
150     {"creation_time", Tag::MEDIA_CREATION_TIME}
151 };
152 
153 std::vector<TagType> g_supportSourceFormat = {
154     Tag::MEDIA_TITLE,
155     Tag::MEDIA_ARTIST,
156     Tag::MEDIA_ALBUM,
157     Tag::MEDIA_ALBUM_ARTIST,
158     Tag::MEDIA_DATE,
159     Tag::MEDIA_COMMENT,
160     Tag::MEDIA_GENRE,
161     Tag::MEDIA_COPYRIGHT,
162     Tag::MEDIA_LANGUAGE,
163     Tag::MEDIA_DESCRIPTION,
164     Tag::MEDIA_LYRICS,
165     Tag::MEDIA_AUTHOR,
166     Tag::MEDIA_COMPOSER,
167     Tag::MEDIA_CREATION_TIME
168 };
169 
SplitByChar(const char * str,const char * pattern)170 std::vector<std::string> SplitByChar(const char* str, const char* pattern)
171 {
172     FALSE_RETURN_V_NOLOG(str != nullptr && pattern != nullptr, {});
173     std::string tempStr(str);
174     std::stringstream strStream(tempStr);
175     std::vector<std::string> resultVec;
176     std::string item;
177     while (std::getline(strStream, item, *pattern)) {
178         if (!item.empty()) {
179             resultVec.push_back(item);
180         }
181     }
182     MEDIA_LOG_D("Split by [" PUBLIC_LOG_S "], get " PUBLIC_LOG_ZU " string", pattern, resultVec.size());
183     return resultVec;
184 }
185 
RemoveDuplication(const std::string origin)186 std::string RemoveDuplication(const std::string origin)
187 {
188     FALSE_RETURN_V_NOLOG(origin.find(";") != std::string::npos, origin);
189     std::vector<std::string> subStrings = SplitByChar(origin.c_str(), ";");
190     FALSE_RETURN_V_NOLOG(subStrings.size() > 1, origin);
191 
192     std::string outString;
193     std::vector<std::string> uniqueSubStrings;
194     for (auto str : subStrings) {
195         if (std::count(uniqueSubStrings.begin(), uniqueSubStrings.end(), str) == 0) {
196             uniqueSubStrings.push_back(str);
197         }
198     }
199     for (size_t idx = 0; idx < uniqueSubStrings.size(); idx++) {
200         outString += uniqueSubStrings[idx];
201         if (idx < uniqueSubStrings.size() - 1) {
202             outString += ";";
203         }
204     }
205     MEDIA_LOG_D("[%{public}s]->[%{public}s]", origin.c_str(), outString.c_str());
206     return outString;
207 }
208 
ToLower(const std::string & str)209 std::string ToLower(const std::string& str)
210 {
211     std::string res = str;
212     std::transform(res.begin(), res.end(), res.begin(), [](unsigned char c) {
213         return (c == '_') ? c : std::tolower(c);
214     });
215     MEDIA_LOG_D("[" PUBLIC_LOG_S "] -> [" PUBLIC_LOG_S "]", str.c_str(), res.c_str());
216     return res;
217 }
218 
IsUTF8Char(unsigned char chr,int32_t & nBytes)219 bool IsUTF8Char(unsigned char chr, int32_t &nBytes)
220 {
221     if (nBytes == 0) {
222         if ((chr & MASK_80) == 0) {
223             return true;
224         }
225         while ((chr & MASK_80) == MASK_80) {
226             chr <<= 1;
227             nBytes++;
228         }
229 
230         if (nBytes < MIN_BYTES || nBytes > MAX_BYTES) {
231             return false;
232         }
233         nBytes--;
234     } else {
235         if ((chr & MASK_C0) != MASK_80) {
236             return false;
237         }
238         nBytes--;
239     }
240     return true;
241 }
242 
IsUTF8(const std::string & data)243 bool IsUTF8(const std::string &data)
244 {
245     int32_t nBytes = 0;
246     for (size_t i = 0; i < data.size(); ++i) {
247         if (!IsUTF8Char(data[i], nBytes)) {
248             MEDIA_LOG_D("Detect char not in uft8");
249             return false;
250         }
251     }
252     return true;
253 }
254 
ConvertGBKToUTF8(const std::string & strGbk)255 std::string ConvertGBKToUTF8(const std::string &strGbk)
256 {
257     if (strGbk.length() == 0) {
258         return "";
259     }
260 
261     const std::string fromCharset = "gb18030";
262     const std::string toCharset = "utf-8";
263     iconv_t cd = iconv_open(toCharset.c_str(), fromCharset.c_str());
264     if (cd == reinterpret_cast<iconv_t>(-1)) { // iconv_t is a void* type
265         MEDIA_LOG_D("Call iconv_open failed");
266         return "";
267     }
268     size_t inLen = strGbk.length();
269     size_t outLen = inLen * 4; // max for chinese character
270     char* inBuf = const_cast<char*>(strGbk.c_str());
271     if (inBuf == nullptr) {
272         MEDIA_LOG_D("Get in buffer failed");
273         iconv_close(cd);
274         return "";
275     }
276     char* outBuf = new char[outLen];
277     if (outBuf == nullptr) {
278         MEDIA_LOG_D("Get out buffer failed");
279         iconv_close(cd);
280         return "";
281     }
282     char* outBufBack = outBuf;
283     if (iconv(cd, &inBuf, &inLen, &outBuf, &outLen) == static_cast<size_t>(-1)) { // iconv return SIZE_MAX when failed
284         MEDIA_LOG_D("Call iconv failed");
285         delete[] outBufBack;
286         outBufBack = nullptr;
287         iconv_close(cd);
288         return "";
289     }
290     std::string strOut(outBufBack, outBuf - outBufBack);
291     delete[] outBufBack;
292     outBufBack = nullptr;
293     iconv_close(cd);
294     return strOut;
295 }
296 
IsGBK(const char * data)297 bool IsGBK(const char* data)
298 {
299     int len = static_cast<int>(strlen(data));
300     int i = 0;
301     while (i < len) {
302         if (static_cast<unsigned char>(data[i]) <= 0x7f) { // one byte encoding or ASCII
303             i++;
304             continue;
305         } else { // double bytes encoding
306             if (i + 1  < len &&
307                 static_cast<unsigned char>(data[i]) >= 0x81 && static_cast<unsigned char>(data[i]) <= 0xfe &&
308                 static_cast<unsigned char>(data[i + 1]) >= 0x40 && static_cast<unsigned char>(data[i + 1]) <= 0xfe) {
309                 i += DOUBLE_BYTES; // double bytes
310                 continue;
311             } else {
312                 return false;
313             }
314         }
315     }
316     return true;
317 }
318 
319 static std::vector<AVCodecID> g_imageCodecID = {
320     AV_CODEC_ID_MJPEG,
321     AV_CODEC_ID_PNG,
322     AV_CODEC_ID_PAM,
323     AV_CODEC_ID_BMP,
324     AV_CODEC_ID_JPEG2000,
325     AV_CODEC_ID_TARGA,
326     AV_CODEC_ID_TIFF,
327     AV_CODEC_ID_GIF,
328     AV_CODEC_ID_PCX,
329     AV_CODEC_ID_XWD,
330     AV_CODEC_ID_XBM,
331     AV_CODEC_ID_WEBP,
332     AV_CODEC_ID_APNG,
333     AV_CODEC_ID_XPM,
334     AV_CODEC_ID_SVG,
335 };
336 
337 static std::map<std::string, VideoRotation> g_pFfRotationMap = {
338     {"0", VIDEO_ROTATION_0},
339     {"90", VIDEO_ROTATION_90},
340     {"180", VIDEO_ROTATION_180},
341     {"270", VIDEO_ROTATION_270},
342 };
343 
344 static const std::map<std::string, VideoOrientationType> matrixTypes = {
345     /**
346      * display matrix
347      *                                  | a b u |
348      *   (a, b, u, c, d, v, x, y, w) -> | c d v |
349      *                                  | x y w |
350      * [a b c d] can confirm the orientation type
351      */
352     {"0 -1 1 0", VideoOrientationType::ROTATE_90},
353     {"-1 0 0 -1", VideoOrientationType::ROTATE_180},
354     {"0 1 -1 0", VideoOrientationType::ROTATE_270},
355     {"-1 0 0 1", VideoOrientationType::FLIP_H},
356     {"1 0 0 -1", VideoOrientationType::FLIP_V},
357     {"0 1 1 0", VideoOrientationType::FLIP_H_ROT90},
358     {"0 -1 -1 0", VideoOrientationType::FLIP_V_ROT90},
359 };
360 
GetMatrixType(const std::string & value)361 VideoOrientationType GetMatrixType(const std::string& value)
362 {
363     auto it = matrixTypes.find(value);
364     if (it!= matrixTypes.end()) {
365         return it->second;
366     } else {
367         return VideoOrientationType::ROTATE_NONE;
368     }
369 }
370 
ConvFp(int32_t x)371 inline int ConvFp(int32_t x)
372 {
373     return static_cast<int32_t>(x / (1 << 16)); // 16 is used for digital conversion
374 }
375 
ConvertArrayToString(const int * array,size_t size)376 std::string ConvertArrayToString(const int* array, size_t size)
377 {
378     std::string result;
379     for (size_t i = 0; i < size; ++i) {
380         if (i > 0) {
381             result += ' ';
382         }
383         result += std::to_string(array[i]);
384     }
385     return result;
386 }
387 
IsPCMStream(AVCodecID codecID)388 bool IsPCMStream(AVCodecID codecID)
389 {
390     MEDIA_LOG_D("CodecID " PUBLIC_LOG_D32 "[" PUBLIC_LOG_S "]",
391         static_cast<int32_t>(codecID), avcodec_get_name(codecID));
392     return StartWith(avcodec_get_name(codecID), "pcm_");
393 }
394 
GetDefaultTrackStartTime(const AVFormatContext & avFormatContext)395 int64_t GetDefaultTrackStartTime(const AVFormatContext& avFormatContext)
396 {
397     int64_t defaultTime = 0;
398     for (uint32_t trackIndex = 0; trackIndex < avFormatContext.nb_streams; ++trackIndex) {
399         auto avStream = avFormatContext.streams[trackIndex];
400         if (avStream != nullptr && avStream->codecpar != nullptr &&
401             avStream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && avStream->start_time != AV_NOPTS_VALUE) {
402             defaultTime = AvTime2Us(ConvertTimeFromFFmpeg(avStream->start_time, avStream->time_base));
403         }
404     }
405     return defaultTime;
406 }
407 
FfAv3aGetNbObjects(AVChannelLayout * channelLayout)408 static int FfAv3aGetNbObjects(AVChannelLayout *channelLayout)
409 {
410     int nbObjects = 0;
411     if (channelLayout->order != AV_CHANNEL_ORDER_CUSTOM) {
412         return 0;
413     }
414     for (int i = 0; i < channelLayout->nb_channels; i++) {
415         if (channelLayout->u.map[i].id == AV3A_CH_AUDIO_OBJECT) {
416             nbObjects++;
417         }
418     }
419     return nbObjects;
420 }
421 
FfAv3aGetChannelLayoutMask(AVChannelLayout * channelLayout)422 static uint64_t FfAv3aGetChannelLayoutMask(AVChannelLayout *channelLayout)
423 {
424     uint64_t mask = 0L;
425     if (channelLayout->order != AV_CHANNEL_ORDER_CUSTOM) {
426         return 0;
427     }
428     for (int i = 0; i < channelLayout->nb_channels; i++) {
429         if (channelLayout->u.map[i].id == AV3A_CH_AUDIO_OBJECT) {
430             return mask;
431         }
432         mask |= (1ULL << channelLayout->u.map[i].id);
433     }
434     return mask;
435 }
436 
ParseTrackType(const AVFormatContext & avFormatContext,Meta & format)437 void FFmpegFormatHelper::ParseTrackType(const AVFormatContext& avFormatContext, Meta& format)
438 {
439     format.Set<Tag::MEDIA_TRACK_COUNT>(static_cast<int32_t>(avFormatContext.nb_streams));
440     bool hasVideo = false;
441     bool hasAudio = false;
442     bool hasSubtitle = false;
443     bool hasTimedMeta = false;
444     for (uint32_t i = 0; i < avFormatContext.nb_streams; ++i) {
445         if (avFormatContext.streams[i] == nullptr || avFormatContext.streams[i]->codecpar == nullptr) {
446             MEDIA_LOG_W("Track " PUBLIC_LOG_U32 " is invalid", i);
447             continue;
448         }
449         if (avFormatContext.streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
450             AVCodecID codecID = avFormatContext.streams[i]->codecpar->codec_id;
451             if (std::count(g_imageCodecID.begin(), g_imageCodecID.end(), codecID) <= 0) {
452                 hasVideo = true;
453             }
454         } else if (avFormatContext.streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
455             hasAudio = true;
456         } else if (avFormatContext.streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
457             hasSubtitle = true;
458         } else if (avFormatContext.streams[i]->codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
459             hasTimedMeta = true;
460         }
461     }
462     format.Set<Tag::MEDIA_HAS_VIDEO>(hasVideo);
463     format.Set<Tag::MEDIA_HAS_AUDIO>(hasAudio);
464     format.Set<Tag::MEDIA_HAS_SUBTITLE>(hasSubtitle);
465     format.Set<Tag::MEDIA_HAS_TIMEDMETA>(hasTimedMeta);
466 }
467 
ParseMediaInfo(const AVFormatContext & avFormatContext,Meta & format)468 void FFmpegFormatHelper::ParseMediaInfo(const AVFormatContext& avFormatContext, Meta& format)
469 {
470     ParseTrackType(avFormatContext, format);
471     format.Set<Tag::MEDIA_FILE_TYPE>(GetFileTypeByName(avFormatContext));
472     int64_t duration = avFormatContext.duration;
473     if (duration == AV_NOPTS_VALUE) {
474         duration = 0;
475         const AVDictionaryEntry *metaDuration = av_dict_get(avFormatContext.metadata, "DURATION", NULL, 0);
476         int64_t us;
477         if (metaDuration != nullptr && (av_parse_time(&us, metaDuration->value, 1) == 0)) {
478             if (us > duration) {
479                 duration = us;
480             }
481         }
482     }
483     if (duration > 0 && duration != AV_NOPTS_VALUE) {
484         format.Set<Tag::MEDIA_DURATION>(static_cast<int64_t>(duration));
485     }
486     if (avFormatContext.start_time != AV_NOPTS_VALUE) {
487         format.Set<Tag::MEDIA_CONTAINER_START_TIME>(static_cast<int64_t>(avFormatContext.start_time));
488     } else {
489         format.Set<Tag::MEDIA_CONTAINER_START_TIME>(static_cast<int64_t>(0));
490         MEDIA_LOG_W("Parse container start time failed");
491     }
492     ParseLocationInfo(avFormatContext, format);
493     ParseInfoFromMetadata(avFormatContext.metadata, format);
494 }
495 
ParseLocationInfo(const AVFormatContext & avFormatContext,Meta & format)496 void FFmpegFormatHelper::ParseLocationInfo(const AVFormatContext& avFormatContext, Meta &format)
497 {
498     MEDIA_LOG_D("Parse location info");
499     AVDictionaryEntry *valPtr = nullptr;
500     valPtr = av_dict_get(avFormatContext.metadata, "location", nullptr, AV_DICT_MATCH_CASE);
501     if (valPtr == nullptr) {
502         valPtr = av_dict_get(avFormatContext.metadata, "LOCATION", nullptr, AV_DICT_MATCH_CASE);
503     }
504     if (valPtr == nullptr) {
505         MEDIA_LOG_D("Parse failed");
506         return;
507     }
508     MEDIA_LOG_D("Get location string successfully: %{private}s", valPtr->value);
509     std::string locationStr = std::string(valPtr->value);
510     std::regex pattern(R"([\+\-]\d+\.\d+)");
511     std::sregex_iterator numbers(locationStr.cbegin(), locationStr.cend(), pattern);
512     std::sregex_iterator end;
513     // at least contain latitude and longitude
514     if (static_cast<uint32_t>(std::distance(numbers, end)) < VALID_LOCATION_LEN) {
515         MEDIA_LOG_D("Info format error");
516         return;
517     }
518     format.Set<Tag::MEDIA_LATITUDE>(std::stof(numbers->str()));
519     format.Set<Tag::MEDIA_LONGITUDE>(std::stof((++numbers)->str()));
520 }
521 
ParseUserMeta(const AVFormatContext & avFormatContext,std::shared_ptr<Meta> format)522 void FFmpegFormatHelper::ParseUserMeta(const AVFormatContext& avFormatContext, std::shared_ptr<Meta> format)
523 {
524     MEDIA_LOG_D("Parse user data info");
525     AVDictionaryEntry *valPtr = nullptr;
526     while ((valPtr = av_dict_get(avFormatContext.metadata, "", valPtr, AV_DICT_IGNORE_SUFFIX)))  {
527         if (StartWith(valPtr->key, "moov_level_meta_key_")) {
528             MEDIA_LOG_D("Ffmpeg key: " PUBLIC_LOG_S, (valPtr->key));
529             if (strlen(valPtr->value) <= VALUE_PREFIX_LEN) {
530                 MEDIA_LOG_D("Parse user data info " PUBLIC_LOG_S " failed, value too short", valPtr->key);
531                 continue;
532             }
533             if (StartWith(valPtr->value, "00000001")) { // string
534                 MEDIA_LOG_D("Key: " PUBLIC_LOG_S " | type: string", (valPtr->key + KEY_PREFIX_LEN));
535                 format->SetData(valPtr->key + KEY_PREFIX_LEN, std::string(valPtr->value + VALUE_PREFIX_LEN));
536             } else if (StartWith(valPtr->value, "00000017")) { // float
537                 MEDIA_LOG_D("Key: " PUBLIC_LOG_S " | type: float", (valPtr->key + KEY_PREFIX_LEN));
538                 format->SetData(valPtr->key + KEY_PREFIX_LEN, std::stof(valPtr->value + VALUE_PREFIX_LEN));
539             } else if (StartWith(valPtr->value, "00000043") || StartWith(valPtr->value, "00000015")) { // int
540                 MEDIA_LOG_D("Key: " PUBLIC_LOG_S " | type: int", (valPtr->key + KEY_PREFIX_LEN));
541                 format->SetData(valPtr->key + KEY_PREFIX_LEN, std::stoi(valPtr->value + VALUE_PREFIX_LEN));
542             } else { // unknow
543                 MEDIA_LOG_D("Key: " PUBLIC_LOG_S " | type: unknow", (valPtr->key + KEY_PREFIX_LEN));
544                 format->SetData(valPtr->key + KEY_PREFIX_LEN, std::string(valPtr->value + VALUE_PREFIX_LEN));
545             }
546         }
547     }
548 }
549 
ParseTrackInfo(const AVStream & avStream,Meta & format,const AVFormatContext & avFormatContext)550 void FFmpegFormatHelper::ParseTrackInfo(const AVStream& avStream, Meta& format, const AVFormatContext& avFormatContext)
551 {
552     FALSE_RETURN_MSG(avStream.codecpar != nullptr, "Codecpar is nullptr");
553     ParseBaseTrackInfo(avStream, format, avFormatContext);
554     if (avStream.codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
555         if ((static_cast<uint32_t>(avStream.disposition) & static_cast<uint32_t>(AV_DISPOSITION_ATTACHED_PIC)) ||
556             (std::count(g_imageCodecID.begin(), g_imageCodecID.end(), avStream.codecpar->codec_id) > 0)) {
557             ParseImageTrackInfo(avStream, format);
558         } else {
559             ParseAVTrackInfo(avStream, format);
560             ParseVideoTrackInfo(avStream, format, avFormatContext);
561         }
562     } else if (avStream.codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
563         ParseAVTrackInfo(avStream, format);
564         ParseAudioTrackInfo(avStream, format, avFormatContext);
565     } else if (avStream.codecpar->codec_type == AVMEDIA_TYPE_TIMEDMETA) {
566         ParseAVTrackInfo(avStream, format);
567         ParseTimedMetaTrackInfo(avStream, format);
568     }
569 }
570 
ParseBaseTrackInfo(const AVStream & avStream,Meta & format,const AVFormatContext & avFormatContext)571 void FFmpegFormatHelper::ParseBaseTrackInfo(const AVStream& avStream, Meta &format,
572                                             const AVFormatContext& avFormatContext)
573 {
574     if (g_codecIdToMime.count(avStream.codecpar->codec_id) != 0) {
575         format.Set<Tag::MIME_TYPE>(std::string(g_codecIdToMime[avStream.codecpar->codec_id]));
576     } else if (IsPCMStream(avStream.codecpar->codec_id)) {
577         format.Set<Tag::MIME_TYPE>(std::string(MimeType::AUDIO_RAW));
578     } else {
579         format.Set<Tag::MIME_TYPE>(std::string(MimeType::INVALID_TYPE));
580         MEDIA_LOG_W("Parse mime type failed: " PUBLIC_LOG_D32, static_cast<int32_t>(avStream.codecpar->codec_id));
581     }
582 
583     AVMediaType mediaType = avStream.codecpar->codec_type;
584     if (g_convertFfmpegTrackType.count(mediaType) > 0) {
585         format.Set<Tag::MEDIA_TYPE>(g_convertFfmpegTrackType[mediaType]);
586     } else {
587         MEDIA_LOG_W("Parse track type failed: " PUBLIC_LOG_D32, static_cast<int32_t>(mediaType));
588     }
589 
590     if (avStream.start_time != AV_NOPTS_VALUE) {
591         format.SetData(Tag::MEDIA_START_TIME,
592             AvTime2Us(ConvertTimeFromFFmpeg(avStream.start_time, avStream.time_base)));
593     } else {
594         if (mediaType == AVMEDIA_TYPE_AUDIO) {
595             format.SetData(Tag::MEDIA_START_TIME, GetDefaultTrackStartTime(avFormatContext));
596         }
597         MEDIA_LOG_W("Parse track start time failed");
598     }
599 }
600 
GetFileTypeByName(const AVFormatContext & avFormatContext)601 FileType FFmpegFormatHelper::GetFileTypeByName(const AVFormatContext& avFormatContext)
602 {
603     FALSE_RETURN_V_MSG_E(avFormatContext.iformat != nullptr, FileType::UNKNOW, "Iformat is nullptr");
604     const char *fileName = avFormatContext.iformat->name;
605     FileType fileType = FileType::UNKNOW;
606     if (StartWith(fileName, "mov,mp4,m4a")) {
607         const AVDictionaryEntry *type = av_dict_get(avFormatContext.metadata, "major_brand", NULL, 0);
608         if (type == nullptr) {
609             MEDIA_LOG_D("Not found ftyp");
610             return FileType::MP4;
611         }
612         if (StartWith(type->value, "m4a") || StartWith(type->value, "M4A") ||
613             StartWith(type->value, "m4v") || StartWith(type->value, "M4V")) {
614             fileType = FileType::M4A;
615         } else if (StartWith(type->value, "qt") || StartWith(type->value, "QT")) {
616             fileType = FileType::MOV;
617         } else {
618             fileType = FileType::MP4;
619         }
620     } else {
621         if (g_convertFfmpegFileType.count(fileName) != 0) {
622             fileType = g_convertFfmpegFileType[fileName];
623         }
624     }
625     MEDIA_LOG_D("File name [" PUBLIC_LOG_S "] file type [" PUBLIC_LOG_D32 "]",
626         fileName, static_cast<int32_t>(fileType));
627     return fileType;
628 }
629 
ParseAVTrackInfo(const AVStream & avStream,Meta & format)630 void FFmpegFormatHelper::ParseAVTrackInfo(const AVStream& avStream, Meta &format)
631 {
632     int64_t bitRate = static_cast<int64_t>(avStream.codecpar->bit_rate);
633     if (bitRate > 0) {
634         format.Set<Tag::MEDIA_BITRATE>(bitRate);
635     } else {
636         MEDIA_LOG_D("Parse bitrate failed: " PUBLIC_LOG_D64, bitRate);
637     }
638 
639     if (avStream.codecpar->extradata_size > 0 && avStream.codecpar->extradata != nullptr) {
640         std::vector<uint8_t> extra(avStream.codecpar->extradata_size);
641         extra.assign(avStream.codecpar->extradata, avStream.codecpar->extradata + avStream.codecpar->extradata_size);
642         format.Set<Tag::MEDIA_CODEC_CONFIG>(extra);
643     } else {
644         MEDIA_LOG_D("Parse codec config failed");
645     }
646     AVDictionaryEntry *valPtr = nullptr;
647     valPtr = av_dict_get(avStream.metadata, "language", nullptr, AV_DICT_MATCH_CASE);
648     if (valPtr != nullptr) {
649         format.SetData(Tag::MEDIA_LANGUAGE, std::string(valPtr->value));
650     } else {
651         MEDIA_LOG_D("Parse track language failed");
652     }
653 }
654 
ParseVideoTrackInfo(const AVStream & avStream,Meta & format,const AVFormatContext & avFormatContext)655 void FFmpegFormatHelper::ParseVideoTrackInfo(const AVStream& avStream, Meta &format,
656                                              const AVFormatContext& avFormatContext)
657 {
658     format.Set<Tag::VIDEO_WIDTH>(static_cast<uint32_t>(avStream.codecpar->width));
659     format.Set<Tag::VIDEO_HEIGHT>(static_cast<uint32_t>(avStream.codecpar->height));
660     format.Set<Tag::VIDEO_DELAY>(static_cast<uint32_t>(avStream.codecpar->video_delay));
661 
662     double frameRate = 0;
663     if (avStream.avg_frame_rate.den == 0 || avStream.avg_frame_rate.num == 0) {
664         frameRate = static_cast<double>(av_q2d(avStream.r_frame_rate));
665     } else {
666         frameRate = static_cast<double>(av_q2d(avStream.avg_frame_rate));
667     }
668     if (frameRate > 0) {
669         format.Set<Tag::VIDEO_FRAME_RATE>(frameRate);
670     } else {
671         MEDIA_LOG_D("Parse frame rate failed: " PUBLIC_LOG_F, frameRate);
672     }
673 
674     AVDictionaryEntry *valPtr = nullptr;
675     valPtr = av_dict_get(avStream.metadata, "rotate", nullptr, AV_DICT_MATCH_CASE);
676     if (valPtr == nullptr) {
677         valPtr = av_dict_get(avStream.metadata, "ROTATE", nullptr, AV_DICT_MATCH_CASE);
678     }
679     if (valPtr == nullptr) {
680         MEDIA_LOG_D("Parse rotate info from meta failed");
681         ParseRotationFromMatrix(avStream, format);
682     } else {
683         if (g_pFfRotationMap.count(std::string(valPtr->value)) > 0) {
684             format.Set<Tag::VIDEO_ROTATION>(g_pFfRotationMap[std::string(valPtr->value)]);
685         }
686     }
687     if (GetFileTypeByName(avFormatContext) == FileType::MP4) {
688         ParseOrientationFromMatrix(avStream, format);
689     }
690 
691     AVRational sar = avStream.sample_aspect_ratio;
692     if (sar.num && sar.den) {
693         format.Set<Tag::VIDEO_SAR>(static_cast<double>(av_q2d(sar)));
694     }
695 
696     if (avStream.codecpar->codec_id == AV_CODEC_ID_HEVC) {
697         ParseHvccBoxInfo(avStream, format);
698         ParseColorBoxInfo(avStream, format);
699     }
700 }
701 
ParseRotationFromMatrix(const AVStream & avStream,Meta & format)702 void FFmpegFormatHelper::ParseRotationFromMatrix(const AVStream& avStream, Meta &format)
703 {
704     int32_t *displayMatrix = (int32_t *)av_stream_get_side_data(&avStream, AV_PKT_DATA_DISPLAYMATRIX, NULL);
705     if (displayMatrix) {
706         float rotation = -round(av_display_rotation_get(displayMatrix));
707         MEDIA_LOG_D("Parse rotate info from display matrix: " PUBLIC_LOG_F, rotation);
708         if (isnan(rotation)) {
709             format.Set<Tag::VIDEO_ROTATION>(g_pFfRotationMap["0"]);
710             return;
711         } else if (rotation < 0) {
712             rotation += VIDEO_ROTATION_360;
713         }
714         switch (int(rotation)) {
715             case VIDEO_ROTATION_90:
716                 format.Set<Tag::VIDEO_ROTATION>(g_pFfRotationMap["90"]);
717                 break;
718             case VIDEO_ROTATION_180:
719                 format.Set<Tag::VIDEO_ROTATION>(g_pFfRotationMap["180"]);
720                 break;
721             case VIDEO_ROTATION_270:
722                 format.Set<Tag::VIDEO_ROTATION>(g_pFfRotationMap["270"]);
723                 break;
724             default:
725                 format.Set<Tag::VIDEO_ROTATION>(g_pFfRotationMap["0"]);
726                 break;
727         }
728     } else {
729         MEDIA_LOG_D("Parse rotate info from display matrix failed, set rotation as dafault 0");
730         format.Set<Tag::VIDEO_ROTATION>(g_pFfRotationMap["0"]);
731     }
732 }
733 
PrintMatrixToLog(int32_t * matrix,const std::string & matrixName)734 void PrintMatrixToLog(int32_t * matrix, const std::string& matrixName)
735 {
736     MEDIA_LOG_D(PUBLIC_LOG_S ": [" PUBLIC_LOG_D32 " " PUBLIC_LOG_D32 " " PUBLIC_LOG_D32 " " PUBLIC_LOG_D32 " "
737             PUBLIC_LOG_D32 " " PUBLIC_LOG_D32 " " PUBLIC_LOG_D32 " " PUBLIC_LOG_D32 " " PUBLIC_LOG_D32 "]",
738             matrixName.c_str(), matrix[0], matrix[1], matrix[2], matrix[3], matrix[4],
739             matrix[5], matrix[6], matrix[7], matrix[8]);
740 }
741 
ParseOrientationFromMatrix(const AVStream & avStream,Meta & format)742 void FFmpegFormatHelper::ParseOrientationFromMatrix(const AVStream& avStream, Meta &format)
743 {
744     VideoOrientationType orientationType = VideoOrientationType::ROTATE_NONE;
745     int32_t *displayMatrix = (int32_t *)av_stream_get_side_data(&avStream, AV_PKT_DATA_DISPLAYMATRIX, NULL);
746     if (displayMatrix) {
747         PrintMatrixToLog(displayMatrix, "displayMatrix");
748         int convertedMatrix[CONVERT_MATRIX_SIZE];
749         std::transform(&displayMatrix[0], &displayMatrix[0] + 1, // 0 is displayMatrix index, 1 is copy lenth
750                        &convertedMatrix[0], ConvFp); // 0 is convertedMatrix index
751         std::transform(&displayMatrix[1], &displayMatrix[1] + 1, // 1 is displayMatrix index, 1 is copy lenth
752                        &convertedMatrix[1], ConvFp); // 1 is convertedMatrix index
753         std::transform(&displayMatrix[3], &displayMatrix[3] + 1, // 3 is displayMatrix index, 1 is copy lenth
754                        &convertedMatrix[2], ConvFp); // 2 is convertedMatrix index
755         std::transform(&displayMatrix[4], &displayMatrix[4] + 1, // 4 is displayMatrix index, 1 is copy lenth
756                        &convertedMatrix[3], ConvFp); // 3 is convertedMatrix index
757         orientationType = GetMatrixType(ConvertArrayToString(convertedMatrix, CONVERT_MATRIX_SIZE));
758     } else {
759         MEDIA_LOG_D("Parse orientation info from display matrix failed, set orientation as dafault 0");
760     }
761     format.Set<Tag::VIDEO_ORIENTATION_TYPE>(orientationType);
762     MEDIA_LOG_D("Type of matrix is: " PUBLIC_LOG_D32, static_cast<int>(orientationType));
763 }
764 
ParseImageTrackInfo(const AVStream & avStream,Meta & format)765 void FFmpegFormatHelper::ParseImageTrackInfo(const AVStream& avStream, Meta &format)
766 {
767     format.Set<Tag::VIDEO_WIDTH>(static_cast<uint32_t>(avStream.codecpar->width));
768     format.Set<Tag::VIDEO_HEIGHT>(static_cast<uint32_t>(avStream.codecpar->height));
769     AVPacket pkt = avStream.attached_pic;
770     if (pkt.size > 0 && pkt.data != nullptr) {
771         std::vector<uint8_t> cover(pkt.size);
772         cover.assign(pkt.data, pkt.data + pkt.size);
773         format.Set<Tag::MEDIA_COVER>(cover);
774     } else {
775         MEDIA_LOG_D("Parse cover failed: " PUBLIC_LOG_D32, pkt.size);
776     }
777 }
778 
ParseAudioTrackInfo(const AVStream & avStream,Meta & format,const AVFormatContext & avFormatContext)779 void FFmpegFormatHelper::ParseAudioTrackInfo(const AVStream& avStream, Meta &format,
780                                              const AVFormatContext& avFormatContext)
781 {
782     int sampelRate = avStream.codecpar->sample_rate;
783     int channels = avStream.codecpar->channels;
784     if (channels <= 0) {
785         channels = avStream.codecpar->ch_layout.nb_channels;
786     }
787     int frameSize = avStream.codecpar->frame_size;
788     if (sampelRate > 0) {
789         format.Set<Tag::AUDIO_SAMPLE_RATE>(static_cast<uint32_t>(sampelRate));
790     } else {
791         MEDIA_LOG_D("Parse sample rate failed: " PUBLIC_LOG_D32, sampelRate);
792     }
793     if (channels > 0) {
794         format.Set<Tag::AUDIO_OUTPUT_CHANNELS>(static_cast<uint32_t>(channels));
795         format.Set<Tag::AUDIO_CHANNEL_COUNT>(static_cast<uint32_t>(channels));
796     } else {
797         MEDIA_LOG_D("Parse channel count failed: " PUBLIC_LOG_D32, channels);
798     }
799     if (frameSize > 0) {
800         format.Set<Tag::AUDIO_SAMPLE_PER_FRAME>(static_cast<uint32_t>(frameSize));
801     } else {
802         MEDIA_LOG_D("Parse frame rate failed: " PUBLIC_LOG_D32, frameSize);
803     }
804     AudioChannelLayout channelLayout = FFMpegConverter::ConvertFFToOHAudioChannelLayoutV2(
805         avStream.codecpar->channel_layout, channels);
806     format.Set<Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT>(channelLayout);
807     format.Set<Tag::AUDIO_CHANNEL_LAYOUT>(channelLayout);
808 
809     AudioSampleFormat fmt = (IsPCMStream(avStream.codecpar->codec_id)) ?
810         FFMpegConverter::ConvertFFMpegAVCodecIdToOHAudioFormat(avStream.codecpar->codec_id) :
811         FFMpegConverter::ConvertFFMpegToOHAudioFormat(static_cast<AVSampleFormat>(avStream.codecpar->format));
812     format.Set<Tag::AUDIO_SAMPLE_FORMAT>(fmt);
813 
814     if (avStream.codecpar->codec_id == AV_CODEC_ID_AAC) {
815         format.Set<Tag::AUDIO_AAC_IS_ADTS>(1);
816     } else if (avStream.codecpar->codec_id == AV_CODEC_ID_AAC_LATM) {
817         format.Set<Tag::AUDIO_AAC_IS_ADTS>(0);
818     }
819     format.Set<Tag::AUDIO_BITS_PER_CODED_SAMPLE>(avStream.codecpar->bits_per_coded_sample);
820     format.Set<Tag::AUDIO_BITS_PER_RAW_SAMPLE>(avStream.codecpar->bits_per_raw_sample);
821 
822     if (avStream.codecpar->codec_id == AV_CODEC_ID_AVS3DA) {
823         format.Set<Tag::AUDIO_CHANNEL_LAYOUT>(AudioChannelLayout::UNKNOWN);
824         format.Set<Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT>(AudioChannelLayout::UNKNOWN);
825         if (avStream.codecpar->ch_layout.order == AV_CHANNEL_ORDER_CUSTOM ||
826             avStream.codecpar->ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC) {
827             ParseAv3aInfo(avStream, format);
828         }
829         ConvertAv3aSampleFormat(avStream, format);
830     }
831 
832     ParseAudioApeTrackInfo(avStream, format, avFormatContext);
833 }
834 
ParseAudioApeTrackInfo(const AVStream & avStream,Meta & format,const AVFormatContext & avFormatContext)835 void FFmpegFormatHelper::ParseAudioApeTrackInfo(const AVStream& avStream, Meta &format,
836                                                 const AVFormatContext& avFormatContext)
837 {
838     if (GetFileTypeByName(avFormatContext) == FileType::APE) {
839         // Ffmpeg ensures that the value is definitely Int type
840         const AVDictionaryEntry *meta = av_dict_get(avFormatContext.metadata, "max_frame_size", NULL, 0);
841         if (meta != nullptr) {
842             int64_t maxFrameSize = std::stoll(meta->value);
843             FALSE_RETURN_MSG(maxFrameSize >= INT32_MIN && maxFrameSize <= INT32_MAX, "Parse max frame size failed");
844             format.Set<Tag::AUDIO_MAX_INPUT_SIZE>(static_cast<int32_t>(maxFrameSize));
845         }
846         meta = av_dict_get(avFormatContext.metadata, "sample_per_frame", NULL, 0);
847         if (meta != nullptr) {
848             int64_t samplePerFrame = std::stoll(meta->value);
849             FALSE_RETURN_MSG(samplePerFrame >= INT32_MIN && samplePerFrame <= INT32_MAX,
850                 "Parse sample per frame failed");
851             format.Set<Tag::AUDIO_SAMPLE_PER_FRAME>(static_cast<int32_t>(samplePerFrame));
852         }
853     }
854 }
855 
ConvertAv3aSampleFormat(const AVStream & avStream,Meta & format)856 void FFmpegFormatHelper::ConvertAv3aSampleFormat(const AVStream& avStream, Meta &format)
857 {
858     AudioSampleFormat fmt;
859     switch (avStream.codecpar->bits_per_raw_sample) {
860         case AV3A_SAMPLE_8BITS: // 8 bits
861             fmt = AudioSampleFormat::SAMPLE_U8;
862             break;
863         case AV3A_SAMPLE_16BITS: // 16 bits
864             fmt = AudioSampleFormat::SAMPLE_S16LE;
865             break;
866         case AV3A_SAMPLE_24BITS: // 24 bits
867             fmt = AudioSampleFormat::SAMPLE_S24LE;
868             break;
869         default:
870             fmt = AudioSampleFormat::INVALID_WIDTH;
871             break;
872     }
873     format.Set<Tag::AUDIO_SAMPLE_FORMAT>(fmt);
874 }
875 
ParseAv3aInfo(const AVStream & avStream,Meta & format)876 void FFmpegFormatHelper::ParseAv3aInfo(const AVStream& avStream, Meta &format)
877 {
878     int channels = avStream.codecpar->channels; // 总通道数
879     AudioChannelLayout channelLayout = AudioChannelLayout::UNKNOWN;
880     int objectNumber = 0; // 对象数量
881     uint64_t channelLayoutMask = 0L;
882     if (avStream.codecpar->ch_layout.order == AV_CHANNEL_ORDER_CUSTOM) {
883         // 获取mask(如果是纯对象模式则不包含声场,返回0L)
884         channelLayoutMask = FfAv3aGetChannelLayoutMask(&avStream.codecpar->ch_layout);
885         objectNumber = FfAv3aGetNbObjects(&avStream.codecpar->ch_layout); // 获取对象数量,如果不包含对象返回0
886         if (channelLayoutMask > 0L) {
887             channelLayout = FFMpegConverter::ConvertAudioVividToOHAudioChannelLayout(
888                 channelLayoutMask, channels - objectNumber);
889             if (channelLayoutMask != static_cast<uint64_t>(channelLayout)) {
890                 MEDIA_LOG_W("Get channel layout failed, use default channel layout");
891             }
892         } else {
893             channelLayout = AudioChannelLayout::UNKNOWN;
894         }
895     } else if (avStream.codecpar->ch_layout.order == AV_CHANNEL_ORDER_AMBISONIC) {
896         int hoaOrder = static_cast<int>(sqrt(channels)) - 1;
897         if (hoaOrder == 1) {
898             channelLayout = AudioChannelLayout::HOA_ORDER1_ACN_SN3D;
899         } else if (hoaOrder == 2) { // hoaOrder is 2
900             channelLayout = AudioChannelLayout::HOA_ORDER2_ACN_SN3D;
901         } else if (hoaOrder == 3) { // hoaOrder is 3
902             channelLayout = AudioChannelLayout::HOA_ORDER3_ACN_SN3D;
903         } else {
904             MEDIA_LOG_W("Get hoa order failed");
905         }
906         format.Set<Tag::AUDIO_HOA_ORDER>(hoaOrder);
907     } else {
908         MEDIA_LOG_W("Get channel layout failed");
909     }
910     format.Set<Tag::AUDIO_OBJECT_NUMBER>(objectNumber);
911     format.Set<Tag::AUDIO_SOUNDBED_CHANNELS_NUMBER>(channels - objectNumber);
912     // 设置一个整个音频内容通道总数
913     format.Set<Tag::AUDIO_OUTPUT_CHANNEL_LAYOUT>(channelLayout);
914     format.Set<Tag::AUDIO_CHANNEL_LAYOUT>(channelLayout);
915     if (channels > 0) {
916         format.Set<Tag::AUDIO_OUTPUT_CHANNELS>(static_cast<uint32_t>(channels));
917         format.Set<Tag::AUDIO_CHANNEL_COUNT>(static_cast<uint32_t>(channels));
918     } else {
919         MEDIA_LOG_D("Parse channel count failed: " PUBLIC_LOG_D32, channels);
920     }
921 }
922 
ParseTimedMetaTrackInfo(const AVStream & avStream,Meta & format)923 void FFmpegFormatHelper::ParseTimedMetaTrackInfo(const AVStream& avStream, Meta &format)
924 {
925     AVDictionaryEntry *valPtr = nullptr;
926     valPtr = av_dict_get(avStream.metadata, "timed_metadata_key", nullptr, AV_DICT_IGNORE_SUFFIX);
927     if (valPtr == nullptr) {
928         MEDIA_LOG_W("Get timed metadata key failed");
929     } else {
930         format.Set<Tag::TIMED_METADATA_KEY>(std::string(valPtr->value));
931     }
932     valPtr = av_dict_get(avStream.metadata, "src_track_id", nullptr, AV_DICT_MATCH_CASE);
933     if (valPtr == nullptr) {
934         MEDIA_LOG_W("Get src track id failed");
935     } else {
936         format.Set<Tag::TIMED_METADATA_SRC_TRACK>(std::stoi(valPtr->value));
937     }
938 }
939 
ParseHvccBoxInfo(const AVStream & avStream,Meta & format)940 void FFmpegFormatHelper::ParseHvccBoxInfo(const AVStream& avStream, Meta &format)
941 {
942     HEVCProfile profile = FFMpegConverter::ConvertFFMpegToOHHEVCProfile(avStream.codecpar->profile);
943     if (profile != HEVCProfile::HEVC_PROFILE_UNKNOW) {
944         format.Set<Tag::VIDEO_H265_PROFILE>(profile);
945         format.Set<Tag::MEDIA_PROFILE>(profile);
946     } else {
947         MEDIA_LOG_D("Parse hevc profile failed: " PUBLIC_LOG_D32, profile);
948     }
949     HEVCLevel level = FFMpegConverter::ConvertFFMpegToOHHEVCLevel(avStream.codecpar->level);
950     if (level != HEVCLevel::HEVC_LEVEL_UNKNOW) {
951         format.Set<Tag::VIDEO_H265_LEVEL>(level);
952         format.Set<Tag::MEDIA_LEVEL>(level);
953     } else {
954         MEDIA_LOG_D("Parse hevc level failed: " PUBLIC_LOG_D32, level);
955     }
956 }
957 
ParseColorBoxInfo(const AVStream & avStream,Meta & format)958 void FFmpegFormatHelper::ParseColorBoxInfo(const AVStream& avStream, Meta &format)
959 {
960     int colorRange = FFMpegConverter::ConvertFFMpegToOHColorRange(avStream.codecpar->color_range);
961     format.Set<Tag::VIDEO_COLOR_RANGE>(static_cast<bool>(colorRange));
962 
963     ColorPrimary colorPrimaries = FFMpegConverter::ConvertFFMpegToOHColorPrimaries(avStream.codecpar->color_primaries);
964     format.Set<Tag::VIDEO_COLOR_PRIMARIES>(colorPrimaries);
965 
966     TransferCharacteristic colorTrans = FFMpegConverter::ConvertFFMpegToOHColorTrans(avStream.codecpar->color_trc);
967     format.Set<Tag::VIDEO_COLOR_TRC>(colorTrans);
968 
969     MatrixCoefficient colorMatrix = FFMpegConverter::ConvertFFMpegToOHColorMatrix(avStream.codecpar->color_space);
970     format.Set<Tag::VIDEO_COLOR_MATRIX_COEFF>(colorMatrix);
971 
972     ChromaLocation chromaLoc = FFMpegConverter::ConvertFFMpegToOHChromaLocation(avStream.codecpar->chroma_location);
973     format.Set<Tag::VIDEO_CHROMA_LOCATION>(chromaLoc);
974 }
975 
ParseHevcInfo(const AVFormatContext & avFormatContext,HevcParseFormat parse,Meta & format)976 void FFmpegFormatHelper::ParseHevcInfo(const AVFormatContext &avFormatContext, HevcParseFormat parse, Meta &format)
977 {
978     if (parse.isHdrVivid) {
979         format.Set<Tag::VIDEO_IS_HDR_VIVID>(true);
980     }
981 
982     format.Set<Tag::VIDEO_COLOR_RANGE>((bool)(parse.colorRange));
983 
984     ColorPrimary colorPrimaries = FFMpegConverter::ConvertFFMpegToOHColorPrimaries(
985         static_cast<AVColorPrimaries>(parse.colorPrimaries));
986     format.Set<Tag::VIDEO_COLOR_PRIMARIES>(colorPrimaries);
987 
988     TransferCharacteristic colorTrans = FFMpegConverter::ConvertFFMpegToOHColorTrans(
989         static_cast<AVColorTransferCharacteristic>(parse.colorTransfer));
990     format.Set<Tag::VIDEO_COLOR_TRC>(colorTrans);
991 
992     MatrixCoefficient colorMatrix = FFMpegConverter::ConvertFFMpegToOHColorMatrix(
993         static_cast<AVColorSpace>(parse.colorMatrixCoeff));
994     format.Set<Tag::VIDEO_COLOR_MATRIX_COEFF>(colorMatrix);
995 
996     ChromaLocation chromaLoc = FFMpegConverter::ConvertFFMpegToOHChromaLocation(
997         static_cast<AVChromaLocation>(parse.chromaLocation));
998     format.Set<Tag::VIDEO_CHROMA_LOCATION>(chromaLoc);
999 
1000     HEVCProfile profile = FFMpegConverter::ConvertFFMpegToOHHEVCProfile(static_cast<int>(parse.profile));
1001     if (profile != HEVCProfile::HEVC_PROFILE_UNKNOW) {
1002         format.Set<Tag::VIDEO_H265_PROFILE>(profile);
1003         format.Set<Tag::MEDIA_PROFILE>(profile);
1004     } else {
1005         MEDIA_LOG_D("Parse hevc profile failed: " PUBLIC_LOG_D32, profile);
1006     }
1007     HEVCLevel level = FFMpegConverter::ConvertFFMpegToOHHEVCLevel(static_cast<int>(parse.level));
1008     if (level != HEVCLevel::HEVC_LEVEL_UNKNOW) {
1009         format.Set<Tag::VIDEO_H265_LEVEL>(level);
1010         format.Set<Tag::MEDIA_LEVEL>(level);
1011     } else {
1012         MEDIA_LOG_D("Parse hevc level failed: " PUBLIC_LOG_D32, level);
1013     }
1014     auto FileType = GetFileTypeByName(avFormatContext);
1015     if (FileType == FileType::MPEGTS ||
1016         FileType == FileType::FLV) {
1017         format.Set<Tag::VIDEO_WIDTH>(static_cast<uint32_t>(parse.picWidInLumaSamples));
1018         format.Set<Tag::VIDEO_HEIGHT>(static_cast<uint32_t>(parse.picHetInLumaSamples));
1019     }
1020 }
1021 
ParseInfoFromMetadata(const AVDictionary * metadata,Meta & format)1022 void FFmpegFormatHelper::ParseInfoFromMetadata(const AVDictionary* metadata, Meta &format)
1023 {
1024     AVDictionaryEntry *valPtr = nullptr;
1025     while ((valPtr = av_dict_get(metadata, "", valPtr, AV_DICT_IGNORE_SUFFIX)) != nullptr) {
1026         std::string tempKey = ToLower(std::string(valPtr->key));
1027         if (tempKey.find("moov_level_meta_key_") == 0) {
1028             MEDIA_LOG_D("UserMeta:" PUBLIC_LOG_S, valPtr->key);
1029             if (g_formatToString.count(tempKey.c_str() + KEY_PREFIX_LEN) > 0 &&
1030                 strlen(valPtr->value) > VALUE_PREFIX_LEN) {
1031                     format.SetData(g_formatToString[tempKey.c_str() + KEY_PREFIX_LEN],
1032                                    std::string(valPtr->value + VALUE_PREFIX_LEN));
1033                 }
1034             continue;
1035         }
1036         if (g_formatToString.count(tempKey) <= 0) {
1037             MEDIA_LOG_D("UnsupportMeta:" PUBLIC_LOG_S, valPtr->key);
1038             continue;
1039         }
1040         MEDIA_LOG_D("SupportMeta:" PUBLIC_LOG_S, valPtr->key);
1041         // ffmpeg use ';' to contact all single value in vorbis-comment, need to remove duplicates
1042         std::string value = RemoveDuplication(std::string(valPtr->value));
1043         format.SetData(g_formatToString[tempKey], value);
1044         if (!IsUTF8(value.c_str()) && IsGBK(value.c_str())) {
1045             std::string resultStr = ConvertGBKToUTF8(value);
1046             if (resultStr.length() > 0) {
1047                 format.SetData(g_formatToString[tempKey], resultStr);
1048             } else {
1049                 MEDIA_LOG_D("Convert utf8 failed");
1050             }
1051         }
1052     }
1053 }
1054 
IsVideoCodecId(const AVCodecID & codecId)1055 bool FFmpegFormatHelper::IsVideoCodecId(const AVCodecID &codecId)
1056 {
1057     if (g_codecIdToMime.count(codecId) == 0) {
1058         return false;
1059     }
1060     return StartWith(std::string(g_codecIdToMime[codecId]).c_str(), "video/");
1061 }
1062 } // namespace Ffmpeg
1063 } // namespace Plugins
1064 } // namespace Media
1065 } // namespace OHOS