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