Home | History | Annotate | Download | only in aacdec
      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