📄 umc_h264_avbr.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 + -