• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = {
__anonea6f63db0202() 115     {"title", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_TITLE>(tag->value); }},
__anonea6f63db0302() 116     {"artist", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_ARTIST>(tag->value); }},
__anonea6f63db0402() 117     {"lyricist", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_LYRICIST>(tag->value); }},
__anonea6f63db0502() 118     {"album", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_ALBUM>(tag->value); }},
__anonea6f63db0602() 119     {"album-artist", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_ALBUM_ARTIST>(tag->value); }},
__anonea6f63db0702() 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     }},
__anonea6f63db0802() 128     {"comment", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_COMMENT>(tag->value); }},
__anonea6f63db0902() 129     {"genre", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_GENRE>(tag->value); }},
__anonea6f63db0a02() 130     {"copyright", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_COPYRIGHT>(tag->value); }},
__anonea6f63db0b02() 131     {"language", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_LANGUAGE>(tag->value); }},
__anonea6f63db0c02() 132     {"description", [](TagMap& meta, AVDictionaryEntry* tag) {meta.Insert<Tag::MEDIA_DESCRIPTION>(tag->value); }},
__anonea6f63db0d02() 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