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