Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65734fba authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "AAC decoder: compensate limiter delay"

parents 798ce934 d4838ed1
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -3,7 +3,8 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
include $(CLEAR_VARS)


LOCAL_SRC_FILES := \
LOCAL_SRC_FILES := \
      SoftAAC2.cpp
      SoftAAC2.cpp \
      DrcPresModeWrap.cpp


LOCAL_C_INCLUDES := \
LOCAL_C_INCLUDES := \
      frameworks/av/media/libstagefright/include \
      frameworks/av/media/libstagefright/include \
+372 −0
Original line number Original line Diff line number Diff line
/*
 * 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 "SoftAAC2_DrcWrapper"
//#define LOG_NDEBUG 0
#include <utils/Log.h>

//#define DRC_PRES_MODE_WRAP_DEBUG

#define GPM_ENCODER_TARGET_LEVEL 64
#define MAX_TARGET_LEVEL 64

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. */
    /* Initialized to the same values as the desired values */
    mLastTarget = -1;
    mLastAttFactor = 0;
    mLastBoostFactor = 0;
    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) {
        // sanity check
        if (mDesTarget < MAX_TARGET_LEVEL){
            mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -16 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

            // Sanity 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)

        // sanity 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)
}
+62 −0
Original line number Original line Diff line number Diff line
/*
 * 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.
 */
#pragma once
#include "aacdecoder_lib.h"

typedef enum
{
    DRC_PRES_MODE_WRAP_DESIRED_TARGET         = 0x0000,
    DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR     = 0x0001,
    DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR   = 0x0002,
    DRC_PRES_MODE_WRAP_DESIRED_HEAVY          = 0x0003,
    DRC_PRES_MODE_WRAP_ENCODER_TARGET         = 0x0004
} DRC_PRES_MODE_WRAP_PARAM;


class CDrcPresModeWrapper {
public:
    CDrcPresModeWrapper();
    ~CDrcPresModeWrapper();
    void setDecoderHandle(const HANDLE_AACDECODER handle);
    void setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value);
    void submitStreamData(CStreamInfo*);
    void update();

protected:
    HANDLE_AACDECODER mHandleDecoder;
    int mDesTarget;
    int mDesAttFactor;
    int mDesBoostFactor;
    int mDesHeavy;

    int mEncoderTarget;

    int mLastTarget;
    int mLastAttFactor;
    int mLastBoostFactor;
    int mLastHeavy;

    SCHAR mStreamPRL;
    SCHAR mStreamDRCPresMode;
    INT mStreamNrAACChan;
    INT mStreamNrOutChan;

    bool mIsDownmix;
    bool mIsMonoDownmix;
    bool mIsStereoDownmix;

    bool mDataUpdate;
};
+516 −211

File changed.

Preview size limit exceeded, changes collapsed.

+21 −6
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@
#include "SimpleSoftOMXComponent.h"
#include "SimpleSoftOMXComponent.h"


#include "aacdecoder_lib.h"
#include "aacdecoder_lib.h"
#include "DrcPresModeWrap.h"


namespace android {
namespace android {


@@ -47,18 +48,19 @@ private:
    enum {
    enum {
        kNumInputBuffers        = 4,
        kNumInputBuffers        = 4,
        kNumOutputBuffers       = 4,
        kNumOutputBuffers       = 4,
        kNumDelayBlocksMax      = 8,
    };
    };


    HANDLE_AACDECODER mAACDecoder;
    HANDLE_AACDECODER mAACDecoder;
    CStreamInfo *mStreamInfo;
    CStreamInfo *mStreamInfo;
    bool mIsADTS;
    bool mIsADTS;
    bool mDecoderHasData;
    bool mIsFirst;
    size_t mInputBufferCount;
    size_t mInputBufferCount;
    size_t mOutputBufferCount;
    bool mSignalledError;
    bool mSignalledError;
    bool mSawInputEos;
    int64_t mAnchorTimeUs[kNumDelayBlocksMax];
    bool mSignalledOutputEos;

    int64_t mAnchorTimeUs;
    CDrcPresModeWrapper mDrcWrap;
    int64_t mNumSamplesOutput;


    enum {
    enum {
        NONE,
        NONE,
@@ -69,9 +71,22 @@ private:
    void initPorts();
    void initPorts();
    status_t initDecoder();
    status_t initDecoder();
    bool isConfigured() const;
    bool isConfigured() const;
    void maybeConfigureDownmix() const;
    void configureDownmix() const;
    void drainDecoder();
    void drainDecoder();


//      delay compensation
    bool mEndOfInput;
    bool mEndOfOutput;
    int32_t mOutputDelayCompensated;
    int32_t mOutputDelayRingBufferSize;
    short *mOutputDelayRingBuffer;
    int32_t mOutputDelayRingBufferWritePos;
    int32_t mOutputDelayRingBufferReadPos;
    bool outputDelayRingBufferPutSamples(INT_PCM *samples, int numSamples);
    int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
    int32_t outputDelayRingBufferSamplesAvailable();
    int32_t outputDelayRingBufferSamplesLeft();

    DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2);
    DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2);
};
};