macroblock.c

来自「h.264标准和jm」· C语言 代码 · 共 1,891 行 · 第 1/5 页

C
1,891
字号

/*!
 *************************************************************************************
 * \file macroblock.c
 *
 * \brief
 *    Process one macroblock
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *    - Inge Lille-Lang鴜               <inge.lille-langoy@telenor.com>
 *    - Rickard Sjoberg                 <rickard.sjoberg@era.ericsson.se>
 *    - Jani Lainema                    <jani.lainema@nokia.com>
 *    - Sebastian Purreiter             <sebastian.purreiter@mch.siemens.de>
 *    - Detlev Marpe                    <marpe@hhi.de>
 *    - Thomas Wedi                     <wedi@tnt.uni-hannover.de>
 *    - Ragip Kurceren                  <ragip.kurceren@nokia.com>
 *************************************************************************************
 */
#include "contributors.h"

#include <math.h>
#include <stdlib.h>
#include <assert.h>

#include "elements.h"
#include "macroblock.h"
#include "refbuf.h"
#include "fmo.h"
#include "vlc.h"
#include "image.h"
#include "mb_access.h"
#include "ratectl.h"              // head file for rate control

//Rate control
int predict_error,dq;
extern int DELTA_QP,DELTA_QP2;
extern int QP,QP2;

 /*!
 ************************************************************************
 * \brief
 *    updates the coordinates for the next macroblock to be processed
 *
 * \input
 *    mb: MB address in scan order
 ************************************************************************
 */

void set_MB_parameters (int mb)
{
  const int number_mb_per_row = img->width / MB_BLOCK_SIZE ;

  img->current_mb_nr = mb;
  img->mb_x = mb % number_mb_per_row;
  img->mb_y = mb / number_mb_per_row;

// printf ("Set_MB_Parameters: mb %d,  mb_x %d,  mb_y %d\n", mb, img->mb_x, img->mb_y);

  // Define vertical positions
  img->block_y = img->mb_y * BLOCK_SIZE;      // vertical luma block position
  img->pix_y   = img->mb_y * MB_BLOCK_SIZE;   // vertical luma macroblock position
  img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2; // vertical chroma macroblock position

  // Define horizontal positions
  img->block_x = img->mb_x * BLOCK_SIZE;        // luma block
  img->pix_x   = img->mb_x * MB_BLOCK_SIZE;     // luma pixel
  img->block_c_x = img->mb_x * BLOCK_SIZE/2;    // chroma block
  img->pix_c_x   = img->mb_x * MB_BLOCK_SIZE/2; // chroma pixel

  if(input->InterlaceCodingOption >= MB_CODING && mb_adaptive && img->field_mode)
  {
    if(img->top_field)
    {
      img->field_mb_y = img->mb_y/2;
      img->field_pix_y  = img->field_mb_y*MB_BLOCK_SIZE;
      img->field_block_y = img->field_mb_y*BLOCK_SIZE;
      img->field_pix_c_y = img->field_mb_y*MB_BLOCK_SIZE/2;
    }
    else
    {
      img->field_mb_y = (img->mb_y-1)/2;
      img->field_pix_y  = img->field_mb_y*MB_BLOCK_SIZE;
      img->field_block_y = img->field_mb_y*BLOCK_SIZE;
      img->field_pix_c_y = img->field_mb_y*MB_BLOCK_SIZE/2;
    } 
  }
}


int clip1a(int a)
{
  return ((a)>255?255:((a)<0?0:(a)));
}

/*!
 ************************************************************************
 * \brief
 *    updates the coordinates and statistics parameter for the
 *    next macroblock
 ************************************************************************
 */
void proceed2nextMacroblock()
{
#if TRACE
  int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
#endif
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
  int*        bitCount = currMB->bitcounter;

#if TRACE
  int i;
  if (p_trace)
  {
    fprintf(p_trace, "\n*********** Pic: %i (I/P) MB: %i Slice: %i **********\n\n", frame_no, img->current_mb_nr, img->current_slice_nr);
    if(use_bitstream_backing)
      fprintf(p_trace, "\n*********** Pic: %i (I/P) MB: %i Slice: %i **********\n\n", frame_no, img->current_mb_nr, img->current_slice_nr);
   // Write out the tracestring for each symbol
    for (i=0; i<currMB->currSEnr; i++)
      trace2out(&(img->MB_SyntaxElements[i]));
  }
#endif

  // Update the statistics
  stat->bit_use_mb_type[img->type]      += bitCount[BITS_MB_MODE];
  stat->bit_use_coeffY[img->type]       += bitCount[BITS_COEFF_Y_MB] ;
  stat->tmp_bit_use_cbp[img->type]      += bitCount[BITS_CBP_MB];
  stat->bit_use_coeffC[img->type]       += bitCount[BITS_COEFF_UV_MB];
  stat->bit_use_delta_quant[img->type]  += bitCount[BITS_DELTA_QUANT_MB];

  if (img->type==I_SLICE)
    ++stat->mode_use_intra[currMB->mb_type];
  else
    if (img->type != B_SLICE)
    {
      ++stat->mode_use_inter[0][currMB->mb_type];
      stat->bit_use_mode_inter[0][currMB->mb_type]+= bitCount[BITS_INTER_MB];

    }
    else
    {
      stat->bit_use_mode_inter[1][currMB->mb_type]+= bitCount[BITS_INTER_MB];
      ++stat->mode_use_inter[1][currMB->mb_type];
    }

  // Statistics
  if ((img->type == P_SLICE)||(img->type==SP_SLICE) )
  {
    ++stat->quant0;
    stat->quant1 += img->qp;      // to find average quant for inter frames
  }
}

/*!
 ************************************************************************
 * \brief
 *    initializes the current macroblock
 ************************************************************************
 */
void start_macroblock()
{
  int i,j,k,l;
  int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
  Macroblock *currMB = &img->mb_data[img->current_mb_nr];
  Slice *curr_slice = img->currentSlice;
  DataPartition *dataPart;
  Bitstream *currStream;
  EncodingEnvironmentPtr eep;

  if(use_bitstream_backing)
  {
    // Keep the current state of the bitstreams
    if(!img->cod_counter)
      for (i=0; i<curr_slice->max_part_nr; i++)
      {
        dataPart = &(curr_slice->partArr[i]);
        currStream = dataPart->bitstream;
        currStream->stored_bits_to_go   = currStream->bits_to_go;
        currStream->stored_byte_pos   = currStream->byte_pos;
        currStream->stored_byte_buf   = currStream->byte_buf;

        if (input->symbol_mode ==CABAC)
        {
          eep = &(dataPart->ee_cabac);
          eep->ElowS            = eep->Elow;
          eep->ErangeS           = eep->Erange;
          eep->EbufferS         = eep->Ebuffer;
          eep->Ebits_to_goS     = eep->Ebits_to_go;
          eep->Ebits_to_followS = eep->Ebits_to_follow;
          eep->EcodestrmS       = eep->Ecodestrm;
          eep->Ecodestrm_lenS   = eep->Ecodestrm_len;
          eep->CS               = eep->C;
          eep->BS               = eep->B;
          eep->ES               = eep->E;
        }
      }
  }

  // Save the slice number of this macroblock. When the macroblock below
  // is coded it will use this to decide if prediction for above is possible
  currMB->slice_nr = img->current_slice_nr;

  // Initialize delta qp change from last macroblock. Feature may be used for future rate control
  // Rate control
	if(input->RCEnable)
  {
	  /*frame layer rate control*/
	  if(input->basicunit==img->Frame_Total_Number_MB)
	  {
		  currMB->delta_qp = 0;
		  currMB->qp       = img->qp;
	  }
/*basic unit layer rate control*/
	  else
	  {
/*each I or B frame has only one QP*/
		 if((img->type==I_SLICE)||(img->type==B_SLICE))
		 {
			 currMB->delta_qp = 0;
			 currMB->qp       = img->qp;
		 }
		 else if(img->type==P_SLICE)
		 {

			 if (!img->write_macroblock) //write macroblock
			 {
				 if (!img->mb_aff_field)  //frame macroblock
				 {
					 if (img->current_mb_nr == 0) //first macroblock
					 {
// Initialize delta qp change from last macroblock. Feature may be used for future rate control
						 currMB->delta_qp = 0;
						 currMB->qp       = img->qp;
						 DELTA_QP = DELTA_QP2 = currMB->delta_qp;
						 QP = QP2 = currMB->qp;
					 }
					 else
					 {
						 if (!((input->InterlaceCodingOption == 3) && img->bot_MB)) //top macroblock
						 {
							 if (img->mb_data[img->current_mb_nr-1].prev_cbp == 1)
							 {
								 currMB->delta_qp = 0;
								 currMB->qp       = img->qp;
							 }
							 else
							 {
								 currMB->qp = img->mb_data[img->current_mb_nr-1].prev_qp;
								 currMB->delta_qp = currMB->qp - img->mb_data[img->current_mb_nr-1].qp;
								 img->qp = currMB->qp;
							 }
							 DELTA_QP = DELTA_QP2 = currMB->delta_qp;
							 QP = QP2 = currMB->qp;
						 }
						 else //bottom macroblock
						 {
// Initialize delta qp change from last macroblock. Feature may be used for future rate control
							 currMB->delta_qp = 0;
							 currMB->qp       = img->qp;       // needed in loop filter (even if constant QP is used)
						 }
					 }
				 }
				 else  //field macroblock
				 {
					 if (!img->bot_MB) //top macroblock 
					 {
						 currMB->delta_qp = DELTA_QP2;
						 currMB->qp   = img->qp    = QP2;
					 }
					 else//bottom macroblock
					 {
						 currMB->qp = img->qp;
						 currMB->delta_qp = 0;
					 }
					 
				 }
				 
			 }
			 else 
			 {
				 if (!img->bot_MB) //write top macroblock
				 {
					 if (img->write_macroblock_frame)
					 {
						 currMB->delta_qp = DELTA_QP;
						 img->qp = currMB->qp = QP;
					 }
					 else
					 {
						 currMB->delta_qp = DELTA_QP2;
						 img->qp = currMB->qp = QP2;
					 }
				 }
				 else //write bottom macroblock
				 {
					 currMB->delta_qp = 0;
					 currMB->qp = img->qp;
				 }
			 }

			 /*compute the quantization parameter for each basic unit of P frame*/

			 if(!((input->InterlaceCodingOption==3)&&img->bot_MB))
			 {
				 if(!img->mb_aff_field)
				 {
					 
					 if((img->NumberofCodedMacroBlocks>0)\
						 &&(img->NumberofCodedMacroBlocks%img->BasicUnit==0))
					 {
						 
						 /*frame coding*/
						 if(input->InterlaceCodingOption==0)
						 {
							 updateRCModel();
							 img->BasicUnitQP=updateQuantizationParameter(img->TopFieldFlag);
						 }
						 /*adaptive field/frame coding*/
						 else if((input->InterlaceCodingOption==1)&&(img->IFLAG==0))
						 {
							 updateRCModel();
							 img->BasicUnitQP=updateQuantizationParameter(img->TopFieldFlag);
						 }
						 /*field coding*/
						 else if((input->InterlaceCodingOption==2)&&(img->IFLAG==0))
						 {
							 updateRCModel();
							 img->BasicUnitQP=updateQuantizationParameter(img->TopFieldFlag);
						 }
						 /*mb adaptive f/f coding, field coding*/
						 else if((input->InterlaceCodingOption==3)&&(img->IFLAG==0)&&(img->FieldControl==1))
						 {
							 updateRCModel();
							 img->BasicUnitQP=updateQuantizationParameter(img->TopFieldFlag);
						 }
						 /*mb adaptive f/f coding, frame coding*/
						 else if((input->InterlaceCodingOption==3)&&(img->IFLAG==0)&&(img->FieldControl==0))
						 {
							 updateRCModel();
							 img->BasicUnitQP=updateQuantizationParameter(img->TopFieldFlag);
						 } 
						 
						 
					 }
					 
					 
					 if(img->current_mb_nr==0)
						 img->BasicUnitQP=img->qp;
					 currMB->predict_qp=img->BasicUnitQP;
					 if(currMB->predict_qp>currMB->qp+25)
						 currMB->predict_qp=currMB->qp+25;
					 else if(currMB->predict_qp<currMB->qp-26)
						 currMB->predict_qp=currMB->qp-26; 
					 currMB->prev_qp = currMB->predict_qp;
					 
					 dq = currMB->delta_qp + currMB->predict_qp-currMB->qp;
					 if(dq < -26) 
					 {
						 dq = -26;
						 predict_error = dq-currMB->delta_qp;
						 img->qp = img->qp+predict_error;
						 currMB->delta_qp = -26;
					 }
					 else if(dq > 25)
					 {
						 dq = 25;
						 predict_error = dq - currMB->delta_qp;
						 img->qp = img->qp + predict_error;
						 currMB->delta_qp = 25;
					 }
					 else
					 {
						 currMB->delta_qp = dq;
						 predict_error=currMB->predict_qp-currMB->qp;
						 img->qp = currMB->predict_qp;
					 }
					 currMB->qp =  img->qp;
					 if (input->InterlaceCodingOption == 3)
					 {

⌨️ 快捷键说明

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