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 "LiteAACDecoderPlugin"
17
18 #include "lite_aac_decoder_plugin.h"
19 #include <cstring>
20 #include <map>
21 #include <set>
22 #include "foundation/log.h"
23 #include "foundation/utils/constants.h"
24 #include "plugin/common/plugin_audio_tags.h"
25 #include "plugin/common/plugin_buffer.h"
26 #include "plugin/common/plugin_caps_builder.h"
27 #include "plugin/interface/codec_plugin.h"
28 #include "securec.h"
29
30 namespace {
31 using namespace OHOS::Media::Plugin;
32 void UpdatePluginDefinition(CodecPluginDef& definition);
33 constexpr int8_t RANK_MAX = 100;
34 constexpr unsigned int BUFFER_ITEM_CNT = 6;
35
LiteAACDecoderCreator(const std::string & name)36 std::shared_ptr<CodecPlugin> LiteAACDecoderCreator(const std::string& name)
37 {
38 return std::make_shared<LiteAacPlugin::LiteAACDecoderPlugin>(name);
39 }
40
RegisterDecoderPlugin(const std::shared_ptr<Register> & reg)41 Status RegisterDecoderPlugin(const std::shared_ptr<Register>& reg)
42 {
43 MEDIA_LOG_D("RegisterDecoderPlugin called.");
44 if (!reg) {
45 MEDIA_LOG_E("RegisterDecoderPlugin failed due to null pointer for reg.");
46 return Status::ERROR_INVALID_PARAMETER;
47 }
48
49 CodecPluginDef definition;
50 definition.name = "LiteAACDecoderPlugin";
51 definition.pluginType = PluginType::AUDIO_DECODER;
52 definition.rank = RANK_MAX;
53 definition.creator = LiteAACDecoderCreator;
54 UpdatePluginDefinition(definition);
55 if (reg->AddPlugin(definition) != Status::OK) {
56 MEDIA_LOG_W("register lite aac decoder plugin failed");
57 }
58 return Status::OK;
59 }
60
UpdateInCaps(CodecPluginDef & definition)61 void UpdateInCaps(CodecPluginDef& definition)
62 {
63 CapabilityBuilder capBuilder;
64 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_AAC);
65 capBuilder.SetAudioSampleRateList({96000, 88200, 64000, 48000, 44100, 32000, 24000,
66 22050, 16000, 12000, 11025, 8000, 7350});
67 capBuilder.SetAudioChannelLayoutList({AudioChannelLayout::MONO,
68 AudioChannelLayout::STEREO});
69 capBuilder.SetAudioSampleFormatList({AudioSampleFormat::S16});
70 capBuilder.SetAudioAacProfileList({AudioAacProfile::LC});
71 capBuilder.SetAudioAacStreamFormatList({AudioAacStreamFormat::MP4ADTS});
72 definition.inCaps.push_back(capBuilder.Build());
73 }
74
UpdateOutCaps(CodecPluginDef & definition)75 void UpdateOutCaps(CodecPluginDef& definition)
76 {
77 CapabilityBuilder capBuilder;
78 capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_RAW);
79 capBuilder.SetAudioSampleFormatList({AudioSampleFormat::S16});
80 definition.outCaps.emplace_back(capBuilder.Build());
81 }
82
UpdatePluginDefinition(CodecPluginDef & definition)83 void UpdatePluginDefinition(CodecPluginDef& definition)
84 {
85 UpdateInCaps(definition);
86 UpdateOutCaps(definition);
87 }
88 }
89
__anon87eac9160202null90 PLUGIN_DEFINITION(LiteAACDecoder, LicenseType::APACHE_V2, RegisterDecoderPlugin, [] {});
91
92 namespace OHOS {
93 namespace Media {
94 namespace Plugin {
95 namespace LiteAacPlugin {
96 constexpr unsigned int AAC_DECODER_SAMPLE_SIZE = sizeof(signed short);
97 constexpr unsigned int PCM_SIZE = 2048 * AAC_DECODER_SAMPLE_SIZE;
98 constexpr unsigned int FRAME_MAX_COUNT = 16 * 1024;
99
LiteAACDecoderPlugin(std::string name)100 LiteAACDecoderPlugin::LiteAACDecoderPlugin(std::string name)
101 : CodecPlugin(std::move(name)),
102 audioParameter_{ { Tag::REQUIRED_OUT_BUFFER_CNT, (unsigned int)BUFFER_ITEM_CNT } },
103 inBuffer_ {nullptr},
104 outBuffer_ {nullptr}
105 {
106 MEDIA_LOG_I("LiteAACDecoderPlugin, plugin name: " PUBLIC_LOG_S, pluginName_.c_str());
107 }
108
~LiteAACDecoderPlugin()109 LiteAACDecoderPlugin::~LiteAACDecoderPlugin()
110 {
111 MEDIA_LOG_I("~LiteAACDecoderPlugin");
112 }
113
Init()114 Status LiteAACDecoderPlugin::Init()
115 {
116 return Status::OK;
117 }
118
Deinit()119 Status LiteAACDecoderPlugin::Deinit()
120 {
121 Reset();
122 return Status::OK;
123 }
124
SetParameter(Tag tag,const ValueType & value)125 Status LiteAACDecoderPlugin::SetParameter(Tag tag, const ValueType& value)
126 {
127 audioParameter_.insert(std::make_pair(tag, value));
128 return Status::OK;
129 }
130
GetParameter(Tag tag,ValueType & value)131 Status LiteAACDecoderPlugin::GetParameter(Tag tag, ValueType& value)
132 {
133 auto item = audioParameter_.find(tag);
134 if (item != audioParameter_.end()) {
135 value = item->second;
136 return Status::OK;
137 }
138 return Status::ERROR_INVALID_PARAMETER;
139 }
140
Prepare()141 Status LiteAACDecoderPlugin::Prepare()
142 {
143 OSAL::ScopedLock lock(avMutex_);
144 Status ret = AudioDecoderAACMp4Open();
145 return ret;
146 }
147
Reset()148 Status LiteAACDecoderPlugin::Reset()
149 {
150 OSAL::ScopedLock lock(avMutex_);
151 AudioDecoderAACMp4Close();
152 audioParameter_.clear();
153 if (outBuffer_) {
154 outBuffer_.reset();
155 outBuffer_ = nullptr;
156 }
157 return Status::OK;
158 }
159
Start()160 Status LiteAACDecoderPlugin::Start()
161 {
162 return Status::OK;
163 }
164
Stop()165 Status LiteAACDecoderPlugin::Stop()
166 {
167 OSAL::ScopedLock lock(avMutex_);
168 AudioDecoderAACMp4Close();
169 if (outBuffer_) {
170 outBuffer_.reset();
171 outBuffer_ = nullptr;
172 }
173 return Status::OK;
174 }
175
GetAllocator()176 std::shared_ptr<Allocator> LiteAACDecoderPlugin::GetAllocator()
177 {
178 return nullptr;
179 }
180
SetCallback(Callback * cb)181 Status LiteAACDecoderPlugin::SetCallback(Callback* cb)
182 {
183 return Status::OK;
184 }
185
SetDataCallback(DataCallback * dataCallback)186 Status LiteAACDecoderPlugin::SetDataCallback(DataCallback* dataCallback)
187 {
188 dataCb_ = dataCallback;
189 return Status::OK;
190 }
191
QueueInputBuffer(const std::shared_ptr<Buffer> & inputBuffer,int32_t timeoutMs)192 Status LiteAACDecoderPlugin::QueueInputBuffer(const std::shared_ptr<Buffer> &inputBuffer, int32_t timeoutMs)
193 {
194 MEDIA_LOG_DD("queue input buffer");
195 if (inBuffer_ != nullptr) {
196 return Status::ERROR_TIMED_OUT;
197 }
198 (void)timeoutMs;
199 if (inputBuffer->IsEmpty() && !(inputBuffer->flag & BUFFER_FLAG_EOS)) {
200 MEDIA_LOG_E("decoder does not support fd buffer");
201 return Status::ERROR_INVALID_DATA;
202 }
203 inBuffer_ = inputBuffer;
204 return Status::OK;
205 }
206
QueueOutputBuffer(const std::shared_ptr<Buffer> & outputBuffers,int32_t timeoutMs)207 Status LiteAACDecoderPlugin::QueueOutputBuffer(const std::shared_ptr<Buffer>& outputBuffers, int32_t timeoutMs)
208 {
209 MEDIA_LOG_DD("queue out put");
210 (void)timeoutMs;
211 if (outBuffer_ != nullptr) {
212 return Status::ERROR_TIMED_OUT;
213 }
214 if (!outputBuffers) {
215 return Status::ERROR_INVALID_PARAMETER;
216 }
217 outBuffer_ = outputBuffers;
218 return SendOutputBuffer();
219 }
220
SendOutputBuffer()221 Status LiteAACDecoderPlugin::SendOutputBuffer()
222 {
223 MEDIA_LOG_D("SendOutputBuffer");
224 Status status = ReceiveBuffer();
225 inBuffer_.reset();
226 inBuffer_ = nullptr;
227 if (status == Status::OK || status == Status::END_OF_STREAM) {
228 dataCb_->OnOutputBufferDone(outBuffer_);
229 }
230 outBuffer_.reset();
231 outBuffer_ = nullptr;
232
233 return status;
234 }
235
ReceiveBufferLocked(const std::shared_ptr<Buffer> & ioInfo)236 Status LiteAACDecoderPlugin::ReceiveBufferLocked(const std::shared_ptr<Buffer> &ioInfo)
237 {
238 Status status;
239 if (inBuffer_->IsEmpty() && (inBuffer_->flag & BUFFER_FLAG_EOS) != 0) {
240 ioInfo->GetMemory()->Reset();
241 ioInfo->flag = BUFFER_FLAG_EOS;
242 status = Status::END_OF_STREAM;
243 } else {
244 status = AudioDecoderAACMp4Process(inBuffer_, ioInfo);
245 }
246 return status;
247 }
248
ReceiveBuffer()249 Status LiteAACDecoderPlugin::ReceiveBuffer()
250 {
251 if (inBuffer_ == nullptr) {
252 return Status::ERROR_NOT_ENOUGH_DATA;
253 }
254 std::shared_ptr<Buffer> ioInfo = outBuffer_;
255 if ((ioInfo == nullptr) || ioInfo->IsEmpty() || (ioInfo->GetBufferMeta()->GetType() != BufferMetaType::AUDIO)) {
256 MEDIA_LOG_W("no buffer");
257 return Status::ERROR_NO_MEMORY;
258 }
259 Status status;
260 {
261 OSAL::ScopedLock lock(avMutex_);
262 status = ReceiveBufferLocked(ioInfo);
263 }
264 return status;
265 }
266
Flush()267 Status LiteAACDecoderPlugin::Flush()
268 {
269 OSAL::ScopedLock lock(avMutex_);
270 outBuffer_.reset();
271 outBuffer_ = nullptr;
272 return Status::OK;
273 }
274
AudioDecoderAACMp4Open()275 Status LiteAACDecoderPlugin::AudioDecoderAACMp4Open()
276 {
277 int ret = aac_decoder_init();
278 return ret == -1 ? Status::ERROR_UNKNOWN : Status::OK;
279 }
280
AudioDecoderAACMp4Close()281 void LiteAACDecoderPlugin::AudioDecoderAACMp4Close()
282 {
283 aac_decoder_close();
284 }
285
AudioDecoderAACMp4Process(std::shared_ptr<Buffer> inBuffer,std::shared_ptr<Buffer> outBuffer)286 Status LiteAACDecoderPlugin::AudioDecoderAACMp4Process(std::shared_ptr<Buffer> inBuffer,
287 std::shared_ptr<Buffer> outBuffer)
288 {
289 if (inBuffer == nullptr || outBuffer == nullptr) {
290 return Status::ERROR_UNKNOWN;
291 }
292 auto inData = inBuffer->GetMemory();
293 auto outData = outBuffer->GetMemory();
294 const uint8_t *FramePtr = const_cast<uint8_t *>(inData->GetReadOnlyData());
295 size_t inputLength = inData->GetSize();
296 unsigned int remain_size = inputLength;
297 int err;
298
299 err = aac_decoder_input_data(const_cast<unsigned char**>(&FramePtr),
300 static_cast<size_t *>(&inputLength), &remain_size);
301 if (err != 0) {
302 MEDIA_LOG_E("aac_decoder_input_data error is " PUBLIC_LOG_D32, err);
303 return Status::ERROR_UNKNOWN;
304 }
305 aac_stream_info_t *aacInfo_ = aac_decoder_get_meida_info();
306 if (aacInfo_ == NULL) {
307 MEDIA_LOG_E("aacInfo_ get error");
308 return Status::ERROR_UNKNOWN;
309 }
310 unsigned int packet_length = static_cast<unsigned int>(aacInfo_->frame_size) *
311 static_cast<unsigned int>(aacInfo_->channel_num) * AAC_DECODER_SAMPLE_SIZE;
312 if ((outData->GetCapacity() >= packet_length) && (packet_length <= PCM_SIZE)) {
313 err = aac_decoder_get_frame(reinterpret_cast<signed short *>(outData->GetWritableAddr(packet_length, 0)),
314 PCM_SIZE / 2, 0); // 2
315 if (err != 0) {
316 MEDIA_LOG_E("aac_decoder_get_frame error is " PUBLIC_LOG_D32 " remain_size " PUBLIC_LOG_D32, err,
317 remain_size);
318 return Status::ERROR_UNKNOWN;
319 }
320 } else {
321 MEDIA_LOG_E("outData not enough memory");
322 return Status::ERROR_NO_MEMORY;
323 }
324 return Status::OK;
325 }
326 } // LiteAacPlugin
327 } // namespace Plugin
328 } // namespace Media
329 } // namespace OHOS