1 /* 2 * Copyright (C) 2014 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 #include "DrcPresModeWrap.h" 17 18 #include <assert.h> 19 20 #define LOG_TAG "SoftAAC2_DrcWrapper" 21 //#define LOG_NDEBUG 0 22 #include <utils/Log.h> 23 24 //#define DRC_PRES_MODE_WRAP_DEBUG 25 26 #define GPM_ENCODER_TARGET_LEVEL 64 27 #define MAX_TARGET_LEVEL 64 28 29 CDrcPresModeWrapper::CDrcPresModeWrapper() 30 { 31 mDataUpdate = true; 32 33 /* Data from streamInfo. */ 34 /* Initialized to the same values as in the aac decoder */ 35 mStreamPRL = -1; 36 mStreamDRCPresMode = -1; 37 mStreamNrAACChan = 0; 38 mStreamNrOutChan = 0; 39 40 /* Desired values (set by user). */ 41 /* Initialized to the same values as in the aac decoder */ 42 mDesTarget = -1; 43 mDesAttFactor = 0; 44 mDesBoostFactor = 0; 45 mDesHeavy = 0; 46 47 mEncoderTarget = -1; 48 49 /* Values from last time. */ 50 /* Initialized to the same values as the desired values */ 51 mLastTarget = -1; 52 mLastAttFactor = 0; 53 mLastBoostFactor = 0; 54 mLastHeavy = 0; 55 } 56 57 CDrcPresModeWrapper::~CDrcPresModeWrapper() 58 { 59 } 60 61 void 62 CDrcPresModeWrapper::setDecoderHandle(const HANDLE_AACDECODER handle) 63 { 64 mHandleDecoder = handle; 65 } 66 67 void 68 CDrcPresModeWrapper::submitStreamData(CStreamInfo* pStreamInfo) 69 { 70 assert(pStreamInfo); 71 72 if (mStreamPRL != pStreamInfo->drcProgRefLev) { 73 mStreamPRL = pStreamInfo->drcProgRefLev; 74 mDataUpdate = true; 75 #ifdef DRC_PRES_MODE_WRAP_DEBUG 76 ALOGV("DRC presentation mode wrapper: drcProgRefLev is %d\n", mStreamPRL); 77 #endif 78 } 79 80 if (mStreamDRCPresMode != pStreamInfo->drcPresMode) { 81 mStreamDRCPresMode = pStreamInfo->drcPresMode; 82 mDataUpdate = true; 83 #ifdef DRC_PRES_MODE_WRAP_DEBUG 84 ALOGV("DRC presentation mode wrapper: drcPresMode is %d\n", mStreamDRCPresMode); 85 #endif 86 } 87 88 if (mStreamNrAACChan != pStreamInfo->aacNumChannels) { 89 mStreamNrAACChan = pStreamInfo->aacNumChannels; 90 mDataUpdate = true; 91 #ifdef DRC_PRES_MODE_WRAP_DEBUG 92 ALOGV("DRC presentation mode wrapper: aacNumChannels is %d\n", mStreamNrAACChan); 93 #endif 94 } 95 96 if (mStreamNrOutChan != pStreamInfo->numChannels) { 97 mStreamNrOutChan = pStreamInfo->numChannels; 98 mDataUpdate = true; 99 #ifdef DRC_PRES_MODE_WRAP_DEBUG 100 ALOGV("DRC presentation mode wrapper: numChannels is %d\n", mStreamNrOutChan); 101 #endif 102 } 103 104 105 106 if (mStreamNrOutChan<mStreamNrAACChan) { 107 mIsDownmix = true; 108 } else { 109 mIsDownmix = false; 110 } 111 112 if (mIsDownmix && (mStreamNrOutChan == 1)) { 113 mIsMonoDownmix = true; 114 } else { 115 mIsMonoDownmix = false; 116 } 117 118 if (mIsDownmix && mStreamNrOutChan == 2){ 119 mIsStereoDownmix = true; 120 } else { 121 mIsStereoDownmix = false; 122 } 123 124 } 125 126 void 127 CDrcPresModeWrapper::setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value) 128 { 129 switch (param) { 130 case DRC_PRES_MODE_WRAP_DESIRED_TARGET: 131 mDesTarget = value; 132 break; 133 case DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR: 134 mDesAttFactor = value; 135 break; 136 case DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR: 137 mDesBoostFactor = value; 138 break; 139 case DRC_PRES_MODE_WRAP_DESIRED_HEAVY: 140 mDesHeavy = value; 141 break; 142 case DRC_PRES_MODE_WRAP_ENCODER_TARGET: 143 mEncoderTarget = value; 144 break; 145 default: 146 break; 147 } 148 mDataUpdate = true; 149 } 150 151 void 152 CDrcPresModeWrapper::update() 153 { 154 // Get Data from Decoder 155 int progRefLevel = mStreamPRL; 156 int drcPresMode = mStreamDRCPresMode; 157 158 // by default, do as desired 159 int newTarget = mDesTarget; 160 int newAttFactor = mDesAttFactor; 161 int newBoostFactor = mDesBoostFactor; 162 int newHeavy = mDesHeavy; 163 164 if (mDataUpdate) { 165 // sanity check 166 if (mDesTarget < MAX_TARGET_LEVEL){ 167 mDesTarget = MAX_TARGET_LEVEL; // limit target level to -16 dB or below 168 newTarget = MAX_TARGET_LEVEL; 169 } 170 171 if (mEncoderTarget != -1) { 172 if (mDesTarget<124) { // if target level > -31 dB 173 if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) { 174 // no stereo or mono downmixing, calculated scaling of light DRC 175 /* use as little compression as possible */ 176 newAttFactor = 0; 177 newBoostFactor = 0; 178 if (mDesTarget<progRefLevel) { // if target level > PRL 179 if (mEncoderTarget < mDesTarget) { // if mEncoderTarget > target level 180 // mEncoderTarget > target level > PRL 181 int calcFactor; 182 float calcFactor_norm; 183 // 0.0f < calcFactor_norm < 1.0f 184 calcFactor_norm = (float)(mDesTarget - progRefLevel) / 185 (float)(mEncoderTarget - progRefLevel); 186 calcFactor = (int)(calcFactor_norm*127.0f); // 0 <= calcFactor < 127 187 // calcFactor is the lower limit 188 newAttFactor = (calcFactor>newAttFactor) ? calcFactor : newAttFactor; 189 // new AttFactor will be always = calcFactor, as it is set to 0 before. 190 newBoostFactor = newAttFactor; 191 } else { 192 /* target level > mEncoderTarget > PRL */ 193 // newTDLimiterEnable = 1; 194 // the time domain limiter must always be active in this case. 195 // It is assumed that the framework activates it by default 196 newAttFactor = 127; 197 newBoostFactor = 127; 198 } 199 } else { // target level <= PRL 200 // no restrictions required 201 // newAttFactor = newAttFactor; 202 } 203 } else { // downmixing 204 // if target level > -23 dB or mono downmix 205 if ( (mDesTarget<92) || mIsMonoDownmix ) { 206 newHeavy = 1; 207 } else { 208 // we perform a downmix, so, we need at least full light DRC 209 newAttFactor = 127; 210 } 211 } 212 } else { // target level <= -31 dB 213 // playback -31 dB: light DRC only needed if we perform downmixing 214 if (mIsDownmix) { // we do downmixing 215 newAttFactor = 127; 216 } 217 } 218 } 219 else { // handle other used encoder target levels 220 221 // Sanity check: DRC presentation mode is only specified for max. 5.1 channels 222 if (mStreamNrAACChan > 6) { 223 drcPresMode = 0; 224 } 225 226 switch (drcPresMode) { 227 case 0: 228 default: // presentation mode not indicated 229 { 230 231 if (mDesTarget<124) { // if target level > -31 dB 232 // no stereo or mono downmixing 233 if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) { 234 if (mDesTarget<progRefLevel) { // if target level > PRL 235 // newTDLimiterEnable = 1; 236 // the time domain limiter must always be active in this case. 237 // It is assumed that the framework activates it by default 238 newAttFactor = 127; // at least, use light compression 239 } else { // target level <= PRL 240 // no restrictions required 241 // newAttFactor = newAttFactor; 242 } 243 } else { // downmixing 244 // newTDLimiterEnable = 1; 245 // the time domain limiter must always be active in this case. 246 // It is assumed that the framework activates it by default 247 248 // if target level > -23 dB or mono downmix 249 if ( (mDesTarget < 92) || mIsMonoDownmix ) { 250 newHeavy = 1; 251 } else{ 252 // we perform a downmix, so, we need at least full light DRC 253 newAttFactor = 127; 254 } 255 } 256 } else { // target level <= -31 dB 257 if (mIsDownmix) { // we do downmixing. 258 // newTDLimiterEnable = 1; 259 // the time domain limiter must always be active in this case. 260 // It is assumed that the framework activates it by default 261 newAttFactor = 127; 262 } 263 } 264 } 265 break; 266 267 // Presentation mode 1 and 2 according to ETSI TS 101 154: 268 // Digital Video Broadcasting (DVB); Specification for the use of Video and Audio Coding 269 // in Broadcasting Applications based on the MPEG-2 Transport Stream, 270 // section C.5.4., "Decoding", and Table C.33 271 // ISO DRC -> newHeavy = 0 (Use light compression, MPEG-style) 272 // Compression_value -> newHeavy = 1 (Use heavy compression, DVB-style) 273 // scaling restricted -> newAttFactor = 127 274 275 case 1: // presentation mode 1, Light:-31/Heavy:-23 276 { 277 if (mDesTarget < 124) { // if target level > -31 dB 278 // playback up to -23 dB 279 newHeavy = 1; 280 } else { // target level <= -31 dB 281 // playback -31 dB 282 if (mIsDownmix) { // we do downmixing. 283 newAttFactor = 127; 284 } 285 } 286 } 287 break; 288 289 case 2: // presentation mode 2, Light:-23/Heavy:-23 290 { 291 if (mDesTarget < 124) { // if target level > -31 dB 292 // playback up to -23 dB 293 if (mIsMonoDownmix) { // if mono downmix 294 newHeavy = 1; 295 } else { 296 newHeavy = 0; 297 newAttFactor = 127; 298 } 299 } else { // target level <= -31 dB 300 // playback -31 dB 301 newHeavy = 0; 302 if (mIsDownmix) { // we do downmixing. 303 newAttFactor = 127; 304 } 305 } 306 } 307 break; 308 309 } // switch() 310 } // if (mEncoderTarget == GPM_ENCODER_TARGET_LEVEL) 311 312 // sanity again 313 if (newHeavy == 1) { 314 newBoostFactor=127; // not really needed as the same would be done by the decoder anyway 315 newAttFactor = 127; 316 } 317 318 // update the decoder 319 if (newTarget != mLastTarget) { 320 aacDecoder_SetParam(mHandleDecoder, AAC_DRC_REFERENCE_LEVEL, newTarget); 321 mLastTarget = newTarget; 322 #ifdef DRC_PRES_MODE_WRAP_DEBUG 323 if (newTarget != mDesTarget) 324 ALOGV("DRC presentation mode wrapper: forced target level to %d (from %d)\n", newTarget, mDesTarget); 325 else 326 ALOGV("DRC presentation mode wrapper: set target level to %d\n", newTarget); 327 #endif 328 } 329 330 if (newAttFactor != mLastAttFactor) { 331 aacDecoder_SetParam(mHandleDecoder, AAC_DRC_ATTENUATION_FACTOR, newAttFactor); 332 mLastAttFactor = newAttFactor; 333 #ifdef DRC_PRES_MODE_WRAP_DEBUG 334 if (newAttFactor != mDesAttFactor) 335 ALOGV("DRC presentation mode wrapper: forced attenuation factor to %d (from %d)\n", newAttFactor, mDesAttFactor); 336 else 337 ALOGV("DRC presentation mode wrapper: set attenuation factor to %d\n", newAttFactor); 338 #endif 339 } 340 341 if (newBoostFactor != mLastBoostFactor) { 342 aacDecoder_SetParam(mHandleDecoder, AAC_DRC_BOOST_FACTOR, newBoostFactor); 343 mLastBoostFactor = newBoostFactor; 344 #ifdef DRC_PRES_MODE_WRAP_DEBUG 345 if (newBoostFactor != mDesBoostFactor) 346 ALOGV("DRC presentation mode wrapper: forced boost factor to %d (from %d)\n", 347 newBoostFactor, mDesBoostFactor); 348 else 349 ALOGV("DRC presentation mode wrapper: set boost factor to %d\n", newBoostFactor); 350 #endif 351 } 352 353 if (newHeavy != mLastHeavy) { 354 aacDecoder_SetParam(mHandleDecoder, AAC_DRC_HEAVY_COMPRESSION, newHeavy); 355 mLastHeavy = newHeavy; 356 #ifdef DRC_PRES_MODE_WRAP_DEBUG 357 if (newHeavy != mDesHeavy) 358 ALOGV("DRC presentation mode wrapper: forced heavy compression to %d (from %d)\n", 359 newHeavy, mDesHeavy); 360 else 361 ALOGV("DRC presentation mode wrapper: set heavy compression to %d\n", newHeavy); 362 #endif 363 } 364 365 #ifdef DRC_PRES_MODE_WRAP_DEBUG 366 ALOGV("DRC config: tgt_lev: %3d, cut: %3d, boost: %3d, heavy: %d\n", newTarget, 367 newAttFactor, newBoostFactor, newHeavy); 368 #endif 369 mDataUpdate = false; 370 371 } // if (mDataUpdate) 372 } 373