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