| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "DrcPresModeWrap.h" |
| |
| #include <assert.h> |
| |
| #define LOG_TAG "C2SoftAacDrcWrapper" |
| //#define LOG_NDEBUG 0 |
| #include <utils/Log.h> |
| |
| //#define DRC_PRES_MODE_WRAP_DEBUG |
| |
| #define GPM_ENCODER_TARGET_LEVEL 64 |
| #define MAX_TARGET_LEVEL 40 |
| |
| CDrcPresModeWrapper::CDrcPresModeWrapper() |
| { |
| mDataUpdate = true; |
| |
| /* Data from streamInfo. */ |
| /* Initialized to the same values as in the aac decoder */ |
| mStreamPRL = -1; |
| mStreamDRCPresMode = -1; |
| mStreamNrAACChan = 0; |
| mStreamNrOutChan = 0; |
| |
| /* Desired values (set by user). */ |
| /* Initialized to the same values as in the aac decoder */ |
| mDesTarget = -1; |
| mDesAttFactor = 0; |
| mDesBoostFactor = 0; |
| mDesHeavy = 0; |
| |
| mEncoderTarget = -1; |
| |
| /* Values from last time. */ |
| mLastTarget = -2; |
| mLastAttFactor = -1; |
| mLastBoostFactor = -1; |
| mLastHeavy = 0; |
| } |
| |
| CDrcPresModeWrapper::~CDrcPresModeWrapper() |
| { |
| } |
| |
| void |
| CDrcPresModeWrapper::setDecoderHandle(const HANDLE_AACDECODER handle) |
| { |
| mHandleDecoder = handle; |
| } |
| |
| void |
| CDrcPresModeWrapper::submitStreamData(CStreamInfo* pStreamInfo) |
| { |
| assert(pStreamInfo); |
| |
| if (mStreamPRL != pStreamInfo->drcProgRefLev) { |
| mStreamPRL = pStreamInfo->drcProgRefLev; |
| mDataUpdate = true; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| ALOGV("DRC presentation mode wrapper: drcProgRefLev is %d\n", mStreamPRL); |
| #endif |
| } |
| |
| if (mStreamDRCPresMode != pStreamInfo->drcPresMode) { |
| mStreamDRCPresMode = pStreamInfo->drcPresMode; |
| mDataUpdate = true; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| ALOGV("DRC presentation mode wrapper: drcPresMode is %d\n", mStreamDRCPresMode); |
| #endif |
| } |
| |
| if (mStreamNrAACChan != pStreamInfo->aacNumChannels) { |
| mStreamNrAACChan = pStreamInfo->aacNumChannels; |
| mDataUpdate = true; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| ALOGV("DRC presentation mode wrapper: aacNumChannels is %d\n", mStreamNrAACChan); |
| #endif |
| } |
| |
| if (mStreamNrOutChan != pStreamInfo->numChannels) { |
| mStreamNrOutChan = pStreamInfo->numChannels; |
| mDataUpdate = true; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| ALOGV("DRC presentation mode wrapper: numChannels is %d\n", mStreamNrOutChan); |
| #endif |
| } |
| |
| |
| |
| if (mStreamNrOutChan<mStreamNrAACChan) { |
| mIsDownmix = true; |
| } else { |
| mIsDownmix = false; |
| } |
| |
| if (mIsDownmix && (mStreamNrOutChan == 1)) { |
| mIsMonoDownmix = true; |
| } else { |
| mIsMonoDownmix = false; |
| } |
| |
| if (mIsDownmix && mStreamNrOutChan == 2){ |
| mIsStereoDownmix = true; |
| } else { |
| mIsStereoDownmix = false; |
| } |
| |
| } |
| |
| void |
| CDrcPresModeWrapper::setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value) |
| { |
| switch (param) { |
| case DRC_PRES_MODE_WRAP_DESIRED_TARGET: |
| mDesTarget = value; |
| break; |
| case DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR: |
| mDesAttFactor = value; |
| break; |
| case DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR: |
| mDesBoostFactor = value; |
| break; |
| case DRC_PRES_MODE_WRAP_DESIRED_HEAVY: |
| mDesHeavy = value; |
| break; |
| case DRC_PRES_MODE_WRAP_ENCODER_TARGET: |
| mEncoderTarget = value; |
| break; |
| default: |
| break; |
| } |
| mDataUpdate = true; |
| } |
| |
| void |
| CDrcPresModeWrapper::update() |
| { |
| // Get Data from Decoder |
| int progRefLevel = mStreamPRL; |
| int drcPresMode = mStreamDRCPresMode; |
| |
| // by default, do as desired |
| int newTarget = mDesTarget; |
| int newAttFactor = mDesAttFactor; |
| int newBoostFactor = mDesBoostFactor; |
| int newHeavy = mDesHeavy; |
| |
| if (mDataUpdate) { |
| // Validation check |
| if ((mDesTarget < MAX_TARGET_LEVEL) && (mDesTarget != -1)){ |
| mDesTarget = MAX_TARGET_LEVEL; // limit target level to -10 dB or below |
| newTarget = MAX_TARGET_LEVEL; |
| } |
| |
| if (mEncoderTarget != -1) { |
| if (mDesTarget<124) { // if target level > -31 dB |
| if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) { |
| // no stereo or mono downmixing, calculated scaling of light DRC |
| /* use as little compression as possible */ |
| newAttFactor = 0; |
| newBoostFactor = 0; |
| if (mDesTarget<progRefLevel) { // if target level > PRL |
| if (mEncoderTarget < mDesTarget) { // if mEncoderTarget > target level |
| // mEncoderTarget > target level > PRL |
| int calcFactor; |
| float calcFactor_norm; |
| // 0.0f < calcFactor_norm < 1.0f |
| calcFactor_norm = (float)(mDesTarget - progRefLevel) / |
| (float)(mEncoderTarget - progRefLevel); |
| calcFactor = (int)(calcFactor_norm*127.0f); // 0 <= calcFactor < 127 |
| // calcFactor is the lower limit |
| newAttFactor = (calcFactor>newAttFactor) ? calcFactor : newAttFactor; |
| // new AttFactor will be always = calcFactor, as it is set to 0 before. |
| newBoostFactor = newAttFactor; |
| } else { |
| /* target level > mEncoderTarget > PRL */ |
| // newTDLimiterEnable = 1; |
| // the time domain limiter must always be active in this case. |
| // It is assumed that the framework activates it by default |
| newAttFactor = 127; |
| newBoostFactor = 127; |
| } |
| } else { // target level <= PRL |
| // no restrictions required |
| // newAttFactor = newAttFactor; |
| } |
| } else { // downmixing |
| // if target level > -23 dB or mono downmix |
| if ( (mDesTarget<92) || mIsMonoDownmix ) { |
| newHeavy = 1; |
| } else { |
| // we perform a downmix, so, we need at least full light DRC |
| newAttFactor = 127; |
| } |
| } |
| } else { // target level <= -31 dB |
| // playback -31 dB: light DRC only needed if we perform downmixing |
| if (mIsDownmix) { // we do downmixing |
| newAttFactor = 127; |
| } |
| } |
| } |
| else { // handle other used encoder target levels |
| |
| // Validation check: DRC presentation mode is only specified for max. 5.1 channels |
| if (mStreamNrAACChan > 6) { |
| drcPresMode = 0; |
| } |
| |
| switch (drcPresMode) { |
| case 0: |
| default: // presentation mode not indicated |
| { |
| |
| if (mDesTarget<124) { // if target level > -31 dB |
| // no stereo or mono downmixing |
| if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) { |
| if (mDesTarget<progRefLevel) { // if target level > PRL |
| // newTDLimiterEnable = 1; |
| // the time domain limiter must always be active in this case. |
| // It is assumed that the framework activates it by default |
| newAttFactor = 127; // at least, use light compression |
| } else { // target level <= PRL |
| // no restrictions required |
| // newAttFactor = newAttFactor; |
| } |
| } else { // downmixing |
| // newTDLimiterEnable = 1; |
| // the time domain limiter must always be active in this case. |
| // It is assumed that the framework activates it by default |
| |
| // if target level > -23 dB or mono downmix |
| if ( (mDesTarget < 92) || mIsMonoDownmix ) { |
| newHeavy = 1; |
| } else{ |
| // we perform a downmix, so, we need at least full light DRC |
| newAttFactor = 127; |
| } |
| } |
| } else { // target level <= -31 dB |
| if (mIsDownmix) { // we do downmixing. |
| // newTDLimiterEnable = 1; |
| // the time domain limiter must always be active in this case. |
| // It is assumed that the framework activates it by default |
| newAttFactor = 127; |
| } |
| } |
| } |
| break; |
| |
| // Presentation mode 1 and 2 according to ETSI TS 101 154: |
| // Digital Video Broadcasting (DVB); Specification for the use of Video and Audio Coding |
| // in Broadcasting Applications based on the MPEG-2 Transport Stream, |
| // section C.5.4., "Decoding", and Table C.33 |
| // ISO DRC -> newHeavy = 0 (Use light compression, MPEG-style) |
| // Compression_value -> newHeavy = 1 (Use heavy compression, DVB-style) |
| // scaling restricted -> newAttFactor = 127 |
| |
| case 1: // presentation mode 1, Light:-31/Heavy:-23 |
| { |
| if (mDesTarget < 124) { // if target level > -31 dB |
| // playback up to -23 dB |
| newHeavy = 1; |
| } else { // target level <= -31 dB |
| // playback -31 dB |
| if (mIsDownmix) { // we do downmixing. |
| newAttFactor = 127; |
| } |
| } |
| } |
| break; |
| |
| case 2: // presentation mode 2, Light:-23/Heavy:-23 |
| { |
| if (mDesTarget < 124) { // if target level > -31 dB |
| // playback up to -23 dB |
| if (mIsMonoDownmix) { // if mono downmix |
| newHeavy = 1; |
| } else { |
| newHeavy = 0; |
| newAttFactor = 127; |
| } |
| } else { // target level <= -31 dB |
| // playback -31 dB |
| newHeavy = 0; |
| if (mIsDownmix) { // we do downmixing. |
| newAttFactor = 127; |
| } |
| } |
| } |
| break; |
| |
| } // switch() |
| } // if (mEncoderTarget == GPM_ENCODER_TARGET_LEVEL) |
| |
| // Validation check again |
| if (newHeavy == 1) { |
| newBoostFactor=127; // not really needed as the same would be done by the decoder anyway |
| newAttFactor = 127; |
| } |
| |
| // update the decoder |
| if (newTarget != mLastTarget) { |
| aacDecoder_SetParam(mHandleDecoder, AAC_DRC_REFERENCE_LEVEL, newTarget); |
| mLastTarget = newTarget; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| if (newTarget != mDesTarget) |
| ALOGV("DRC presentation mode wrapper: forced target level to %d (from %d)\n", newTarget, mDesTarget); |
| else |
| ALOGV("DRC presentation mode wrapper: set target level to %d\n", newTarget); |
| #endif |
| } |
| |
| if (newAttFactor != mLastAttFactor) { |
| aacDecoder_SetParam(mHandleDecoder, AAC_DRC_ATTENUATION_FACTOR, newAttFactor); |
| mLastAttFactor = newAttFactor; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| if (newAttFactor != mDesAttFactor) |
| ALOGV("DRC presentation mode wrapper: forced attenuation factor to %d (from %d)\n", newAttFactor, mDesAttFactor); |
| else |
| ALOGV("DRC presentation mode wrapper: set attenuation factor to %d\n", newAttFactor); |
| #endif |
| } |
| |
| if (newBoostFactor != mLastBoostFactor) { |
| aacDecoder_SetParam(mHandleDecoder, AAC_DRC_BOOST_FACTOR, newBoostFactor); |
| mLastBoostFactor = newBoostFactor; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| if (newBoostFactor != mDesBoostFactor) |
| ALOGV("DRC presentation mode wrapper: forced boost factor to %d (from %d)\n", |
| newBoostFactor, mDesBoostFactor); |
| else |
| ALOGV("DRC presentation mode wrapper: set boost factor to %d\n", newBoostFactor); |
| #endif |
| } |
| |
| if (newHeavy != mLastHeavy) { |
| aacDecoder_SetParam(mHandleDecoder, AAC_DRC_HEAVY_COMPRESSION, newHeavy); |
| mLastHeavy = newHeavy; |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| if (newHeavy != mDesHeavy) |
| ALOGV("DRC presentation mode wrapper: forced heavy compression to %d (from %d)\n", |
| newHeavy, mDesHeavy); |
| else |
| ALOGV("DRC presentation mode wrapper: set heavy compression to %d\n", newHeavy); |
| #endif |
| } |
| |
| #ifdef DRC_PRES_MODE_WRAP_DEBUG |
| ALOGV("DRC config: tgt_lev: %3d, cut: %3d, boost: %3d, heavy: %d\n", newTarget, |
| newAttFactor, newBoostFactor, newHeavy); |
| #endif |
| mDataUpdate = false; |
| |
| } // if (mDataUpdate) |
| } |