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