📄 encratecontrol.c
字号:
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- In the event of publication, the following notice is applicable: --
-- --
-- (C) COPYRIGHT 2004 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced on all copies. --
-- --
--------------------------------------------------------------------------------
--
-- Description : Encoder internal
--
-------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
Table of context
1. Include headers
2. External compiler flags
3. Module defines
4. Local function prototypes
5. Functions
5.1 EncInitRateControl
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include "EncRateControl.h"
#include "EncRcTable.h"
#include "EncTrace.h"
/*------------------------------------------------------------------------------
2. External compiler flags
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
3. Module defines
------------------------------------------------------------------------------*/
#define MAX_PREDICTIONS 132 /* DCT refresh after this many predictions */
/*------------------------------------------------------------------------------
4. Local function prototypes
------------------------------------------------------------------------------*/
static void MbQuant(rateControl_s *rc);
static void SourceParameter(rateControl_s *rc);
static void CirSw(cir_s *cir);
static void VirtualBuffer(virtualBuffer_s *vb, i32 timeInc);
static void VopQuant(rateControl_s *rc);
static void VideoBufferVerifierSet(vbv_s *, i32, i32);
static void LinearModel(rateControl_s *rc);
static void AdaptiveModel(rateControl_s *rc);
static void VopSkip(rateControl_s *rc);
static void VopQuantLimit(rateControl_s *rc);
static void VideoBufferVerifier(vbv_s *, i32);
static i32 Calculate(i32, i32, i32);
static void Limit(virtualBuffer_s *);
/*------------------------------------------------------------------------------
EncRcCheck
------------------------------------------------------------------------------*/
bool_e EncRcCheck(rateControl_s *rc)
{
virtualBuffer_s *vb = &rc->virtualBuffer;
vbv_s *vbv = &rc->videoBuffer;
if (rc->qpHdr > 31) {
return NOK;
}
ASSERT(vb->vopTimeIncRes > 0);
/* Cir */
rc->cir.mbPerVop = rc->mbPerVop;
rc->cir.mbCnt = 0;
rc->cir.firstMbNum = 0;
/* Virtual buffer Initial bit counts, first vop is special case because
* timeInc = 0 */
vb->bitPerVop = Calculate(vb->bitPerSecond, vb->timeInc,
vb->vopTimeIncRes);
vb->bitPerVop = MIN(0x7fffff, vb->bitPerVop);
if (vb->setFirstVop == YES) {
vb->virtualBitCnt = vb->bitPerVop;
vb->vopTimeInc = vb->timeInc;
} else {
vb->virtualBitCnt = 0;
vb->vopTimeInc = 0;
}
vb->realBitCnt = 0;
vb->skipBuffBit = 0;
vb->skipBuffFlush = NO;
/* Video buffer verifier */
if (rc->videoBuffer.videoBufferSize > 0) {
vbv->vbv = YES;
}
vbv->bitPerSecond = vb->bitPerSecond;
vbv->bitPerVop = vb->bitPerVop;
if (vb->setFirstVop == YES) {
vbv->timeInc = vb->timeInc;
vbv->vopTimeInc = vb->timeInc;
vbv->vopTimeIncRes = vb->vopTimeIncRes;
}
vb->setFirstVop = NO;
return OK;
}
/*------------------------------------------------------------------------------
VirtualBuffer
Virtual buffer and real bit count grow until one second. After one
second output bit rate per second must remove from virtual buffer and
realBitCnt. Bit drifting has been take care.
------------------------------------------------------------------------------*/
void VirtualBuffer(virtualBuffer_s *vb, i32 timeInc)
{
i32 drift;
vb->vopTimeInc += timeInc;
vb->virtualBitCnt += Calculate(vb->bitPerSecond, timeInc,
vb->vopTimeIncRes);
vb->bitAvailable = vb->virtualBitCnt - vb->realBitCnt;
/* vopTimeInc must be range of [0, vopTimeIncRes) */
while (vb->vopTimeInc >= vb->vopTimeIncRes) {
vb->vopTimeInc -= vb->vopTimeIncRes;
vb->virtualBitCnt -= vb->bitPerSecond;
vb->realBitCnt -= vb->bitPerSecond;
}
drift = Calculate(vb->bitPerSecond, vb->vopTimeInc, vb->vopTimeIncRes);
drift -= vb->virtualBitCnt;
vb->driftPerVop = drift;
vb->virtualBitCnt += drift;
Limit(vb);
return;
}
/*------------------------------------------------------------------------------
EncAfterVopRc
Check video buffer verifier and update source model.
------------------------------------------------------------------------------*/
void EncAfterVopRc(rateControl_s *rc, i32 zeroCnt, i32 byteCnt)
{
rc->zeroCnt = zeroCnt;
rc->bitCntLastVop = byteCnt*8;
/* Calculate source model of current vop */
SourceParameter(rc);
/* Video buffer verifier */
VideoBufferVerifier(&rc->videoBuffer, rc->bitCntLastVop);
/* After video buffer verifier underflow */
if (rc->videoBuffer.underflow == YES) {
return;
}
rc->vopTypePrev = rc->vopTypeCur;
rc->qpHdrPrev[1] = rc->qpHdrPrev[0];
rc->qpHdrPrev[0] = rc->qpHdr;
rc->virtualBuffer.realBitCnt += byteCnt*8;
return;
}
/*------------------------------------------------------------------------------
EncBeforeVopRc
------------------------------------------------------------------------------*/
void EncBeforeVopRc(rateControl_s *rc, i32 timeInc)
{
/* After vbv Underflow */
if (rc->videoBuffer.underflow == YES) {
rc->vopTypeCur = IVOP;
rc->qpHdrPrev[0] = 31;
rc->qpHdrPrev[1] = 31;
}
/* Virtual buffer */
VirtualBuffer(&rc->virtualBuffer, timeInc);
/* Video buffer verifier model */
VideoBufferVerifierSet(&rc->videoBuffer, timeInc,
rc->virtualBuffer.driftPerVop);
/* Vop skiping */
VopSkip(rc);
/* Vop quantization parameter (source model rate control) */
VopQuant(rc);
/* Vop quantization parameter user defined limitations */
VopQuantLimit(rc);
/* Mb rate control (check point rate control) */
MbQuant(rc);
/* CIR */
CirSw(&rc->cir);
/* Necessaries changes of structures */
rc->zeroCnt = 0;
rc->bitCntLastVop = 0;
rc->qpSum = 0;
#ifdef TRACE_RC
EncRcTrace(rc);
#endif
return;
}
/*------------------------------------------------------------------------------
CirSw
Calculate cyclic intra refres. Cir is distance between two INTRA
macroblock.
Input cir Pointer to cir structure.
------------------------------------------------------------------------------*/
void CirSw(cir_s *cir)
{
cir->period = cir->mbPerVop;
cir->seed = cir->mbPerVop;
if (cir->cir > 0) {
if (cir->cir < cir->mbPerVop) {
if (cir->firstMbNum >= cir->cir) {
cir->firstMbNum = 0;
}
cir->seed = cir->firstMbNum;
cir->period = cir->cir;
cir->firstMbNum++;
} else {
cir->mbCnt -= cir->mbPerVop;
if (cir->mbCnt < 0) {
cir->mbCnt += cir->cir;
if (cir->firstMbNum >= cir->mbPerVop) {
cir->firstMbNum = 0;
}
cir->seed = cir->firstMbNum;
cir->period = cir->mbPerVop;
cir->firstMbNum++;
}
}
}
return;
}
/*------------------------------------------------------------------------------
MbQuant
Caclucate table ChekPoint:
mbNum bitCntTarget
0 0 Mb nro. 0 no rc action.
1 1 Mb nro. 1 no rc action, stuffin enabled.
2 300 Mb nro. 2 target byte cnt is 300.
Caclucate table of qpChange:
-400 -3 Check point error -400 bit. Qp change is -3.
Input rc Pointer to structure.
------------------------------------------------------------------------------*/
void MbQuant(rateControl_s *rc)
{
qpCtrl_s *qc = &rc->qpCtrl;
i32 i, tmp;
/* Check points are smootly distributed except last one */
tmp = rc->mbPerVop / CHECK_POINT;
for (i = 0; i < CHECK_POINT-1; i++) {
qc->checkPoint[i] = tmp * (i+1);
qc->wordCntTarget[i] = 0;
}
qc->checkPoint[CHECK_POINT-1] = rc->mbPerVop-1;
qc->wordCntTarget[CHECK_POINT-1] = 0;
/* Stuffing mb befere last mabroblock if needed */
if (rc->videoBuffer.vbv == YES) {
qc->wordCntTarget[CHECK_POINT-1] = 1;
}
if (rc->mbRc != YES) {
return;
}
/* Check point model */
if ((rc->bitCntLastVop == 0) || (rc->vopTypeCur != rc->vopTypePrev)) {
LinearModel(rc);
} else {
AdaptiveModel(rc);
}
return;
}
/*------------------------------------------------------------------------------
LinearModel
wordCntTarget and wordError must scale down by 256 because of ASIC.
wordCntTarget range is [2 ... 2^13-1] (using 13bit) because of ASIC.
wordError range is [-2^13 ... 2^13-1] (sing 14bit) because of ASIC.
------------------------------------------------------------------------------*/
void LinearModel(rateControl_s *rc)
{
qpCtrl_s *qc = &rc->qpCtrl;
i32 bitAvailable;
i32 scaler;
i32 i, tmp;
bitAvailable = rc->virtualBuffer.bitAvailable;
if (bitAvailable > 0) {
scaler = (bitAvailable*256) / CHECK_POINT;
} else {
scaler = 0;
}
for (i = 0; i < CHECK_POINT-1; i++) {
tmp = (i+1)*scaler / 256;
qc->wordCntTarget[i] = MIN(MAX(2, tmp/256), 0x1FFF);
}
/* Qp change table */
tmp = rc->virtualBuffer.bitPerVop/2/256;
qc->wordError[ 0] = -tmp*4; qc->qpChange[ 0] = -3;
qc->wordError[ 1] = -tmp*3; qc->qpChange[ 1] = -2;
qc->wordError[ 2] = -tmp*2; qc->qpChange[ 2] = -1;
qc->wordError[ 3] = tmp*1; qc->qpChange[ 3] = 0;
qc->wordError[ 4] = tmp*2; qc->qpChange[ 4] = 1;
qc->wordError[ 5] = tmp*3; qc->qpChange[ 5] = 2;
qc->wordError[ 6] = tmp*4; qc->qpChange[ 6] = 3;
for (i = 0; i < 7; i++) {
tmp = qc->wordError[i];
qc->wordError[i] = MIN(MAX(-0x2000, tmp) , 0x1FFF);
}
return;
}
/*------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -