blob: 4d00d35680739a66a90c80e4cd52434a6049432f [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:
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800208 std::shared_ptr<C2StreamBufferTypeSetting::input> mInputFormat;
209 std::shared_ptr<C2StreamBufferTypeSetting::output> mOutputFormat;
210 std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType;
211 std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800212 std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
213 std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
Lajos Molnar3bb81cd2019-02-20 15:10:30 -0800214 std::shared_ptr<C2StreamBitrateInfo::input> mBitrate;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800215 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
216 std::shared_ptr<C2StreamAacFormatInfo::input> mAacFormat;
217 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
218 std::shared_ptr<C2StreamDrcCompressionModeTuning::input> mDrcCompressMode;
219 std::shared_ptr<C2StreamDrcTargetReferenceLevelTuning::input> mDrcTargetRefLevel;
220 std::shared_ptr<C2StreamDrcEncodedTargetLevelTuning::input> mDrcEncTargetLevel;
221 std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor;
222 std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor;
223 std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType;
224 // TODO Add : C2StreamAacSbrModeTuning
225};
226
Pawin Vongmasa36653902018-11-15 00:10:25 -0800227C2SoftAacDec::C2SoftAacDec(
228 const char *name,
229 c2_node_id_t id,
230 const std::shared_ptr<IntfImpl> &intfImpl)
231 : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
232 mIntf(intfImpl),
233 mAACDecoder(nullptr),
234 mStreamInfo(nullptr),
235 mSignalledError(false),
236 mOutputDelayRingBuffer(nullptr) {
237}
238
239C2SoftAacDec::~C2SoftAacDec() {
240 onRelease();
241}
242
243c2_status_t C2SoftAacDec::onInit() {
244 status_t err = initDecoder();
245 return err == OK ? C2_OK : C2_CORRUPTED;
246}
247
248c2_status_t C2SoftAacDec::onStop() {
249 drainDecoder();
250 // reset the "configured" state
251 mOutputDelayCompensated = 0;
252 mOutputDelayRingBufferWritePos = 0;
253 mOutputDelayRingBufferReadPos = 0;
254 mOutputDelayRingBufferFilled = 0;
255 mBuffersInfo.clear();
256
257 // To make the codec behave the same before and after a reset, we need to invalidate the
258 // streaminfo struct. This does that:
259 mStreamInfo->sampleRate = 0; // TODO: mStreamInfo is read only
260
261 mSignalledError = false;
262
263 return C2_OK;
264}
265
266void C2SoftAacDec::onReset() {
267 (void)onStop();
268}
269
270void C2SoftAacDec::onRelease() {
271 if (mAACDecoder) {
272 aacDecoder_Close(mAACDecoder);
273 mAACDecoder = nullptr;
274 }
275 if (mOutputDelayRingBuffer) {
276 delete[] mOutputDelayRingBuffer;
277 mOutputDelayRingBuffer = nullptr;
278 }
279}
280
281status_t C2SoftAacDec::initDecoder() {
282 ALOGV("initDecoder()");
283 status_t status = UNKNOWN_ERROR;
284 mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1);
285 if (mAACDecoder != nullptr) {
286 mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder);
287 if (mStreamInfo != nullptr) {
288 status = OK;
289 }
290 }
291
292 mOutputDelayCompensated = 0;
293 mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax;
294 mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize];
295 mOutputDelayRingBufferWritePos = 0;
296 mOutputDelayRingBufferReadPos = 0;
297 mOutputDelayRingBufferFilled = 0;
298
299 if (mAACDecoder == nullptr) {
300 ALOGE("AAC decoder is null. TODO: Can not call aacDecoder_SetParam in the following code");
301 }
302
303 //aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE, 0);
304
305 //init DRC wrapper
306 mDrcWrap.setDecoderHandle(mAACDecoder);
307 mDrcWrap.submitStreamData(mStreamInfo);
308
309 // for streams that contain metadata, use the mobile profile DRC settings unless overridden by platform properties
310 // TODO: change the DRC settings depending on audio output device type (HDMI, loadspeaker, headphone)
311
312 // DRC_PRES_MODE_WRAP_DESIRED_TARGET
313 int32_t targetRefLevel = mIntf->getDrcTargetRefLevel();
314 ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel);
315 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, (unsigned)targetRefLevel);
316
317 // DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
318
319 int32_t attenuationFactor = mIntf->getDrcAttenuationFactor();
320 ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor);
321 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, (unsigned)attenuationFactor);
322
323 // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
324 int32_t boostFactor = mIntf->getDrcBoostFactor();
325 ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor);
326 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, (unsigned)boostFactor);
327
328 // DRC_PRES_MODE_WRAP_DESIRED_HEAVY
329 int32_t compressMode = mIntf->getDrcCompressMode();
330 ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
331 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
332
333 // DRC_PRES_MODE_WRAP_ENCODER_TARGET
334 int32_t encTargetLevel = mIntf->getDrcEncTargetLevel();
335 ALOGV("AAC decoder using encoder-side DRC reference level of %d", encTargetLevel);
336 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, (unsigned)encTargetLevel);
337
338 // AAC_UNIDRC_SET_EFFECT
339 int32_t effectType = mIntf->getDrcEffectType();
340 ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
341 aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
342
343 // By default, the decoder creates a 5.1 channel downmix signal.
344 // For seven and eight channel input streams, enable 6.1 and 7.1 channel output
345 aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
346
347 return status;
348}
349
350bool C2SoftAacDec::outputDelayRingBufferPutSamples(INT_PCM *samples, int32_t numSamples) {
351 if (numSamples == 0) {
352 return true;
353 }
354 if (outputDelayRingBufferSpaceLeft() < numSamples) {
355 ALOGE("RING BUFFER WOULD OVERFLOW");
356 return false;
357 }
358 if (mOutputDelayRingBufferWritePos + numSamples <= mOutputDelayRingBufferSize
359 && (mOutputDelayRingBufferReadPos <= mOutputDelayRingBufferWritePos
360 || mOutputDelayRingBufferReadPos > mOutputDelayRingBufferWritePos + numSamples)) {
361 // faster memcopy loop without checks, if the preconditions allow this
362 for (int32_t i = 0; i < numSamples; i++) {
363 mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos++] = samples[i];
364 }
365
366 if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
367 mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
368 }
369 } else {
370 ALOGV("slow C2SoftAacDec::outputDelayRingBufferPutSamples()");
371
372 for (int32_t i = 0; i < numSamples; i++) {
373 mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos] = samples[i];
374 mOutputDelayRingBufferWritePos++;
375 if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) {
376 mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize;
377 }
378 }
379 }
380 mOutputDelayRingBufferFilled += numSamples;
381 return true;
382}
383
384int32_t C2SoftAacDec::outputDelayRingBufferGetSamples(INT_PCM *samples, int32_t numSamples) {
385
386 if (numSamples > mOutputDelayRingBufferFilled) {
387 ALOGE("RING BUFFER WOULD UNDERRUN");
388 return -1;
389 }
390
391 if (mOutputDelayRingBufferReadPos + numSamples <= mOutputDelayRingBufferSize
392 && (mOutputDelayRingBufferWritePos < mOutputDelayRingBufferReadPos
393 || mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferReadPos + numSamples)) {
394 // faster memcopy loop without checks, if the preconditions allow this
395 if (samples != nullptr) {
396 for (int32_t i = 0; i < numSamples; i++) {
397 samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos++];
398 }
399 } else {
400 mOutputDelayRingBufferReadPos += numSamples;
401 }
402 if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
403 mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
404 }
405 } else {
406 ALOGV("slow C2SoftAacDec::outputDelayRingBufferGetSamples()");
407
408 for (int32_t i = 0; i < numSamples; i++) {
409 if (samples != nullptr) {
410 samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos];
411 }
412 mOutputDelayRingBufferReadPos++;
413 if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) {
414 mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize;
415 }
416 }
417 }
418 mOutputDelayRingBufferFilled -= numSamples;
419 return numSamples;
420}
421
422int32_t C2SoftAacDec::outputDelayRingBufferSamplesAvailable() {
423 return mOutputDelayRingBufferFilled;
424}
425
426int32_t C2SoftAacDec::outputDelayRingBufferSpaceLeft() {
427 return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable();
428}
429
430void C2SoftAacDec::drainRingBuffer(
431 const std::unique_ptr<C2Work> &work,
432 const std::shared_ptr<C2BlockPool> &pool,
433 bool eos) {
434 while (!mBuffersInfo.empty() && outputDelayRingBufferSamplesAvailable()
435 >= mStreamInfo->frameSize * mStreamInfo->numChannels) {
436 Info &outInfo = mBuffersInfo.front();
437 ALOGV("outInfo.frameIndex = %" PRIu64, outInfo.frameIndex);
438 int samplesize __unused = mStreamInfo->numChannels * sizeof(int16_t);
439
440 int available = outputDelayRingBufferSamplesAvailable();
441 int numFrames = outInfo.decodedSizes.size();
442 int numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels);
443 if (available < numSamples) {
444 if (eos) {
445 numSamples = available;
446 } else {
447 break;
448 }
449 }
450 ALOGV("%d samples available (%d), or %d frames",
451 numSamples, available, numFrames);
452 ALOGV("getting %d from ringbuffer", numSamples);
453
454 std::shared_ptr<C2LinearBlock> block;
455 std::function<void(const std::unique_ptr<C2Work>&)> fillWork =
456 [&block, numSamples, pool, this]()
457 -> std::function<void(const std::unique_ptr<C2Work>&)> {
458 auto fillEmptyWork = [](
459 const std::unique_ptr<C2Work> &work, c2_status_t err) {
460 work->result = err;
461 C2FrameData &output = work->worklets.front()->output;
462 output.flags = work->input.flags;
463 output.buffers.clear();
464 output.ordinal = work->input.ordinal;
465
466 work->workletsProcessed = 1u;
467 };
468
469 using namespace std::placeholders;
470 if (numSamples == 0) {
471 return std::bind(fillEmptyWork, _1, C2_OK);
472 }
473
474 // TODO: error handling, proper usage, etc.
475 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
476 c2_status_t err = pool->fetchLinearBlock(
477 numSamples * sizeof(int16_t), usage, &block);
478 if (err != C2_OK) {
479 ALOGD("failed to fetch a linear block (%d)", err);
480 return std::bind(fillEmptyWork, _1, C2_NO_MEMORY);
481 }
482 C2WriteView wView = block->map().get();
483 // TODO
484 INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(wView.data());
485 int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples);
486 if (ns != numSamples) {
487 ALOGE("not a complete frame of samples available");
488 mSignalledError = true;
489 return std::bind(fillEmptyWork, _1, C2_CORRUPTED);
490 }
491 return [buffer = createLinearBuffer(block)](
492 const std::unique_ptr<C2Work> &work) {
493 work->result = C2_OK;
494 C2FrameData &output = work->worklets.front()->output;
495 output.flags = work->input.flags;
496 output.buffers.clear();
497 output.buffers.push_back(buffer);
498 output.ordinal = work->input.ordinal;
499 work->workletsProcessed = 1u;
500 };
501 }();
502
503 if (work && work->input.ordinal.frameIndex == c2_cntr64_t(outInfo.frameIndex)) {
504 fillWork(work);
505 } else {
506 finish(outInfo.frameIndex, fillWork);
507 }
508
509 ALOGV("out timestamp %" PRIu64 " / %u", outInfo.timestamp, block ? block->capacity() : 0);
510 mBuffersInfo.pop_front();
511 }
512}
513
514void C2SoftAacDec::process(
515 const std::unique_ptr<C2Work> &work,
516 const std::shared_ptr<C2BlockPool> &pool) {
517 // Initialize output work
518 work->result = C2_OK;
519 work->workletsProcessed = 1u;
520 work->worklets.front()->output.configUpdate.clear();
521 work->worklets.front()->output.flags = work->input.flags;
522
523 if (mSignalledError) {
524 return;
525 }
526
527 UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
528 UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
529 UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
530
531 INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
532 C2ReadView view = mDummyReadView;
533 size_t offset = 0u;
534 size_t size = 0u;
535 if (!work->input.buffers.empty()) {
536 view = work->input.buffers[0]->data().linearBlocks().front().map().get();
537 size = view.capacity();
538 }
539
540 bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
541 bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
542
543 //TODO
544#if 0
545 if (mInputBufferCount == 0 && !codecConfig) {
546 ALOGW("first buffer should have FLAG_CODEC_CONFIG set");
547 codecConfig = true;
548 }
549#endif
550 if (codecConfig && size > 0u) {
551 // const_cast because of libAACdec method signature.
552 inBuffer[0] = const_cast<UCHAR *>(view.data() + offset);
553 inBufferLength[0] = size;
554
555 AAC_DECODER_ERROR decoderErr =
556 aacDecoder_ConfigRaw(mAACDecoder,
557 inBuffer,
558 inBufferLength);
559
560 if (decoderErr != AAC_DEC_OK) {
561 ALOGE("aacDecoder_ConfigRaw decoderErr = 0x%4.4x", decoderErr);
562 mSignalledError = true;
563 work->result = C2_CORRUPTED;
564 return;
565 }
566 work->worklets.front()->output.flags = work->input.flags;
567 work->worklets.front()->output.ordinal = work->input.ordinal;
568 work->worklets.front()->output.buffers.clear();
569 return;
570 }
571
572 Info inInfo;
573 inInfo.frameIndex = work->input.ordinal.frameIndex.peeku();
574 inInfo.timestamp = work->input.ordinal.timestamp.peeku();
575 inInfo.bufferSize = size;
576 inInfo.decodedSizes.clear();
577 while (size > 0u) {
578 ALOGV("size = %zu", size);
579 if (mIntf->isAdts()) {
580 size_t adtsHeaderSize = 0;
581 // skip 30 bits, aac_frame_length follows.
582 // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
583
584 const uint8_t *adtsHeader = view.data() + offset;
585
586 bool signalError = false;
587 if (size < 7) {
588 ALOGE("Audio data too short to contain even the ADTS header. "
589 "Got %zu bytes.", size);
590 hexdump(adtsHeader, size);
591 signalError = true;
592 } else {
593 bool protectionAbsent = (adtsHeader[1] & 1);
594
595 unsigned aac_frame_length =
596 ((adtsHeader[3] & 3) << 11)
597 | (adtsHeader[4] << 3)
598 | (adtsHeader[5] >> 5);
599
600 if (size < aac_frame_length) {
601 ALOGE("Not enough audio data for the complete frame. "
602 "Got %zu bytes, frame size according to the ADTS "
603 "header is %u bytes.",
604 size, aac_frame_length);
605 hexdump(adtsHeader, size);
606 signalError = true;
607 } else {
608 adtsHeaderSize = (protectionAbsent ? 7 : 9);
609 if (aac_frame_length < adtsHeaderSize) {
610 signalError = true;
611 } else {
612 // const_cast because of libAACdec method signature.
613 inBuffer[0] = const_cast<UCHAR *>(adtsHeader + adtsHeaderSize);
614 inBufferLength[0] = aac_frame_length - adtsHeaderSize;
615
616 offset += adtsHeaderSize;
617 size -= adtsHeaderSize;
618 }
619 }
620 }
621
622 if (signalError) {
623 mSignalledError = true;
624 work->result = C2_CORRUPTED;
625 return;
626 }
627 } else {
628 // const_cast because of libAACdec method signature.
629 inBuffer[0] = const_cast<UCHAR *>(view.data() + offset);
630 inBufferLength[0] = size;
631 }
632
633 // Fill and decode
634 bytesValid[0] = inBufferLength[0];
635
636 INT prevSampleRate = mStreamInfo->sampleRate;
637 INT prevNumChannels = mStreamInfo->numChannels;
638
639 aacDecoder_Fill(mAACDecoder,
640 inBuffer,
641 inBufferLength,
642 bytesValid);
643
644 // run DRC check
645 mDrcWrap.submitStreamData(mStreamInfo);
646 mDrcWrap.update();
647
648 UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
649 size -= inBufferUsedLength;
650 offset += inBufferUsedLength;
651
652 AAC_DECODER_ERROR decoderErr;
653 do {
654 if (outputDelayRingBufferSpaceLeft() <
655 (mStreamInfo->frameSize * mStreamInfo->numChannels)) {
656 ALOGV("skipping decode: not enough space left in ringbuffer");
657 // discard buffer
658 size = 0;
659 break;
660 }
661
662 int numConsumed = mStreamInfo->numTotalBytes;
663 decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
664 tmpOutBuffer,
665 2048 * MAX_CHANNEL_COUNT,
666 0 /* flags */);
667
668 numConsumed = mStreamInfo->numTotalBytes - numConsumed;
669
670 if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
671 break;
672 }
673 inInfo.decodedSizes.push_back(numConsumed);
674
675 if (decoderErr != AAC_DEC_OK) {
676 ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
677 }
678
679 if (bytesValid[0] != 0) {
680 ALOGE("bytesValid[0] != 0 should never happen");
681 mSignalledError = true;
682 work->result = C2_CORRUPTED;
683 return;
684 }
685
686 size_t numOutBytes =
687 mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
688
689 if (decoderErr == AAC_DEC_OK) {
690 if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
691 mStreamInfo->frameSize * mStreamInfo->numChannels)) {
692 mSignalledError = true;
693 work->result = C2_CORRUPTED;
694 return;
695 }
696 } else {
697 ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr);
698
699 memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow
700
701 if (!outputDelayRingBufferPutSamples(tmpOutBuffer,
702 mStreamInfo->frameSize * mStreamInfo->numChannels)) {
703 mSignalledError = true;
704 work->result = C2_CORRUPTED;
705 return;
706 }
707
708 // Discard input buffer.
709 size = 0;
710
711 aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
712
713 // After an error, replace bufferSize with the sum of the
714 // decodedSizes to resynchronize the in/out lists.
715 inInfo.decodedSizes.pop_back();
716 inInfo.bufferSize = std::accumulate(
717 inInfo.decodedSizes.begin(), inInfo.decodedSizes.end(), 0);
718
719 // fall through
720 }
721
722 /*
723 * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
724 * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
725 * rate system and the sampling rate in the final output is actually
726 * doubled compared with the core AAC decoder sampling rate.
727 *
728 * Explicit signalling is done by explicitly defining SBR audio object
729 * type in the bitstream. Implicit signalling is done by embedding
730 * SBR content in AAC extension payload specific to SBR, and hence
731 * requires an AAC decoder to perform pre-checks on actual audio frames.
732 *
733 * Thus, we could not say for sure whether a stream is
734 * AAC+/eAAC+ until the first data frame is decoded.
735 */
736 if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) {
737 // if ((mInputBufferCount > 2) && (mOutputBufferCount <= 1)) {
738 ALOGD("Invalid AAC stream");
739 // TODO: notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
740 // mSignalledError = true;
741 // }
742 } else if ((mStreamInfo->sampleRate != prevSampleRate) ||
743 (mStreamInfo->numChannels != prevNumChannels)) {
744 ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels",
745 prevSampleRate, mStreamInfo->sampleRate,
746 prevNumChannels, mStreamInfo->numChannels);
747
748 C2StreamSampleRateInfo::output sampleRateInfo(0u, mStreamInfo->sampleRate);
749 C2StreamChannelCountInfo::output channelCountInfo(0u, mStreamInfo->numChannels);
750 std::vector<std::unique_ptr<C2SettingResult>> failures;
751 c2_status_t err = mIntf->config(
752 { &sampleRateInfo, &channelCountInfo },
753 C2_MAY_BLOCK,
754 &failures);
755 if (err == OK) {
756 // TODO: this does not handle the case where the values are
757 // altered during config.
758 C2FrameData &output = work->worklets.front()->output;
759 output.configUpdate.push_back(C2Param::Copy(sampleRateInfo));
760 output.configUpdate.push_back(C2Param::Copy(channelCountInfo));
761 } else {
762 ALOGE("Config Update failed");
763 mSignalledError = true;
764 work->result = C2_CORRUPTED;
765 return;
766 }
767 }
768 ALOGV("size = %zu", size);
769 } while (decoderErr == AAC_DEC_OK);
770 }
771
772 int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels;
773
774 mBuffersInfo.push_back(std::move(inInfo));
775 work->workletsProcessed = 0u;
776 if (!eos && mOutputDelayCompensated < outputDelay) {
777 // discard outputDelay at the beginning
778 int32_t toCompensate = outputDelay - mOutputDelayCompensated;
779 int32_t discard = outputDelayRingBufferSamplesAvailable();
780 if (discard > toCompensate) {
781 discard = toCompensate;
782 }
783 int32_t discarded = outputDelayRingBufferGetSamples(nullptr, discard);
784 mOutputDelayCompensated += discarded;
785 return;
786 }
787
788 if (eos) {
789 drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
790 } else {
791 drainRingBuffer(work, pool, false /* not EOS */);
792 }
793}
794
795c2_status_t C2SoftAacDec::drainInternal(
796 uint32_t drainMode,
797 const std::shared_ptr<C2BlockPool> &pool,
798 const std::unique_ptr<C2Work> &work) {
799 if (drainMode == NO_DRAIN) {
800 ALOGW("drain with NO_DRAIN: no-op");
801 return C2_OK;
802 }
803 if (drainMode == DRAIN_CHAIN) {
804 ALOGW("DRAIN_CHAIN not supported");
805 return C2_OMITTED;
806 }
807
808 bool eos = (drainMode == DRAIN_COMPONENT_WITH_EOS);
809
810 drainDecoder();
811 drainRingBuffer(work, pool, eos);
812
813 if (eos) {
814 auto fillEmptyWork = [](const std::unique_ptr<C2Work> &work) {
815 work->worklets.front()->output.flags = work->input.flags;
816 work->worklets.front()->output.buffers.clear();
817 work->worklets.front()->output.ordinal = work->input.ordinal;
818 work->workletsProcessed = 1u;
819 };
820 while (mBuffersInfo.size() > 1u) {
821 finish(mBuffersInfo.front().frameIndex, fillEmptyWork);
822 mBuffersInfo.pop_front();
823 }
824 if (work && work->workletsProcessed == 0u) {
825 fillEmptyWork(work);
826 }
827 mBuffersInfo.clear();
828 }
829
830 return C2_OK;
831}
832
833c2_status_t C2SoftAacDec::drain(
834 uint32_t drainMode,
835 const std::shared_ptr<C2BlockPool> &pool) {
836 return drainInternal(drainMode, pool, nullptr);
837}
838
839c2_status_t C2SoftAacDec::onFlush_sm() {
840 drainDecoder();
841 mBuffersInfo.clear();
842
843 int avail;
844 while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) {
845 if (avail > mStreamInfo->frameSize * mStreamInfo->numChannels) {
846 avail = mStreamInfo->frameSize * mStreamInfo->numChannels;
847 }
848 int32_t ns = outputDelayRingBufferGetSamples(nullptr, avail);
849 if (ns != avail) {
850 ALOGW("not a complete frame of samples available");
851 break;
852 }
853 }
854 mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos;
855
856 return C2_OK;
857}
858
859void C2SoftAacDec::drainDecoder() {
860 // flush decoder until outputDelay is compensated
861 while (mOutputDelayCompensated > 0) {
862 // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC
863 INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT];
864
865 // run DRC check
866 mDrcWrap.submitStreamData(mStreamInfo);
867 mDrcWrap.update();
868
869 AAC_DECODER_ERROR decoderErr =
870 aacDecoder_DecodeFrame(mAACDecoder,
871 tmpOutBuffer,
872 2048 * MAX_CHANNEL_COUNT,
873 AACDEC_FLUSH);
874 if (decoderErr != AAC_DEC_OK) {
875 ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
876 }
877
878 int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels;
879 if (tmpOutBufferSamples > mOutputDelayCompensated) {
880 tmpOutBufferSamples = mOutputDelayCompensated;
881 }
882 outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples);
883
884 mOutputDelayCompensated -= tmpOutBufferSamples;
885 }
886}
887
888class C2SoftAacDecFactory : public C2ComponentFactory {
889public:
890 C2SoftAacDecFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
891 GetCodec2PlatformComponentStore()->getParamReflector())) {
892 }
893
894 virtual c2_status_t createComponent(
895 c2_node_id_t id,
896 std::shared_ptr<C2Component>* const component,
897 std::function<void(C2Component*)> deleter) override {
898 *component = std::shared_ptr<C2Component>(
899 new C2SoftAacDec(COMPONENT_NAME,
900 id,
901 std::make_shared<C2SoftAacDec::IntfImpl>(mHelper)),
902 deleter);
903 return C2_OK;
904 }
905
906 virtual c2_status_t createInterface(
907 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
908 std::function<void(C2ComponentInterface*)> deleter) override {
909 *interface = std::shared_ptr<C2ComponentInterface>(
910 new SimpleInterface<C2SoftAacDec::IntfImpl>(
911 COMPONENT_NAME, id, std::make_shared<C2SoftAacDec::IntfImpl>(mHelper)),
912 deleter);
913 return C2_OK;
914 }
915
916 virtual ~C2SoftAacDecFactory() override = default;
917
918private:
919 std::shared_ptr<C2ReflectorHelper> mHelper;
920};
921
922} // namespace android
923
924extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
925 ALOGV("in %s", __func__);
926 return new ::android::C2SoftAacDecFactory();
927}
928
929extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
930 ALOGV("in %s", __func__);
931 delete factory;
932}