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