blob: 2d4e1264c9a9b603ba7bc80774391c30ec8bd957 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
2 * Copyright (C) 2017 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 "C2SoftAacDec"
19#include <log/log.h>
20
21#include <inttypes.h>
22#include <math.h>
23#include <numeric>
24
25#include <cutils/properties.h>
26#include <media/stagefright/foundation/MediaDefs.h>
27#include <media/stagefright/foundation/hexdump.h>
28#include <media/stagefright/MediaErrors.h>
29#include <utils/misc.h>
30
31#include <C2PlatformSupport.h>
32#include <SimpleC2Interface.h>
33
34#include "C2SoftAacDec.h"
35
36#define FILEREAD_MAX_LAYERS 2
37
38#define DRC_DEFAULT_MOBILE_REF_LEVEL -16.0 /* 64*-0.25dB = -16 dB below full scale for mobile conf */
39#define DRC_DEFAULT_MOBILE_DRC_CUT 1.0 /* maximum compression of dynamic range for mobile conf */
40#define DRC_DEFAULT_MOBILE_DRC_BOOST 1.0 /* maximum compression of dynamic range for mobile conf */
41#define DRC_DEFAULT_MOBILE_DRC_HEAVY C2Config::DRC_COMPRESSION_HEAVY /* switch for heavy compression for mobile conf */
42#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */
43#define DRC_DEFAULT_MOBILE_ENC_LEVEL (0.25) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
44#define MAX_CHANNEL_COUNT 8 /* maximum number of audio channels that can be decoded */
45// names of properties that can be used to override the default DRC settings
46#define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level"
47#define PROP_DRC_OVERRIDE_CUT "aac_drc_cut"
48#define PROP_DRC_OVERRIDE_BOOST "aac_drc_boost"
49#define PROP_DRC_OVERRIDE_HEAVY "aac_drc_heavy"
50#define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level"
51#define PROP_DRC_OVERRIDE_EFFECT "ro.aac_drc_effect_type"
52
53namespace android {
54
Wonsik Kimab34ed62019-01-31 15:28:46 -080055constexpr char COMPONENT_NAME[] = "c2.android.aac.decoder";
56
57class C2SoftAacDec::IntfImpl : public SimpleInterface<void>::BaseParams {
Pawin Vongmasa36653902018-11-15 00:10:25 -080058public:
59 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
Wonsik Kimab34ed62019-01-31 15:28:46 -080060 : SimpleInterface<void>::BaseParams(
61 helper,
62 COMPONENT_NAME,
63 C2Component::KIND_DECODER,
64 C2Component::DOMAIN_AUDIO,
65 MEDIA_MIMETYPE_AUDIO_AAC) {
66 noPrivateBuffers();
67 noInputReferences();
68 noOutputReferences();
69 noInputLatency();
70 noTimeStretch();
Pawin Vongmasa36653902018-11-15 00:10:25 -080071
72 addParameter(
Wonsik Kimab34ed62019-01-31 15:28:46 -080073 DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
74 .withConstValue(new C2PortActualDelayTuning::output(2u))
Pawin Vongmasa36653902018-11-15 00:10:25 -080075 .build());
76
77 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080078 DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
Pawin Vongmasa36653902018-11-15 00:10:25 -080079 .withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
80 .withFields({C2F(mSampleRate, value).oneOf({
81 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
82 })})
83 .withSetter(Setter<decltype(*mSampleRate)>::NonStrictValueWithNoDeps)
84 .build());
85
86 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080087 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
Pawin Vongmasa36653902018-11-15 00:10:25 -080088 .withDefault(new C2StreamChannelCountInfo::output(0u, 1))
89 .withFields({C2F(mChannelCount, value).inRange(1, 8)})
90 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
91 .build());
92
93 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -080094 DefineParam(mBitrate, C2_PARAMKEY_BITRATE)
95 .withDefault(new C2StreamBitrateInfo::input(0u, 64000))
Pawin Vongmasa36653902018-11-15 00:10:25 -080096 .withFields({C2F(mBitrate, value).inRange(8000, 960000)})
97 .withSetter(Setter<decltype(*mBitrate)>::NonStrictValueWithNoDeps)
98 .build());
99
100 addParameter(
101 DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
102 .withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 8192))
103 .build());
104
105 addParameter(
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800106 DefineParam(mAacFormat, C2_PARAMKEY_AAC_PACKAGING)
107 .withDefault(new C2StreamAacFormatInfo::input(0u, C2Config::AAC_PACKAGING_RAW))
Pawin Vongmasa36653902018-11-15 00:10:25 -0800108 .withFields({C2F(mAacFormat, value).oneOf({
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800109 C2Config::AAC_PACKAGING_RAW, C2Config::AAC_PACKAGING_ADTS
Pawin Vongmasa36653902018-11-15 00:10:25 -0800110 })})
111 .withSetter(Setter<decltype(*mAacFormat)>::StrictValueWithNoDeps)
112 .build());
113
114 addParameter(
115 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
116 .withDefault(new C2StreamProfileLevelInfo::input(0u,
117 C2Config::PROFILE_AAC_LC, C2Config::LEVEL_UNUSED))
118 .withFields({
119 C2F(mProfileLevel, profile).oneOf({
120 C2Config::PROFILE_AAC_LC,
121 C2Config::PROFILE_AAC_HE,
122 C2Config::PROFILE_AAC_HE_PS,
123 C2Config::PROFILE_AAC_LD,
124 C2Config::PROFILE_AAC_ELD,
125 C2Config::PROFILE_AAC_ER_SCALABLE,
126 C2Config::PROFILE_AAC_XHE}),
127 C2F(mProfileLevel, level).oneOf({
128 C2Config::LEVEL_UNUSED
129 })
130 })
131 .withSetter(ProfileLevelSetter)
132 .build());
133
134 addParameter(
135 DefineParam(mDrcCompressMode, C2_PARAMKEY_DRC_COMPRESSION_MODE)
136 .withDefault(new C2StreamDrcCompressionModeTuning::input(0u, C2Config::DRC_COMPRESSION_HEAVY))
137 .withFields({
138 C2F(mDrcCompressMode, value).oneOf({
139 C2Config::DRC_COMPRESSION_ODM_DEFAULT,
140 C2Config::DRC_COMPRESSION_NONE,
141 C2Config::DRC_COMPRESSION_LIGHT,
142 C2Config::DRC_COMPRESSION_HEAVY})
143 })
144 .withSetter(Setter<decltype(*mDrcCompressMode)>::StrictValueWithNoDeps)
145 .build());
146
147 addParameter(
148 DefineParam(mDrcTargetRefLevel, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL)
149 .withDefault(new C2StreamDrcTargetReferenceLevelTuning::input(0u, DRC_DEFAULT_MOBILE_REF_LEVEL))
150 .withFields({C2F(mDrcTargetRefLevel, value).inRange(-31.75, 0.25)})
151 .withSetter(Setter<decltype(*mDrcTargetRefLevel)>::StrictValueWithNoDeps)
152 .build());
153
154 addParameter(
155 DefineParam(mDrcEncTargetLevel, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL)
156 .withDefault(new C2StreamDrcEncodedTargetLevelTuning::input(0u, DRC_DEFAULT_MOBILE_ENC_LEVEL))
157 .withFields({C2F(mDrcEncTargetLevel, value).inRange(-31.75, 0.25)})
158 .withSetter(Setter<decltype(*mDrcEncTargetLevel)>::StrictValueWithNoDeps)
159 .build());
160
161 addParameter(
162 DefineParam(mDrcBoostFactor, C2_PARAMKEY_DRC_BOOST_FACTOR)
163 .withDefault(new C2StreamDrcBoostFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_BOOST))
164 .withFields({C2F(mDrcBoostFactor, value).inRange(0, 1.)})
165 .withSetter(Setter<decltype(*mDrcBoostFactor)>::StrictValueWithNoDeps)
166 .build());
167
168 addParameter(
169 DefineParam(mDrcAttenuationFactor, C2_PARAMKEY_DRC_ATTENUATION_FACTOR)
170 .withDefault(new C2StreamDrcAttenuationFactorTuning::input(0u, DRC_DEFAULT_MOBILE_DRC_CUT))
171 .withFields({C2F(mDrcAttenuationFactor, value).inRange(0, 1.)})
172 .withSetter(Setter<decltype(*mDrcAttenuationFactor)>::StrictValueWithNoDeps)
173 .build());
174
175 addParameter(
176 DefineParam(mDrcEffectType, C2_PARAMKEY_DRC_EFFECT_TYPE)
177 .withDefault(new C2StreamDrcEffectTypeTuning::input(0u, C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE))
178 .withFields({
179 C2F(mDrcEffectType, value).oneOf({
180 C2Config::DRC_EFFECT_ODM_DEFAULT,
181 C2Config::DRC_EFFECT_OFF,
182 C2Config::DRC_EFFECT_NONE,
183 C2Config::DRC_EFFECT_LATE_NIGHT,
184 C2Config::DRC_EFFECT_NOISY_ENVIRONMENT,
185 C2Config::DRC_EFFECT_LIMITED_PLAYBACK_RANGE,
186 C2Config::DRC_EFFECT_LOW_PLAYBACK_LEVEL,
187 C2Config::DRC_EFFECT_DIALOG_ENHANCEMENT,
188 C2Config::DRC_EFFECT_GENERAL_COMPRESSION})
189 })
190 .withSetter(Setter<decltype(*mDrcEffectType)>::StrictValueWithNoDeps)
191 .build());
192 }
193
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800194 bool isAdts() const { return mAacFormat->value == C2Config::AAC_PACKAGING_ADTS; }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800195 static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me) {
196 (void)mayBlock;
197 (void)me; // TODO: validate
198 return C2R::Ok();
199 }
200 int32_t getDrcCompressMode() const { return mDrcCompressMode->value == C2Config::DRC_COMPRESSION_HEAVY ? 1 : 0; }
201 int32_t getDrcTargetRefLevel() const { return (mDrcTargetRefLevel->value <= 0 ? -mDrcTargetRefLevel->value * 4. + 0.5 : -1); }
202 int32_t getDrcEncTargetLevel() const { return (mDrcEncTargetLevel->value <= 0 ? -mDrcEncTargetLevel->value * 4. + 0.5 : -1); }
203 int32_t getDrcBoostFactor() const { return mDrcBoostFactor->value * 127. + 0.5; }
204 int32_t getDrcAttenuationFactor() const { return mDrcAttenuationFactor->value * 127. + 0.5; }
205 int32_t getDrcEffectType() const { return mDrcEffectType->value; }
206
207private:
Pawin Vongmasa36653902018-11-15 00:10:25 -0800208 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
209 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800210 std::shared_ptr<C2StreamBitrateInfo::input> mBitrate;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800211 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
212 std::shared_ptr<C2StreamAacFormatInfo::input> mAacFormat;
213 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
214 std::shared_ptr<C2StreamDrcCompressionModeTuning::input> mDrcCompressMode;
215 std::shared_ptr<C2StreamDrcTargetReferenceLevelTuning::input> mDrcTargetRefLevel;
216 std::shared_ptr<C2StreamDrcEncodedTargetLevelTuning::input> mDrcEncTargetLevel;
217 std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor;
218 std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor;
219 std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType;
220 // TODO Add : C2StreamAacSbrModeTuning
221};
222
Pawin Vongmasa36653902018-11-15 00:10:25 -0800223C2SoftAacDec::C2SoftAacDec(
224 const char *name,
225 c2_node_id_t id,
226 const std::shared_ptr<IntfImpl> &intfImpl)
227 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
228 mIntf(intfImpl),
229 mAACDecoder(nullptr),
230 mStreamInfo(nullptr),
231 mSignalledError(false),
232 mOutputDelayRingBuffer(nullptr) {
233}
234
235C2SoftAacDec::~C2SoftAacDec() {
236 onRelease();
237}
238
239c2_status_t C2SoftAacDec::onInit() {
240 status_t err = initDecoder();
241 return err == OK ? C2_OK : C2_CORRUPTED;
242}
243
244c2_status_t C2SoftAacDec::onStop() {
245 drainDecoder();
246 // reset the "configured" state
247 mOutputDelayCompensated = 0;
248 mOutputDelayRingBufferWritePos = 0;
249 mOutputDelayRingBufferReadPos = 0;
250 mOutputDelayRingBufferFilled = 0;
251 mBuffersInfo.clear();
252
253 // To make the codec behave the same before and after a reset, we need to invalidate the
254 // streaminfo struct. This does that:
255 mStreamInfo->sampleRate = 0; // TODO: mStreamInfo is read only
256
257 mSignalledError = false;
258
259 return C2_OK;
260}
261
262void C2SoftAacDec::onReset() {
263 (void)onStop();
264}
265
266void C2SoftAacDec::onRelease() {
267 if (mAACDecoder) {
268 aacDecoder_Close(mAACDecoder);
269 mAACDecoder = nullptr;
270 }
271 if (mOutputDelayRingBuffer) {
272 delete[] mOutputDelayRingBuffer;
273 mOutputDelayRingBuffer = nullptr;
274 }
275}
276
277status_t C2SoftAacDec::initDecoder() {
278 ALOGV("initDecoder()");
279 status_t status = UNKNOWN_ERROR;
280 mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1);
281 if (mAACDecoder != nullptr) {
282 mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder);
283 if (mStreamInfo != nullptr) {
284 status = OK;
285 }
286 }
287
288 mOutputDelayCompensated = 0;
289 mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax;
290 mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize];
291 mOutputDelayRingBufferWritePos = 0;
292 mOutputDelayRingBufferReadPos = 0;
293 mOutputDelayRingBufferFilled = 0;
294
295 if (mAACDecoder == nullptr) {
296 ALOGE("AAC decoder is null. TODO: Can not call aacDecoder_SetParam in the following code");
297 }
298
299 //aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE, 0);
300
301 //init DRC wrapper
302 mDrcWrap.setDecoderHandle(mAACDecoder);
303 mDrcWrap.submitStreamData(mStreamInfo);
304
305 // for streams that contain metadata, use the mobile profile DRC settings unless overridden by platform properties
306 // TODO: change the DRC settings depending on audio output device type (HDMI, loadspeaker, headphone)
307
308 // DRC_PRES_MODE_WRAP_DESIRED_TARGET
309 int32_t targetRefLevel = mIntf->getDrcTargetRefLevel();
310 ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel);
311 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, (unsigned)targetRefLevel);
312
313 // DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
314
315 int32_t attenuationFactor = mIntf->getDrcAttenuationFactor();
316 ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor);
317 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, (unsigned)attenuationFactor);
318
319 // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
320 int32_t boostFactor = mIntf->getDrcBoostFactor();
321 ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor);
322 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, (unsigned)boostFactor);
323
324 // DRC_PRES_MODE_WRAP_DESIRED_HEAVY
325 int32_t compressMode = mIntf->getDrcCompressMode();
326 ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
327 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
328
329 // DRC_PRES_MODE_WRAP_ENCODER_TARGET
330 int32_t encTargetLevel = mIntf->getDrcEncTargetLevel();
331 ALOGV("AAC decoder using encoder-side DRC reference level of %d", encTargetLevel);
332 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, (unsigned)encTargetLevel);
333
334 // AAC_UNIDRC_SET_EFFECT
335 int32_t effectType = mIntf->getDrcEffectType();
336 ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
337 aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
338
339 // By default, the decoder creates a 5.1 channel downmix signal.
340 // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
341 aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
342
343 return status;
344}
345
346bool C2SoftAacDec::outputDelayRingBufferPutSamples(INT_PCM *samples, int32_t numSamples) {
347 if (numSamples == 0) {
348 return true;
349 }
350 if (outputDelayRingBufferSpaceLeft() < numSamples) {
351 ALOGE("RING BUFFER WOULD OVERFLOW");
352 return false;
353 }
354 if (mOutputDelayRingBufferWritePos + numSamples <= mOutputDelayRingBufferSize
355 && (mOutputDelayRingBufferReadPos <= mOutputDelayRingBufferWritePos
356 || mOutputDelayRingBufferReadPos > mOutputDelayRingBufferWritePos + numSamples)) {
357 // faster memcopy loop without checks, if the preconditions allow this
358 for (int32_t i = 0; i < numSamples; i++) {
359 mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos++] = samples[i];
360 }
361
362 if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
363 mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
364 }
365 } else {
366 ALOGV("slow C2SoftAacDec::outputDelayRingBufferPutSamples()");
367
368 for (int32_t i = 0; i < numSamples; i++) {
369 mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos] = samples[i];
370 mOutputDelayRingBufferWritePos++;
371 if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
372 mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
373 }
374 }
375 }
376 mOutputDelayRingBufferFilled += numSamples;
377 return true;
378}
379
380int32_t C2SoftAacDec::outputDelayRingBufferGetSamples(INT_PCM *samples, int32_t numSamples) {
381
382 if (numSamples > mOutputDelayRingBufferFilled) {
383 ALOGE("RING BUFFER WOULD UNDERRUN");
384 return -1;
385 }
386
387 if (mOutputDelayRingBufferReadPos + numSamples <= mOutputDelayRingBufferSize
388 && (mOutputDelayRingBufferWritePos < mOutputDelayRingBufferReadPos
389 || mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferReadPos + numSamples)) {
390 // faster memcopy loop without checks, if the preconditions allow this
391 if (samples != nullptr) {
392 for (int32_t i = 0; i < numSamples; i++) {
393 samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos++];
394 }
395 } else {
396 mOutputDelayRingBufferReadPos += numSamples;
397 }
398 if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
399 mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
400 }
401 } else {
402 ALOGV("slow C2SoftAacDec::outputDelayRingBufferGetSamples()");
403
404 for (int32_t i = 0; i < numSamples; i++) {
405 if (samples != nullptr) {
406 samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos];
407 }
408 mOutputDelayRingBufferReadPos++;
409 if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
410 mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
411 }
412 }
413 }
414 mOutputDelayRingBufferFilled -= numSamples;
415 return numSamples;
416}
417
418int32_t C2SoftAacDec::outputDelayRingBufferSamplesAvailable() {
419 return mOutputDelayRingBufferFilled;
420}
421
422int32_t C2SoftAacDec::outputDelayRingBufferSpaceLeft() {
423 return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable();
424}
425
426void C2SoftAacDec::drainRingBuffer(
427 const std::unique_ptr<C2Work> &work,
428 const std::shared_ptr<C2BlockPool> &pool,
429 bool eos) {
430 while (!mBuffersInfo.empty() && outputDelayRingBufferSamplesAvailable()
431 >= mStreamInfo->frameSize * mStreamInfo->numChannels) {
432 Info &outInfo = mBuffersInfo.front();
433 ALOGV("outInfo.frameIndex = %" PRIu64, outInfo.frameIndex);
434 int samplesize __unused = mStreamInfo->numChannels * sizeof(int16_t);
435
436 int available = outputDelayRingBufferSamplesAvailable();
437 int numFrames = outInfo.decodedSizes.size();
438 int numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels);
439 if (available < numSamples) {
440 if (eos) {
441 numSamples = available;
442 } else {
443 break;
444 }
445 }
446 ALOGV("%d samples available (%d), or %d frames",
447 numSamples, available, numFrames);
448 ALOGV("getting %d from ringbuffer", numSamples);
449
450 std::shared_ptr<C2LinearBlock> block;
451 std::function<void(const std::unique_ptr<C2Work>&)> fillWork =
452 [&block, numSamples, pool, this]()
453 -> std::function<void(const std::unique_ptr<C2Work>&)> {
454 auto fillEmptyWork = [](
455 const std::unique_ptr<C2Work> &work, c2_status_t err) {
456 work->result = err;
457 C2FrameData &output = work->worklets.front()->output;
458 output.flags = work->input.flags;
459 output.buffers.clear();
460 output.ordinal = work->input.ordinal;
461
462 work->workletsProcessed = 1u;
463 };
464
465 using namespace std::placeholders;
466 if (numSamples == 0) {
467 return std::bind(fillEmptyWork, _1, C2_OK);
468 }
469
470 // TODO: error handling, proper usage, etc.
471 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
472 c2_status_t err = pool->fetchLinearBlock(
473 numSamples * sizeof(int16_t), usage, &block);
474 if (err != C2_OK) {
475 ALOGD("failed to fetch a linear block (%d)", err);
476 return std::bind(fillEmptyWork, _1, C2_NO_MEMORY);
477 }
478 C2WriteView wView = block->map().get();
479 // TODO
480 INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(wView.data());
481 int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples);
482 if (ns != numSamples) {
483 ALOGE("not a complete frame of samples available");
484 mSignalledError = true;
485 return std::bind(fillEmptyWork, _1, C2_CORRUPTED);
486 }
487 return [buffer = createLinearBuffer(block)](
488 const std::unique_ptr<C2Work> &work) {
489 work->result = C2_OK;
490 C2FrameData &output = work->worklets.front()->output;
491 output.flags = work->input.flags;
492 output.buffers.clear();
493 output.buffers.push_back(buffer);
494 output.ordinal = work->input.ordinal;
495 work->workletsProcessed = 1u;
496 };
497 }();
498
499 if (work && work->input.ordinal.frameIndex == c2_cntr64_t(outInfo.frameIndex)) {
500 fillWork(work);
501 } else {
502 finish(outInfo.frameIndex, fillWork);
503 }
504
505 ALOGV("out timestamp %" PRIu64 " / %u", outInfo.timestamp, block ? block->capacity() : 0);
506 mBuffersInfo.pop_front();
507 }
508}
509
510void C2SoftAacDec::process(
511 const std::unique_ptr<C2Work> &work,
512 const std::shared_ptr<C2BlockPool> &pool) {
513 // Initialize output work
514 work->result = C2_OK;
515 work->workletsProcessed = 1u;
516 work->worklets.front()->output.configUpdate.clear();
517 work->worklets.front()->output.flags = work->input.flags;
518
519 if (mSignalledError) {
520 return;
521 }
522
523 UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
524 UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
525 UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
526
527 INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
528 C2ReadView view = mDummyReadView;
529 size_t offset = 0u;
530 size_t size = 0u;
531 if (!work->input.buffers.empty()) {
532 view = work->input.buffers[0]->data().linearBlocks().front().map().get();
533 size = view.capacity();
534 }
535
536 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
537 bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
538
539 //TODO
540#if 0
541 if (mInputBufferCount == 0 && !codecConfig) {
542 ALOGW("first buffer should have FLAG_CODEC_CONFIG set");
543 codecConfig = true;
544 }
545#endif
546 if (codecConfig && size > 0u) {
547 // const_cast because of libAACdec method signature.
548 inBuffer[0] = const_cast<UCHAR *>(view.data() + offset);
549 inBufferLength[0] = size;
550
551 AAC_DECODER_ERROR decoderErr =
552 aacDecoder_ConfigRaw(mAACDecoder,
553 inBuffer,
554 inBufferLength);
555
556 if (decoderErr != AAC_DEC_OK) {
557 ALOGE("aacDecoder_ConfigRaw decoderErr = 0x%4.4x", decoderErr);
558 mSignalledError = true;
559 work->result = C2_CORRUPTED;
560 return;
561 }
562 work->worklets.front()->output.flags = work->input.flags;
563 work->worklets.front()->output.ordinal = work->input.ordinal;
564 work->worklets.front()->output.buffers.clear();
565 return;
566 }
567
568 Info inInfo;
569 inInfo.frameIndex = work->input.ordinal.frameIndex.peeku();
570 inInfo.timestamp = work->input.ordinal.timestamp.peeku();
571 inInfo.bufferSize = size;
572 inInfo.decodedSizes.clear();
573 while (size > 0u) {
574 ALOGV("size = %zu", size);
575 if (mIntf->isAdts()) {
576 size_t adtsHeaderSize = 0;
577 // skip 30 bits, aac_frame_length follows.
578 // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
579
580 const uint8_t *adtsHeader = view.data() + offset;
581
582 bool signalError = false;
583 if (size < 7) {
584 ALOGE("Audio data too short to contain even the ADTS header. "
585 "Got %zu bytes.", size);
586 hexdump(adtsHeader, size);
587 signalError = true;
588 } else {
589 bool protectionAbsent = (adtsHeader[1] & 1);
590
591 unsigned aac_frame_length =
592 ((adtsHeader[3] & 3) << 11)
593 | (adtsHeader[4] << 3)
594 | (adtsHeader[5] >> 5);
595
596 if (size < aac_frame_length) {
597 ALOGE("Not enough audio data for the complete frame. "
598 "Got %zu bytes, frame size according to the ADTS "
599 "header is %u bytes.",
600 size, aac_frame_length);
601 hexdump(adtsHeader, size);
602 signalError = true;
603 } else {
604 adtsHeaderSize = (protectionAbsent ? 7 : 9);
605 if (aac_frame_length < adtsHeaderSize) {
606 signalError = true;
607 } else {
608 // const_cast because of libAACdec method signature.
609 inBuffer[0] = const_cast<UCHAR *>(adtsHeader + adtsHeaderSize);
610 inBufferLength[0] = aac_frame_length - adtsHeaderSize;
611
612 offset += adtsHeaderSize;
613 size -= adtsHeaderSize;
614 }
615 }
616 }
617
618 if (signalError) {
619 mSignalledError = true;
620 work->result = C2_CORRUPTED;
621 return;
622 }
623 } else {
624 // const_cast because of libAACdec method signature.
625 inBuffer[0] = const_cast<UCHAR *>(view.data() + offset);
626 inBufferLength[0] = size;
627 }
628
629 // Fill and decode
630 bytesValid[0] = inBufferLength[0];
631
632 INT prevSampleRate = mStreamInfo->sampleRate;
633 INT prevNumChannels = mStreamInfo->numChannels;
634
635 aacDecoder_Fill(mAACDecoder,
636 inBuffer,
637 inBufferLength,
638 bytesValid);
639
640 // run DRC check
641 mDrcWrap.submitStreamData(mStreamInfo);
642 mDrcWrap.update();
643
644 UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
645 size -= inBufferUsedLength;
646 offset += inBufferUsedLength;
647
648 AAC_DECODER_ERROR decoderErr;
649 do {
650 if (outputDelayRingBufferSpaceLeft() <
651 (mStreamInfo->frameSize * mStreamInfo->numChannels)) {
652 ALOGV("skipping decode: not enough space left in ringbuffer");
653 // discard buffer
654 size = 0;
655 break;
656 }
657
658 int numConsumed = mStreamInfo->numTotalBytes;
659 decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
660 tmpOutBuffer,
661 2048 * MAX_CHANNEL_COUNT,
662 0 /* flags */);
663
664 numConsumed = mStreamInfo->numTotalBytes - numConsumed;
665
666 if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
667 break;
668 }
669 inInfo.decodedSizes.push_back(numConsumed);
670
671 if (decoderErr != AAC_DEC_OK) {
672 ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
673 }
674
675 if (bytesValid[0] != 0) {
676 ALOGE("bytesValid[0] != 0 should never happen");
677 mSignalledError = true;
678 work->result = C2_CORRUPTED;
679 return;
680 }
681
682 size_t numOutBytes =
683 mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
684
685 if (decoderErr == AAC_DEC_OK) {
686 if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
687 mStreamInfo->frameSize * mStreamInfo->numChannels)) {
688 mSignalledError = true;
689 work->result = C2_CORRUPTED;
690 return;
691 }
692 } else {
693 ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr);
694
695 memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow
696
697 if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
698 mStreamInfo->frameSize * mStreamInfo->numChannels)) {
699 mSignalledError = true;
700 work->result = C2_CORRUPTED;
701 return;
702 }
703
704 // Discard input buffer.
705 size = 0;
706
707 aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
708
709 // After an error, replace bufferSize with the sum of the
710 // decodedSizes to resynchronize the in/out lists.
711 inInfo.decodedSizes.pop_back();
712 inInfo.bufferSize = std::accumulate(
713 inInfo.decodedSizes.begin(), inInfo.decodedSizes.end(), 0);
714
715 // fall through
716 }
717
718 /*
719 * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
720 * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
721 * rate system and the sampling rate in the final output is actually
722 * doubled compared with the core AAC decoder sampling rate.
723 *
724 * Explicit signalling is done by explicitly defining SBR audio object
725 * type in the bitstream. Implicit signalling is done by embedding
726 * SBR content in AAC extension payload specific to SBR, and hence
727 * requires an AAC decoder to perform pre-checks on actual audio frames.
728 *
729 * Thus, we could not say for sure whether a stream is
730 * AAC+/eAAC+ until the first data frame is decoded.
731 */
732 if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
733 // if ((mInputBufferCount > 2) && (mOutputBufferCount <= 1)) {
734 ALOGD("Invalid AAC stream");
735 // TODO: notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
736 // mSignalledError = true;
737 // }
738 } else if ((mStreamInfo->sampleRate != prevSampleRate) ||
739 (mStreamInfo->numChannels != prevNumChannels)) {
740 ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
741 prevSampleRate, mStreamInfo->sampleRate,
742 prevNumChannels, mStreamInfo->numChannels);
743
744 C2StreamSampleRateInfo::output sampleRateInfo(0u, mStreamInfo->sampleRate);
745 C2StreamChannelCountInfo::output channelCountInfo(0u, mStreamInfo->numChannels);
746 std::vector<std::unique_ptr<C2SettingResult>> failures;
747 c2_status_t err = mIntf->config(
748 { &sampleRateInfo, &channelCountInfo },
749 C2_MAY_BLOCK,
750 &failures);
751 if (err == OK) {
752 // TODO: this does not handle the case where the values are
753 // altered during config.
754 C2FrameData &output = work->worklets.front()->output;
755 output.configUpdate.push_back(C2Param::Copy(sampleRateInfo));
756 output.configUpdate.push_back(C2Param::Copy(channelCountInfo));
757 } else {
758 ALOGE("Config Update failed");
759 mSignalledError = true;
760 work->result = C2_CORRUPTED;
761 return;
762 }
763 }
764 ALOGV("size = %zu", size);
765 } while (decoderErr == AAC_DEC_OK);
766 }
767
768 int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
769
770 mBuffersInfo.push_back(std::move(inInfo));
771 work->workletsProcessed = 0u;
772 if (!eos && mOutputDelayCompensated < outputDelay) {
773 // discard outputDelay at the beginning
774 int32_t toCompensate = outputDelay - mOutputDelayCompensated;
775 int32_t discard = outputDelayRingBufferSamplesAvailable();
776 if (discard > toCompensate) {
777 discard = toCompensate;
778 }
779 int32_t discarded = outputDelayRingBufferGetSamples(nullptr, discard);
780 mOutputDelayCompensated += discarded;
781 return;
782 }
783
784 if (eos) {
785 drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
786 } else {
787 drainRingBuffer(work, pool, false /* not EOS */);
788 }
789}
790
791c2_status_t C2SoftAacDec::drainInternal(
792 uint32_t drainMode,
793 const std::shared_ptr<C2BlockPool> &pool,
794 const std::unique_ptr<C2Work> &work) {
795 if (drainMode == NO_DRAIN) {
796 ALOGW("drain with NO_DRAIN: no-op");
797 return C2_OK;
798 }
799 if (drainMode == DRAIN_CHAIN) {
800 ALOGW("DRAIN_CHAIN not supported");
801 return C2_OMITTED;
802 }
803
804 bool eos = (drainMode == DRAIN_COMPONENT_WITH_EOS);
805
806 drainDecoder();
807 drainRingBuffer(work, pool, eos);
808
809 if (eos) {
810 auto fillEmptyWork = [](const std::unique_ptr<C2Work> &work) {
811 work->worklets.front()->output.flags = work->input.flags;
812 work->worklets.front()->output.buffers.clear();
813 work->worklets.front()->output.ordinal = work->input.ordinal;
814 work->workletsProcessed = 1u;
815 };
816 while (mBuffersInfo.size() > 1u) {
817 finish(mBuffersInfo.front().frameIndex, fillEmptyWork);
818 mBuffersInfo.pop_front();
819 }
820 if (work && work->workletsProcessed == 0u) {
821 fillEmptyWork(work);
822 }
823 mBuffersInfo.clear();
824 }
825
826 return C2_OK;
827}
828
829c2_status_t C2SoftAacDec::drain(
830 uint32_t drainMode,
831 const std::shared_ptr<C2BlockPool> &pool) {
832 return drainInternal(drainMode, pool, nullptr);
833}
834
835c2_status_t C2SoftAacDec::onFlush_sm() {
836 drainDecoder();
837 mBuffersInfo.clear();
838
839 int avail;
840 while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) {
841 if (avail > mStreamInfo->frameSize * mStreamInfo->numChannels) {
842 avail = mStreamInfo->frameSize * mStreamInfo->numChannels;
843 }
844 int32_t ns = outputDelayRingBufferGetSamples(nullptr, avail);
845 if (ns != avail) {
846 ALOGW("not a complete frame of samples available");
847 break;
848 }
849 }
850 mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos;
851
852 return C2_OK;
853}
854
855void C2SoftAacDec::drainDecoder() {
856 // flush decoder until outputDelay is compensated
857 while (mOutputDelayCompensated > 0) {
858 // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
859 INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
860
861 // run DRC check
862 mDrcWrap.submitStreamData(mStreamInfo);
863 mDrcWrap.update();
864
865 AAC_DECODER_ERROR decoderErr =
866 aacDecoder_DecodeFrame(mAACDecoder,
867 tmpOutBuffer,
868 2048 * MAX_CHANNEL_COUNT,
869 AACDEC_FLUSH);
870 if (decoderErr != AAC_DEC_OK) {
871 ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
872 }
873
874 int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels;
875 if (tmpOutBufferSamples > mOutputDelayCompensated) {
876 tmpOutBufferSamples = mOutputDelayCompensated;
877 }
878 outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples);
879
880 mOutputDelayCompensated -= tmpOutBufferSamples;
881 }
882}
883
884class C2SoftAacDecFactory : public C2ComponentFactory {
885public:
886 C2SoftAacDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
887 GetCodec2PlatformComponentStore()->getParamReflector())) {
888 }
889
890 virtual c2_status_t createComponent(
891 c2_node_id_t id,
892 std::shared_ptr<C2Component>* const component,
893 std::function<void(C2Component*)> deleter) override {
894 *component = std::shared_ptr<C2Component>(
895 new C2SoftAacDec(COMPONENT_NAME,
896 id,
897 std::make_shared<C2SoftAacDec::IntfImpl>(mHelper)),
898 deleter);
899 return C2_OK;
900 }
901
902 virtual c2_status_t createInterface(
903 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
904 std::function<void(C2ComponentInterface*)> deleter) override {
905 *interface = std::shared_ptr<C2ComponentInterface>(
906 new SimpleInterface<C2SoftAacDec::IntfImpl>(
907 COMPONENT_NAME, id, std::make_shared<C2SoftAacDec::IntfImpl>(mHelper)),
908 deleter);
909 return C2_OK;
910 }
911
912 virtual ~C2SoftAacDecFactory() override = default;
913
914private:
915 std::shared_ptr<C2ReflectorHelper> mHelper;
916};
917
918} // namespace android
919
920extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
921 ALOGV("in %s", __func__);
922 return new ::android::C2SoftAacDecFactory();
923}
924
925extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
926 ALOGV("in %s", __func__);
927 delete factory;
928}