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

📄 encratecontrol.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------------
--                                                                            --
--       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 + -