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

📄 coder.c

📁 H.263+(VC++商业源代码)
💻 C
📖 第 1 页 / 共 2 页
字号:

#include"sim.h"
_inline void MeanMB(MB_Structure *, int mean[6]);
_inline int VarMB(MB_Structure *, int);


/**********************************************************************
 *
 *	Name:		CodeOneOrTwo
 *	Description:	code one image normally or two images
 *                      as a PB-frame (CodeTwoPB and CodeOnePred merged)
 *	
 *	Input:		pointer to image, prev_image, prev_recon, Q
 *			
 *	Returns:	pointer to reconstructed image
 *	Side effects:	memory is allocated to recon image
 *
 *	
 *
 ***********************************************************************/

void CodeOneOrTwo(PictImage *curr, PictImage _huge *pr, int QP, int frameskip, Bits *bits,
		  Pict *pic)
{

/* 	
	curr  ---- current orignal image to be coded 
	pr	  ---- reconstruced image
*/

	MotionVector ZERO = {0,0,0,0,0};
	int Mode;  
	int CBP, CBPB=0;
	int newgob;
	int i,j,k;         

  /* buffer control vars */
	float QP_cumulative = (float)0;
	int abs_mb_num = 0, QuantChangePostponed = 0;
	int QP_new, QP_prev, dquant, QP_xmitted=QP;

	ZeroBits(bits);

  /* make edge and interpolate image */

	MakeEdgeImage(pr->lum, prev_recon.lum, pels, lines, B<<1);
	MakeEdgeImage(pr->Cr, prev_recon.Cr, cpels, lines>>1, B);
	MakeEdgeImage(pr->Cb, prev_recon.Cb, cpels, lines>>1, B);

  /* mark PMV's outside the frame */
	for (i = 1; i < mbc + 1; i++) 
	{
	   for (k = 0; k < 6; k++) 
	   {	
			MarkVec(pMV[k][0][i]);
	   }
	   pMV[0][0][i]->Mode = MODE_INTRA;
	}
  /* zero out PMV's outside the frame */
	for (i = 0; i < mbr + 1; i++) 
	{
		for (k = 0; k < 6; k++) 
		{
			ZeroVec(pMV[k][i][0]);
			ZeroVec(pMV[k][i][mbc+1]);
		}
		pMV[0][i][0]->Mode = MODE_INTRA;
		pMV[0][i][mbc+1]->Mode = MODE_INTRA;
	}

/* Integer and half pel motion estimation */
	MotionEstimatePicture(curr->lum,prev_recon.lum,pic->seek_dist,pMV);

  /* note: integer pel motion estimation is now based on previous
     reconstructed image, not the previous original image. We have
     found that this works better for some sequences and not worse for
     others.  Note that it can not easily be changed back by
     substituting prev_recon->lum with orig_lum in the line above,
     because SAD for zero vector is not re-calculated in the half
     pel search. The half pel search has always been based on the
     previous reconstructed image */

    QP_new = QP_xmitted = QP_prev = QP; /* Copy the passed value of QP */
    dquant = 0; 

	for ( j = 0; j < mbr; j++) 
	{
		newgob = 0;
/* global block syntax */
		if (j == 0) 
		{
			pic->QUANT = QP_new;
			bits->header += CountBitsPicture(pic);
			QP_xmitted = QP_prev = QP_new;
		}
		else if (pic->use_gobsync && j%pic->use_gobsync == 0) 
		{
			bits->header += CountBitsSlice(j,QP_new); // insert gob sync 
			QP_xmitted = QP_prev = QP_new;
			newgob = 1;
		}

		for ( i = 0; i < mbc; i++) 
		{
      // Update of dquant, check and correct its limit 
			dquant = QP_new - QP_prev;
			if (dquant != 0 && i != 0 && pMV[0][j+1][i+1]->Mode == MODE_INTER4V) 
			 {
	// It is not possible to change the quantizer and at the same
	//   time use 8x8 vectors. Turning off 8x8 vectors is not
	//   possible at this stage because the previous macroblock
	//   encoded assumed this one should use 8x8 vectors. Therefore
	//   the change of quantizer is postponed until the first MB
	//   without 8x8 vectors 
	 
	  			dquant = 0;
			  	QP_xmitted = QP_prev;
	  			QuantChangePostponed = 1;
			}
			else 
			{
				QP_xmitted = QP_new;
				QuantChangePostponed = 0;
			}
			if (dquant > 2)  { dquant =  2; QP_xmitted = QP_prev + dquant;}
			if (dquant < -2) { dquant = -2; QP_xmitted = QP_prev + dquant;}

			pic->DQUANT = dquant;
      // modify mode if dquant != 0 (e.g. MODE_INTER -> MODE_INTER_Q) 

			Mode = ModifyMode(pMV[0][j+1][i+1]->Mode,pic->DQUANT);
			pMV[0][j+1][i+1]->Mode = Mode;

			pic->MB = i + j * MBC;

			if (Mode == MODE_INTER || Mode == MODE_INTER_Q || Mode==MODE_INTER4V) 
			{
				MB_Pred(pr_edge.lum,&prev_recon, recon_data_P, i*MB_SIZE, j*MB_SIZE, pMV);
				FillBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);
				DiffMB(diff, recon_data_P, 0);
			}
			else if(Mode == MODE_INTER0) 
			{
				MB_Pred(pr_edge.lum,&prev_recon, recon_data_P, i*MB_SIZE, j*MB_SIZE, pMV);
			}
			else
				FillBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);

      // P or INTRA Macroblock 
			if(Mode == MODE_INTER0)
			{
				QP_xmitted = QP_prev;
				pic->DQUANT = 0;
				Mode = MODE_INTER;
					if (!syntax_arith_coding)
      					CountBitsMB(Mode,1,0,0,pic,bits);
					else
       					Count_sac_BitsMB(Mode,1,0,0,pic,bits);
				pMV[0][j+1][i+1]->Mode = Mode;
			}
			else
			{
				MB_Encode(diff, QP_xmitted, Mode);
				CBP = FindCBP(qbase, Mode, 64);
				if (CBP == 0 && (Mode == MODE_INTER || Mode == MODE_INTER_Q)) 
					ZeroMBlock(diff);
				else
					MB_Decode(qbase, diff, QP_xmitted, Mode);
	  			DiffMB(recon_data_P, diff, 1);
				Clip(recon_data_P);
	
				if ((CBP==0) && (CBPB==0) && (EqualVec(pMV[0][j+1][i+1],&ZERO)) && 
				(Mode == MODE_INTER || Mode == MODE_INTER_Q)) 
				{
	// Skipped MB : both CBP and CBPB are zero, 16x16 vector is zero,
	// PB delta vector is zero and Mode = MODE_INTER 
					if (Mode == MODE_INTER_Q) 
					{
    // DQUANT != 0 but not coded anyway 
						QP_xmitted = QP_prev;
						pic->DQUANT = 0;
						Mode = MODE_INTER;
					}
					if (!syntax_arith_coding)
      					CountBitsMB(Mode,1,CBP,CBPB,pic,bits);
					else
       					Count_sac_BitsMB(Mode,1,CBP,CBPB,pic,bits);
				}
				else 
				{
			// Normal MB 
					if (!syntax_arith_coding) 
					{ // VLC 
			   			CountBitsMB(Mode,0,CBP,CBPB,pic,bits);

	  					if (Mode == MODE_INTER  || Mode == MODE_INTER_Q) 
	  					{
			 				bits->no_inter++;
			  				CountBitsVectors(pMV, bits, i, j, Mode, newgob, pic);
		 				}
						else if (Mode == MODE_INTER4V) 
	  					{
			  				bits->no_inter4v++;
	    					CountBitsVectors(pMV, bits, i, j, Mode, newgob, pic);
	  					}
	  					else 
	  					{
	    // MODE_INTRA or MODE_INTRA_Q 
	    					bits->no_intra++;
	    					if (pic->PB)
	      						CountBitsVectors(pMV, bits, i, j, Mode, newgob, pic);
	  					}
	  
	  					if (CBP || Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
	    					CountBitsCoeff(qbase, Mode, CBP, bits, 64);
					} // end VLC 
					else 
					{ // SAC 
          				Count_sac_BitsMB(Mode,0,CBP,CBPB,pic,bits);
	          			if (Mode == MODE_INTER  || Mode == MODE_INTER_Q) 
						{
							bits->no_inter++;
							Count_sac_BitsVectors(pMV, bits, i, j, Mode, newgob, pic);
          				}
          				else if (Mode == MODE_INTER4V) 
						{
            				bits->no_inter4v++;
           					Count_sac_BitsVectors(pMV, bits, i, j, Mode, newgob, pic);
          				}
          				else 
	    // MODE_INTRA or MODE_INTRA_Q 
            				bits->no_intra++;
										 
	  					if (CBP || Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
	    					Count_sac_BitsCoeff(qbase, Mode, CBP, bits, 64);
					} // end SAC 

					QP_prev = QP_xmitted;
				}
			}
			abs_mb_num++;
			QP_cumulative += QP_xmitted;     
			ReconImage(i,j,recon_data_P, pr);
		}
	}
	pic->QP_mean = QP_cumulative/(float)abs_mb_num;
	return;
}


/**********************************************************************
 *
 *	Name:		CodeOneIntra
 *	Description:	codes one image intra
 *	
 *	Input:		pointer to image, QP
 *			
 *	Returns:	pointer to reconstructed image
 *	Side effects:	memory is allocated to recon image
 *
 *
 *
 ***********************************************************************/


void CodeOneIntra(PictImage *curr, PictImage *recon, int QP, Bits *bits, Pict *pic)
{
  MB_Structure data;
  int Mode = MODE_INTRA;
  int CBP,COD;
  int i,j,k;
  int mean, means[6], var;
  pic->QUANT = QP;
  COD = 0; /* Every block is coded in Intra frame */
  pic->MB = 0;
  bits->header += CountBitsPicture(pic);

  for ( j = 0; j < mbr; j++) 
  {

    /* insert sync in *every* slice if use_gobsync is chosen */
    if (pic->use_gobsync && j != 0)
      bits->header += CountBitsSlice(j,QP);
    for ( i = 0; i < mbc; i++) 
    {
      bits->no_intra++;
      FillBlock(i*MB_SIZE, j*MB_SIZE, curr, &data);    //to be modified
	  MeanMB(&data, means);
	  mean = (means[0] + means[1] + means[2] + means[3])>>2;
	  var = VarMB(&data, mean);

 	  if(var < 0)
	  {
		  for(k = 0; k < 384; k++)
			qbase[k] = 0;
		  qbase[0]   = means[0];
		  qbase[64]  = means[1];
		  qbase[128] = means[2];
		  qbase[192] = means[3];
		  qbase[256] = means[4];
		  qbase[320] = means[5];
	  }
	  else	  
		  MB_Encode(&data, QP, Mode);
      CBP = FindCBP(qbase,Mode,64);

      if (!syntax_arith_coding) {
        CountBitsMB(Mode,COD,CBP,0,pic,bits);
        CountBitsCoeff(qbase, Mode, CBP,bits,64);
      } else {
        Count_sac_BitsMB(Mode,COD,CBP,0,pic,bits);
        Count_sac_BitsCoeff(qbase, Mode, CBP,bits,64);
      }

	  MB_Decode(qbase, &data, QP, Mode);
      Clip(&data);
      ReconImage(i,j,&data,recon);
      pic->MB++;
    }
  }
  pic->QP_mean = (float)QP;
}

/**********************************************************************
 *
 *	Name:		MB_Encode
 *	Description:	DCT and quantization of Macroblocks
 *
 *	Input:		MB data struct, mquant (1-31, 0 = no quant),
 *			MB info struct
 *	Returns:	Pointer to quantized coefficients 
 *	Side effects:	
 *
 *	
 *  
 *
 **********************************************************************/


void MB_Encode(MB_Structure *mb_orig, int QP, int I)
{
  int		i, j, k, l, row, col;
  int		fblock[64];
  int		*qcoeff_ind;

  qcoeff_ind = qbase;
  for (k=0;k<16;k+=8) 
  {
    for (l=0;l<16;l+=8) 
    {
      for (i=k,row=0;row<64;i++,row+=8) 
      {
        for (j=l,col=0;col<8;j++,col++) 
		{
	  		*(fblock+row+col) = mb_orig->lum[i][j];
		}
      }
      dct(fblock);
      Quant(fblock,qcoeff_ind,QP,I);
      qcoeff_ind += 64;
    }
  }
/* chrominance block */

  dct(mb_orig->Cb[0]);
  Quant(mb_orig->Cb[0],qcoeff_ind,QP,I); 
  qcoeff_ind += 64;

  dct(mb_orig->Cr[0]);
  Quant(mb_orig->Cr[0],qcoeff_ind,QP,I); 
}

/**********************************************************************
 *
 *	Name:		MB_Decode
 *	Description:	Reconstruction of quantized DCT-coded Macroblocks
 *
 *	Input:		Quantized coefficients, MB data
 *				QP (1-31, 0 = no quant), MB info block
 *	Returns:	int (just 0)
 *	Side effects:	
 *
 *
 *
 *
 **********************************************************************/

void MB_Decode(int *qcoeff, MB_Structure *mb_recon, int QP, int I)
{
  int i, j, k, l, row, col;
  int rcoeff[256];
  int *qcoeff_ind;
  int *rcoeff_ind;

  /* For control purposes */
  /* Zero data */
  qcoeff_ind = qcoeff;
  rcoeff_ind = rcoeff;
/*
  for (i = 0; i < 16; i++)
    for (j = 0; j < 16; j++)
      mb_recon->lum[j][i] = 0;
 
  for (i = 0; i < 8; i++)
    for (j = 0; j < 8; j++) 
    {
      mb_recon->Cb[j][i] = 0;
      mb_recon->Cr[j][i] = 0;
    }
 */

  for (k=0;k<16;k+=8) 
  {
    for (l=0;l<16;l+=8) 
    {
      Dequant(qcoeff_ind,rcoeff_ind,QP,I);
      idct(rcoeff_ind);
      for (i=k,row=0;row<64;i++,row+=8) 
      {
    	for (j=l,col=0;col<8;j++,col++) 
    	{
      		mb_recon->lum[i][j] = *(rcoeff_ind+row+col);
    	}
      }
      qcoeff_ind += 64;
      rcoeff_ind += 64;
    }  
  }

  Dequant(qcoeff_ind,mb_recon->Cb[0],QP,I);
  idct(mb_recon->Cb[0]);
  qcoeff_ind += 64;

  Dequant(qcoeff_ind,mb_recon->Cr[0],QP,I);
  idct(mb_recon->Cr[0]);
}     


/**********************************************************************
 * *	Name:			FillBlock
 *	Description:   	Fills the luminance of one block of PictImage
 *	
 *	Input:	      	Position, pointer to PictImage, array to fill
 *	Returns:       	
 *	Side effects:	fills array
 *
 *
 *
 ***********************************************************************/
void FillBlock( int x, int y, PictImage *image, MB_Structure *data)
{
  int n;
  int m;
  unsigned char _huge *pi = image->lum + (long)y*pels + x;
  unsigned char _huge *pr = image->Cr + (long)(y>>1)*cpels + (x>>1);
  unsigned char _huge *pb = image->Cb + (long)(y>>1)*cpels + (x>>1);
  int *aa, *bb;
  int cmbsize = MB_SIZE >> 1;
  
  aa = data->lum[0];
  for (n = 0; n < MB_SIZE; n++)
  { 
    for (m = 0; m < MB_SIZE; m++,aa++)
      *aa = (int)(*(pi + m ));
    pi += pels;
  }

  aa = data->Cr[0];
  bb = data->Cb[0];
  for (n = 0; n < cmbsize; n++)
  {
    for (m = 0; m < cmbsize; m++,aa++,bb++) {
      *aa = (int)(*(pr + m));
      *bb = (int)(*(pb + m));
    }
	pr += cpels;
	pb += cpels;
  }
  return;
}

/**********************************************************************
 *
 *	Name:		ZeroMBlock
 *	Description:   	Fills one MB with Zeros
 *	
 *	Input:	      	MB_Structure to zero out
 *	Returns:       	
 *	Side effects:	
 *
 *	
 *  
 *
 ***********************************************************************/

void ZeroMBlock(MB_Structure *data)
{
  memset(data,0,sizeof(MB_Structure));
  return;
}

/**********************************************************************
 *
 *	Name:		ReconImage
 *	Description:	Puts together reconstructed image
 *	
 *	Input:		position of curr block, reconstructed
 *			macroblock, pointer to recontructed image
 *	Returns:
 *	Side effects:
 *
 *	
 *  
 *
 ***********************************************************************/

void ReconImage (int i, int j, MB_Structure *data, PictImage *recon)
{
  int n, m, cmbsize = MB_SIZE>>1;
  int x_curr, y_curr;
  unsigned char _huge *pl, _huge *pr, _huge *pb;
  int *dl, *dr, *db;

  x_curr = i * MB_SIZE;
  y_curr = j * MB_SIZE;

  /* Fill in luminance data */
  pl = recon->lum + (long)y_curr*pels + x_curr;
  pr = recon->Cr + (long)(y_curr>>1)*cpels + (x_curr>>1);
  pb = recon->Cb + (long)(y_curr>>1)*cpels + (x_curr>>1);
  dl = data->lum[0];
  dr = data->Cr[0];
  db = data->Cb[0];

  for (n = 0; n < MB_SIZE; n++)
  {
    for (m= 0; m < MB_SIZE; m++,dl++) 
      *(pl + m) = *dl;
	pl += pels;
  }

  /* Fill in chrominance data */
  for (n = 0; n < cmbsize; n++)
  { 
    for (m = 0; m < cmbsize; m++,dr++,db++) {
      *(pr + m) = *dr;
      *(pb + m) = *db;
    }
	pr += cpels;
	pb += cpels;
  }
  return;
}


/**********************************************************************
 *
 *	Name:		InterpolateImage
 *	Description:    Interpolates a complete image for easier half

⌨️ 快捷键说明

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