1 /*
2 * Copyright (c) 2021-2021 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 #include "ffmpeg_utils.h"
17
18 #include <algorithm>
19 #include <functional>
20
21 #include "foundation/log.h"
22 #include "libavutil/channel_layout.h"
23 #include "libavutil/pixfmt.h"
24 #include "plugin/common/plugin_audio_tags.h"
25 #include "plugin/common/plugin_time.h"
26
27 namespace OHOS {
28 namespace Media {
29 namespace Plugin {
30 namespace Ffmpeg {
31 // Internal definitions
32 namespace {
33 // Histreamer channel layout to ffmpeg channel layout
34 std::map<AudioChannelLayout, uint64_t> g_toFFMPEGChannelLayout = {
35 {AudioChannelLayout::MONO, AV_CH_LAYOUT_MONO},
36 {AudioChannelLayout::STEREO, AV_CH_LAYOUT_STEREO},
37 {AudioChannelLayout::CH_2POINT1, AV_CH_LAYOUT_2POINT1},
38 {AudioChannelLayout::CH_2_1, AV_CH_LAYOUT_2_1},
39 {AudioChannelLayout::SURROUND, AV_CH_LAYOUT_SURROUND},
40 {AudioChannelLayout::CH_3POINT1, AV_CH_LAYOUT_3POINT1},
41 {AudioChannelLayout::CH_4POINT0, AV_CH_LAYOUT_4POINT0},
42 {AudioChannelLayout::CH_4POINT1, AV_CH_LAYOUT_4POINT1},
43 {AudioChannelLayout::CH_2_2, AV_CH_LAYOUT_2_2},
44 {AudioChannelLayout::QUAD, AV_CH_LAYOUT_QUAD},
45 {AudioChannelLayout::CH_5POINT0, AV_CH_LAYOUT_5POINT0},
46 {AudioChannelLayout::CH_5POINT1, AV_CH_LAYOUT_5POINT1},
47 {AudioChannelLayout::CH_5POINT0_BACK, AV_CH_LAYOUT_5POINT0_BACK},
48 {AudioChannelLayout::CH_5POINT1_BACK, AV_CH_LAYOUT_5POINT1_BACK},
49 {AudioChannelLayout::CH_6POINT0, AV_CH_LAYOUT_6POINT0},
50 {AudioChannelLayout::CH_6POINT0_FRONT, AV_CH_LAYOUT_6POINT0_FRONT},
51 {AudioChannelLayout::HEXAGONAL, AV_CH_LAYOUT_HEXAGONAL},
52 {AudioChannelLayout::CH_6POINT1, AV_CH_LAYOUT_6POINT1},
53 {AudioChannelLayout::CH_6POINT1_BACK, AV_CH_LAYOUT_6POINT1_BACK},
54 {AudioChannelLayout::CH_6POINT1_FRONT, AV_CH_LAYOUT_6POINT1_FRONT},
55 {AudioChannelLayout::CH_7POINT0, AV_CH_LAYOUT_7POINT0},
56 {AudioChannelLayout::CH_7POINT0_FRONT, AV_CH_LAYOUT_7POINT0_FRONT},
57 {AudioChannelLayout::CH_7POINT1, AV_CH_LAYOUT_7POINT1},
58 {AudioChannelLayout::CH_7POINT1_WIDE, AV_CH_LAYOUT_7POINT1_WIDE},
59 {AudioChannelLayout::CH_7POINT1_WIDE_BACK, AV_CH_LAYOUT_7POINT1_WIDE_BACK},
60 {AudioChannelLayout::OCTAGONAL, AV_CH_LAYOUT_OCTAGONAL},
61 {AudioChannelLayout::HEXADECAGONAL, AV_CH_LAYOUT_HEXADECAGONAL},
62 {AudioChannelLayout::STEREO_DOWNMIX, AV_CH_LAYOUT_STEREO_DOWNMIX},
63 };
64
65 // ffmpeg channel layout to histreamer channel layout
66 std::map<uint64_t, AudioChannelMasks> g_fromFFMPEGChannelLayout = {
67 {AV_CH_FRONT_LEFT, AudioChannelMasks::FRONT_LEFT},
68 {AV_CH_FRONT_RIGHT, AudioChannelMasks::FRONT_RIGHT},
69 {AV_CH_FRONT_CENTER, AudioChannelMasks::FRONT_CENTER},
70 {AV_CH_LOW_FREQUENCY, AudioChannelMasks::LOW_FREQUENCY},
71 {AV_CH_BACK_LEFT, AudioChannelMasks::BACK_LEFT},
72 {AV_CH_BACK_RIGHT, AudioChannelMasks::BACK_RIGHT},
73 {AV_CH_FRONT_LEFT_OF_CENTER, AudioChannelMasks::FRONT_LEFT_OF_CENTER},
74 {AV_CH_FRONT_RIGHT_OF_CENTER, AudioChannelMasks::FRONT_RIGHT_OF_CENTER},
75 {AV_CH_BACK_CENTER, AudioChannelMasks::BACK_CENTER},
76 {AV_CH_SIDE_LEFT, AudioChannelMasks::SIDE_LEFT},
77 {AV_CH_SIDE_RIGHT, AudioChannelMasks::SIDE_RIGHT},
78 {AV_CH_TOP_CENTER, AudioChannelMasks::TOP_CENTER},
79 {AV_CH_TOP_FRONT_LEFT, AudioChannelMasks::TOP_FRONT_LEFT},
80 {AV_CH_TOP_FRONT_CENTER, AudioChannelMasks::TOP_FRONT_CENTER},
81 {AV_CH_TOP_FRONT_RIGHT, AudioChannelMasks::TOP_FRONT_RIGHT},
82 {AV_CH_TOP_BACK_LEFT, AudioChannelMasks::TOP_BACK_LEFT},
83 {AV_CH_TOP_BACK_CENTER, AudioChannelMasks::TOP_BACK_CENTER},
84 {AV_CH_TOP_BACK_RIGHT, AudioChannelMasks::TOP_BACK_RIGHT},
85 {AV_CH_STEREO_LEFT, AudioChannelMasks::STEREO_LEFT},
86 {AV_CH_STEREO_RIGHT, AudioChannelMasks::STEREO_RIGHT},
87 {AV_CH_WIDE_LEFT, AudioChannelMasks::WIDE_LEFT},
88 {AV_CH_WIDE_RIGHT, AudioChannelMasks::WIDE_RIGHT},
89 {AV_CH_SURROUND_DIRECT_LEFT, AudioChannelMasks::SURROUND_DIRECT_LEFT},
90 {AV_CH_SURROUND_DIRECT_RIGHT, AudioChannelMasks::SURROUND_DIRECT_RIGHT},
91 {AV_CH_LOW_FREQUENCY_2, AudioChannelMasks::LOW_FREQUENCY_2},
92 {AV_CH_TOP_SIDE_LEFT, AudioChannelMasks::TOP_SIDE_LEFT},
93 {AV_CH_TOP_SIDE_RIGHT, AudioChannelMasks::TOP_SIDE_RIGHT},
94 {AV_CH_BOTTOM_FRONT_CENTER, AudioChannelMasks::BOTTOM_FRONT_CENTER},
95 {AV_CH_BOTTOM_FRONT_LEFT, AudioChannelMasks::BOTTOM_FRONT_LEFT},
96 {AV_CH_BOTTOM_FRONT_RIGHT, AudioChannelMasks::BOTTOM_FRONT_RIGHT},
97 };
98
99 const std::map<std::string, Tag> g_tagMap = {
100 {"title", Tag::MEDIA_TITLE},
101 {"artist", Tag::MEDIA_ARTIST},
102 {"lyricist", Tag::MEDIA_LYRICIST},
103 {"album", Tag::MEDIA_ALBUM},
104 {"album-artist", Tag::MEDIA_ALBUM_ARTIST},
105 {"date", Tag::MEDIA_DATE},
106 {"comment", Tag::MEDIA_COMMENT},
107 {"genre", Tag::MEDIA_GENRE},
108 {"copyright", Tag::MEDIA_COPYRIGHT},
109 {"language", Tag::MEDIA_LANGUAGE},
110 {"description", Tag::MEDIA_DESCRIPTION},
111 {"lyrics", Tag::MEDIA_LYRICS},
112 };
113
114 std::map<std::string, std::function<void(TagMap&, AVDictionaryEntry*)>> g_MediaMap = {
__anonc214609a0202() 115 {"title", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_TITLE>(tag->value); }},
__anonc214609a0302() 116 {"artist", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_ARTIST>(tag->value); }},
__anonc214609a0402() 117 {"lyricist", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_LYRICIST>(tag->value); }},
__anonc214609a0502() 118 {"album", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_ALBUM>(tag->value); }},
__anonc214609a0602() 119 {"album-artist", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_ALBUM_ARTIST>(tag->value); }},
__anonc214609a0702() 120 {"date", [](TagMap& meta, AVDictionaryEntry* tag) {
121 uint32_t year;
122 uint32_t month;
123 uint32_t day = 0;
124 if (sscanf_s(tag->value, "%04u-%02u-%02u", &year, &month, &day) == 3) { // 3
125 meta.Insert<Tag::MEDIA_DATE>(RemoveDelimiter(tag->value, '-'));
126 }
127 }},
__anonc214609a0802() 128 {"comment", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_COMMENT>(tag->value); }},
__anonc214609a0902() 129 {"genre", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_GENRE>(tag->value); }},
__anonc214609a0a02() 130 {"copyright", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_COPYRIGHT>(tag->value); }},
__anonc214609a0b02() 131 {"language", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_LANGUAGE>(tag->value); }},
__anonc214609a0c02() 132 {"description", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_DESCRIPTION>(tag->value); }},
__anonc214609a0d02() 133 {"lyrics", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_LYRICS>(tag->value); }}
134 };
135
136 const std::vector<std::pair<AudioAacProfile, int32_t>> g_AacProfileMap = {
137 {AudioAacProfile::MAIN, FF_PROFILE_AAC_MAIN},
138 {AudioAacProfile::LC, FF_PROFILE_AAC_LOW},
139 {AudioAacProfile::SSR, FF_PROFILE_AAC_SSR},
140 {AudioAacProfile::LTP, FF_PROFILE_AAC_LTP},
141 {AudioAacProfile::HE, FF_PROFILE_AAC_HE},
142 {AudioAacProfile::HE_PS, FF_PROFILE_AAC_HE_V2},
143 {AudioAacProfile::LD, FF_PROFILE_AAC_LD},
144 {AudioAacProfile::ELD, FF_PROFILE_AAC_ELD},
145 };
146
147 // Histreamer pixel format to ffmpeg pixel format
148 std::map<VideoPixelFormat, AVPixelFormat> g_pixelFormatMap = {
149 {VideoPixelFormat::YUV410P, AV_PIX_FMT_YUV410P},
150 {VideoPixelFormat::YUV411P, AV_PIX_FMT_YUV411P},
151 {VideoPixelFormat::YUV420P, AV_PIX_FMT_YUV420P},
152 {VideoPixelFormat::NV12, AV_PIX_FMT_NV12},
153 {VideoPixelFormat::NV21, AV_PIX_FMT_NV21},
154 {VideoPixelFormat::YUYV422, AV_PIX_FMT_YUYV422},
155 {VideoPixelFormat::YUV422P, AV_PIX_FMT_YUV422P},
156 {VideoPixelFormat::YUV444P, AV_PIX_FMT_YUV444P},
157 {VideoPixelFormat::RGBA, AV_PIX_FMT_RGBA},
158 {VideoPixelFormat::ARGB, AV_PIX_FMT_ARGB},
159 {VideoPixelFormat::ABGR, AV_PIX_FMT_ABGR},
160 {VideoPixelFormat::BGRA, AV_PIX_FMT_BGRA},
161 {VideoPixelFormat::RGB24, AV_PIX_FMT_RGB24},
162 {VideoPixelFormat::BGR24, AV_PIX_FMT_BGR24},
163 {VideoPixelFormat::PAL8, AV_PIX_FMT_PAL8},
164 {VideoPixelFormat::GRAY8, AV_PIX_FMT_GRAY8},
165 {VideoPixelFormat::MONOWHITE, AV_PIX_FMT_MONOWHITE},
166 {VideoPixelFormat::MONOBLACK, AV_PIX_FMT_MONOBLACK},
167 {VideoPixelFormat::YUVJ420P, AV_PIX_FMT_YUVJ420P},
168 {VideoPixelFormat::YUVJ422P, AV_PIX_FMT_YUVJ422P},
169 {VideoPixelFormat::YUVJ444P, AV_PIX_FMT_YUVJ444P},
170 };
171
172 std::map<VideoH264Profile, int32_t> g_H264ProfileMap = {
173 {VideoH264Profile::BASELINE, FF_PROFILE_H264_BASELINE},
174 {VideoH264Profile::MAIN, FF_PROFILE_H264_MAIN},
175 {VideoH264Profile::EXTENDED, FF_PROFILE_H264_EXTENDED},
176 {VideoH264Profile::HIGH, FF_PROFILE_H264_HIGH},
177 {VideoH264Profile::HIGH10, FF_PROFILE_H264_HIGH_10},
178 {VideoH264Profile::HIGH422, FF_PROFILE_H264_HIGH_422},
179 {VideoH264Profile::HIGH444, FF_PROFILE_H264_HIGH_444}
180 };
181 std::vector<std::pair<AudioSampleFormat, AVSampleFormat>> g_pFfSampleFmtMap = {
182 {AudioSampleFormat::U8, AVSampleFormat::AV_SAMPLE_FMT_U8},
183 {AudioSampleFormat::U8P, AVSampleFormat::AV_SAMPLE_FMT_U8P},
184 {AudioSampleFormat::S16, AVSampleFormat::AV_SAMPLE_FMT_S16},
185 {AudioSampleFormat::S16P, AVSampleFormat::AV_SAMPLE_FMT_S16P},
186 {AudioSampleFormat::S32, AVSampleFormat::AV_SAMPLE_FMT_S32},
187 {AudioSampleFormat::S32P, AVSampleFormat::AV_SAMPLE_FMT_S32P},
188 {AudioSampleFormat::F32, AVSampleFormat::AV_SAMPLE_FMT_FLT},
189 {AudioSampleFormat::F32P, AVSampleFormat::AV_SAMPLE_FMT_FLTP},
190 {AudioSampleFormat::F64, AVSampleFormat::AV_SAMPLE_FMT_DBL},
191 {AudioSampleFormat::F64P, AVSampleFormat::AV_SAMPLE_FMT_DBLP},
192 {AudioSampleFormat::S64, AVSampleFormat::AV_SAMPLE_FMT_S64},
193 {AudioSampleFormat::S64P, AVSampleFormat::AV_SAMPLE_FMT_S64P},
194 };
195 } // namespace
196
AVStrError(int errnum)197 std::string AVStrError(int errnum)
198 {
199 char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0};
200 av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
201 return std::string(errbuf);
202 }
203
ConvertTimeFromFFmpeg(int64_t pts,AVRational base)204 int64_t ConvertTimeFromFFmpeg(int64_t pts, AVRational base)
205 {
206 int64_t out;
207 if (pts == AV_NOPTS_VALUE) {
208 out = -1;
209 } else {
210 AVRational bq = {1, HST_SECOND};
211 out = av_rescale_q(pts, base, bq);
212 }
213 return out;
214 }
215
ConvertTimeToFFmpeg(int64_t timestampUs,AVRational base)216 int64_t ConvertTimeToFFmpeg(int64_t timestampUs, AVRational base)
217 {
218 int64_t result;
219 if (base.num == 0) {
220 result = AV_NOPTS_VALUE;
221 } else {
222 AVRational bq = {1, HST_SECOND};
223 result = av_rescale_q(timestampUs, bq, base);
224 }
225 return result;
226 }
227
FillAVPicture(AVFrame * picture,uint8_t * ptr,enum AVPixelFormat pixFmt,int width,int height)228 int FillAVPicture(AVFrame* picture, uint8_t* ptr, enum AVPixelFormat pixFmt, int width, int height)
229 {
230 (void)picture;
231 (void)ptr;
232 (void)pixFmt;
233 (void)width;
234 (void)height;
235 return 0;
236 }
237
GetAVPictureSize(int pixFmt,int width,int height)238 int GetAVPictureSize(int pixFmt, int width, int height)
239 {
240 AVFrame dummy;
241 return FillAVPicture(&dummy, nullptr, static_cast<AVPixelFormat>(pixFmt), width, height);
242 }
243
RemoveDelimiter(const char * str,char delimiter)244 std::string RemoveDelimiter(const char* str, char delimiter)
245 {
246 std::string tmp(str);
247 RemoveDelimiter(delimiter, tmp);
248 return tmp;
249 }
250
RemoveDelimiter(char delimiter,std::string & str)251 void RemoveDelimiter(char delimiter, std::string& str)
252 {
253 for (auto it = std::find(str.begin(), str.end(), delimiter); it != str.end();) {
254 it = str.erase(it);
255 if (*it != delimiter) {
256 it = std::find(it, str.end(), delimiter);
257 }
258 }
259 }
260
ReplaceDelimiter(const std::string & delmiters,char newDelimiter,std::string & str)261 void ReplaceDelimiter(const std::string& delmiters, char newDelimiter, std::string& str)
262 {
263 for (auto it = str.begin(); it != str.end(); ++it) {
264 if (delmiters.find(newDelimiter) != std::string::npos) {
265 *it = newDelimiter;
266 }
267 }
268 }
269
SplitString(const char * str,char delimiter)270 std::vector<std::string> SplitString(const char* str, char delimiter)
271 {
272 std::vector<std::string> rtv;
273 if (str) {
274 SplitString(std::string(str), delimiter).swap(rtv);
275 }
276 return rtv;
277 }
278
SplitString(const std::string & str,char delimiter)279 std::vector<std::string> SplitString(const std::string& str, char delimiter)
280 {
281 if (str.empty()) {
282 return {};
283 }
284 std::vector<std::string> rtv;
285 std::string::size_type startPos = 0;
286 std::string::size_type endPos = str.find_first_of(delimiter, startPos);
287 while (startPos != endPos) {
288 rtv.emplace_back(str.substr(startPos, endPos - startPos));
289 if (endPos == std::string::npos) {
290 break;
291 }
292 startPos = endPos + 1;
293 endPos = str.find_first_of(delimiter, startPos);
294 }
295 return rtv;
296 }
297
ConvFf2PSampleFmt(AVSampleFormat sampleFormat)298 AudioSampleFormat ConvFf2PSampleFmt(AVSampleFormat sampleFormat)
299 {
300 auto ite = std::find_if(g_pFfSampleFmtMap.begin(), g_pFfSampleFmtMap.end(),
301 [&sampleFormat] (const std::pair<AudioSampleFormat, AVSampleFormat>& item) ->bool {
302 return item.second == sampleFormat;
303 });
304 if (ite == g_pFfSampleFmtMap.end()) {
305 return AudioSampleFormat::NONE;
306 }
307 return ite->first;
308 }
309
ConvP2FfSampleFmt(AudioSampleFormat sampleFormat)310 AVSampleFormat ConvP2FfSampleFmt(AudioSampleFormat sampleFormat)
311 {
312 auto ite = std::find_if(g_pFfSampleFmtMap.begin(), g_pFfSampleFmtMap.end(),
313 [&sampleFormat] (const std::pair<AudioSampleFormat, AVSampleFormat>& item) ->bool {
314 return item.first == sampleFormat;
315 });
316 if (ite == g_pFfSampleFmtMap.end()) {
317 return AV_SAMPLE_FMT_NONE;
318 }
319 return ite->second;
320 }
321
GetDefaultChannelLayout(int channels)322 AudioChannelLayout GetDefaultChannelLayout(int channels)
323 {
324 AudioChannelLayout ret;
325 switch (channels) {
326 case 1: { // 1: MONO
327 ret = AudioChannelLayout::MONO;
328 break;
329 }
330 case 2: { // 2: STEREO
331 ret = AudioChannelLayout::STEREO;
332 break;
333 }
334 case 4: { // 4: CH_4POINT0
335 ret = AudioChannelLayout::CH_4POINT0;
336 break;
337 }
338 case 6: { // 6: CH_5POINT1
339 ret = AudioChannelLayout::CH_5POINT1;
340 break;
341 }
342 case 8: { // 8: CH_5POINT1POINT2 or CH_7POINT1
343 ret = AudioChannelLayout::CH_5POINT1POINT2;
344 break;
345 }
346 case 10: { // 10: CH_7POINT1POINT2 or CH_5POINT1POINT4 ?
347 ret = AudioChannelLayout::CH_7POINT1POINT2;
348 break;
349 }
350 case 12: { // 12: CH_7POINT1POINT4 or CH_10POINT2 ?
351 ret = AudioChannelLayout::CH_7POINT1POINT4;
352 break;
353 }
354 case 14: { // 14: CH_9POINT1POINT4
355 ret = AudioChannelLayout::CH_9POINT1POINT4;
356 break;
357 }
358 case 16: { // 16: CH_9POINT1POINT6
359 ret = AudioChannelLayout::CH_9POINT1POINT6;
360 break;
361 }
362 case 24: { // 24: CH_22POINT2
363 ret = AudioChannelLayout::CH_22POINT2;
364 break;
365 }
366 default: {
367 ret = AudioChannelLayout::UNKNOWN;
368 break;
369 }
370 }
371 return ret;
372 }
373
ConvertChannelLayoutFromFFmpeg(int channels,uint64_t ffChannelLayout)374 AudioChannelLayout ConvertChannelLayoutFromFFmpeg(int channels, uint64_t ffChannelLayout)
375 {
376 uint64_t channelLayout = 0;
377 uint64_t mask;
378 for (uint8_t bitPos = 0, channelNum = 0; (bitPos < 64) && (channelNum < channels); ++bitPos) { // 64
379 mask = 1ULL << bitPos;
380 if (!(mask & ffChannelLayout)) {
381 continue;
382 }
383 channelNum++;
384 auto it = g_fromFFMPEGChannelLayout.find(mask);
385 if (it != g_fromFFMPEGChannelLayout.end()) {
386 channelLayout |= static_cast<uint64_t>(it->second);
387 } else {
388 MEDIA_LOG_W("unsupported audio channel layout: " PUBLIC_LOG_U64, mask);
389 }
390 }
391 auto ret = static_cast<AudioChannelLayout>(channelLayout);
392 if (ffChannelLayout == 0) {
393 ret = GetDefaultChannelLayout(channels);
394 }
395 return ret;
396 }
397
ConvertChannelLayoutToFFmpeg(AudioChannelLayout channelLayout)398 uint64_t ConvertChannelLayoutToFFmpeg(AudioChannelLayout channelLayout)
399 {
400 auto it = g_toFFMPEGChannelLayout.find(channelLayout);
401 if (it == g_toFFMPEGChannelLayout.end()) {
402 MEDIA_LOG_E("ConvertChannelLayoutToFFmpeg: unknown audio channel layout: " PUBLIC_LOG_U64, channelLayout);
403 return 0;
404 }
405 return it->second;
406 }
407
FindAvMetaNameByTag(Tag tag,std::string & metaName)408 bool FindAvMetaNameByTag(Tag tag, std::string& metaName)
409 {
410 for (const auto& pair : g_tagMap) {
411 if (pair.second == tag) {
412 metaName = pair.first;
413 return true;
414 }
415 }
416 return false;
417 }
418
InsertMediaTag(TagMap & meta,AVDictionaryEntry * tag)419 void InsertMediaTag(TagMap& meta, AVDictionaryEntry* tag)
420 {
421 for (auto e : g_MediaMap) {
422 if (e.first == tag->key) {
423 e.second(meta, tag);
424 return;
425 }
426 }
427 }
428
ConvAacProfileFromFfmpeg(int32_t ffmpegProfile)429 AudioAacProfile ConvAacProfileFromFfmpeg(int32_t ffmpegProfile)
430 {
431 auto ite = std::find_if(g_AacProfileMap.begin(), g_AacProfileMap.end(),
432 [&] (const std::pair<AudioAacProfile, int32_t>& tmp) -> bool {
433 return tmp.second == ffmpegProfile;
434 });
435 return ite == g_AacProfileMap.end() ? AudioAacProfile::NONE : ite->first;
436 }
437
ConvAacProfileToFfmpeg(AudioAacProfile profile)438 int32_t ConvAacProfileToFfmpeg(AudioAacProfile profile)
439 {
440 auto ite = std::find_if(g_AacProfileMap.begin(), g_AacProfileMap.end(),
441 [&] (const std::pair<AudioAacProfile, int32_t>& tmp) -> bool {
442 return tmp.first == profile;
443 });
444 return ite == g_AacProfileMap.end() ? FF_PROFILE_UNKNOWN : ite->second;
445 }
446
ConvertPixelFormatFromFFmpeg(int32_t ffmpegPixelFormat)447 VideoPixelFormat ConvertPixelFormatFromFFmpeg(int32_t ffmpegPixelFormat)
448 {
449 auto iter = std::find_if(g_pixelFormatMap.begin(), g_pixelFormatMap.end(),
450 [&] (const std::pair<VideoPixelFormat, AVPixelFormat>& tmp) -> bool {
451 return tmp.second == ffmpegPixelFormat;
452 });
453 return iter == g_pixelFormatMap.end() ? VideoPixelFormat::UNKNOWN : iter->first;
454 }
455
ConvertPixelFormatToFFmpeg(VideoPixelFormat pixelFormat)456 AVPixelFormat ConvertPixelFormatToFFmpeg(VideoPixelFormat pixelFormat)
457 {
458 auto iter = std::find_if(g_pixelFormatMap.begin(), g_pixelFormatMap.end(),
459 [&] (const std::pair<VideoPixelFormat, AVPixelFormat>& tmp) -> bool {
460 return tmp.first == pixelFormat;
461 });
462 return iter == g_pixelFormatMap.end() ? AV_PIX_FMT_NONE : iter->second;
463 }
464
IsYuvFormat(AVPixelFormat format)465 bool IsYuvFormat(AVPixelFormat format)
466 {
467 return (format == AV_PIX_FMT_YUV420P || format == AV_PIX_FMT_NV12 || format == AV_PIX_FMT_NV21 ||
468 format == AV_PIX_FMT_YUYV422 || format == AV_PIX_FMT_YUV422P || format == AV_PIX_FMT_YUV444P ||
469 format == AV_PIX_FMT_YUV410P || format == AV_PIX_FMT_YUV411P || format == AV_PIX_FMT_YUVJ420P ||
470 format == AV_PIX_FMT_YUVJ422P || format == AV_PIX_FMT_YUVJ444P);
471 }
472
IsRgbFormat(AVPixelFormat format)473 bool IsRgbFormat(AVPixelFormat format)
474 {
475 return (format == AV_PIX_FMT_ABGR || format == AV_PIX_FMT_ARGB || format == AV_PIX_FMT_RGBA ||
476 format == AV_PIX_FMT_BGRA || format == AV_PIX_FMT_RGB24 || format == AV_PIX_FMT_BGR24);
477 }
478
ConvH264ProfileFromFfmpeg(int32_t ffmpegProfile)479 VideoH264Profile ConvH264ProfileFromFfmpeg(int32_t ffmpegProfile)
480 {
481 auto iter = std::find_if(g_H264ProfileMap.begin(), g_H264ProfileMap.end(),
482 [&] (const std::pair<VideoH264Profile, int32_t>& tmp) -> bool {
483 return tmp.second == ffmpegProfile;
484 });
485 return (iter == g_H264ProfileMap.end()) ? VideoH264Profile::UNKNOWN : iter->first;
486 }
487
ConvH264ProfileToFfmpeg(VideoH264Profile profile)488 int32_t ConvH264ProfileToFfmpeg(VideoH264Profile profile)
489 {
490 auto iter = std::find_if(g_H264ProfileMap.begin(), g_H264ProfileMap.end(),
491 [&] (const std::pair<VideoH264Profile, int32_t>& tmp) -> bool {
492 return tmp.first == profile;
493 });
494 return (iter == g_H264ProfileMap.end()) ? FF_PROFILE_UNKNOWN : iter->second;
495 }
496
Init(const ResamplePara & resamplePara)497 Status Resample::Init(const ResamplePara& resamplePara)
498 {
499 resamplePara_ = resamplePara;
500 #if defined(_WIN32) || !defined(OHOS_LITE)
501 if (resamplePara_.bitsPerSample != 8 && resamplePara_.bitsPerSample != 24) { // 8 24
502 auto destFrameSize = av_samples_get_buffer_size(nullptr, resamplePara_.channels,
503 resamplePara_.destSamplesPerFrame, resamplePara_.destFmt, 0);
504 resampleCache_.reserve(destFrameSize);
505 resampleChannelAddr_.reserve(resamplePara_.channels);
506 auto tmp = resampleChannelAddr_.data();
507 av_samples_fill_arrays(tmp, nullptr, resampleCache_.data(), resamplePara_.channels,
508 resamplePara_.destSamplesPerFrame, resamplePara_.destFmt, 0);
509 SwrContext* swrContext = swr_alloc();
510 if (swrContext == nullptr) {
511 MEDIA_LOG_E("cannot allocate swr context");
512 return Status::ERROR_NO_MEMORY;
513 }
514 swrContext = swr_alloc_set_opts(swrContext, resamplePara_.channelLayout, resamplePara_.destFmt,
515 resamplePara_.sampleRate, resamplePara_.channelLayout,
516 resamplePara_.srcFfFmt, resamplePara_.sampleRate, 0, nullptr);
517 if (swr_init(swrContext) != 0) {
518 MEDIA_LOG_E("swr init error");
519 return Status::ERROR_UNKNOWN;
520 }
521 swrCtx_ = std::shared_ptr<SwrContext>(swrContext, [](SwrContext *ptr) {
522 if (ptr) {
523 swr_free(&ptr);
524 }
525 });
526 }
527 #endif
528 return Status::OK;
529 }
530
Convert(const uint8_t * srcBuffer,const size_t srcLength,uint8_t * & destBuffer,size_t & destLength)531 Status Resample::Convert(const uint8_t* srcBuffer, const size_t srcLength, uint8_t*& destBuffer, size_t& destLength)
532 {
533 #if defined(_WIN32) || !defined(OHOS_LITE)
534 if (resamplePara_.bitsPerSample == 8) { // 8
535 FALSE_RETURN_V_MSG(resamplePara_.destFmt == AV_SAMPLE_FMT_S16, Status::ERROR_UNIMPLEMENTED,
536 "resample 8bit to other format can not support");
537 destLength = srcLength * 2; // 2
538 resampleCache_.reserve(destLength);
539 resampleCache_.assign(destLength, 0);
540 for (size_t i {0}; i < destLength / 2; i++) { // 2
541 memcpy_s(&resampleCache_[0] + i * 2 + 1, 1, srcBuffer + i, 1); // 0 2 1
542 *(&resampleCache_[0] + i * 2 + 1) += 0x80; // 0x80
543 }
544 destBuffer = resampleCache_.data();
545 } else if (resamplePara_.bitsPerSample == 24) { // 24
546 FALSE_RETURN_V_MSG(resamplePara_.destFmt == AV_SAMPLE_FMT_S16, Status::ERROR_UNIMPLEMENTED,
547 "resample 24bit to other format can not support");
548 destLength = srcLength / 3 * 2; // 3 2
549 resampleCache_.reserve(destLength);
550 resampleCache_.assign(destLength, 0);
551 for (size_t i = 0; i < destLength / 2; i++) { // 2
552 memcpy_s(&resampleCache_[0] + i * 2, 2, srcBuffer + i * 3 + 1, 2); // 2 3 1
553 }
554 destBuffer = resampleCache_.data();
555 } else {
556 size_t lineSize = srcLength / resamplePara_.channels;
557 std::vector<const uint8_t*> tmpInput(resamplePara_.channels);
558 tmpInput[0] = srcBuffer;
559 if (av_sample_fmt_is_planar(resamplePara_.srcFfFmt)) {
560 for (size_t i = 1; i < tmpInput.size(); ++i) {
561 tmpInput[i] = tmpInput[i-1] + lineSize;
562 }
563 }
564 auto samples = lineSize / av_get_bytes_per_sample(resamplePara_.srcFfFmt);
565 auto res = swr_convert(swrCtx_.get(), resampleChannelAddr_.data(), resamplePara_.destSamplesPerFrame,
566 tmpInput.data(), samples);
567 if (res < 0) {
568 MEDIA_LOG_E("resample input failed");
569 destLength = 0;
570 } else {
571 destBuffer = resampleCache_.data();
572 destLength = res * av_get_bytes_per_sample(resamplePara_.destFmt) * resamplePara_.channels;
573 }
574 }
575 #endif
576 return Status::OK;
577 }
578 } // namespace Ffmpeg
579 } // namespace Plugin
580 } // namespace Media
581 } // namespace OHOS
582