⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 umc_h264_avbr.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
字号:
/*
//
//               INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in accordance with the terms of that agreement.
//      Copyright (c) 2006-2007 Intel Corporation. All Rights Reserved.
//
//  Purpose
//    AVBR frame adaptive bitrate control
*/

#include <math.h>
#include "umc_h264_avbr.h"
#include "umc_h264_config.h"

namespace UMC_H264_ENCODER {


H264_AVBR::H264_AVBR()
{
    memset(this, 0, sizeof(H264_AVBR));
}


H264_AVBR::~H264_AVBR()
{
    Close();
}


void H264_AVBR::Close()
{
    if (mIsInit) {
        if (mMethod == 0 && mRCqb)
            delete [] mRCqb;
    }
    mIsInit = false;
}


Ipp32s H264_AVBR::GetInitQP(Ipp32s bitRate, Ipp64f frameRate, Ipp32s fWidth, Ipp32s fHeight, Ipp32s bitDepth, Ipp32s chromaSampling, Ipp32s alpha)
{
    const Ipp64f x0 = 0, y0 = 1.19, x1 = 1.75, y1 = 1.75;
    Ipp32s fs, fsLuma;

    fsLuma = fWidth * fHeight;
    fs = fsLuma;
    if (alpha)
        fs += fsLuma;
    if (chromaSampling == 1)
        fs += fsLuma / 2;
    else if (chromaSampling == 2)
        fs += fsLuma;
    else if (chromaSampling == 3)
        fs += fsLuma * 2;
    fs = fs * bitDepth / 8;
    Ipp32s q = (Ipp32s)(1. / 1.2 * pow(10.0, (log10(fs * 2. / 3. * frameRate / bitRate) - x0) * (y1 - y0) / (x1 - x0) + y0) + 0.5);
    h264_Clip(q, 1, mQuantMax);
    return q;
}


#define SetQuantB() \
    mQuantB = ((mQuantP + mQuantPrev) * 563 >> 10) + 1; \
    h264_Clip(mQuantB, 1, mQuantMax)


UMC::Status H264_AVBR::Init(Ipp32s histLen, Ipp32s bitRate, Ipp64f frameRate, Ipp32s fWidth, Ipp32s fHeight, Ipp32s bitDepth, Ipp32s chromaSampling, Ipp32s alpha)
{
    if (mIsInit) {
        Close();
    }
    mQuantOffset = 6 * (bitDepth - 8);
    mQuantMax = 51 + mQuantOffset;
    mMethod = 0;
    if (histLen <= 0)
        histLen = 32;
    mRCqb = new Ipp8u [histLen];
    if (!mRCqb)
        return UMC::UMC_ERR_ALLOC;
    mRClen = histLen;
    mBitRate = bitRate;
    mBitsDesiredFrame = (Ipp32s)((Ipp64f)mBitRate / frameRate);
    mBitsDesiredTotal = 0;
    Ipp32s q = GetInitQP(bitRate, frameRate, fWidth, fHeight, bitDepth, chromaSampling, alpha);
    mQuantPrev = mQuantI = mQuantP = q;
    SetQuantB();
    mRCqh = -1; mRCqs = 0; mRCbf = 0;
    mIsInit = true;
    return UMC::UMC_OK;
}


UMC::Status H264_AVBR::Init(Ipp32s qas, Ipp32s fas, Ipp32s bas, Ipp32s bitRate, Ipp64f frameRate, Ipp32s fWidth, Ipp32s fHeight, Ipp32s bitDepth, Ipp32s chromaSampling, Ipp32s alpha)
{
    if (mIsInit) {
        Close();
    }
    mQuantOffset = 6 * (bitDepth - 8);
    mQuantMax = 51 + mQuantOffset;
    mMethod = 1;
    if (qas <= 0)
        qas = 100;
    if (fas <= 0)
        fas = 30;
    if (bas <= 0)
        bas = 100;
    mBitRate = bitRate;
    mBitsDesiredTotal = 0;
    mBitsDesiredFrame = (Ipp32s)((Ipp64f)mBitRate / frameRate);
    Ipp32s q = GetInitQP(bitRate, frameRate, fWidth, fHeight, bitDepth, chromaSampling, alpha);
    mQuantPrev = mQuantI = mQuantP = q;
    SetQuantB();
    mRCfap = fas;
    mRCqap = qas;
    mRCbap = bas;
    mRCq = q;
    mRCqa = 1. / (Ipp64f)mRCq;
    mRCfa = mBitsDesiredFrame;
    mIsInit = true;
    return UMC::UMC_OK;
}


void H264_AVBR::PostFrame(EnumPicCodType frameType, Ipp32s bEncoded)
{
    if (mMethod == 0) {
        Ipp32s   bpfExpected, delay, quant, qa;
        Ipp64s   bpfEncoded;

        bpfEncoded = bEncoded - mBitsEncodedTotal;
        mBitsEncodedTotal = bEncoded;
        mBitsDesiredTotal += mBitsDesiredFrame;
        SetQuantB();
        if (frameType == BPREDPIC) return;
        delay = (Ipp32s)(mBitsDesiredTotal - mBitsEncodedTotal);
        if (frameType == INTRAPIC) {
            bpfExpected = (mBitsDesiredFrame << 2) + (delay >> 1);
            h264_ClipL(bpfExpected, mBitsDesiredFrame * 7 >> 3);
        } else if (frameType == BPREDPIC) {
            bpfExpected = (mBitsDesiredFrame / 3) + (delay >> 2);
            h264_Clip(bpfExpected, mBitsDesiredFrame / 4, mBitsDesiredFrame * 3 >> 2);
        } else {
            bpfExpected = mBitsDesiredFrame + (delay >> 1);
            h264_Clip(bpfExpected, mBitsDesiredFrame >> 1, mBitsDesiredFrame << 1);
        }
        quant = (frameType == INTRAPIC) ? mQuantI : (frameType == BPREDPIC) ? mQuantB : mQuantP;
        mRCqs += quant;
        mRCqh ++; if (mRCqh >= mRClen) mRCqh = 0;
        if (mRCbf) {
            mRCqs -= mRCqb[mRCqh];
            qa = (mRCqs + mRClen/2) / mRClen;
        } else {
            if (mRCqh == mRClen-1)
                mRCbf = 1;
            qa = (mRCqs + ((mRCqh + 1) >> 1)) / (mRCqh + 1);
        }
        mRCqb[mRCqh] = (Ipp8u)quant;
        if (h264_Abs(bpfEncoded - bpfExpected) > (bpfExpected >> 4)) {
            if (bpfEncoded > bpfExpected) {
                quant ++;
                if (bpfEncoded > 4 * bpfExpected)
                    quant ++;
                if (bpfEncoded > 8 * bpfExpected)
                    quant ++;
                Ipp32s cq = IPP_MIN(mQuantMax, qa + 7);
                h264_ClipR(quant, cq);
            } else if (bpfEncoded < bpfExpected) {
                quant --;
                if (bpfEncoded * 4 < bpfExpected)
                    quant --;
                if (bpfEncoded * 8 < bpfExpected)
                    quant --;
                Ipp32s cq = IPP_MAX(1, qa - 7);
                h264_ClipL(quant, cq);
            }
        }
        //if (frameType == BPREDPIC) {
            //if (quant <= mQuantP + 1) {
            //   quant = mQuantP + 2;
            //   h264_ClipR(quant, mQuantMax);
            //}
            //quant = mQuantP * 3 >> 1;
            //h264_Clip(quant, 4, mQuantMax);
        //    mQuantB = quant;
        //} else {
            mQuantPrev = mQuantP;
            mQuantI = mQuantP = quant;
        //}
    } else {
        Ipp64f  bo, qs, dq;
        Ipp32s  quant;
        Ipp64s   bpfEncoded;

        bpfEncoded = bEncoded - mBitsEncodedTotal;
        mBitsEncodedTotal = bEncoded;
        mBitsDesiredTotal += mBitsDesiredFrame;
        quant = (frameType == INTRAPIC) ? mQuantI : (frameType == BPREDPIC) ? mQuantB : mQuantP;
        mRCqa += (1. / quant - mRCqa) / mRCqap;
        h264_Clip(mRCqa, 1./mQuantMax , 1./1.);
        if (frameType != INTRAPIC || mRCfap < 30)
            mRCfa += (bpfEncoded - mRCfa) / mRCfap;
        SetQuantB();
        //if (frameType == BPREDPIC) return;
        qs = pow(mBitsDesiredFrame / mRCfa, 2.0);
        dq = mRCqa * qs;
        bo = (Ipp64f)((Ipp64s)mBitsEncodedTotal - (Ipp64s)mBitsDesiredTotal) / mRCbap / mBitsDesiredFrame;
        h264_Clip(bo, -1.0, 1.0);
        //dq = dq * (1.0 - bo);
        dq = dq + (1./mQuantMax - dq) * bo;
        h264_Clip(dq, 1./mQuantMax, 1./1.);
        quant = (int) (1. / dq + 0.5);
        //h264_Clip(quant, 1, mQuantMax);
        if (quant >= mRCq + 5)
            quant = mRCq + 3;
        else if (quant >= mRCq + 3)
            quant = mRCq + 2;
        else if (quant > mRCq + 1)
            quant = mRCq + 1;
        else if (quant <= mRCq - 5)
            quant = mRCq - 3;
        else if (quant <= mRCq - 3)
            quant = mRCq - 2;
        else if (quant < mRCq - 1)
            quant = mRCq - 1;
if (frameType != BPREDPIC)
            mQuantPrev = mQuantP;
        mRCq = mQuantI = mQuantP = quant;
    }
}


Ipp8u H264_AVBR::GetQP(EnumPicCodType frameType)
{
    return ((frameType == INTRAPIC) ? mQuantI : (frameType == BPREDPIC) ? mQuantB : mQuantP) - mQuantOffset;
}

void H264_AVBR::SetQP( EnumPicCodType frameType, Ipp32s qp )
{
    if(frameType == BPREDPIC)
        mQuantB = qp + mQuantOffset;
    else
        mRCq = mQuantI = mQuantP = qp + mQuantOffset;
}


} //namespace UMC_H264_ENCODER

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -