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