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

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    : coder.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  **************************************************/       /* Modyfied by Roalt Aalmoes with better algorithms and performance
  21.  * objectives  *  * Warning: Although I tried to remove all advanced options code,
  22.  * there might still be some artifacts in the code. Please do not
  23.  * blame me for not removing all of it. 
  24.  * Removing all advanced and alternating quantization code was done
  25.  * for performance reasons. I'm sorry these options are not 
  26.  * implemented here, but see the tmn1.7 code for a slow functioning
  27.  * advanced H.263 compression algorithm. 
  28.  *****************************************************************/ /* Notes for clear code: */
  29. /* var. j is used for row indexing of MB in frame */
  30. /* var. i is used for column indexing of MB in frame */
  31. /*  pic is declared global */
  32. /* MV is changed: it is now a real array of MV instead of array of pointers
  33.    to MV. Its range is also equal to MVs encoded, without border MVs 
  34.    Advantages: No more mallocs and frees in the code, disadvantages: ?? */
  35. /* PictImage structure is replaced by int pointer. Drawback: not flexible for
  36.    other format. */
  37. #include"coder.h"
  38. #include "countbit.h"
  39. #include "pred.h"
  40. #include "quant.h"
  41. #include "mot_est.h"
  42. #include "dct.h" /**********************************************************************  *
  43.  * Name: Clip
  44.  * Description:    clips recontructed data 0-255
  45.  *
  46.  * Input:         pointer to recon. data structure
  47.  * Side effects:   data structure clipped
  48.  *
  49.  * Date: 960715  Author: Roalt Aalmoes
  50.  *
  51.  ***********************************************************************/ //__inline__ void Clip(MB_Structure *data)  void Clip(MB_Structure *data) 
  52. {   int n;   int *mb_ptr = (int *) data;   for (n = 0; n < 256 + 64 + 64; n++) {     *mb_ptr = mmin(255,mmax(0,*mb_ptr));     mb_ptr++;   } } /* Encodes one frame intra using params */ void CodeIntraH263(CParam *params, Bits *bits) {   unsigned int *new_recon;   MB_Structure *data = (MB_Structure *)malloc(sizeof(MB_Structure));   int *qcoeff;   int Mode = MODE_INTRA;   int CBP;   int i,j;   new_recon = params->recon;      ZeroBits(bits);      Global::pic->QUANT = params->Q_intra;   Global::pic->picture_coding_type = PCT_INTRA;   bits->header += CountBitsPicture(Global::pic);      for ( j = 0; j < Global::mbr; j++) {     /* insert sync in *every* slice if use_gobsync is chosen */     if (Global::pic->use_gobsync && j != 0)       bits->header += CountBitsSlice(j,params->Q_intra);         for ( i = 0; i < Global::mbc; i++) {       Global::pic->MB = i + j * Global::mbc;       bits->no_intra++;       FillLumBlock(i*MB_SIZE, j*MB_SIZE, params->data, data);       FillChromBlock(i*MB_SIZE, j*MB_SIZE, params->data, data);       qcoeff = MB_EncodeAndFindCBP(data, params->Q_intra, Mode, &CBP);       /* Do standard VLC encoding */       /* COD = 0 ,Every block is coded as Intra frame */       CountBitsMB(Mode,0,CBP,0,Global::pic,bits);
  53.       CountBitsCoeff(qcoeff, Mode, CBP,bits,64);
  54.      
  55.       MB_Decode(qcoeff, data, params->Q_intra, Mode);
  56.       Clip(data);
  57.       ReconImage(i,j,data,new_recon);
  58.       free(qcoeff);     }   }   Global::pic->QP_mean = params->Q_intra;
  59.   params->recon = new_recon;
  60.   AddBitsPicture(bits);
  61.   free(data);   return; } /**********************************************************************  *  * Name: MB_Encode
  62.  * Description: DCT and quantization of Macroblocks
  63.  *
  64.  * Input: MB data struct, mquant (1-31, 0 = no quant),
  65.  * MB info struct
  66.  * Returns: Pointer to quantized coefficients 
  67.  * Side effects:
  68.  *
  69.  * Date: 930128 Author: Robert.Danielsen@nta.no
  70.  *  **********************************************************************/ /* If you compare original quant with FindCBP, you see they both act    on the same range of coefficients in the cases INTRA (1..63) or     INTER (0..63) */ int *MB_EncodeAndFindCBP(MB_Structure *mb_orig, int QP, int I, int *CBP) {   int i, j, k, l, row, col;   int fblock[64];   int coeff[384];   int *coeff_ind;   int          *qcoeff;   int *qcoeff_ind;   int CBP_Mask = 32;   *CBP = 0; /* CBP gives bit pattern of lowest 6 bits    that specify which coordinates are not     zero. Bits 6 (32) to 2 (4) repr. four    8x8 Y parts of macroblock, while bits    1 (2) and 0 (1) repr. resp. the U and    V component */   if ((qcoeff=(int *)malloc(sizeof(int)*384)) == 0) {
  71.     fprintf(stderr,"mb_encode(): Couldn't allocate qcoeff.n");
  72.     exit(0);
  73.   }   coeff_ind = coeff;   qcoeff_ind = qcoeff;   for (k=0;k<16;k+=8) {     for (l=0;l<16;l+=8) {       for (i=k,row=0;row<64;i++,row+=8) { #if LONGISDOUBLEINT for (j=l,col=0;col<8;j += 2,col +=2 ) {   *(long *) (fblock+row+col) = * (long *) &(mb_orig->lum[i][j]); } #else for (j=l,col=0;col<8;j++ , col++ ) {   *(int *) (fblock+row+col) = * (int *) &(mb_orig->lum[i][j]); } #endif       }       Dct(fblock,coeff_ind);       *CBP |= QuantAndFindCBP(coeff_ind,qcoeff_ind,QP,I,CBP_Mask);       coeff_ind += 64;       qcoeff_ind += 64;       CBP_Mask = CBP_Mask>>1;     } /* end l */   } /* End k */   for (i=0;i<8;i++) { #ifdef LONGISDOUBLEINT     for (j=0;j<8;j += 2) {       *(long *) (fblock+i*8+j) = *(long *) &(mb_orig->Cb[i][j]);     } #else     for (j=0;j<8;j++) {       *(int *) (fblock+i*8+j) = *(int *) &(mb_orig->Cb[i][j]);     }     #endif   }   Dct(fblock,coeff_ind);
  74.   *CBP |= QuantAndFindCBP(coeff_ind,qcoeff_ind,QP,I,CBP_Mask /* i == 4 */); 
  75.   coeff_ind += 64;
  76.   qcoeff_ind += 64;
  77.   CBP_Mask = CBP_Mask>>1;   for (i=0;i<8;i++) { #ifdef LONGISDOUBLEINT     for (j=0;j<8;j += 2) {       * (long *) (fblock+i*8+j) = *(long *) &(mb_orig->Cr[i][j]);     } #else     for (j=0;j<8;j ++) {       * (int *) (fblock+i*8+j) = *(int *) &(mb_orig->Cr[i][j]);     } #endif   }   Dct(fblock,coeff_ind);   *CBP |= QuantAndFindCBP(coeff_ind,qcoeff_ind,QP,I, CBP_Mask /* i == 5 */);       return qcoeff; } /**********************************************************************  *  * Name: MB_Decode  * Description: Reconstruction of quantized DCT-coded Macroblocks  *
  78.  * Input: Quantized coefficients, MB data
  79.  * QP (1-31, 0 = no quant), MB info block
  80.  * Returns: int (just 0)
  81.  * Side effects:  *  * Date: 930128 Author: Robert.Danielsen@nta.no  *  **********************************************************************/       int MB_Decode(int *qcoeff, MB_Structure *mb_recon, int QP, int I) {   int i, j, k, l, row, col;   int *iblock;   int *qcoeff_ind;   int *rcoeff, *rcoeff_ind;   if ((iblock = (int *)malloc(sizeof(int)*64)) == NULL) {     fprintf(stderr,"MB_Coder: Could not allocate space for iblockn");     exit(-1);   }   if ((rcoeff = (int *)malloc(sizeof(int)*384)) == NULL) {     fprintf(stderr,"MB_Coder: Could not allocate space for rcoeffn");     exit(-1);   }     /* For control purposes */   /* Zero data */   for (i = 0; i < 16; i++) #ifdef LONGISDOUBLEINT     for (j = 0; j < 8; j+=2)       *(long *) &(mb_recon->lum[i][j]) = 0L; #else     for (j = 0; j < 8; j++)       *(int *) &(mb_recon->lum[i][j]) = 0; #endif   for (i = 0; i < 8; i++)  #ifdef LONGISDOUBLEINT     for (j = 0; j < 8; j += 2) {       *(long *) &(mb_recon->Cb[i][j]) = 0L;       *(long *) &(mb_recon->Cr[i][j]) = 0L;     } #else     for (j = 0; j < 8; j ++) {       *(int *) &(mb_recon->Cb[i][j]) = 0;       *(int *) &(mb_recon->Cr[i][j]) = 0;     } #endif   qcoeff_ind = qcoeff;   rcoeff_ind = rcoeff;   for (k=0;k<16;k+=8) {     for (l=0;l<16;l+=8) {       Dequant(qcoeff_ind,rcoeff_ind,QP,I); #ifdef STANDARDIDCT   idctref(rcoeff_ind,iblock);  #else   idct(rcoeff_ind,iblock);  #endif       qcoeff_ind += 64;       rcoeff_ind += 64;       for (i=k,row=0;row<64;i++,row+=8) { #ifdef LONGISDOUBLEINT for (j=l,col=0;col<8;j += 2,col += 2) {   *(long *) &(mb_recon->lum[i][j]) = * (long *) (iblock+row+col);         } #else for (j=l,col=0;col<8; j++, col++) {   *(int *) &(mb_recon->lum[i][j]) = * (int *) (iblock+row+col);         } #endif       }     }   }   Dequant(qcoeff_ind,rcoeff_ind,QP,I); #ifdef STANDARDIDCT   idctref(rcoeff_ind,iblock);  #else   idct(rcoeff_ind,iblock);  #endif   qcoeff_ind += 64;   rcoeff_ind += 64;   for (i=0;i<8;i++) { #ifdef LONGISDOUBLEINT     for (j=0;j<8;j +=2 ) {       *(long *) &(mb_recon->Cb[i][j]) = *(long *) (iblock+i*8+j);     } #else     for (j=0;j<8;j++ ) {       *(int *) &(mb_recon->Cb[i][j]) = *(int *) (iblock+i*8+j);     } #endif   }   Dequant(qcoeff_ind,rcoeff_ind,QP,I); #ifdef STANDARDIDCT   idctref(rcoeff_ind,iblock);  #else   idct(rcoeff_ind,iblock);  #endif   for (i=0;i<8;i++) { #ifdef LONGISDOUBLEINT     for (j=0;j<8;j += 2) {       *(long *) &(mb_recon->Cr[i][j]) = *(long *) (iblock+i*8+j);     } #else     for (j=0;j<8;j++) {       *(int *) &(mb_recon->Cr[i][j]) = *(int *) (iblock+i*8+j);     } #endif   }   free(iblock);   free(rcoeff);   return 0; } /**********************************************************************  *  * Name: FillLumBlock  * Description:    Fills the luminance of one block of lines*pels  *  * Input:        Position, pointer to qcif, array to fill  * Returns:         * Side effects: fills array  *  * Date: 930129 Author: Karl.Lillevold@nta.no  *  ***********************************************************************/ void FillLumBlock( int x, int y, unsigned int *image, MB_Structure *data) {   int n, m; /* OPTIMIZE HERE */   /* m -> int conversion is done here, so no long optimiz. possible */   for (n = 0; n < MB_SIZE; n++)     for (m = 0; m < MB_SIZE; m++)       data->lum[n][m] =  (int) (*(image + x+m + (y+n)*Global::pels));   return; } /**********************************************************************  *  * Name: FillChromBlock
  82.  * Description:    Fills the chrominance of one block of qcif
  83.  *
  84.  * Input:        Position, pointer to qcif, array to fill
  85.  * Returns:       
  86.  * Side effects: fills array
  87.  *                      128 subtracted from each
  88.  *
  89.  * Date: 930129 Author: Karl.Lillevold@nta.no  *  ***********************************************************************/ void FillChromBlock(int x_curr, int y_curr, unsigned int *image,     MB_Structure *data) {   int n;   register int m;   int x, y;   x = x_curr>>1;   y = y_curr>>1;   for (n = 0; n < (MB_SIZE>>1); n++)     for (m = 0; m < (MB_SIZE>>1); m++) {       data->Cr[n][m] =  (int) (*(image + Global::vskip + x+m + (y+n)*Global::cpels));       data->Cb[n][m] =  (int) (*(image + Global::uskip + x+m + (y+n)*Global::cpels));     }   return; } /**********************************************************************  *  * Name: ZeroMBlock  * Description:    Fills one MB with Zeros  *  * Input:        MB_Structure to zero out  * Returns:         * Side effects:  *  * Date: 940829 Author: Karl.Lillevold@nta.no  *  ***********************************************************************/ void ZeroMBlock(MB_Structure *data) {   int n;   register int m;   /* ALPHA optimization */ #ifdef LONGISDOUBLEINT   for (n = 0; n < MB_SIZE; n++)     for (m = 0; m < MB_SIZE; m +=2 )       *(long *) &(data->lum[n][m]) = 0L;   for (n = 0; n < (MB_SIZE>>1); n++)     for (m = 0; m < (MB_SIZE>>1); m +=2 ) {       *(long *) &(data->Cr[n][m]) = 0L;       *(long *) &(data->Cb[n][m]) = 0L;     } #else   for (n = 0; n < MB_SIZE; n++)     for (m = 0; m < MB_SIZE; m++ )       *(int *) &(data->lum[n][m]) = 0;   for (n = 0; n < (MB_SIZE>>1); n++)     for (m = 0; m < (MB_SIZE>>1); m++ ) {       *(int *) &(data->Cr[n][m]) = 0;       *(int *) &(data->Cb[n][m]) = 0;     } #endif   return; } /**********************************************************************  *  * Name: ReconImage  * Description: Puts together reconstructed image  *  * Input: position of curr block, reconstructed
  90.  * macroblock, pointer to recontructed image  * Returns:  * Side effects:  *  * Date: 930123   Author: Karl.Lillevold@nta.no  *  ***********************************************************************/ void ReconImage (int i, int j, MB_Structure *data, unsigned int *recon) {   int n;   int x_curr, y_curr;   int *lum_ptr, *Cb_ptr, *Cr_ptr;   unsigned int *recon_ptr, *recon_Cb_ptr, *recon_Cr_ptr;     x_curr = i * MB_SIZE;   y_curr = j * MB_SIZE;      lum_ptr = &(data->lum[0][0]);   recon_ptr = recon + x_curr + y_curr*Global::pels;   /* Fill in luminance data */   for (n = 0; n < MB_SIZE; n++) { #ifdef LONGISDOUBLEINT     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += 2; lum_ptr += 2;     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += 2; lum_ptr += 2;     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += 2; lum_ptr += 2;     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += 2; lum_ptr += 2;     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += 2; lum_ptr += 2;     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += 2; lum_ptr += 2;     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += 2; lum_ptr += 2;     * (long *) recon_ptr = * (long *) lum_ptr;     recon_ptr += Global::pels - 14; lum_ptr += 2;     /* Was: for every m = 0..15 :      *(recon->lum + x_curr+m + (y_curr+n)*Global::pels) = *(lum_ptr++);      */ #else     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr++; lum_ptr++;     * (int *) recon_ptr = * (int *) lum_ptr;     recon_ptr += Global::pels - 15; lum_ptr++; #endif   }   recon_Cb_ptr = recon+Global::uskip+ (x_curr>>1) + (y_curr>>1)*Global::cpels;   recon_Cr_ptr = recon+Global::vskip+ (x_curr>>1) + (y_curr>>1)*Global::cpels;   Cb_ptr = &(data->Cb[0][0]);   Cr_ptr = &(data->Cr[0][0]);   /* Fill in chrominance data */   for (n = 0; n < MB_SIZE>>1; n++) { #ifdef LONGISDOUBLEINT     * (long *) recon_Cb_ptr = * (long *) Cb_ptr;     recon_Cb_ptr += 2; Cb_ptr += 2;     * (long *) recon_Cr_ptr = * (long *) Cr_ptr;     recon_Cr_ptr += 2; Cr_ptr += 2;     * (long *) recon_Cb_ptr = * (long *) Cb_ptr;     recon_Cb_ptr += 2; Cb_ptr += 2;     * (long *) recon_Cr_ptr = * (long *) Cr_ptr;     recon_Cr_ptr += 2; Cr_ptr += 2;     * (long *) recon_Cb_ptr = * (long *) Cb_ptr;     recon_Cb_ptr += 2; Cb_ptr += 2;     * (long *) recon_Cr_ptr = * (long *) Cr_ptr;     recon_Cr_ptr += 2; Cr_ptr += 2;     * (long *) recon_Cb_ptr = * (long *) Cb_ptr;     recon_Cb_ptr += Global::cpels - 6; Cb_ptr += 2;     * (long *) recon_Cr_ptr = * (long *) Cr_ptr;     recon_Cr_ptr += Global::cpels - 6; Cr_ptr += 2; #else     * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     recon_Cb_ptr++; Cb_ptr++;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cr_ptr++; Cr_ptr++;         * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     recon_Cb_ptr++; Cb_ptr++;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cr_ptr++; Cr_ptr++;         * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     recon_Cb_ptr++; Cb_ptr++;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cr_ptr++; Cr_ptr++;         * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     recon_Cb_ptr++; Cb_ptr++;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cr_ptr++; Cr_ptr++;        * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     recon_Cb_ptr++; Cb_ptr++;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cr_ptr++; Cr_ptr++;         * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     recon_Cb_ptr++; Cb_ptr++;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cr_ptr++; Cr_ptr++;         * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     recon_Cb_ptr++; Cb_ptr++;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cr_ptr++; Cr_ptr++;         * (int *) recon_Cb_ptr = * (int *) Cb_ptr;     * (int *) recon_Cr_ptr = * (int *) Cr_ptr;     recon_Cb_ptr += Global::cpels - 7; Cb_ptr ++;     recon_Cr_ptr += Global::cpels - 7; Cr_ptr ++; #endif   }   /* WAS:         for (m = 0; m < MB_SIZE>>1; m++) {      *(recon->Cr + (x_curr>>1)+m + ((y_curr>>1)+n)*Global::cpels) = data->Cr[n][m];      *(recon->Cb + (x_curr>>1)+m + ((y_curr>>1)+n)*Global::cpels) = data->Cb[n][m];      }      */   return; } /**********************************************************************  *  * Name: ReconCopyImage  * Description: Copies previous recon_image to current recon image  *  * Input: position of curr block, reconstructed  * macroblock, pointer to recontructed image  * Returns:  * Side effects:  *  * Date: 960423   Author: Roalt Aalmoes  *  ***********************************************************************/ void ReconCopyImage (int i, int j, unsigned int *recon, unsigned int *prev_recon) {   int n;   int x_curr, y_curr;   unsigned int *lum_now, *lum_prev, *cb_now, *cr_now, *cb_prev, *cr_prev;     x_curr = i * MB_SIZE;   y_curr = j * MB_SIZE;   lum_now = recon + x_curr + y_curr*Global::pels;   lum_prev = prev_recon + x_curr + y_curr*Global::pels;   /* Fill in luminance data */   for (n = 0; n < 16; n++) { #ifdef LONGISDOUBLEINT     *(long *)(lum_now) = *(long *)(lum_prev);     *(long *)(lum_now + 2) = *(long *)(lum_prev + 2);     *(long *)(lum_now + 4) = *(long *)(lum_prev + 4);     *(long *)(lum_now + 6) = *(long *)(lum_prev + 6);     *(long *)(lum_now + 8) = *(long *)(lum_prev + 8);     *(long *)(lum_now + 10) = *(long *)(lum_prev + 10);     *(long *)(lum_now + 12) = *(long *)(lum_prev + 12);     *(long *)(lum_now + 14) = *(long *)(lum_prev + 14); #else     *(int *)(lum_now) = *(int *)(lum_prev);     *(int *)(lum_now + 1) = *(int *)(lum_prev + 1);     *(int *)(lum_now + 2) = *(int *)(lum_prev + 2);     *(int *)(lum_now + 3) = *(int *)(lum_prev + 3);     *(int *)(lum_now + 4) = *(int *)(lum_prev + 4);     *(int *)(lum_now + 5) = *(int *)(lum_prev + 5);     *(int *)(lum_now + 6) = *(int *)(lum_prev + 6);     *(int *)(lum_now + 7) = *(int *)(lum_prev + 7);     *(int *)(lum_now + 8) = *(int *)(lum_prev + 8);     *(int *)(lum_now + 9) = *(int *)(lum_prev + 9);     *(int *)(lum_now + 10) = *(int *)(lum_prev + 10);     *(int *)(lum_now + 11) = *(int *)(lum_prev + 11);     *(int *)(lum_now + 12) = *(int *)(lum_prev + 12);     *(int *)(lum_now + 13) = *(int *)(lum_prev + 13);     *(int *)(lum_now + 14) = *(int *)(lum_prev + 14);     *(int *)(lum_now + 15) = *(int *)(lum_prev + 15); #endif     lum_now += Global::pels;     lum_prev += Global::pels;         }   cb_now = recon+Global::uskip + (x_curr>>1) + (y_curr>>1)*Global::cpels;
  91.   cr_now = recon+Global::vskip + (x_curr>>1) + (y_curr>>1)*Global::cpels;
  92.   cb_prev = prev_recon+Global::uskip+ (x_curr>>1) + (y_curr>>1)*Global::cpels;
  93.   cr_prev = prev_recon+Global::vskip + (x_curr>>1) + (y_curr>>1)*Global::cpels;
  94.   /* Fill in chrominance data */   for (n = 0; n < (MB_SIZE>>1); n++) { #ifdef LONGISDOUBLEINT     *(long *)(cb_now) = *(long *)(cb_prev);     *(long *)(cb_now + 2) = *(long *)(cb_prev + 2);     *(long *)(cb_now + 4) = *(long *)(cb_prev + 4);     *(long *)(cb_now + 6) = *(long *)(cb_prev + 6);     cb_now += Global::cpels;     cb_prev += Global::cpels;     *(long *)(cr_now) = *(long *)(cr_prev);     *(long *)(cr_now + 2) = *(long *)(cr_prev + 2);     *(long *)(cr_now + 4) = *(long *)(cr_prev + 4);     *(long *)(cr_now + 6) = *(long *)(cr_prev + 6);     cr_now += Global::cpels;     cr_prev += Global::cpels; #else     *(int *)(cb_now) = *(int *)(cb_prev);     *(int *)(cb_now + 1) = *(int *)(cb_prev + 1);     *(int *)(cb_now + 2) = *(int *)(cb_prev + 2);     *(int *)(cb_now + 3) = *(int *)(cb_prev + 3);     *(int *)(cb_now + 4) = *(int *)(cb_prev + 4);     *(int *)(cb_now + 5) = *(int *)(cb_prev + 5);     *(int *)(cb_now + 6) = *(int *)(cb_prev + 6);     *(int *)(cb_now + 7) = *(int *)(cb_prev + 7);     cb_now += Global::cpels;     cb_prev += Global::cpels;     *(int *)(cr_now) = *(int *)(cr_prev);     *(int *)(cr_now + 1) = *(int *)(cr_prev + 1);     *(int *)(cr_now + 2) = *(int *)(cr_prev + 2);     *(int *)(cr_now + 3) = *(int *)(cr_prev + 3);     *(int *)(cr_now + 4) = *(int *)(cr_prev + 4);     *(int *)(cr_now + 5) = *(int *)(cr_prev + 5);     *(int *)(cr_now + 6) = *(int *)(cr_prev + 6);     *(int *)(cr_now + 7) = *(int *)(cr_prev + 7);     cr_now += Global::cpels;     cr_prev += Global::cpels; #endif   }   return; } /**********************************************************************  *  * Name: InterpolateImage  * Description:    Interpolates a complete image for easier half  *                      pel prediction  *
  95.  * Input:         pointer to image structure
  96.  * Returns:        pointer to interpolated image
  97.  * Side effects:   allocates memory to interpolated image
  98.  *  * Date: 950207  Author: Karl.Lillevold@nta.no  *            960207    Author: Roalt aalmoes  ***********************************************************************/ void InterpolateImage(unsigned int *image, unsigned int *ipol_image,         int width, int height) {   /* If anyone has better ideas to optimize this code, be my guest!      note: assembly or some advanced bitshifts routine might do the trick...*/   register unsigned int *ii, *oo,      *ii_new,      *ii_new_line2,      *oo_prev,      *oo_prev_line2;      register int i,j;   register unsigned int pix1,pix2,pix3,pix4;   ii = ipol_image;   oo = image;   oo_prev = image;   oo_prev_line2 = image + width;   ii_new = ipol_image;   ii_new_line2 = ipol_image + (width<<1);   /* main image */   for (j = 0; j < height-1; j++) { /* get Pix1 and Pix3, because they are    not known the first time */     pix1 = *oo_prev;     pix3 = *oo_prev_line2;     for (i = 0; i  < width-1; i++) { /* Pix1 Pix2    Pix3 Pix4 */       /* Pix2 and Pix4 are used here for first time */       pix2 = *(oo_prev + 1);       pix4 = *(oo_prev_line2 + 1);       *(ii_new) = pix1; /* X.    ..*/       *(ii_new + 1) = (pix1 + pix2 + 1)>>1;  /* *X    .. */       *ii_new_line2 = (pix1 + pix3 + 1)>>1;  /* *.            X. */       *(ii_new_line2 + 1) = (pix1 + pix2 + pix3 + pix4 + 2)>>2;              oo_prev++; oo_prev_line2++; ii_new += 2; ii_new_line2 += 2;              pix1 = pix2;       pix3 = pix4; /* Pix1 Pix2=Pix1' Pix2' */ /* Pix3 Pix4=Pix3' Pix4' */     }          /* One but last column */     *(ii_new++) = pix1;     *(ii_new++) = pix3;          /* Last column -On the Edge - */     *(ii_new_line2++) = (pix1 + pix3 + 1 ) >>1;     *(ii_new_line2++) = (pix1 + pix3 + 1 ) >>1;     ii_new += (width<<1); /* ii_new now on old position ii_new_line2,so    one interpolated screen line must be added*/     ii_new_line2 += (width<<1); /* In fact, ii_new_line here has same value    as ii_new */     oo_prev += 1; /* Remember, loop is done one time less! */     oo_prev_line2 += 1;        }   /* last lines */   pix1 = *oo_prev;   for (i = 0; i < width-1; i++) {     pix2 = *(oo_prev + 1);     *ii_new = *ii_new_line2 = pix1;     *(ii_new + 1) = *(ii_new_line2 + 1) = (pix1 + pix2 + 1)>>1;     ii_new += 2;     ii_new_line2 += 2;     oo_prev += 1;     pix1 = pix2; /* Pix1 Pix2=Pix1' Pix2' */   }      /* bottom right corner Global::pels */   *(ii_new) = pix1;   *(ii_new + 1) = pix1;   *(ii_new_line2) = pix1;   *(ii_new_line2+1) = pix1;   return; } /**********************************************************************  *  * Name: FullMotionEstimatePicture  * Description:    Finds integer and half pel motion estimation  *  * Input:        current image, previous image, interpolated  *                     reconstructed previous image, seek_dist,  *                     motion vector array  * Returns:         * Side effects: allocates memory for MV structure  *  * Date: 960418 Author: Roatlt  *  ***********************************************************************/ void FullMotionEstimatePicture(unsigned int *curr, unsigned int *prev,         unsigned int *prev_ipol, int seek_dist,         MotionVector *MV_ptr,        int advanced_method,        int *EncodeThisBlock) {   int i,j;   MotionVector *current_MV;   for(j = 0; j < Global::mbr; j++) {    for(i = 0; i < Global::mbc; i++) {      current_MV = MV_ptr + j*Global::mbc + i;      if(advanced_method && !*(EncodeThisBlock + j*Global::mbc + i) ) {        current_MV->x = current_MV->y = current_MV->x_half =   current_MV->y_half = 0;        current_MV->Mode = MODE_SKIP;       } else { /* EncodeThisBlock */         FullMotionEstimation(curr, prev_ipol, seek_dist, current_MV,       i*MB_SIZE, j*MB_SIZE); current_MV->Mode = ChooseMode(curr,i*MB_SIZE,j*MB_SIZE,       current_MV->min_error); if(current_MV->Mode == MODE_INTRA)    ZeroVec(current_MV);       }     }   } } void CodeInterH263(CParam *params, Bits *bits) {   MotionVector *MV;   MotionVector ZERO = {0,0,0,0,0};   MB_Structure *recon_data_P;    MB_Structure *diff;   int *qcoeff_P;   unsigned int *new_recon=NULL;   unsigned int *prev_recon;   int Mode;     int CBP, CBPB=0;   int newgob;   int i,j;   Global::search_p_frames = params->search_method;   MV =(struct motionvector*) malloc(sizeof(MotionVector)*Global::mbc*Global::mbr);   new_recon =(unsigned int*) malloc(Global::sizeof_frame);   prev_recon = params->recon;   /* buffer control vars */      ZeroBits(bits);   /* Interpolate luminance from reconstr. picture */   InterpolateImage(prev_recon,params->interpolated_lum,Global::pels,Global::lines);   FullMotionEstimatePicture( params->data,      prev_recon,      params->interpolated_lum,      params->half_pixel_searchwindow,MV,     params->advanced_method, params->EncodeThisBlock);      /* Calculate MV for each MB */   /* ENCODE TO H.263 STREAM */      for ( j = 0; j < Global::mbr; j++) {     newgob = 0;     if (j == 0) {       Global::pic->QUANT = params->Q_inter;       Global::pic->picture_coding_type = PCT_INTER;       bits->header += CountBitsPicture(Global::pic);     }     else if (Global::pic->use_gobsync && j%Global::pic->use_gobsync == 0) {       bits->header += CountBitsSlice(j,params->Q_inter); /* insert gob sync */       newgob = 1;     }     for ( i = 0; i < Global::mbc; i++) {       /* This means: For every macroblock (i,j) do ... */       /* We have 4 different situations:
  99.          1) !EncodeThisBlock: this means that the
  100.     macroblock in not encoded
  101.          2) EncodeThisBlock: This means that the MB is      encoded by using the predicted motion vector.          3) EncodeThisBlock: However, the approx of the     motion vector was so bad, that INTRA coding is more     appropiate here ...  4) EncodeThisBlock: The approx is so good that             the coefficients are all zero (after quant.) and are not     send.       */ /* This means: For every macroblock (i,j) do ... */         Global::pic->DQUANT = 0; Mode = MV[j*Global::mbc + i].Mode; /* Determine position of MB */ Global::pic->MB = i + j * Global::mbc; if(Mode == MODE_SKIP) {   /* SITUATION 1 */   Mode = MODE_INTRA; /* This might be done "better" in the future*/   MV[j*Global::mbc + i].Mode = Mode;   ZeroVec(&(MV[j*Global::mbc + i]));     CBP = CBPB = 0;     /* Now send code for "skip this MB" */   CountBitsMB(Mode,1,CBP,CBPB,Global::pic,bits);       ReconCopyImage(i,j,new_recon,prev_recon); } else { /* Encode this block */   if (Mode == MODE_INTER) {     /* SITUATION 2 */     /* Predict P-MB */     diff = Predict_P(params->data,
  102.      prev_recon,
  103.      params->interpolated_lum,i*MB_SIZE,
  104.      j*MB_SIZE,MV);   } else {     /* SITUATION 3 */     /* Create MB_Structure diff that contains coefficients that must be        sent to the other end */     diff = (MB_Structure *)malloc(sizeof(MB_Structure));     FillLumBlock(i*MB_SIZE, j*MB_SIZE, params->data, diff);      /* Copy curr->lum to diff for macroblock (i,j) */     FillChromBlock(i*MB_SIZE, j*MB_SIZE, params->data, diff);     /* Equiv. for curr->Cb and curr->Cr */   }   /* P or INTRA Macroblock */   /*  diff -> DCT -> QUANTIZED -> qcoeff_P */   qcoeff_P = MB_EncodeAndFindCBP(diff, params->Q_inter, Mode,&CBP);   /*   CBP = FindCBP(qcoeff_P, Mode, 64); -> Not required anymore */   /* All encoded, now calculate decoded image      for comparison in next frame */   /* Do DECODING */   if (CBP == 0 && (Mode == MODE_INTER) ) { /* SITUATION 4 */     ZeroMBlock(diff);   } else {     /*  qcoeff_P -> Dequantized -> IDCT -> diff */     MB_Decode(qcoeff_P, diff, params->Q_inter, Mode);   }   recon_data_P = MB_Recon_P(prev_recon,      params->interpolated_lum,diff,      i*MB_SIZE,j*MB_SIZE,MV);   Clip(recon_data_P);   free(diff);   /* Do bitstream encoding */   if((CBP==0) && (EqualVec(&(MV[j*Global::mbc+i]),&ZERO)) &&      (Mode == MODE_INTER) ) {     /* Skipped MB : both CBP and CBPB are zero, 16x16 vector is zero,        PB delta vector is zero and Mode = MODE_INTER */     /* Now send code for "skip this MB" */     CountBitsMB(Mode,1,CBP,CBPB,Global::pic,bits);   } else {     /* Normal MB */     /* VLC */     CountBitsMB(Mode,0,CBP,CBPB,Global::pic,bits);     if (Mode == MODE_INTER) {       bits->no_inter++;       CountBitsVectors(MV, bits, i, j, Mode, newgob, Global::pic);
  105.     } else {
  106.       /* MODE_INTRA */       bits->no_intra++;     }     /* Only encode coefficient if they are nonzero or Mode is INTRA*/
  107.     
  108.     if (CBP || Mode == MODE_INTRA)
  109.       CountBitsCoeff(qcoeff_P, Mode, CBP, bits, 64);       } /* End skip/not skip macroblock encoding */   ReconImage(i,j,recon_data_P,new_recon);   free(recon_data_P);   free(qcoeff_P); }      /* End advanced */             } /* End for i */   } /* End for j */   Global::pic->QP_mean = params->Q_inter;      free(prev_recon);   params->recon = new_recon;   AddBitsPicture(bits);   free(MV);   return; }