1 /*
2 * Copyright (c) 2022-2022 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 "Fmpeg_Au_Enc_Config"
17 #include "ffmpeg_au_enc_config.h"
18
19 #include <functional>
20 #include "foundation/log.h"
21 #include "plugin/common/plugin_audio_tags.h"
22 #include "plugins/ffmpeg_adapter/utils/ffmpeg_utils.h"
23
24 namespace {
25 #define ASSIGN_IF_NOT_NULL(exec, target) \
26 do { \
27 auto tmp = (exec); \
28 if (tmp != nullptr) { \
29 (target) = *tmp; \
30 } \
31 } while (0) \
32
33 using namespace OHOS::Media::Plugin;
34 using namespace Ffmpeg;
35 template <typename T>
FindTagInMap(Tag tag,const std::map<Tag,ValueType> & tagStore)36 const T* FindTagInMap(Tag tag, const std::map<Tag, ValueType>& tagStore)
37 {
38 auto ite = tagStore.find(tag);
39 if (ite != tagStore.end() && Any::IsSameTypeWith<T>(ite->second)) {
40 return AnyCast<T>(&ite->second);
41 } else {
42 MEDIA_LOG_W("parameter " PUBLIC_LOG_D32 " is not found or type mismatch", static_cast<int32_t>(tag));
43 return nullptr;
44 }
45 }
46
ConfigAudioCommonAttr(AVCodecContext & codecContext,const std::map<Tag,ValueType> & tagStore)47 void ConfigAudioCommonAttr(AVCodecContext& codecContext, const std::map<Tag, ValueType>& tagStore)
48 {
49 ASSIGN_IF_NOT_NULL(FindTagInMap<uint32_t>(Tag::AUDIO_CHANNELS, tagStore), codecContext.channels);
50 ASSIGN_IF_NOT_NULL(FindTagInMap<uint32_t>(Tag::AUDIO_SAMPLE_RATE, tagStore), codecContext.sample_rate);
51 ASSIGN_IF_NOT_NULL(FindTagInMap<int64_t>(Tag::MEDIA_BITRATE, tagStore), codecContext.bit_rate);
52 auto audioSampleFmtPtr = FindTagInMap<AudioSampleFormat>(Tag::AUDIO_SAMPLE_FORMAT, tagStore);
53 if (audioSampleFmtPtr != nullptr) {
54 auto ffFmt = ConvP2FfSampleFmt(*audioSampleFmtPtr);
55 if (ffFmt != AV_SAMPLE_FMT_NONE) {
56 codecContext.sample_fmt = ffFmt;
57 }
58 }
59 auto layoutPtr = FindTagInMap<AudioChannelLayout>(Tag::AUDIO_CHANNEL_LAYOUT, tagStore);
60 if (layoutPtr != nullptr) {
61 auto ffLayout = ConvertChannelLayoutToFFmpeg(*layoutPtr);
62 codecContext.channel_layout = ffLayout;
63 }
64 }
65
ConfigAacCodec(AVCodecContext & codecContext,const std::map<Tag,ValueType> & tagStore)66 void ConfigAacCodec(AVCodecContext& codecContext, const std::map<Tag, ValueType>& tagStore)
67 {
68 ASSIGN_IF_NOT_NULL(FindTagInMap<uint32_t>(Tag::AUDIO_AAC_LEVEL, tagStore), codecContext.level);
69 if (codecContext.level == FF_LEVEL_UNKNOWN) {
70 codecContext.level = 1; // set to default 1
71 }
72 auto profilePtr = FindTagInMap<AudioAacProfile>(Tag::AUDIO_AAC_PROFILE, tagStore);
73 if (profilePtr != nullptr) {
74 auto ffProfile = ConvAacProfileToFfmpeg(*profilePtr);
75 if (ffProfile != FF_PROFILE_UNKNOWN) {
76 codecContext.profile = ffProfile;
77 }
78 }
79 }
80 using ConfigFunc = std::function<void(AVCodecContext&, const std::map<Tag, ValueType>&)>;
81 std::map<AVCodecID, ConfigFunc> g_ConfigFuncMap = {
82 {AV_CODEC_ID_AAC, ConfigAacCodec},
83 {AV_CODEC_ID_AAC_LATM, ConfigAacCodec}
84 };
85
GetAudioCommonAttr(const AVCodecContext & codecContext,Tag tag,ValueType & outVal)86 void GetAudioCommonAttr(const AVCodecContext& codecContext, Tag tag, ValueType& outVal)
87 {
88 switch (tag) {
89 case Tag::AUDIO_SAMPLE_PER_FRAME:
90 outVal = static_cast<uint32_t>(codecContext.frame_size);
91 break;
92 case Tag::MEDIA_CODEC_CONFIG: {
93 std::vector<uint8_t> extra(codecContext.extradata_size);
94 extra.assign(codecContext.extradata, codecContext.extradata + codecContext.extradata_size);
95 outVal = extra;
96 break;
97 }
98 default:
99 break;
100 }
101 }
102
GetAacAttr(const AVCodecContext & codecContext,Tag tag,ValueType & outVal)103 void GetAacAttr(const AVCodecContext& codecContext, Tag tag, ValueType& outVal)
104 {
105 switch (tag) {
106 case Tag::AUDIO_AAC_LEVEL:
107 outVal = static_cast<uint32_t>(codecContext.level);
108 break;
109 case Tag::AUDIO_AAC_PROFILE:
110 outVal = ConvAacProfileFromFfmpeg(codecContext.profile);
111 break;
112 default:
113 break;
114 }
115 }
116
117 using GetAttrFunc = std::function<void(const AVCodecContext&, Tag, ValueType&)>;
118 std::map<AVCodecID, GetAttrFunc> g_GetAttrFuncMap = {
119 {AV_CODEC_ID_AAC, GetAacAttr},
120 {AV_CODEC_ID_AAC_LATM, GetAacAttr}
121 };
122 }
123
124 namespace OHOS {
125 namespace Media {
126 namespace Plugin {
127 namespace Ffmpeg {
ConfigAudioEncoder(AVCodecContext & codecContext,const std::map<Tag,ValueType> & meta)128 void ConfigAudioEncoder(AVCodecContext& codecContext, const std::map<Tag, ValueType>& meta)
129 {
130 ConfigAudioCommonAttr(codecContext, meta);
131 if (g_ConfigFuncMap.count(codecContext.codec_id) != 0) {
132 g_ConfigFuncMap.at(codecContext.codec_id)(codecContext, meta);
133 }
134 }
GetAudioEncoderParameters(const AVCodecContext & codecContext,Tag tag,Plugin::ValueType & outVal)135 Status GetAudioEncoderParameters(const AVCodecContext& codecContext, Tag tag, Plugin::ValueType& outVal)
136 {
137 outVal.Reset();
138 GetAudioCommonAttr(codecContext, tag, outVal);
139 if (!outVal.HasValue() && g_GetAttrFuncMap.count(codecContext.codec_id) != 0) {
140 g_GetAttrFuncMap.at(codecContext.codec_id)(codecContext, tag, outVal);
141 }
142 if (outVal.HasValue()) {
143 return Status::OK;
144 } else {
145 return Status::ERROR_INVALID_PARAMETER;
146 }
147 }
148 } // Ffmpeg
149 } // namespace Plugin
150 } // namespace Media
151 } // namespace OHOS