📄 encratecontrol.c
字号:
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 + -