1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2SoftMp3Dec"
19 #include <log/log.h>
20
21 #include <numeric>
22
23 #include <media/stagefright/foundation/MediaDefs.h>
24
25 #include <C2PlatformSupport.h>
26 #include <SimpleC2Interface.h>
27
28 #include "C2SoftMp3Dec.h"
29 #include "pvmp3decoder_api.h"
30
31 namespace android {
32
33 constexpr char COMPONENT_NAME[] = "c2.android.mp3.decoder";
34
35 class C2SoftMP3::IntfImpl : public C2InterfaceHelper {
36 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)37 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
38 : C2InterfaceHelper(helper) {
39
40 setDerivedInstance(this);
41
42 addParameter(
43 DefineParam(mInputFormat, C2_NAME_INPUT_STREAM_FORMAT_SETTING)
44 .withConstValue(new C2StreamFormatConfig::input(0u, C2FormatCompressed))
45 .build());
46
47 addParameter(
48 DefineParam(mOutputFormat, C2_NAME_OUTPUT_STREAM_FORMAT_SETTING)
49 .withConstValue(new C2StreamFormatConfig::output(0u, C2FormatAudio))
50 .build());
51
52 addParameter(
53 DefineParam(mInputMediaType, C2_NAME_INPUT_PORT_MIME_SETTING)
54 .withConstValue(AllocSharedString<C2PortMimeConfig::input>(
55 MEDIA_MIMETYPE_AUDIO_MPEG))
56 .build());
57
58 addParameter(
59 DefineParam(mOutputMediaType, C2_NAME_OUTPUT_PORT_MIME_SETTING)
60 .withConstValue(AllocSharedString<C2PortMimeConfig::output>(
61 MEDIA_MIMETYPE_AUDIO_RAW))
62 .build());
63
64 addParameter(
65 DefineParam(mSampleRate, C2_NAME_STREAM_SAMPLE_RATE_SETTING)
66 .withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
67 .withFields({C2F(mSampleRate, value).oneOf({8000, 11025, 12000, 16000,
68 22050, 24000, 32000, 44100, 48000})})
69 .withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
70 .build());
71
72 addParameter(
73 DefineParam(mChannelCount, C2_NAME_STREAM_CHANNEL_COUNT_SETTING)
74 .withDefault(new C2StreamChannelCountInfo::output(0u, 2))
75 .withFields({C2F(mChannelCount, value).inRange(1, 2)})
76 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
77 .build());
78
79 addParameter(
80 DefineParam(mBitrate, C2_NAME_STREAM_BITRATE_SETTING)
81 .withDefault(new C2BitrateTuning::input(0u, 64000))
82 .withFields({C2F(mBitrate, value).inRange(8000, 320000)})
83 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
84 .build());
85 }
86
87 private:
88 std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
89 std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
90 std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
91 std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
92 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
93 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
94 std::shared_ptr<C2BitrateTuning::input> mBitrate;
95 };
96
C2SoftMP3(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)97 C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id,
98 const std::shared_ptr<IntfImpl> &intfImpl)
99 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
100 mIntf(intfImpl),
101 mConfig(nullptr),
102 mDecoderBuf(nullptr) {
103 }
104
~C2SoftMP3()105 C2SoftMP3::~C2SoftMP3() {
106 onRelease();
107 }
108
onInit()109 c2_status_t C2SoftMP3::onInit() {
110 status_t err = initDecoder();
111 return err == OK ? C2_OK : C2_NO_MEMORY;
112 }
113
onStop()114 c2_status_t C2SoftMP3::onStop() {
115 // Make sure that the next buffer output does not still
116 // depend on fragments from the last one decoded.
117 pvmp3_InitDecoder(mConfig, mDecoderBuf);
118 mSignalledError = false;
119 mIsFirst = true;
120 mSignalledOutputEos = false;
121 mAnchorTimeStamp = 0;
122 mProcessedSamples = 0;
123
124 return C2_OK;
125 }
126
onReset()127 void C2SoftMP3::onReset() {
128 (void)onStop();
129 }
130
onRelease()131 void C2SoftMP3::onRelease() {
132 if (mDecoderBuf) {
133 free(mDecoderBuf);
134 mDecoderBuf = nullptr;
135 }
136
137 if (mConfig) {
138 delete mConfig;
139 mConfig = nullptr;
140 }
141 }
142
initDecoder()143 status_t C2SoftMP3::initDecoder() {
144 mConfig = new tPVMP3DecoderExternal{};
145 if (!mConfig) return NO_MEMORY;
146 mConfig->equalizerType = flat;
147 mConfig->crcEnabled = false;
148
149 size_t memRequirements = pvmp3_decoderMemRequirements();
150 mDecoderBuf = malloc(memRequirements);
151 if (!mDecoderBuf) return NO_MEMORY;
152
153 pvmp3_InitDecoder(mConfig, mDecoderBuf);
154
155 mIsFirst = true;
156 mSignalledError = false;
157 mSignalledOutputEos = false;
158 mAnchorTimeStamp = 0;
159 mProcessedSamples = 0;
160
161 return OK;
162 }
163
164 /* The below code is borrowed from ./test/mp3reader.cpp */
parseMp3Header(uint32_t header,size_t * frame_size,uint32_t * out_sampling_rate=nullptr,uint32_t * out_channels=nullptr,uint32_t * out_bitrate=nullptr,uint32_t * out_num_samples=nullptr)165 static bool parseMp3Header(uint32_t header, size_t *frame_size,
166 uint32_t *out_sampling_rate = nullptr,
167 uint32_t *out_channels = nullptr,
168 uint32_t *out_bitrate = nullptr,
169 uint32_t *out_num_samples = nullptr) {
170 *frame_size = 0;
171 if (out_sampling_rate) *out_sampling_rate = 0;
172 if (out_channels) *out_channels = 0;
173 if (out_bitrate) *out_bitrate = 0;
174 if (out_num_samples) *out_num_samples = 1152;
175
176 if ((header & 0xffe00000) != 0xffe00000) return false;
177
178 unsigned version = (header >> 19) & 3;
179 if (version == 0x01) return false;
180
181 unsigned layer = (header >> 17) & 3;
182 if (layer == 0x00) return false;
183
184 unsigned bitrate_index = (header >> 12) & 0x0f;
185 if (bitrate_index == 0 || bitrate_index == 0x0f) return false;
186
187 unsigned sampling_rate_index = (header >> 10) & 3;
188 if (sampling_rate_index == 3) return false;
189
190 static const int kSamplingRateV1[] = { 44100, 48000, 32000 };
191 int sampling_rate = kSamplingRateV1[sampling_rate_index];
192 if (version == 2 /* V2 */) {
193 sampling_rate /= 2;
194 } else if (version == 0 /* V2.5 */) {
195 sampling_rate /= 4;
196 }
197
198 unsigned padding = (header >> 9) & 1;
199
200 if (layer == 3) { // layer I
201 static const int kBitrateV1[] =
202 {
203 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448
204 };
205 static const int kBitrateV2[] =
206 {
207 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256
208 };
209
210 int bitrate = (version == 3 /* V1 */) ? kBitrateV1[bitrate_index - 1] :
211 kBitrateV2[bitrate_index - 1];
212
213 if (out_bitrate) {
214 *out_bitrate = bitrate;
215 }
216 *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
217 if (out_num_samples) {
218 *out_num_samples = 384;
219 }
220 } else { // layer II or III
221 static const int kBitrateV1L2[] =
222 {
223 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384
224 };
225
226 static const int kBitrateV1L3[] =
227 {
228 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320
229 };
230
231 static const int kBitrateV2[] =
232 {
233 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160
234 };
235
236 int bitrate;
237 if (version == 3 /* V1 */) {
238 bitrate = (layer == 2 /* L2 */) ? kBitrateV1L2[bitrate_index - 1] :
239 kBitrateV1L3[bitrate_index - 1];
240
241 if (out_num_samples) {
242 *out_num_samples = 1152;
243 }
244 } else { // V2 (or 2.5)
245 bitrate = kBitrateV2[bitrate_index - 1];
246 if (out_num_samples) {
247 *out_num_samples = (layer == 1 /* L3 */) ? 576 : 1152;
248 }
249 }
250
251 if (out_bitrate) {
252 *out_bitrate = bitrate;
253 }
254
255 if (version == 3 /* V1 */) {
256 *frame_size = 144000 * bitrate / sampling_rate + padding;
257 } else { // V2 or V2.5
258 size_t tmp = (layer == 1 /* L3 */) ? 72000 : 144000;
259 *frame_size = tmp * bitrate / sampling_rate + padding;
260 }
261 }
262
263 if (out_sampling_rate) {
264 *out_sampling_rate = sampling_rate;
265 }
266
267 if (out_channels) {
268 int channel_mode = (header >> 6) & 3;
269
270 *out_channels = (channel_mode == 3) ? 1 : 2;
271 }
272
273 return true;
274 }
275
U32_AT(const uint8_t * ptr)276 static uint32_t U32_AT(const uint8_t *ptr) {
277 return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
278 }
279
calculateOutSize(uint8 * header,size_t inSize,std::vector<size_t> * decodedSizes)280 static status_t calculateOutSize(uint8 *header, size_t inSize,
281 std::vector<size_t> *decodedSizes) {
282 uint32_t channels;
283 uint32_t numSamples;
284 size_t frameSize;
285 size_t totalInSize = 0;
286
287 while (totalInSize + 4 < inSize) {
288 if (!parseMp3Header(U32_AT(header + totalInSize), &frameSize,
289 nullptr, &channels, nullptr, &numSamples)) {
290 ALOGE("Error in parse mp3 header during outSize estimation");
291 return UNKNOWN_ERROR;
292 }
293 totalInSize += frameSize;
294 decodedSizes->push_back(numSamples * channels * sizeof(int16_t));
295 }
296
297 if (decodedSizes->empty()) return UNKNOWN_ERROR;
298
299 return OK;
300 }
301
onFlush_sm()302 c2_status_t C2SoftMP3::onFlush_sm() {
303 return onStop();
304 }
305
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)306 c2_status_t C2SoftMP3::drain(
307 uint32_t drainMode,
308 const std::shared_ptr<C2BlockPool> &pool) {
309 (void) pool;
310 if (drainMode == NO_DRAIN) {
311 ALOGW("drain with NO_DRAIN: no-op");
312 return C2_OK;
313 }
314 if (drainMode == DRAIN_CHAIN) {
315 ALOGW("DRAIN_CHAIN not supported");
316 return C2_OMITTED;
317 }
318
319 return C2_OK;
320 }
321
322 // TODO: Can overall error checking be improved? As in the check for validity of
323 // work, pool ptr, work->input.buffers.size() == 1, ...
324 // TODO: Blind removal of 529 samples from the output may not work. Because
325 // mpeg layer 1 frame size is 384 samples per frame. This should introduce
326 // negative values and can cause SEG faults. Soft omx mp3 plugin can have
327 // this problem (CHECK!)
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)328 void C2SoftMP3::process(
329 const std::unique_ptr<C2Work> &work,
330 const std::shared_ptr<C2BlockPool> &pool) {
331 work->result = C2_OK;
332 work->workletsProcessed = 0u;
333 work->worklets.front()->output.configUpdate.clear();
334 if (mSignalledError || mSignalledOutputEos) {
335 work->result = C2_BAD_VALUE;
336 return;
337 }
338
339 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
340 size_t inSize = 0u;
341 C2ReadView rView = mDummyReadView;
342 if (!work->input.buffers.empty()) {
343 rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
344 inSize = rView.capacity();
345 if (inSize && rView.error()) {
346 ALOGE("read view map failed %d", rView.error());
347 work->result = rView.error();
348 return;
349 }
350 }
351
352 if (inSize == 0 && !eos) {
353 work->worklets.front()->output.flags = work->input.flags;
354 work->worklets.front()->output.buffers.clear();
355 work->worklets.front()->output.ordinal = work->input.ordinal;
356 work->workletsProcessed = 1u;
357 return;
358 }
359 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d", inSize,
360 (int)work->input.ordinal.timestamp.peeku(), (int)work->input.ordinal.frameIndex.peeku());
361
362 int32_t numChannels = mConfig->num_channels;
363 size_t calOutSize;
364 std::vector<size_t> decodedSizes;
365 if (inSize && OK != calculateOutSize(const_cast<uint8 *>(rView.data()),
366 inSize, &decodedSizes)) {
367 work->result = C2_CORRUPTED;
368 return;
369 }
370 calOutSize = std::accumulate(decodedSizes.begin(), decodedSizes.end(), 0);
371 if (eos) {
372 calOutSize += kPVMP3DecoderDelay * numChannels * sizeof(int16_t);
373 }
374
375 std::shared_ptr<C2LinearBlock> block;
376 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
377 c2_status_t err = pool->fetchLinearBlock(calOutSize, usage, &block);
378 if (err != C2_OK) {
379 ALOGE("fetchLinearBlock for Output failed with status %d", err);
380 work->result = C2_NO_MEMORY;
381 return;
382 }
383 C2WriteView wView = block->map().get();
384 if (wView.error()) {
385 ALOGE("write view map failed %d", wView.error());
386 work->result = wView.error();
387 return;
388 }
389
390 int outSize = 0;
391 int outOffset = 0;
392 auto it = decodedSizes.begin();
393 size_t inPos = 0;
394 int32_t samplingRate = mConfig->samplingRate;
395 while (inPos < inSize) {
396 if (it == decodedSizes.end()) {
397 ALOGE("unexpected trailing bytes, ignoring them");
398 break;
399 }
400
401 mConfig->pInputBuffer = const_cast<uint8 *>(rView.data() + inPos);
402 mConfig->inputBufferCurrentLength = (inSize - inPos);
403 mConfig->inputBufferMaxLength = 0;
404 mConfig->inputBufferUsedLength = 0;
405 mConfig->outputFrameSize = (calOutSize - outSize);
406 mConfig->pOutputBuffer = reinterpret_cast<int16_t *> (wView.data() + outSize);
407
408 ERROR_CODE decoderErr;
409 if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
410 != NO_DECODING_ERROR) {
411 ALOGE("mp3 decoder returned error %d", decoderErr);
412 if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
413 && decoderErr != SIDE_INFO_ERROR) {
414 mSignalledError = true;
415 work->result = C2_CORRUPTED;
416 return;
417 }
418
419 // This is recoverable, just ignore the current frame and
420 // play silence instead.
421 ALOGV("ignoring error and sending silence");
422 if (mConfig->outputFrameSize == 0) {
423 mConfig->outputFrameSize = *it / sizeof(int16_t);
424 }
425 memset(mConfig->pOutputBuffer, 0, mConfig->outputFrameSize * sizeof(int16_t));
426 } else if (mConfig->samplingRate != samplingRate
427 || mConfig->num_channels != numChannels) {
428 ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
429 samplingRate, mConfig->samplingRate,
430 numChannels, mConfig->num_channels);
431 samplingRate = mConfig->samplingRate;
432 numChannels = mConfig->num_channels;
433
434 C2StreamSampleRateInfo::output sampleRateInfo(0u, samplingRate);
435 C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels);
436 std::vector<std::unique_ptr<C2SettingResult>> failures;
437 c2_status_t err = mIntf->config(
438 { &sampleRateInfo, &channelCountInfo },
439 C2_MAY_BLOCK,
440 &failures);
441 if (err == OK) {
442 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(sampleRateInfo));
443 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(channelCountInfo));
444 } else {
445 ALOGE("Config Update failed");
446 mSignalledError = true;
447 work->result = C2_CORRUPTED;
448 return;
449 }
450 }
451 if (*it != mConfig->outputFrameSize * sizeof(int16_t)) {
452 ALOGE("panic, parsed size does not match decoded size");
453 mSignalledError = true;
454 work->result = C2_CORRUPTED;
455 return;
456 }
457 outSize += mConfig->outputFrameSize * sizeof(int16_t);
458 inPos += mConfig->inputBufferUsedLength;
459 it++;
460 }
461 if (mIsFirst) {
462 mIsFirst = false;
463 // The decoder delay is 529 samples, so trim that many samples off
464 // the start of the first output buffer. This essentially makes this
465 // decoder have zero delay, which the rest of the pipeline assumes.
466 outOffset = kPVMP3DecoderDelay * numChannels * sizeof(int16_t);
467 mAnchorTimeStamp = work->input.ordinal.timestamp.peekull();
468 }
469 if (eos) {
470 if (calOutSize >=
471 outSize + kPVMP3DecoderDelay * numChannels * sizeof(int16_t)) {
472 if (!memset(reinterpret_cast<int16_t*>(wView.data() + outSize), 0,
473 kPVMP3DecoderDelay * numChannels * sizeof(int16_t))) {
474 mSignalledError = true;
475 work->result = C2_CORRUPTED;
476 return;
477 }
478 ALOGV("Adding 529 samples at end");
479 outSize += kPVMP3DecoderDelay * numChannels * sizeof(int16_t);
480 }
481 }
482
483 uint64_t outTimeStamp = mProcessedSamples * 1000000ll / samplingRate;
484 mProcessedSamples += ((outSize - outOffset) / (numChannels * sizeof(int16_t)));
485 ALOGV("out buffer attr. offset %d size %d timestamp %u", outOffset, outSize - outOffset,
486 (uint32_t)(mAnchorTimeStamp + outTimeStamp));
487
488 decodedSizes.clear();
489 work->worklets.front()->output.flags = work->input.flags;
490 work->worklets.front()->output.buffers.clear();
491 work->worklets.front()->output.buffers.push_back(
492 createLinearBuffer(block, outOffset, outSize - outOffset));
493 work->worklets.front()->output.ordinal = work->input.ordinal;
494 work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
495 work->workletsProcessed = 1u;
496 if (eos) {
497 mSignalledOutputEos = true;
498 ALOGV("signalled EOS");
499 }
500 }
501
502 class C2SoftMp3DecFactory : public C2ComponentFactory {
503 public:
C2SoftMp3DecFactory()504 C2SoftMp3DecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
505 GetCodec2PlatformComponentStore()->getParamReflector())) {
506 }
507
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)508 virtual c2_status_t createComponent(
509 c2_node_id_t id,
510 std::shared_ptr<C2Component>* const component,
511 std::function<void(C2Component*)> deleter) override {
512 *component = std::shared_ptr<C2Component>(
513 new C2SoftMP3(COMPONENT_NAME,
514 id,
515 std::make_shared<C2SoftMP3::IntfImpl>(mHelper)),
516 deleter);
517 return C2_OK;
518 }
519
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)520 virtual c2_status_t createInterface(
521 c2_node_id_t id,
522 std::shared_ptr<C2ComponentInterface>* const interface,
523 std::function<void(C2ComponentInterface*)> deleter) override {
524 *interface = std::shared_ptr<C2ComponentInterface>(
525 new SimpleInterface<C2SoftMP3::IntfImpl>(
526 COMPONENT_NAME, id, std::make_shared<C2SoftMP3::IntfImpl>(mHelper)),
527 deleter);
528 return C2_OK;
529 }
530
531 virtual ~C2SoftMp3DecFactory() override = default;
532
533 private:
534 std::shared_ptr<C2ReflectorHelper> mHelper;
535 };
536
537 } // namespace android
538
CreateCodec2Factory()539 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
540 ALOGV("in %s", __func__);
541 return new ::android::C2SoftMp3DecFactory();
542 }
543
DestroyCodec2Factory(::C2ComponentFactory * factory)544 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
545 ALOGV("in %s", __func__);
546 delete factory;
547 }
548
549