📄 rdoq_cavlc.c
字号:
/*!
*************************************************************************************
* \file rdoq_cavlc.c
*
* \brief
* Rate Distortion Optimized Quantization based on VCEG-AH21 related to CAVLC
*************************************************************************************
*/
#include "contributors.h"
#include <math.h>
#include <float.h>
#include "global.h"
#include "image.h"
#include "fmo.h"
#include "macroblock.h"
#include "mb_access.h"
#include "ratectl.h"
#include "rdoq.h"
extern const int estErr4x4[6][4][4];
extern const int estErr8x8[6][8][8];
extern const byte SNGL_SCAN[16][2]; // need to revisit
extern const byte FIELD_SCAN[16][2];
/*!
************************************************************************
* \brief
* estimate VLC for Coeff Level
************************************************************************
*/
int estSyntaxElement_Level_VLC1(SyntaxElement *se)
{
int level = se->value1;
int sign = (level < 0 ? 1 : 0);
int levabs = iabs(level);
if (levabs < 8)
{
se->len = levabs * 2 + sign - 1;
}
else if (levabs < 16)
{
// escape code1
se->len = 19;
}
else
{
// escape code2
se->len = 28;
}
return (se->len);
}
/*!
************************************************************************
* \brief
* estimate VLC for Coeff Level
************************************************************************
*/
int estSyntaxElement_Level_VLCN(SyntaxElement *se, int vlc)//, DataPartition *this_dataPart)
{
int level = se->value1;
int levabs = iabs(level) - 1;
int shift = vlc - 1;
int escape = (15 << shift);
if (levabs < escape)
{
se->len = ((levabs) >> shift) + 1 + vlc;
}
else
{
se->len = 28;
}
return (se->len);
}
int cmp(const void *arg1, const void *arg2)
{
return (((levelDataStruct *)arg2)->levelDouble - ((levelDataStruct *)arg1)->levelDouble);
}
/*!
************************************************************************
* \brief
* estimate CAVLC bits
************************************************************************
*/
int est_CAVLC_bits (levelDataStruct *levelData, int level_to_enc[16], int sign_to_enc[16], int nnz, int block_type)
{
int no_bits = 0;
SyntaxElement se;
int coeff_ctr, scan_pos = 0;
int k, level = 1, run = -1, vlcnum;
int numcoeff = 0, lastcoeff = 0, numtrailingones = 0;
int numones = 0, totzeros = 0, zerosleft, numcoef;
int numcoeff_vlc;
int level_two_or_higher;
int max_coeff_num = 0, cdc = (block_type == CHROMA_DC ? 1 : 0);
int yuv = img->yuv_format - 1;
static const int incVlc[] = {0, 3, 6, 12, 24, 48, 32768}; // maximum vlc = 6
int pLevel[16] = {0};
int pRun[16] = {0};
static const int Token_lentab[3][4][17] =
{
{
{ 1, 6, 8, 9,10,11,13,13,13,14,14,15,15,16,16,16,16},
{ 0, 2, 6, 8, 9,10,11,13,13,14,14,15,15,15,16,16,16},
{ 0, 0, 3, 7, 8, 9,10,11,13,13,14,14,15,15,16,16,16},
{ 0, 0, 0, 5, 6, 7, 8, 9,10,11,13,14,14,15,15,16,16}
},
{
{ 2, 6, 6, 7, 8, 8, 9,11,11,12,12,12,13,13,13,14,14},
{ 0, 2, 5, 6, 6, 7, 8, 9,11,11,12,12,13,13,14,14,14},
{ 0, 0, 3, 6, 6, 7, 8, 9,11,11,12,12,13,13,13,14,14},
{ 0, 0, 0, 4, 4, 5, 6, 6, 7, 9,11,11,12,13,13,13,14}
},
{
{ 4, 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, 9,10,10,10,10},
{ 0, 4, 5, 5, 5, 5, 6, 6, 7, 8, 8, 9, 9, 9,10,10,10},
{ 0, 0, 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,10},
{ 0, 0, 0, 4, 4, 4, 4, 4, 5, 6, 7, 8, 8, 9,10,10,10}
}
};
static const int Totalzeros_lentab[TOTRUN_NUM][16] =
{
{ 1,3,3,4,4,5,5,6,6,7,7,8,8,9,9,9},
{ 3,3,3,3,3,4,4,4,4,5,5,6,6,6,6},
{ 4,3,3,3,4,4,3,3,4,5,5,6,5,6},
{ 5,3,4,4,3,3,3,4,3,4,5,5,5},
{ 4,4,4,3,3,3,3,3,4,5,4,5},
{ 6,5,3,3,3,3,3,3,4,3,6},
{ 6,5,3,3,3,2,3,4,3,6},
{ 6,4,5,3,2,2,3,3,6},
{ 6,6,4,2,2,3,2,5},
{ 5,5,3,2,2,2,4},
{ 4,4,3,3,1,3},
{ 4,4,2,1,3},
{ 3,3,1,2},
{ 2,2,1},
{ 1,1},
};
static const int Run_lentab[TOTRUN_NUM][16] =
{
{1,1},
{1,2,2},
{2,2,2,2},
{2,2,2,3,3},
{2,2,3,3,3,3},
{2,3,3,3,3,3,3},
{3,3,3,3,3,3,3,4,5,6,7,8,9,10,11},
};
static const int Token_lentab_cdc[3][4][17] =
{
//YUV420
{{ 2, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 1, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 3, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
//YUV422
{{ 1, 7, 7, 9, 9,10,11,12,13, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 2, 7, 7, 9,10,11,12,12, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 3, 7, 7, 9,10,11,12, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 5, 6, 7, 7,10,11, 0, 0, 0, 0, 0, 0, 0, 0}},
//YUV444
{{ 1, 6, 8, 9,10,11,13,13,13,14,14,15,15,16,16,16,16},
{ 0, 2, 6, 8, 9,10,11,13,13,14,14,15,15,15,16,16,16},
{ 0, 0, 3, 7, 8, 9,10,11,13,13,14,14,15,15,16,16,16},
{ 0, 0, 0, 5, 6, 7, 8, 9,10,11,13,14,14,15,15,16,16}}
};
static const int Totalzeros_lentab_cdc[3][TOTRUN_NUM][16] =
{
//YUV420
{{ 1,2,3,3},
{ 1,2,2},
{ 1,1}},
//YUV422
{{ 1,3,3,4,4,4,5,5},
{ 3,2,3,3,3,3,3},
{ 3,3,2,2,3,3},
{ 3,2,2,2,3},
{ 2,2,2,2},
{ 2,2,1},
{ 1,1}},
//YUV444
{{ 1,3,3,4,4,5,5,6,6,7,7,8,8,9,9,9},
{ 3,3,3,3,3,4,4,4,4,5,5,6,6,6,6},
{ 4,3,3,3,4,4,3,3,4,5,5,6,5,6},
{ 5,3,4,4,3,3,3,4,3,4,5,5,5},
{ 4,4,4,3,3,3,3,3,4,5,4,5},
{ 6,5,3,3,3,3,3,3,4,3,6},
{ 6,5,3,3,3,2,3,4,3,6},
{ 6,4,5,3,2,2,3,3,6},
{ 6,6,4,2,2,3,2,5},
{ 5,5,3,2,2,2,4},
{ 4,4,3,3,1,3},
{ 4,4,2,1,3},
{ 3,3,1,2},
{ 2,2,1},
{ 1,1}}
};
max_coeff_num = ( (block_type == CHROMA_DC) ? img->num_cdc_coeff :
( (block_type == LUMA_INTRA16x16AC || block_type == CB_INTRA16x16AC || block_type == CR_INTRA16x16AC || block_type == CHROMA_AC) ? 15 : 16) );
//convert zigzag scan to (run, level) pairs
for (coeff_ctr = 0; coeff_ctr < max_coeff_num; coeff_ctr++)
{
run++;
level = level_to_enc[coeff_ctr];
if (level != 0)
{
pLevel[scan_pos] = isignab(level, sign_to_enc[coeff_ctr]);
pRun [scan_pos] = run;
++scan_pos;
run = -1; // reset zero level counter
}
}
level = 1;
for(k = 0; (k < max_coeff_num) && level != 0; k++)
{
level = pLevel[k]; // level
run = pRun[k]; // run
if (level)
{
totzeros += run; // lets add run always (even if zero) to avoid conditional
if (iabs(level) == 1)
{
numones ++;
numtrailingones ++;
numtrailingones = imin(numtrailingones, 3); // clip to 3
}
else
{
numtrailingones = 0;
}
numcoeff ++;
lastcoeff = k;
}
}
if (!cdc)
{
if (nnz < 2)
{
numcoeff_vlc = 0;
}
else if (nnz < 4)
{
numcoeff_vlc = 1;
}
else if (nnz < 8)
{
numcoeff_vlc = 2;
}
else
{
numcoeff_vlc = 3;
}
}
else
{
// chroma DC (has its own VLC)
// numcoeff_vlc not relevant
numcoeff_vlc = 0;
}
se.value1 = numcoeff;
se.value2 = numtrailingones;
se.len = numcoeff_vlc; /* use len to pass vlcnum */
if (!cdc)
{
if (se.len == 3)
no_bits += 6; // 4 + 2 bit FLC
else
no_bits += Token_lentab[se.len][se.value2][se.value1];
}
else
no_bits += Token_lentab_cdc[yuv][se.value2][se.value1];
if (!numcoeff)
return no_bits;
else
{
if (numtrailingones)
no_bits += numtrailingones;
// encode levels
level_two_or_higher = (numcoeff > 3 && numtrailingones == 3) ? 0 : 1;
vlcnum = (numcoeff > 10 && numtrailingones < 3) ? 1 : 0;
for (k = lastcoeff - numtrailingones; k >= 0; k--)
{
level = pLevel[k]; // level
se.value1 = level;
if (level_two_or_higher)
{
level_two_or_higher = 0;
if (se.value1 > 0)
se.value1 --;
else
se.value1 ++;
}
// encode level
if (vlcnum == 0)
estSyntaxElement_Level_VLC1(&se);
else
estSyntaxElement_Level_VLCN(&se, vlcnum);
// update VLC table
if (iabs(level) > incVlc[vlcnum])
vlcnum++;
if ((k == lastcoeff - numtrailingones) && iabs(level) > 3)
vlcnum = 2;
no_bits += se.len;
}
// encode total zeroes
if (numcoeff < max_coeff_num)
{
se.value1 = totzeros;
vlcnum = numcoeff-1;
se.len = vlcnum;
if (!cdc)
no_bits += Totalzeros_lentab[se.len][se.value1];
else
no_bits += Totalzeros_lentab_cdc[yuv][se.len][se.value1];
}
// encode run before each coefficient
zerosleft = totzeros;
numcoef = numcoeff;
for (k = lastcoeff; k >= 0; k--)
{
run = pRun[k]; // run
se.value1 = run;
// for last coeff, run is remaining totzeros
// when zerosleft is zero, remaining coeffs have 0 run
if ((!zerosleft) || (numcoeff <= 1 ))
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -