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
}