Re: VLC funcs
skal <[email protected]> 17 Mar 2003 10:38:59 +0100
| Newsgroups | gmane.comp.video.h264.devel |
|---|---|
| Message-ID | <1047893939.1907.4.camel@latitude344> |
Hi, On Fri, 2003-03-14 at 17:23, [email protected] wrote: > Hi, > please find attached some replacement functions > for the corresponding ones in 'vlc.c' file (ldecod). > So far I've seen, they're ok, but additional testing > wouldn't hurt... > (don't forget to disable CABAC in encoder.cfg!) hmm.. i think i found a bug in the ref software, in function ShowBits() (vlc.c): the "--numbits" line should be: "if (!--numbits) break;", otherwise, 'bitoffset' will be tested anyway, and might return -1 (error). This case does happen, in practice (!!). Generally speaking, all these bit I/O funcs should be switched to xvid's ones ASAP... Attached are some other replacement functions I forgot last time, as well as a "cleared" version of readCoeff4x4_CAVLC() in macroblock.c bye, Skal (Btw, i think there's another bug in InterpretPPS (parset.c) around 'num_slice_groups_minus1', but that's less interesting)
hdot264_2.c
(text/x-c, 7.7 KB)
/*!
************************************************************************
* \brief
* read Total Zeros Chroma DC codeword from UVLC-partition
************************************************************************
*/
static const SKL_VLC Tab_99_Total_Zeros0[8] = {
{ 3, 3},{ 2, 3},{ 1, 2},{ 1, 2},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1}
};
static const SKL_VLC Tab_99_Total_Zeros1[4] = {
{ 2, 2},{ 1, 2},{ 0, 1},{ 0, 1}
};
static const SKL_VLC Tab_99_Total_Zeros2[2] = {
{ 1, 1},{ 0, 1}
};
int readSyntaxElement_TotalZerosChromaDC(SyntaxElement *sym, DataPartition *dP)
{
int retval = 0;
const int tC = sym->value1;
const SKL_VLC *Tab = 0;
const unsigned int Code = See_Bits(dP, 3);
if (tC== 0) Tab = &Tab_99_Total_Zeros0 [Code>>0]; // 3b
else if (tC== 1) Tab = &Tab_99_Total_Zeros1 [Code>>1]; // 2b
else/*(tC== 2)*/ Tab = &Tab_99_Total_Zeros2 [Code>>2]; // 1b
sym->value1 = Tab->Val;
sym->len = Tab->Len;
if (sym->len) Discard_Bits(dP,Tab->Len);
else retval = 1;
if (retval)
{
printf("ERROR: failed to find Total Zeros\n");
exit(-1);
}
#if TRACE
tracebits2(sym->tracestring, sym->len, Code);
#endif
return retval;
}
/*!
************************************************************************
* \brief
* read Run codeword from UVLC-partition
************************************************************************
*/
static const SKL_VLC Tab_910_Total_Run1[2] = {
{ 1, 1},{ 0, 1}
};
static const SKL_VLC Tab_910_Total_Run2[4] = {
{ 2, 2},{ 1, 2},{ 0, 1},{ 0, 1}
};
static const SKL_VLC Tab_910_Total_Run3[4] = {
{ 3, 2},{ 2, 2},{ 1, 2},{ 0, 2}
};
static const SKL_VLC Tab_910_Total_Run4[8] = {
{ 4, 3},{ 3, 3},{ 2, 2},{ 2, 2},{ 1, 2},{ 1, 2},{ 0, 2},{ 0, 2}
};
static const SKL_VLC Tab_910_Total_Run5[8] = {
{ 5, 3},{ 4, 3},{ 3, 3},{ 2, 3},{ 1, 2},{ 1, 2},{ 0, 2},{ 0, 2}
};
static const SKL_VLC Tab_910_Total_Run6[8] = {
{ 1, 3},{ 2, 3},{ 4, 3},{ 3, 3},{ 6, 3},{ 5, 3},{ 0, 2},{ 0, 2}
};
static const SKL_VLC Tab_910_Total_Run7[7] = {
{ 6, 3},{ 5, 3},{ 4, 3},{ 3, 3},{ 2, 3},{ 1, 3},{ 0, 3}
};
int readSyntaxElement_Run(SyntaxElement *sym, DataPartition *dP)
{
int retval = 0;
const SKL_VLC *Tab;
const unsigned int Code = See_Bits(dP, 3);
const int zLeft = sym->value1;
if (zLeft==0) Tab = &Tab_910_Total_Run1[Code>>2]; // 1b
else if (zLeft==1) Tab = &Tab_910_Total_Run2[Code>>1]; // 2b
else if (zLeft==2) Tab = &Tab_910_Total_Run3[Code>>1]; // 2b
else if (zLeft==3) Tab = &Tab_910_Total_Run4[Code>>0]; // 3b
else if (zLeft==4) Tab = &Tab_910_Total_Run5[Code>>0]; // 3b
else if (zLeft==5) Tab = &Tab_910_Total_Run6[Code>>0]; // 3b
else { // special case for zerosleft>6
if (Code) Tab = Tab = &Tab_910_Total_Run7[(Code>>0)-1]; // 3b. Could be hardcoded
else {
int Val = 7;
Discard_Bits(dP, 3);
while(!Get_Bits(dP, 1)) Val++;
sym->value1 = Val;
sym->len = Val-7+4;
goto ok;
}
}
sym->value1 = Tab->Val;
sym->len = Tab->Len;
if (sym->len) Discard_Bits(dP,Tab->Len);
else retval = 1;
if (retval)
{
printf("ERROR: failed to find Run\n");
exit(-1);
}
ok:
#if TRACE
tracebits2(sym->tracestring, sym->len, Code);
#endif
return retval;
}
#endif
/*!
************************************************************************
* \brief
* Reads coeff of an 4x4 block (CAVLC)
*
* \author
* Karl Lillevold <[email protected]>
* contributions by James Au <[email protected]>
************************************************************************
*/
void readCoeff4x4_CAVLC (struct img_par *img,struct inp_par *inp,
int block_type,
int i, int j, int levarr[16], int runarr[16],
int *number_coefficients)
{
int mb_nr = img->map_mb_nr; // GBimg->current_mb_nr;
Macroblock *currMB = &img->mb_data[mb_nr];
SyntaxElement currSE;
Slice *currSlice = img->currentSlice;
DataPartition *dP;
int *partMap = assignSE2partition[currSlice->dp_mode];
int k, code, vlcnum;
int cdc=0, cac=0, dptype = 0;
int numcoeff, numtrailingones;
int zerosleft;
int max_coeff_num = 0;
numcoeff = 0;
switch (block_type)
{
case LUMA:
max_coeff_num = 16;
if (IS_INTRA (currMB)) dptype = SE_LUM_AC_INTRA;
else dptype = SE_LUM_AC_INTER;
break;
case LUMA_INTRA16x16DC:
max_coeff_num = 16;
dptype = SE_LUM_DC_INTRA;
break;
case LUMA_INTRA16x16AC:
max_coeff_num = 15;
dptype = SE_LUM_AC_INTRA;
break;
case CHROMA_DC:
max_coeff_num = 4;
cdc = 1;
if (IS_INTRA (currMB)) dptype = SE_CHR_DC_INTRA;
else dptype = SE_CHR_DC_INTER;
break;
case CHROMA_AC:
max_coeff_num = 15;
cac = 1;
if (IS_INTRA (currMB)) dptype = SE_CHR_AC_INTRA;
else dptype = SE_CHR_AC_INTER;
break;
default:
error ("readCoeff4x4_CAVLC: invalid block type", 600);
break;
}
if(img->type == B_SLICE)
dptype = SE_BFRAME;
currSE.type = dptype;
dP = &(currSlice->partArr[partMap[dptype]]);
img->nz_coeff[img->mb_x ][img->mb_y][i][j] = 0;
if (!cdc)
{
int nnz, numcoeff_vlc;
// luma or chroma AC
if (!cac) nnz = predict_nnz(img, i, j);
else nnz = predict_nnz_chroma(img, i, j);
if (nnz < 2) numcoeff_vlc = 0;
else if (nnz < 4) numcoeff_vlc = 1;
else if (nnz < 8) numcoeff_vlc = 2;
else numcoeff_vlc = 3;
currSE.value1 = numcoeff_vlc;
readSyntaxElement_NumCoeffTrailingOnes(&currSE, dP, "num-trainling-ones");
numcoeff = currSE.value1;
numtrailingones = currSE.value2;
img->nz_coeff[img->mb_x ][img->mb_y][i][j] = numcoeff;
}
else
{
// chroma DC
readSyntaxElement_NumCoeffTrailingOnesChromaDC(&currSE, dP);
numcoeff = currSE.value1;
numtrailingones = currSE.value2;
}
assert(numtrailingones<=numcoeff);
*number_coefficients = numcoeff;
if (numcoeff==0)
return;
k = numcoeff-1;
if (numtrailingones)
{
currSE.len = numtrailingones;
readSyntaxElement_FLC (&currSE, dP->bitstream);
code = currSE.inf;
k -= numtrailingones;
levarr[k+1] = (code&1) ? -1 : 1;
if (numtrailingones>1) {
levarr[k+2] = (code&2) ? -1 : 1;
if (numtrailingones>2)
levarr[k+3] = (code&4) ? -1 : 1;
}
}
// decode levels
if (k>=0)
{
int level;
// special case for first decoded symbol
if (!(numcoeff > 10 && numtrailingones < 3)) // vlc #0
readSyntaxElement_Level_VLC0(&currSE, dP);
else
readSyntaxElement_Level_VLCN(&currSE, 1, dP);
level = currSE.inf;
if (!(numcoeff > 3 && numtrailingones == 3)) { // level #2 or higher
if (level>0) level++;
else level--;
}
levarr[k] = level;
if (abs(level)>3) vlcnum = 2;
else vlcnum = 1;
while(k-->0)
{
readSyntaxElement_Level_VLCN(&currSE, vlcnum, dP);
levarr[k] = currSE.inf;
if (abs(levarr[k])>(3<<(vlcnum-1))) // increment VLC table
vlcnum++;
}
}
// decode runs
for (k = 0; k < numcoeff; k++) runarr[k] = 0;
if (numcoeff < max_coeff_num)
{
// total run
currSE.value1 = numcoeff-1;
if (cdc) readSyntaxElement_TotalZerosChromaDC(&currSE, dP);
else readSyntaxElement_TotalZeros(&currSE, dP);
zerosleft = currSE.value1;
// decode one run-before per coeff
k = numcoeff-1;
while (zerosleft>0 && k>0)
{
// select VLC for runbefore
currSE.value1 = (zerosleft>RUNBEFORE_NUM) ? RUNBEFORE_NUM-1 : zerosleft-1;
readSyntaxElement_Run(&currSE, dP);
runarr[k] = currSE.value1;
zerosleft -= currSE.value1;
k--;
}
runarr[k] = zerosleft;
}
// else => all full
}