countbit.cpp
上传用户:panstart
上传日期:2022-04-12
资源大小:199k
文件大小:18k
源码类别:

IP电话/视频会议

开发平台:

C++ Builder

  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. //
  4. //    Project     : VideoNet version 1.1.
  5. //    Description : Peer to Peer Video Conferencing over the LAN.
  6. //   Author      : Nagareshwar Y Talekar ( nsry2002@yahoo.co.in)
  7. //    Date        : 15-6-2004.
  8. //
  9. //    I have converted origional fast h.263 encoder library from C to C++ 
  10. //   so that it can be integrated into any windows application easily.
  11. //   I have removed some of unnecessary codes/files from the
  12. //   fast h263 library.Also moved definitions and declarations
  13. //   in their proper .h and .cpp files.
  14. //
  15. //    File description : 
  16. //    Name    : countbit.cpp
  17. //
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. /*************************************************  * libr263: fast H.263 encoder library  *  * Copyright (C) 1996, Roalt Aalmoes, Twente University  * SPA multimedia group  *  * Based on Telenor TMN 1.6 encoder (Copyright (C) 1995, Telenor R&D)  * created by Karl Lillevold   *  * Author encoder: Roalt Aalmoes, <aalmoes@huygens.nl>  *   * Date: 31-07-96  **************************************************/   /**********************************************************************  *  * Name: CountBitsMB  * Description:    counts bits used for MB info
  21.  *
  22.  * Input:         Mode, COD, CBP, Picture and Bits structures
  23.  * Returns:       
  24.  * Side effects:
  25.  *
  26.  * Date: 941129 Author: Karl.Lillevold@nta.no  *  ***********************************************************************/
  27. #include "countbit.h"
  28. void CountBitsMB(int Mode, int COD, int CBP, int CBPB, Pict *pic, Bits *bits) {   extern EHUFF *vlc_cbpy, *vlc_cbpcm, *vlc_cbpcm_intra;   int cbpy, cbpcm, length;   /* COD */   if (Global::trace) {     fprintf(Global::tf,"MB-nr: %d",pic->MB);     if (pic->picture_coding_type == PCT_INTER)       fprintf(Global::tf,"  COD: %dn",COD);   }   if (pic->picture_coding_type == PCT_INTER) {     mputv(1,COD);     bits->COD++;   }   if (COD)      return;    /* not coded */   /* CBPCM */   cbpcm = Mode | ((CBP&3)<<4);   if (Global::trace) {     fprintf(Global::tf,"CBPCM (CBP=%d) (cbpcm=%d): ",CBP,cbpcm);   }   if (pic->picture_coding_type == PCT_INTRA) {     length = Encode(cbpcm,vlc_cbpcm_intra);   } else {     length = Encode(cbpcm,vlc_cbpcm);   }   bits->CBPCM += length;        /* CBPY */   cbpy = CBP>>2;   if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q) /* Intra */     cbpy = cbpy^15;   if (Global::trace) {     fprintf(Global::tf,"CBPY (CBP=%d) (cbpy=%d): ",CBP,cbpy);   }   length = Encode(cbpy, vlc_cbpy);   bits->CBPY += length;      return; } /**********************************************************************  *  * Name: CountBitsSlice  * Description:    couonts bits used for slice (GOB) info  *  * Input:         slice no., quantizer  *  * Date: 94???? Author: Karl.Lillevold@nta.no  *  ***********************************************************************/ int CountBitsSlice(int slice, int quant) {   int bits = 0;   /* Picture Start Code */   if (Global::trace)     fprintf(Global::tf,"GOB sync (GBSC): ");   mputv(PSC_LENGTH,PSC); /* PSC */   bits += PSC_LENGTH;   /* Group Number */   if (Global::trace)     fprintf(Global::tf,"GN: ");   mputv(5,slice);   bits += 5;   /* GOB Sub Bitstream Indicator */   /* if CPM == 1: read 2 bits GSBI */   /* not supported in this version */   /* GOB Frame ID */   if (Global::trace)     fprintf(Global::tf,"GFID: ");   mputv(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 (Global::trace)     fprintf(Global::tf,"GQUANT: ");   mputv(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:  *  * Date: 940111 Author: Karl.Lillevold@nta.no  *  ***********************************************************************/ void CountBitsCoeff(int *qcoeff, int Mode, int CBP, Bits *bits, int ncoeffs) {      int i;   if (Mode == MODE_INTRA) {     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_ind, ind, prev_s, s, length;   extern EHUFF *vlc_3d;   run = bits = 0;   first = 1;   prev_run = prev_level = prev_ind = level = s = prev_s = ind = 0;      for (j = block*ncoeffs; j< (block + 1)*ncoeffs; j++) {     /* Do this block's DC-coefficient first */     if (!(j%ncoeffs) && (Mode == MODE_INTRA)) {       /* DC coeff */       if (Global::trace) { fprintf(Global::tf,"DC: ");       }       if (qcoeff[block*ncoeffs] != 128) mputv(8,qcoeff[block*ncoeffs]);       else mputv(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; } ind = level | run<<4; ind = ind | 0<<12; /* Not last coeff */ if (!first) {   /* Encode the previous ind */   if (prev_level  < 13 && prev_run < 64) {     length = Encode(prev_ind,vlc_3d);   } else     length = 0;   if (length == 0) {  /* Escape coding */     if (Global::trace) {       fprintf(Global::tf,"Escape coding:n");     }     if (prev_s == 1) {prev_level = (prev_level^0xff)+1;}     Encode(ESCAPE,vlc_3d);     mputv(1,0);     mputv(6,prev_run);     mputv(8,prev_level);     bits += 22;   }   else {     mputv(1,prev_s);     bits += length + 1;   } } prev_run = run; prev_s = s; prev_level = level; prev_ind = ind; run = first = 0;       }     }   }   /* Encode the last coeff */   if (!first) {     if (Global::trace) {       fprintf(Global::tf,"Last coeff: ");     }     prev_ind = prev_ind | 1<<12;   /* last coeff */     if (prev_level  < 13 && prev_run < 64) {        length = Encode(prev_ind,vlc_3d);     } else       length = 0;     if (length == 0) {  /* Escape coding */       if (Global::trace) { fprintf(Global::tf,"Escape coding:n");       }       if (prev_s == 1) {prev_level = (prev_level^0xff)+1;}       Encode(ESCAPE,vlc_3d);       mputv(1,1);       mputv(6,prev_run);       mputv(8,prev_level);       bits += 22;     }     else {       mputv(1,prev_s);       bits += length + 1;     }   }   return bits; }   /**********************************************************************  *  * Name: FindCBP  * Description: Finds the CBP for a macroblock  *  * Input: qcoeff and mode  *  * Returns: CBP  * Side effects:  *  * Date: 940829 Author: Karl.Lillevold@nta.no  *  ***********************************************************************/ int FindCBP(int *qcoeff, int Mode, int ncoeffs) {      int i,j;   int CBP = 0; /* IF INTRABLOCK then intra =1 else 0 */   int intra = (Mode == MODE_INTRA);   /* Set CBP for this Macroblock */   for (i = 0; i < 6; i++) {     /* First time i = 0: j = 0 ..64-1  set bit 5 if coeff != 0        Sec. time  i = 1; j = 64..128-1 set bit 4 if coeff != 0        */     /* OPTIMIZE: I think for i can be removed         and only values i=0 must be proessed */     for (j = i*ncoeffs + intra; j < (i+1)*ncoeffs; j++) {       if (qcoeff[j]) { if (i == 0) {CBP |= 32;} else if (i == 1) {CBP |= 16;} else if (i == 2) {CBP |= 8;} else if (i == 3) {CBP |= 4;} else if (i == 4) {CBP |= 2;} else if (i == 5) {CBP |= 1;} else {   fprintf(stderr,"Error in CBP assignmentn");   exit(-1); } break;       }     }   }   return CBP; } void CountBitsVectors(MotionVector *MV_ptr, Bits *bits,        int x, int y, int Mode, int newgob, Pict *pic) {   int y_vec, x_vec;   extern EHUFF *vlc_mv;   int pmv0, pmv1;   int start,stop,block;   MotionVector *MV_xy;   start = 0; stop = 0;   MV_xy = MV_ptr + y*Global::mbc + x;   for (block = start; block <= stop;  block++) {     FindPMV(MV_ptr,x,y,&pmv0,&pmv1, block, newgob, 1);     x_vec = (2*(*MV_xy).x + (*MV_xy).x_half) - pmv0;     y_vec = (2*(*MV_xy).y + (*MV_xy).y_half) - pmv1;     if (!Global::long_vectors) {       if (x_vec < -32) x_vec += 64;       else if (x_vec > 31) x_vec -= 64;       if (y_vec < -32) y_vec += 64;       else if (y_vec > 31) y_vec -= 64;     }     else {       if (pmv0 < -31 && x_vec < -63) x_vec += 64;       else if (pmv0 > 32 && x_vec > 63) x_vec -= 64;       if (pmv1 < -31 && y_vec < -63) y_vec += 64;       else if (pmv1 > 32 && y_vec > 63) y_vec -= 64;     }          if (x_vec < 0) x_vec += 64;     if (y_vec < 0) y_vec += 64;     if (Global::trace) {       fprintf(Global::tf,"Vectors:n");     }     bits->vec += Encode(x_vec,vlc_mv);     bits->vec += Encode(y_vec,vlc_mv);     if (Global::trace) {       if (x_vec > 31) x_vec -= 64;       if (y_vec > 31) y_vec -= 64;       fprintf(Global::tf,"(x,y) = (%d,%d) - ",       (2*(*MV_xy).x + (*MV_xy).x_half),       (2*(*MV_xy).y + (*MV_xy).y_half));       fprintf(Global::tf,"(Px,Py) = (%d,%d)n", pmv0,pmv1);       fprintf(Global::tf,"(x_diff,y_diff) = (%d,%d)n",x_vec,y_vec);     }   }   return; } void FindPMV(MotionVector *MV_ptr, int x, int y,       int *pmv0, int *pmv1, int block, int newgob, int half_pel) {   int p1,p2,p3;   int xin1,xin2,xin3;   int yin1,yin2,yin3;   int vec1,vec2,vec3;   int l8,o8,or8;   l8 = o8 = or8 = 0;     vec1 = (l8 ? 2 : 0) ; yin1 = y  ; xin1 = x-1;   vec2 = (o8 ? 3 : 0) ; yin2 = y-1; xin2 = x;   vec3 = (or8? 3 : 0) ; yin3 = y-1; xin3 = x+1;   if (half_pel) {     p1 = (x > 0) ?        2*((*(MV_ptr + yin1*Global::mbc + xin1)).x) + (*(MV_ptr+ yin1*Global::mbc + xin1)).x_half : 0;     p2 = (y > 0) ?        2*((*(MV_ptr + yin2*Global::mbc + xin2)).x) + (*(MV_ptr + yin2*Global::mbc + xin2)).x_half : 2*NO_VEC;     if((y > 0) && (x < Global::mbc - 1))       p3 = 2*((*(MV_ptr+yin3*Global::mbc + xin3)).x) + ((*(MV_ptr + yin3*Global::mbc + xin3)).x_half);     else if(x == Global::mbc - 1)       p3 = 0;     else /* y == 0 && x != Global::mbc - 1 */       p3 = 2*NO_VEC;     }   else {     p1 =  (x > 0) ?        (2*((*(MV_ptr + yin1*Global::mbc + xin1)).x)) : 0;     p2 =  (y > 0) ?        (2*((*(MV_ptr + yin2*Global::mbc + xin2)).x)) : 2*NO_VEC;     if((y > 0) && (x < Global::mbc - 1))       p3 = 2*((*(MV_ptr + yin3*Global::mbc + xin3)).x);     else if(x == Global::mbc - 1)       p3 = 0;     else /* y == 0 && x != Global::mbc - 1 */       p3 = 2*NO_VEC;   }   if (newgob && (block == 0 || block == 1 || block == 2))     p2 = 2*NO_VEC;   if (p2 == 2*NO_VEC) { p2 = p3 = p1; }   *pmv0 = p1+p2+p3 - mmax(p1,mmax(p2,p3)) - mmin(p1,mmin(p2,p3));   if (half_pel) {     p1 =  (x > 0) ?        (2*((*(MV_ptr + yin1*Global::mbc + xin1)).y)) + ((*(MV_ptr + yin1*Global::mbc + xin1)).y_half) : 0;     p2 =  (y > 0) ?        2*((*(MV_ptr + yin2*Global::mbc + xin2)).y) + ((*(MV_ptr + yin2*Global::mbc + xin2)).y_half) : 2*NO_VEC;     if((y > 0) && (x < Global::mbc - 1))       p3 = 2*((*(MV_ptr + yin3*Global::mbc + xin3)).y) + ((*(MV_ptr + Global::mbc*yin3 + xin3)).y_half);     else if(x == Global::mbc - 1)       p3 = 0;     else /* y == 0 && x != Global::mbc - 1 */       p3 = 2*NO_VEC;     }   else {     p1 = (x > 0) ?       (2*((*(MV_ptr + yin1*Global::mbc + xin1)).y)) : 0;     p2 =  (y > 0) ?       (2*((*(MV_ptr + yin2*Global::mbc + xin2)).y)) : 2*NO_VEC;     if((y > 0) && (x < Global::mbc - 1))       p3 = 2*((*(MV_ptr + yin3*Global::mbc + xin3)).y);     else if(x == Global::mbc - 1)       p3 = 0;     else /* y == 0 && x != Global::mbc - 1 */       p3 = 2*NO_VEC;   }         if (newgob && (block == 0 || block == 1 || block == 2))     p2 = 2*NO_VEC;   if (p2 == 2*NO_VEC) { p2 = p3 = p1; }   *pmv1 = p1+p2+p3 - mmax(p1,mmax(p2,p3)) - mmin(p1,mmin(p2,p3));      return; } void ZeroBits(Bits *bits) { #ifndef MINIMAL_REPORT   bits->Y = 0;   bits->C = 0;   bits->vec = 0;   bits->CBPY = 0;   bits->CBPCM = 0;   bits->MODB = 0;   bits->CBPB = 0;   bits->COD = 0;   bits->DQUANT = 0;   bits->header = 0;   bits->total = 0;   bits->no_inter = 0;   bits->no_inter4v = 0;   bits->no_intra = 0; #endif   return; } void ZeroRes(Results *res) { #ifndef MINIMAL_REPORT   res->SNR_l = 0;   res->SNR_Cr = 0;   res->SNR_Cb = 0;   res->QP_mean = 0; #endif } void AddBits(Bits *total, Bits *bits) { #ifndef MINIMAL_REPORT   total->Y += bits->Y;   total->C += bits->C;   total->vec += bits->vec;   total->CBPY += bits->CBPY;   total->CBPCM += bits->CBPCM;   total->MODB += bits->MODB;   total->CBPB += bits->CBPB;   total->COD += bits->COD;   total->DQUANT += bits->DQUANT;   total->header += bits->header;   total->total += bits->total;   total->no_inter += bits->no_inter;   total->no_inter4v += bits->no_inter4v;   total->no_intra += bits->no_intra; #endif   return; } void AddRes(Results *total, Results *res, Pict *pic) { #ifndef MINIMAL_REPORT   total->SNR_l += res->SNR_l;   total->SNR_Cr += res->SNR_Cr;   total->SNR_Cb += res->SNR_Cb;   total->QP_mean += pic->QP_mean; #endif   return; } void AddBitsPicture(Bits *bits) { #ifndef MINIMAL_REPORT   bits->total =      bits->Y +      bits->C +      bits->vec +       bits->CBPY +      bits->CBPCM +      bits->MODB +     bits->CBPB +     bits->COD +      bits->DQUANT +     bits->header ; #endif }  void ZeroVec(MotionVector *MV) {   MV->x = 0;   MV->y = 0;   MV->x_half = 0;   MV->y_half = 0;   return; } void MarkVec(MotionVector *MV) {   MV->x = NO_VEC;   MV->y = NO_VEC;   MV->x_half = 0;   MV->y_half = 0;   return; } void CopyVec(MotionVector *MV2, MotionVector *MV1) {   MV2->x = MV1->x;   MV2->x_half = MV1->x_half;   MV2->y = MV1->y;   MV2->y_half = MV1->y_half;   return; } int EqualVec(MotionVector *MV2, MotionVector *MV1) {   if (MV1->x != MV2->x)     return 0;   if (MV1->y != MV2->y)     return 0;   if (MV1->x_half != MV2->x_half)     return 0;   if (MV1->y_half != MV2->y_half)     return 0;   return 1; } /**********************************************************************  *  * Name: CountBitsPicture(Pict *pic)  * Description:    counts the number of bits needed for picture  *                      header  *  * Input:         pointer to picture structure  * Returns:        number of bits  * Side effects:  *  * Date: 941128 Author:Karl.Lillevold@nta.no  *  ***********************************************************************/ int CountBitsPicture(Pict *pic) {   int bits = 0;     /* Picture start code */   if (Global::trace) {     fprintf(Global::tf,"picture_start_code: ");   }   mputv(PSC_LENGTH,PSC);   bits += PSC_LENGTH;   /* Group number */   if (Global::trace) {     fprintf(Global::tf,"Group number in picture header: ");   }   mputv(5,0);    bits += 5;      /* Time reference */   if (Global::trace) {     fprintf(Global::tf,"Time reference: ");   }   mputv(8,pic->TR);   bits += 8;  /* bit 1 */   if (Global::trace) {     fprintf(Global::tf,"spare: ");   }   pic->spare = 1; /* always 1 to avoid start code emulation */   mputv(1,pic->spare);   bits += 1;   /* bit 2 */   if (Global::trace) {     fprintf(Global::tf,"always zero for distinction with H.261n");   }   mputv(1,0);   bits += 1;      /* bit 3 */   if (Global::trace) {     fprintf(Global::tf,"split_screen_indicator: ");   }   mputv(1,0);     /* no support for split-screen in this software */   bits += 1;   /* bit 4 */   if (Global::trace) {     fprintf(Global::tf,"document_camera_indicator: ");   }   mputv(1,0);   bits += 1;   /* bit 5 */   if (Global::trace) {     fprintf(Global::tf,"freeze_picture_release: ");   }   mputv(1,0);   bits += 1;   /* bit 6-8 */   if (Global::trace) {     fprintf(Global::tf,"source_format: ");   }   mputv(3,pic->source_format);   bits += 3;   /* bit 9 */   if (Global::trace) {     fprintf(Global::tf,"picture_coding_type: ");   }   mputv(1,pic->picture_coding_type);   bits += 1;   /* bit 10 */   if (Global::trace) {     fprintf(Global::tf,"Global::mv_outside_frame: ");   }   mputv(1,pic->unrestricted_mv_mode);  /* Unrestricted Motion Vector mode */   bits += 1;   /* bit 11 */   if (Global::trace) {     fprintf(Global::tf,"sac_coding: ");   }   mputv(1,0); /* Syntax-based Arithmetic Coding mode not used*/   bits += 1;   /* bit 12 */   if (Global::trace) {     fprintf(Global::tf,"adv_pred_mode: ");   }   mputv(1,Global::advanced); /* Advanced Prediction mode */   bits += 1;   /* bit 13 */   if (Global::trace) {     fprintf(Global::tf,"PB-coded: "); /* PB-frames mode */   }   mputv(1,pic->PB);   bits += 1;   /* QUANT */   if (Global::trace) {     fprintf(Global::tf,"QUANT: ");   }   mputv(5,pic->QUANT);   bits += 5;   /* Continuous Presence Multipoint (CPM) */   mputv(1,0); /* CPM is not supported in this software */   bits += 1;   /* Picture Sub Bitstream Indicator (PSBI) */   /* if CPM == 1: 2 bits PSBI */   /* not supported */   /* PEI (extra information) */   if (Global::trace) {     fprintf(Global::tf,"PEI: ");   }   /* "Encoders shall not insert PSPARE until specified by the ITU" */   mputv(1,0);    bits += 1;   /* PSPARE */   /* if PEI == 1: 8 bits PSPARE + another PEI bit */   /* not supported */   return bits; }