• 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 #define HST_LOG_TAG "Minimp3DecoderPlugin"
17 
18 #include "minimp3_decoder_plugin.h"
19 #include <cstring>
20 #include <map>
21 #include <set>
22 #include "utils/constants.h"
23 
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 
29 namespace OHOS {
30 namespace Media {
31 namespace Plugin {
32 namespace Minimp3 {
33 namespace {
34     constexpr uint32_t MP3_384_SAMPLES_PER_FRAME  = 384;  // 384
35     constexpr uint32_t MP3_576_SAMPLES_PER_FRAME  = 576;  // 576
36     constexpr uint32_t MP3_MAX_SAMPLES_PER_FRAME  = 1152; // 1152
37     constexpr uint32_t BUFFER_ITEM_CNT            = 6;    // 6
38     constexpr uint32_t MAX_RANK                   = 100;  // 100
39 }
40 
Minimp3DecoderPlugin(std::string name)41 Minimp3DecoderPlugin::Minimp3DecoderPlugin(std::string name)
42     : CodecPlugin(std::move(name)),
43       samplesPerFrame_(0),
44       channels_(0),
45       mp3Parameter_()
46 {
47     FALSE_LOG(memset_s(&mp3DecoderAttr_, sizeof(mp3DecoderAttr_), 0x00, sizeof(AudioDecoderMp3Attr)) == 0);
48     FALSE_LOG(memset_s(&minimp3DecoderImpl_, sizeof(minimp3DecoderImpl_), 0x00, sizeof(Minimp3DemuxerOp)) == 0);
49     MEDIA_LOG_I("Minimp3DecoderPlugin, plugin name: " PUBLIC_LOG_S, pluginName_.c_str());
50 }
51 
~Minimp3DecoderPlugin()52 Minimp3DecoderPlugin::~Minimp3DecoderPlugin()
53 {
54     MEDIA_LOG_I("~Minimp3DecoderPlugin, plugin name: " PUBLIC_LOG_S, pluginName_.c_str());
55 }
56 
Init()57 Status Minimp3DecoderPlugin::Init()
58 {
59     minimp3DecoderImpl_ = MiniMp3GetOpt();
60     AudioDecoderMp3Open();
61     mp3Parameter_[Tag::REQUIRED_OUT_BUFFER_CNT] = BUFFER_ITEM_CNT;
62     mp3Parameter_[Tag::AUDIO_SAMPLE_PER_FRAME] = MP3_MAX_SAMPLES_PER_FRAME;
63     return Status::OK;
64 }
65 
Deinit()66 Status Minimp3DecoderPlugin::Deinit()
67 {
68     AudioDecoderMp3Close();
69     return Status::OK;
70 }
71 
SetParameter(Tag tag,const ValueType & value)72 Status Minimp3DecoderPlugin::SetParameter(Tag tag, const ValueType& value)
73 {
74     mp3Parameter_.insert(std::make_pair(tag, value));
75     return Status::OK;
76 }
77 
GetParameter(Tag tag,ValueType & value)78 Status Minimp3DecoderPlugin::GetParameter(Tag tag, ValueType& value)
79 {
80     auto res = mp3Parameter_.find(tag);
81     if (res != mp3Parameter_.end()) {
82         value = res->second;
83         return Status::OK;
84     }
85     return Status::ERROR_INVALID_PARAMETER;
86 }
87 
Prepare()88 Status Minimp3DecoderPlugin::Prepare()
89 {
90     if (mp3Parameter_.find(Tag::AUDIO_CHANNELS) != mp3Parameter_.end()) {
91         channels_ = AnyCast<uint32_t>((mp3Parameter_.find(Tag::AUDIO_CHANNELS))->second);
92     }
93     if (mp3Parameter_.find(Tag::AUDIO_SAMPLE_PER_FRAME) != mp3Parameter_.end()) {
94         samplesPerFrame_ = AnyCast<uint32_t>(mp3Parameter_.find(Tag::AUDIO_SAMPLE_PER_FRAME)->second);
95     }
96     if (samplesPerFrame_ != MP3_384_SAMPLES_PER_FRAME && samplesPerFrame_ != MP3_576_SAMPLES_PER_FRAME &&
97         samplesPerFrame_ != MP3_MAX_SAMPLES_PER_FRAME) {
98         return Status::ERROR_INVALID_PARAMETER;
99     }
100     MEDIA_LOG_I("channels_ = " PUBLIC_LOG_D32 " samplesPerFrame_ = " PUBLIC_LOG_D32, channels_, samplesPerFrame_);
101     return Status::OK;
102 }
103 
Reset()104 Status Minimp3DecoderPlugin::Reset()
105 {
106     mp3Parameter_.clear();
107     return Status::OK;
108 }
109 
Start()110 Status Minimp3DecoderPlugin::Start()
111 {
112     return Status::OK;
113 }
114 
Stop()115 Status Minimp3DecoderPlugin::Stop()
116 {
117     return Status::OK;
118 }
119 
GetAllocator()120 std::shared_ptr<Allocator> Minimp3DecoderPlugin::GetAllocator()
121 {
122     return nullptr;
123 }
124 
SetCallback(Callback * cb)125 Status Minimp3DecoderPlugin::SetCallback(Callback* cb)
126 {
127     return Status::OK;
128 }
129 
GetPcmDataProcess(const std::shared_ptr<Buffer> & inputBuffer,std::shared_ptr<Buffer> & outputBuffer)130 Status Minimp3DecoderPlugin::GetPcmDataProcess(const std::shared_ptr<Buffer>& inputBuffer,
131                                                std::shared_ptr<Buffer>& outputBuffer)
132 {
133     if (inputBuffer == nullptr) {
134         return Status::ERROR_NOT_ENOUGH_DATA;
135     }
136     if (outputBuffer == nullptr || outputBuffer->IsEmpty()) {
137         MEDIA_LOG_W("outputBuffer nullptr warning");
138         return Status::ERROR_INVALID_PARAMETER;
139     }
140     if (inputBuffer->IsEmpty() && (inputBuffer->flag & BUFFER_FLAG_EOS) != 0) {
141         MEDIA_LOG_I("eos received");
142         outputBuffer->GetMemory()->Reset();
143         outputBuffer->flag |= BUFFER_FLAG_EOS;
144         return Status::END_OF_STREAM;
145     }
146     return AudioDecoderMp3Process(inputBuffer_, outputBuffer);
147 }
148 
QueueOutputBuffer(const std::shared_ptr<Buffer> & outputBuffers,int32_t timeoutMs)149 Status Minimp3DecoderPlugin::QueueOutputBuffer(const std::shared_ptr<Buffer>& outputBuffers, int32_t timeoutMs)
150 {
151     MEDIA_LOG_DD("queue output buffer");
152     (void)timeoutMs;
153     if (!outputBuffers) {
154         return Status::ERROR_INVALID_PARAMETER;
155     }
156     outputBuffer_ = outputBuffers;
157     return SendOutputBuffer();
158 }
159 
SendOutputBuffer()160 Status Minimp3DecoderPlugin::SendOutputBuffer()
161 {
162     MEDIA_LOG_DD("send output buffer");
163     OSAL::ScopedLock lock(ioMutex_);
164     Status status = GetPcmDataProcess(inputBuffer_, outputBuffer_);
165     inputBuffer_.reset();
166     inputBuffer_ = nullptr;
167     if (status == Status::OK || status == Status::END_OF_STREAM) {
168         dataCb_->OnOutputBufferDone(outputBuffer_);
169     }
170     outputBuffer_.reset();
171     outputBuffer_ = nullptr;
172     return status;
173 }
174 
QueueInputBuffer(const std::shared_ptr<Buffer> & inputBuffer,int32_t timeoutMs)175 Status Minimp3DecoderPlugin::QueueInputBuffer(const std::shared_ptr<Buffer>& inputBuffer, int32_t timeoutMs)
176 {
177     MEDIA_LOG_DD("queue input buffer");
178     (void)timeoutMs;
179     if (inputBuffer->IsEmpty() && !(inputBuffer->flag & BUFFER_FLAG_EOS)) {
180         MEDIA_LOG_E("decoder does not support fd buffer");
181         return Status::ERROR_INVALID_DATA;
182     } else {
183         inputBuffer_ = inputBuffer;
184         return Status::OK;
185     }
186 }
187 
Flush()188 Status Minimp3DecoderPlugin::Flush()
189 {
190     return Status::OK;
191 }
192 
SetDataCallback(DataCallback * dataCallback)193 Status Minimp3DecoderPlugin::SetDataCallback(DataCallback* dataCallback)
194 {
195     dataCb_ = dataCallback;
196     return Status::OK;
197 }
198 
AudioDecoderMp3Open()199 void Minimp3DecoderPlugin::AudioDecoderMp3Open()
200 {
201     Minimp3WrapperMp3decInit(&mp3DecoderAttr_.mp3DecoderHandle);
202 }
203 
AudioDecoderMp3Close()204 int Minimp3DecoderPlugin::AudioDecoderMp3Close()
205 {
206     return 0;
207 }
208 
AudioDecoderMp3Process(std::shared_ptr<Buffer> inBuffer,std::shared_ptr<Buffer> outBuffer)209 Status Minimp3DecoderPlugin::AudioDecoderMp3Process(std::shared_ptr<Buffer> inBuffer, std::shared_ptr<Buffer> outBuffer)
210 {
211     auto inData  = inBuffer->GetMemory();
212     auto outData = outBuffer->GetMemory();
213     Minimp3WrapperMp3decFrameInfo frameInfo;
214 
215     uint32_t probePcmLength = samplesPerFrame_ * sizeof(Mp3DecoderSample) * channels_;
216     if (outData->GetCapacity() < probePcmLength) {
217         return Status::ERROR_UNKNOWN;
218     }
219     int16_t *pcmPtr = (int16_t *)outData->GetWritableAddr(probePcmLength, 0);
220     int sampleCount = minimp3DecoderImpl_.decoderFrame(&mp3DecoderAttr_.mp3DecoderHandle, inData->GetReadOnlyData(),
221                                                        inData->GetSize(), pcmPtr, &frameInfo);
222     outBuffer->pts = inBuffer->pts;
223     if (sampleCount > 0) {
224         if (frameInfo.frame_bytes) {
225             return Status::OK;
226         }
227     } else if (sampleCount == 0) {
228         return Status::OK;
229     }
230     return Status::ERROR_UNKNOWN;
231 }
232 
233 namespace {
234 void UpdatePluginDefinition(CodecPluginDef& definition);
Minimp3DecoderCreator(const std::string & name)235 std::shared_ptr<CodecPlugin> Minimp3DecoderCreator(const std::string& name)
236 {
237     return std::make_shared<Minimp3DecoderPlugin>(name);
238 }
239 
RegisterDecoderPlugin(const std::shared_ptr<Register> & reg)240 Status RegisterDecoderPlugin(const std::shared_ptr<Register>& reg)
241 {
242     MEDIA_LOG_I("RegisterPlugins called.");
243     if (!reg) {
244         MEDIA_LOG_E("RegisterPlugins failed due to nullptr pointer for reg.");
245         return Status::ERROR_INVALID_PARAMETER;
246     }
247 
248     CodecPluginDef definition;
249     definition.name      = "Minimp3DecoderPlugin";
250     definition.codecType = CodecType::AUDIO_DECODER;
251     definition.rank      = MAX_RANK;
252     definition.creator   = Minimp3DecoderCreator;
253     UpdatePluginDefinition(definition);
254     if (reg->AddPlugin(definition) != Status::OK) {
255         MEDIA_LOG_W("register minimp3 decoder plugin failed");
256     }
257     return Status::OK;
258 }
259 
UpdateInCaps(CodecPluginDef & definition)260 void UpdateInCaps(CodecPluginDef& definition)
261 {
262     CapabilityBuilder capBuilder;
263     capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_MPEG)
264         .SetAudioMpegVersion(1)
265         .SetAudioMpegLayerRange(1, 3); // 3
266     DiscreteCapability<uint32_t> values = {8000, 16000, 22050, 44100, 48000, 32000}; // 8000, 16000 etc. sample rates
267     capBuilder.SetAudioSampleRateList(values);
268     DiscreteCapability<AudioChannelLayout> channelLayoutValues = {
269         AudioChannelLayout::MONO, AudioChannelLayout::STEREO};
270     capBuilder.SetAudioChannelLayoutList(channelLayoutValues);
271     definition.inCaps.push_back(capBuilder.Build());
272 }
273 
UpdateOutCaps(CodecPluginDef & definition)274 void UpdateOutCaps(CodecPluginDef& definition)
275 {
276     CapabilityBuilder capBuilder;
277     capBuilder.SetMime(OHOS::Media::MEDIA_MIME_AUDIO_RAW);
278     capBuilder.SetAudioSampleFormatList({AudioSampleFormat::S16});
279     definition.outCaps.emplace_back(capBuilder.Build());
280 }
281 
UpdatePluginDefinition(CodecPluginDef & definition)282 void UpdatePluginDefinition(CodecPluginDef& definition)
283 {
284     UpdateInCaps(definition);
285     UpdateOutCaps(definition);
286 }
287 }
288 
__anon55f69a5d0302null289 PLUGIN_DEFINITION(Minimp3Decoder, LicenseType::CC0, RegisterDecoderPlugin, [] {});
290 } // namespace Minimp3
291 } // namespace Plugin
292 } // namespace Media
293 } // namespace OHOS