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