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

📄 encratecontrol.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 2 页
字号:

	AdaptiveModel

	wordCntPrev has been scaled down by 256, see CheckPoint(). Also
	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 AdaptiveModel(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) / rc->bitCntLastVop;
	} else {
		scaler = 0;
	}
	for (i = 0; i < CHECK_POINT-1; i++) {
		tmp = qc->wordCntPrev[i]*scaler / 256;
		qc->wordCntTarget[i] = MIN(MAX(2, tmp), 0x1FFF);
	}

	/* Qp change table */
	tmp = rc->virtualBuffer.bitPerVop/2/256;
	qc->wordError[ 0] = -tmp*4;	qc->qpChange[ 0] = -2;
	qc->wordError[ 1] = -tmp*3;	qc->qpChange[ 1] = -1;
	qc->wordError[ 2] = -tmp*2;	qc->qpChange[ 2] = 0;
	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;
}

/*------------------------------------------------------------------------------

	SourceParameter

	Source parameter and scaler of last coded VOP. Parameters has been
	scaled up by factor 256.

------------------------------------------------------------------------------*/
void SourceParameter(rateControl_s *rc)
{
	const i32 *srcTable;
	i32 notZeroCnt;
	i32 zeroCnt;
	i32 bitCntLastVop;
	i32 tmp;

	/* Stuffing macroblock fix */
	bitCntLastVop = rc->bitCntLastVop;
	if (rc->videoBuffer.vbv == YES) {
		rc->videoBuffer.stuffBitCnt = 0;
		if (rc->videoBuffer.stuffWordCnt > 0) {
			/* Word count of last check point */
			tmp = rc->qpCtrl.wordCntPrev[CHECK_POINT-1] * 8;
			if (tmp < rc->videoBuffer.stuffWordCnt) {
				bitCntLastVop = tmp * 32;
				tmp = rc->bitCntLastVop - bitCntLastVop;
				rc->videoBuffer.stuffBitCnt = tmp;
			}
		}
	}

	zeroCnt = rc->zeroCnt;
	notZeroCnt = rc->coeffCnt - zeroCnt;
	if (notZeroCnt > 0) {
		rc->srcPrm = Calculate(bitCntLastVop, 256, notZeroCnt);
	} else {
		rc->srcPrm = bitCntLastVop*256;
	}
	ASSERT(zeroCnt <= rc->coeffCnt);
	ASSERT(zeroCnt >= 0);

	/* Map zero cnt table based on source parameter **/
	tmp = MIN(31, MAX(0, rc->srcPrm/256));
	srcTable = srcInter[tmp];

	/* Zero count is scaled to average qp */
	tmp = rc->qpSum / rc->mbPerVop;
	ASSERT(tmp < 32);
	tmp = MIN(31, MAX(1, tmp));
	zeroCnt = MAX(1, zeroCnt);
	rc->scaler = (srcTable[tmp-1]*256) / zeroCnt;

	return;
}

/*------------------------------------------------------------------------------

	VopSkip

	Try to avoid vop skip by bufferin.

------------------------------------------------------------------------------*/
void VopSkip(rateControl_s *rc)
{
	virtualBuffer_s *vb = &rc->virtualBuffer;
	i32 bitAvailable;
	i32 skipLimit;

	rc->vopCoded = YES;
	if (rc->vopSkip != YES) {
		return;
	}

	if (vb->bitAvailable > vb->bitPerVop) {
		vb->skipBuffBit = 0;
	}

	/* Skip buffer recovery */
	if ((vb->skipBuffBit == 0) && (vb->bitAvailable > 0)) {
		vb->skipBuffFlush = NO;
		vb->skipBuffBit = vb->bitPerVop/2;
	}

	bitAvailable = vb->bitAvailable;
	skipLimit = vb->bitPerVop/4;
	if (bitAvailable <= skipLimit) {
		vb->skipBuffFlush = YES;
		bitAvailable += vb->skipBuffBit;
		if (bitAvailable <= skipLimit) {
			rc->vopCoded = NO;
		}
	}

	/* Flush skip buffer */
	if (vb->skipBuffFlush == YES) {
		vb->bitAvailable += vb->skipBuffBit;
		vb->skipBuffBit /= 2;
		Limit(vb);
	}

	return;
}

/*------------------------------------------------------------------------------

	VopQuant

	Next quantization parameter of VOP based on source model.

------------------------------------------------------------------------------*/
void VopQuant(rateControl_s *rc)
{
	const i32 *srcTable;
	i32 tmp;
	i32 bitLeft = 0;
	i32 zeroCntReq;
	i32 min;
	i32 qp = 1;
	i32 i;

	if (rc->vopRc != YES) {
		return;
	}

	if (rc->srcPrm == 0) {
		return;
	}

	/* Stuffing macroblock fix */
	if (rc->videoBuffer.vbv == YES) {
		bitLeft = rc->videoBuffer.stuffBitCnt;
	}

	/* Required zero cnt */
	bitLeft += rc->virtualBuffer.bitAvailable;
	zeroCntReq = rc->coeffCnt - Calculate(bitLeft, 256, rc->srcPrm);
	zeroCntReq = Calculate(zeroCntReq, rc->scaler, 256);

	/* Map zero cnt table based on source parameter **/
	tmp = MIN(31, MAX(0, rc->srcPrm/256));
	srcTable = srcInter[tmp];

	min = ABS(zeroCntReq - srcTable[0]);
	for (i = 1; i < 31; i++) {
		tmp = ABS(zeroCntReq - srcTable[i]);
		if (tmp <= min) {
			min = tmp;
			qp = i+1;
		}
	}

	/* Quantization parameter resistance */
	if (rc->qpHdrPrev[0] == rc->qpHdrPrev[1]) {
		rc->qpHdr = (rc->qpHdrPrev[0] + qp*3 + 2)/4;
	} else {
		rc->qpHdr = (rc->qpHdrPrev[1] + rc->qpHdrPrev[0]*2 + qp*3 +
				3)/6;
	}

	return;
}

/*------------------------------------------------------------------------------

	VopQuantLimit

------------------------------------------------------------------------------*/
void VopQuantLimit(rateControl_s *rc)
{
	rc->qpHdr = MIN(rc->qpHdrMax, MAX(rc->qpHdr, rc->qpHdrMin));

	return;
}

/*------------------------------------------------------------------------------

	VideoBufferVerifierSet

	Fix video buffer driting and set minimum bit count of nex vop.

------------------------------------------------------------------------------*/
void VideoBufferVerifierSet(vbv_s *vbv, i32 timeInc, i32 driftPerVop)
{
	i32 tmp;

	if (vbv->vbv != YES) {
		return;
	}

	/* Fix video buffer drifting */
	vbv->videoBufferBitCnt += driftPerVop;

	/* Time since last coded Vop */
	vbv->vopTimeInc += timeInc;

	/* Next vop mimimum word count */
	tmp = Calculate(vbv->bitPerSecond, vbv->vopTimeInc,
			vbv->vopTimeIncRes);

	vbv->stuffWordCnt = 2*tmp;
	vbv->stuffWordCnt += vbv->videoBufferBitCnt - vbv->videoBufferSize;
	vbv->stuffWordCnt += vbv->bitPerVop*2;
	vbv->stuffWordCnt /= 32;		/* Words */
	tmp = vbv->videoBufferSize*3/4/32;	/* Words */
	vbv->stuffWordCnt = MIN(vbv->stuffWordCnt, tmp);
	vbv->stuffWordCnt = MAX(0, vbv->stuffWordCnt);

	return;
}

/*------------------------------------------------------------------------------

	VideoBufferVerifier

------------------------------------------------------------------------------*/
void VideoBufferVerifier(vbv_s *vbv, i32 bitCntLastVop)
{
	i32 tmp;
	i32 bitCnt;

	if (vbv->vbv != YES) {
		return;
	}

	/* Video buffer fullnes */
	bitCnt = vbv->videoBufferBitCnt - bitCntLastVop;

	bitCnt += Calculate(vbv->bitPerSecond, vbv->vopTimeInc,
			vbv->vopTimeIncRes);

#ifdef TRACE_RC
	printf("\nVIDEO BUFFER VERIFIER:\n");
	printf("Video buffer size\t%i\n",vbv->videoBufferSize);
	printf("Video buffer bit Cnt\t%i\n",bitCnt);
	printf("Video buffer fullnes\t%i\n",bitCnt*100/vbv->videoBufferSize);
	printf("Last vop bit Cnt\t%i\n",bitCntLastVop);
	printf("Used vopTimeInc\t\t%i\n\n",vbv->vopTimeInc);
#endif

	/* Video buffer status */
	vbv->underflow = NO;
	vbv->overflow = NO;
	if (bitCnt < 0) {
		vbv->underflow = YES;
		return;
	}

	tmp = bitCnt + bitCntLastVop;
	if (tmp > vbv->videoBufferSize) {
		vbv->overflow = YES;
	}

	/* Coded vop is new time reference */
	vbv->vopTimeInc = 0;
	vbv->videoBufferBitCnt = bitCnt;

	return;
}

/*------------------------------------------------------------------------------

	Calculate

	I try to avoid overflow and calculate good enough result of a*b/c.

------------------------------------------------------------------------------*/
i32 Calculate(i32 a, i32 b, i32 c)
{
	i32 left = 32;
	i32 right = 0;
	i32 sift;
	i32 sign = 1;
	i32 tmp;

	if (a < 0) {
		sign = -1;
		a = -a;
	}
	if (b < 0) {
		sign *= -1;
		b = -b;
	}
	if (c < 0) {
		sign *= -1;
		c = -c;
	}

	if (c == 0) {
		return 0x7FFFFFFF * sign;
	}

	if (b > a) {
		tmp = b;
		b = a;
		a = tmp;
	}

	while (((a<<--left)>>left) != a);
	while ((b>>right++) > c);
	sift = left - right;

	return (((a<<sift) / c * b)>>sift)*sign;
}

/*------------------------------------------------------------------------------

	Limit

	Try to avoid virtual buffer overflow: Limit bitAvailable to range [0
	(2^31-1)/256] and realBitCnt to range [-2^30 2^30-1]. After realBitCnt
	limit rate control will not work properly because it lose bits.

------------------------------------------------------------------------------*/
void Limit(virtualBuffer_s *vb)
{
	vb->bitAvailable = MIN(vb->bitPerVop*5, vb->bitAvailable);
	vb->bitAvailable = MIN(0x7fffff, vb->bitAvailable);
	vb->bitAvailable = MAX(-0x7fffff, vb->bitAvailable);
	vb->realBitCnt = MIN(0x3FFFFFFF, MAX(-0x40000000, vb->realBitCnt));

	return;
}

⌨️ 快捷键说明

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