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