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

📄 macroblock.c

📁 H.264编码解码器源码(c语言).zip
💻 C
📖 第 1 页 / 共 5 页
字号:

/*!
 *************************************************************************************
 * \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"

 /*!
 ************************************************************************
 * \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
  currMB->delta_qp = 0;
  currMB->qp       = img->qp;       // needed in loop filter (even if constant QP is used)

  // Initialize counter for MB symbols
  currMB->currSEnr=0;

  // If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction
  CheckAvailabilityOfNeighbors(img);

  // Reset vectors before doing motion search in motion_search().
  if (img->type != B_SLICE)
  {
    for (k=0; k < 2; k++)
    {
      for (j=0; j < BLOCK_MULTIPLE; j++)
        for (i=0; i < BLOCK_MULTIPLE; i++)
          tmp_mv[k][img->block_y+j][img->block_x+i+4]=0;
    }
  }

  for (l=0; l<2; l++)
  {
    for (j=0; j < BLOCK_MULTIPLE; j++)
      for (i=0; i < BLOCK_MULTIPLE; i++)
        for (k=0; k < 2; k++)
          enc_picture->mv[l][img->block_x+i][img->block_y+j][k]=0;
  }

  //initialize reference index 
	for (j=0; j < BLOCK_MULTIPLE; j++)
  {
    for (i=0; i < BLOCK_MULTIPLE; i++)
      for (l=0; l<2; l++)
			{
        enc_picture->ref_idx[l][img->block_x+i][img->block_y + j] =-1;
        enc_picture->ref_pic_id[l][img->block_x+i][img->block_y+j] = -1;
      }
    }
  
  // Reset syntax element entries in MB struct
  currMB->mb_type   = 0;
  currMB->cbp_blk   = 0;
  currMB->cbp       = 0;
  currMB->mb_field  = 0;

  for (l=0; l < 2; l++)
    for (j=0; j < BLOCK_MULTIPLE; j++)
      for (i=0; i < BLOCK_MULTIPLE; i++)
        for (k=0; k < 2; k++)
          currMB->mvd[l][j][i][k] = 0;
 
  currMB->cbp_bits   = 0;
  currMB->c_ipred_mode = DC_PRED_8; //GB

  for (i=0; i < (BLOCK_MULTIPLE*BLOCK_MULTIPLE); i++)
    currMB->intra_pred_modes[i] = DC_PRED;

  //initialize the whole MB as INTRA coded
  //Blocks ar set to notINTRA in write_one_macroblock
  if (input->UseConstrainedIntraPred)
  {
    img->intra_block[img->current_mb_nr] = 1;
  }

  // store filtering parameters for this MB; For now, we are using the
  // same offset throughout the sequence
  currMB->lf_disable = input->LFDisableIdc;
  currMB->lf_alpha_c0_offset = input->LFAlphaC0Offset;
  currMB->lf_beta_offset = input->LFBetaOffset;


  // Initialize bitcounters for this macroblock
  if(img->current_mb_nr == 0) // No slice header to account for
  {
    currMB->bitcounter[BITS_HEADER] = 0;
  }
  else if (currMB->slice_nr == img->mb_data[img->current_mb_nr-1].slice_nr) // current MB belongs to the
  // same slice as the last MB
  {
    currMB->bitcounter[BITS_HEADER] = 0;
  }

  currMB->bitcounter[BITS_MB_MODE] = 0;
  currMB->bitcounter[BITS_COEFF_Y_MB] = 0;
  currMB->bitcounter[BITS_INTER_MB] = 0;
  currMB->bitcounter[BITS_CBP_MB] = 0;
  currMB->bitcounter[BITS_DELTA_QUANT_MB] = 0;
  currMB->bitcounter[BITS_COEFF_UV_MB] = 0;

#ifdef _FAST_FULL_ME_
  ResetFastFullIntegerSearch ();
#endif
}

/*!
 ************************************************************************
 * \brief
 *    terminates processing of the current macroblock depending
 *    on the chosen slice mode
 ************************************************************************
 */
void terminate_macroblock(Boolean *end_of_slice, Boolean *recode_macroblock)
{
  int i;
  Slice *currSlice = img->currentSlice;
  Macroblock    *currMB    = &img->mb_data[img->current_mb_nr];
  SyntaxElement *currSE    = &img->MB_SyntaxElements[currMB->currSEnr];
  int *partMap = assignSE2partition[input->partition_mode];
  DataPartition *dataPart;
  Bitstream *currStream;
  int rlc_bits=0;
  EncodingEnvironmentPtr eep;
  int use_bitstream_backing = (input->slice_mode == FIXED_RATE || input->slice_mode == CALLBACK);
  int new_slice = ( (img->current_mb_nr == 0) || img->mb_data[img->current_mb_nr-1].slice_nr != img->current_slice_nr);
  static int skip = FALSE;

  switch(input->slice_mode)
  {
  case NO_SLICES:
    currSlice->num_mb++;
    *recode_macroblock = FALSE;
    if ((currSlice->num_mb) == img->total_number_mb) // maximum number of MBs reached
      *end_of_slice = TRUE;
    break;
  case FIXED_MB:
    // For slice mode one, check if a new slice boundary follows
    currSlice->num_mb++;
    *recode_macroblock = FALSE;
    *end_of_slice = (currSlice->num_mb >= input->slice_argument);  // End of Slice
    *end_of_slice |= (img->current_mb_nr+1) == img->total_number_mb;    // End of Picture condition
    break;

    // For slice modes two and three, check if coding of this macroblock
    // resulted in too many bits for this slice. If so, indicate slice
    // boundary before this macroblock and code the macroblock again
  case FIXED_RATE:
     // in case of skip MBs check if there is a slice boundary
     // only for UVLC (img->cod_counter is always 0 in case of CABAC)
     if(img->cod_counter)
     {
       // write out the skip MBs to know how many bits we need for the RLC
       currSE->value1 = img->cod_counter;
       currSE->mapping = ue_linfo;
       currSE->type = SE_MBTYPE;
	
			 if (img->type != B_SLICE)   dataPart = &(currSlice->partArr[partMap[currSE->type]]);
       else                    dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
       dataPart->writeSyntaxElement(  currSE, dataPart);
       rlc_bits=currSE->len;

       currStream = dataPart->bitstream;
       // save the bitstream as it would be if we write the skip MBs
       currStream->bits_to_go_skip  = currStream->bits_to_go;
       currStream->byte_pos_skip    = currStream->byte_pos;
       currStream->byte_buf_skip    = currStream->byte_buf;
       // restore the bitstream
       currStream->bits_to_go = currStream->stored_bits_to_go;
       currStream->byte_pos = currStream->stored_byte_pos;
       currStream->byte_buf = currStream->stored_byte_buf;
       skip = TRUE;
     }
     //! Check if the last coded macroblock fits into the size of the slice
     //! But only if this is not the first macroblock of this slice
     if (!new_slice)
     {
       if(slice_too_big(rlc_bits))
       {
         *recode_macroblock = TRUE;
         *end_of_slice = TRUE;
       }

⌨️ 快捷键说明

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