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

📄 countbit.c

📁 基于H.263的图像压缩编解码的C源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************
 *
 *  countbit.c, bitstream generation for tmn (TMN encoder)
 *  
 ************************************************************************/

#include"sim.h"
#include"sactbls.h"
#include"indices.h"
#include "putvlc.h"
 
int arith_used = 0;

/**********************************************************************
 *
 *      Name:           CountBitsMB
 *	Description:    counts bits used for MB info
 *	
 *	Input:	        Mode, COD, CBP, Picture and Bits structures
 *	Returns:       
 *	Side effects:
 *
 ***********************************************************************/

void CountBitsMB(int Mode, int COD, int CBP, int CBPB, Pict *pic, Bits *bits)
{
  int cbpy, cbpcm, length;

  /* COD */
  if (trace) {
    fprintf(tf,"MB-nr: %d",pic->MB);
    if (pic->picture_coding_type == PCT_INTER)
      fprintf(tf,"  COD: %d\n",COD);
  }
  if (pic->picture_coding_type == PCT_INTER) {
    putbits(1,COD);
    bits->COD++;
  }

  if (COD) 
    return;    /* not coded */

  /* CBPCM */
  cbpcm = Mode | ((CBP&3)<<4);
  if (trace) {
    fprintf(tf,"CBPCM (CBP=%d) (cbpcm=%d): ",CBP,cbpcm);
  }
  if (pic->picture_coding_type == PCT_INTRA)
    length = put_cbpcm_intra (CBP, Mode);
  else
    length = put_cbpcm_inter (CBP, Mode);
  bits->CBPCM += length;

    /* MODB & CBPB */
  if (pic->PB) {
    switch (pic->MODB) {
    case PBMODE_NORMAL:
      putbits(1,0);
      bits->MODB += 1;
      break;
    case PBMODE_MVDB:
      putbits(2,2);
      bits->MODB += 2;
      break;
    case PBMODE_CBPB_MVDB:
      putbits(2,3);
      bits->MODB += 2;
      /* CBPB */
      putbits(6,CBPB);
      bits->CBPB += 6;
      break;
    }
    if (trace) 
      fprintf(tf,"MODB: %d, CBPB: %d\n", pic->MODB, CBPB);
  }
    
  /* CBPY */
  cbpy = CBP>>2;
  if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q) /* Intra */
    cbpy = cbpy^15;
  if (trace) {
    fprintf(tf,"CBPY (CBP=%d) (cbpy=%d): ",CBP,cbpy);
  }
  length = put_cbpy (CBP, Mode);

  bits->CBPY += length;
  
  /* DQUANT */
  if ((Mode == MODE_INTER_Q) || (Mode == MODE_INTRA_Q)) {
    if (trace) {
      fprintf(tf,"DQUANT: ");
    }
    switch (pic->DQUANT) {
    case -1:
      putbits(2,0);
      break;
    case -2:
      putbits(2,1);
      break;
    case 1:
      putbits(2,2);
      break;
    case 2:
      putbits(2,3);
      break;
    default:
      fprintf(stderr,"Invalid DQUANT\n");
      exit(-1);
    }
    bits->DQUANT += 2;
  }
  return;
}

/**********************************************************************
 *
 *      Name:           Count_sac_BitsMB
 *      Description:    counts bits used for MB info using SAC models
 *                      modified from CountBitsMB
 *
 *      Input:          Mode, COD, CBP, Picture and Bits structures
 *      Returns:	none
 *      Side effects:	Updates Bits structure.
 *
 ***********************************************************************/
 
void Count_sac_BitsMB(int Mode,int COD,int CBP,int CBPB,Pict *pic,Bits *bits)
{
  int cbpy, cbpcm, length, i;
 
  arith_used = 1;
 
  /* COD */
 
  if (trace) {
    fprintf(tf,"MB-nr: %d",pic->MB);
    if (pic->picture_coding_type == PCT_INTER)
      fprintf(tf,"  COD: %d ",COD);
  }
 
  if (pic->picture_coding_type == PCT_INTER)
    bits->COD+=AR_Encode(COD, cumf_COD);
 
  if (COD)
    return;    /* not coded */
 
  /* CBPCM */
 
  cbpcm = Mode | ((CBP&3)<<4);
  if (trace) {
    fprintf(tf,"CBPCM (CBP=%d) (cbpcm=%d): ",CBP,cbpcm);
  }
  if (pic->picture_coding_type == PCT_INTRA)
    length = AR_Encode(indexfn(cbpcm,mcbpc_intratab,9),cumf_MCBPC_intra);
  else
    length = AR_Encode(indexfn(cbpcm,mcbpctab,21),cumf_MCBPC);
 
  bits->CBPCM += length;
 
  /* MODB & CBPB */
   if (pic->PB) {
     switch (pic->MODB) {
     case PBMODE_NORMAL:
       bits->MODB += AR_Encode(0, cumf_MODB);
       break;
     case PBMODE_MVDB:
       bits->MODB += AR_Encode(1, cumf_MODB);
       break;
     case PBMODE_CBPB_MVDB:
       bits->MODB += AR_Encode(2, cumf_MODB);
       /* CBPB */
       for(i=5; i>1; i--)
         bits->CBPB += AR_Encode(((CBPB & 1<<i)>>i), cumf_YCBPB);
       for(i=1; i>-1; i--)
         bits->CBPB += AR_Encode(((CBPB & 1<<i)>>i), cumf_UVCBPB);
       break;
     }
     if (trace) 
       fprintf(tf,"MODB: %d, CBPB: %d\n", pic->MODB, CBPB);
   }

  /* CBPY */
 
  cbpy = CBP>>2;
  if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q) { /* Intra */
    length = AR_Encode(indexfn(cbpy,cbpy_intratab,16),cumf_CBPY_intra);
  } else {
    length = AR_Encode(indexfn(cbpy,cbpytab,16),cumf_CBPY);
  }
  if (trace) {
    fprintf(tf,"CBPY (CBP=%d) (cbpy=%d): ",CBP,cbpy);
  }
  bits->CBPY += length;
 
  /* DQUANT */
 
  if ((Mode == MODE_INTER_Q) || (Mode == MODE_INTRA_Q)) {
    if (trace) {
      fprintf(tf,"DQUANT: ");
    }
    bits->DQUANT += AR_Encode(indexfn(pic->DQUANT+2,dquanttab,4), cumf_DQUANT);
  }
  return;
}


/**********************************************************************
 *
 *      Name:           CountBitsSlice
 *	Description:    couonts bits used for slice (GOB) info
 *	
 *	Input:	        slice no., quantizer
 *
 ***********************************************************************/

int CountBitsSlice(int slice, int quant)
{
  int bits = 0;

  if (arith_used) {
    bits+=encoder_flush(); /* Need to call before fixed length string output */
    arith_used = 0;
  }

  /* Picture Start Code */
  if (trace)
    fprintf(tf,"GOB sync (GBSC): ");
  putbits(PSC_LENGTH,PSC); /* PSC */
  bits += PSC_LENGTH;

  /* Group Number */
  if (trace)
    fprintf(tf,"GN: ");
  putbits(5,slice);
  bits += 5;

  /* GOB Sub Bitstream Indicator */
  /* if CPM == 1: read 2 bits GSBI */
  /* not supported in this version */

  /* GOB Frame ID */
  if (trace)
    fprintf(tf,"GFID: ");
  putbits(2, 0);  
  /* NB: in error-prone environments this value should change if 
     PTYPE in picture header changes. In this version of the encoder
     PTYPE only changes when PB-frames are used in the following cases:
     (i) after the first intra frame
     (ii) if the distance between two P-frames is very large 
     Therefore I haven't implemented this GFID change */
  /* GFID is not allowed to change unless PTYPE changes */
  bits += 2;

  /* Gquant */
  if (trace)
    fprintf(tf,"GQUANT: ");
  putbits(5,quant);
  bits += 5;

  return bits;
}

/**********************************************************************
 *
 *      Name:           CountBitsCoeff
 *	Description:	counts bits used for coeffs
 *	
 *      Input:          qcoeff, coding mode CBP, bits structure, no. of 
 *                      coeffs
 *        
 *	Returns:	struct with no. of bits used
 *	Side effects:	
 *
 ***********************************************************************/

void CountBitsCoeff(int *qcoeff, int Mode, int CBP, Bits *bits, int ncoeffs)
{
  
  int i;

  if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q) {
    for (i = 0; i < 4; i++) {
      bits->Y += CodeCoeff(Mode, qcoeff,i,ncoeffs);
    }
    for (i = 4; i < 6; i++) {
      bits->C += CodeCoeff(Mode, qcoeff,i,ncoeffs);
    }
  }
  else {
    for (i = 0; i < 4; i++) {
      if ((i==0 && CBP&32) || 
          (i==1 && CBP&16) ||
          (i==2 && CBP&8) || 
          (i==3 && CBP&4) || 
          (i==4 && CBP&2) ||
          (i==5 && CBP&1)) {
        bits->Y += CodeCoeff(Mode, qcoeff, i, ncoeffs);
      }
    }
    for (i = 4; i < 6; i++) {
      if ((i==0 && CBP&32) || 
          (i==1 && CBP&16) ||
          (i==2 && CBP&8) || 
          (i==3 && CBP&4) || 
          (i==4 && CBP&2) ||
          (i==5 && CBP&1)) {
        bits->C += CodeCoeff(Mode, qcoeff, i, ncoeffs);
      }
    }
  }
  return;
}
  
int CodeCoeff(int Mode, int *qcoeff, int block, int ncoeffs)
{
  int j, bits;
  int prev_run, run, prev_level, level, first;
  int prev_s, s, length;

  run = bits = 0;
  first = 1;
  prev_run = prev_level = level = s = prev_s = 0;
  
  if (trace) {
    fprintf(tf,"Coeffs block %d:\n",block);
  }

  for (j = block*ncoeffs; j< (block + 1)*ncoeffs; j++) {
    /* Do this block's DC-coefficient first */
    if (!(j%ncoeffs) && (Mode == MODE_INTRA || Mode == MODE_INTRA_Q)) {
      /* DC coeff */
      if (trace) {
        fprintf(tf,"DC: ");
      }
      if (qcoeff[block*ncoeffs] != 128)
        putbits(8,qcoeff[block*ncoeffs]);
      else
        putbits(8,255);
      bits += 8;
    }
    else {
      /* AC coeff */
      s = 0;
      /* Increment run if coeff is zero */
      if ((level = qcoeff[j]) == 0) {
        run++;
      }
      else {
        /* code run & level and count bits */
        if (level < 0) {
          s = 1;
          level = -level;
        }

        if (!first) {
          /* Encode the previous coefficient */
          if (prev_level  < 13 && prev_run < 64)
            length = put_coeff (prev_run, prev_level, 0);  
          else
            length = 0;
          if (length == 0) {  /* Escape coding */
            if (trace) {
              fprintf(tf,"Escape code: ");
            }
            if (prev_s == 1) {prev_level = (prev_level^0xff)+1;}
            putbits(7,3);	/* Escape code */
            if (trace)
              fprintf(tf,"last: ");
            putbits(1,0);
            if (trace)
              fprintf(tf,"run: ");
            putbits(6,prev_run);
            if (trace)
              fprintf(tf,"level: ");
            putbits(8,prev_level);
            bits += 22;
          }
          else {
            putbits(1,prev_s);
            bits += length + 1;
          }
        }
        prev_run = run; prev_s = s;
        prev_level = level; 

        run = first = 0;
      }
    }
  }
  /* Encode the last coeff */
  if (!first) {
    if (trace) {
      fprintf(tf,"Last coeff: ");
    }
    if (prev_level  < 13 && prev_run < 64) 
      length = put_coeff (prev_run, prev_level, 1);   
    else
      length = 0;
    if (length == 0) {  /* Escape coding */
      if (trace) {
        fprintf(tf,"Escape code: ");
      }
      if (prev_s == 1) {prev_level = (prev_level^0xff)+1;}
      putbits (7,3);	/* Escape code */
      if (trace)
        fprintf(tf,"last: ");
      putbits(1,1);
      if (trace)
        fprintf(tf,"run: ");
      putbits(6,prev_run);
      if (trace)
        fprintf(tf,"level: ");
      putbits(8,prev_level);
      bits += 22;
    }
    else {
      putbits(1,prev_s);
      bits += length + 1;
    }
  }
  return bits;

⌨️ 快捷键说明

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