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

📄 macroblock.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  currMB->bitcounter[BITS_INTER_MB      ] = 0;
  currMB->bitcounter[BITS_CBP_MB        ] = 0;
  currMB->bitcounter[BITS_COEFF_Y_MB    ] = 0;    
  currMB->bitcounter[BITS_COEFF_UV_MB   ] = 0;    
  currMB->bitcounter[BITS_COEFF_CB_MB   ] = 0; 
  currMB->bitcounter[BITS_COEFF_CR_MB   ] = 0;
  currMB->bitcounter[BITS_DELTA_QUANT_MB] = 0;
  currMB->bitcounter[BITS_STUFFING ]      = 0;

}


/*!
 ************************************************************************
 * \brief
 *    initializes the current macroblock
 *
 * \param currMB
 *    current macroblock
 * \param mb_addr
 *    current macroblock address
 * \param mb_field
 *    true for field macroblock coding
 ************************************************************************
 */
void start_macroblock(Slice *curr_slice, Macroblock **currMB, int mb_addr, byte mb_field)
{
  int i, mb_qp;
  int use_bitstream_backing = (params->slice_mode == FIXED_RATE || params->slice_mode == CALL_BACK);
  DataPartition *dataPart;
  Bitstream *currStream;
  int prev_mb;

  *currMB = &img->mb_data[mb_addr];
  (*currMB)->mbAddrX = mb_addr;


  (*currMB)->mb_field = mb_field;

  enc_picture->motion.mb_field[mb_addr] = mb_field;
  (*currMB)->is_field_mode = (img->field_picture || ( img->MbaffFrameFlag && (*currMB)->mb_field));

  set_MB_parameters (mb_addr);

  prev_mb = FmoGetPreviousMBNr(img->current_mb_nr);

  if ( params->ChromaMCBuffer )
    OneComponentChromaPrediction4x4 = OneComponentChromaPrediction4x4_retrieve;
  else
    OneComponentChromaPrediction4x4 = OneComponentChromaPrediction4x4_regenerate;

  if(use_bitstream_backing)
  {
    if ((!params->MbInterlace)||((mb_addr & 0x01)==0)) // KS: MB AFF -> store stream positions for 1st MB only
    {
      // 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;
          stats->stored_bit_slice       = stats->bit_slice;

          if (curr_slice->symbol_mode ==CABAC)
          {
            dataPart->ee_recode = dataPart->ee_cabac;
          }
        }
      }
    }
  }

  // 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
  (*currMB)->qpsp       = img->qpsp;

  if (prev_mb > -1 && (img->mb_data[prev_mb].slice_nr == img->current_slice_nr))
  {
    (*currMB)->prev_qp  = img->mb_data[prev_mb].qp;
    (*currMB)->prev_dqp = img->mb_data[prev_mb].delta_qp;
  }
  else
  {
    (*currMB)->prev_qp  = curr_slice->qp;
    (*currMB)->prev_dqp = 0;
  }

  if(params->RCEnable)
    mb_qp = rc_handle_mb( prev_mb, *currMB, curr_slice );
  else
  {
    mb_qp = img->qp;

  }

  mb_qp = iClip3(-img->bitdepth_luma_qp_scale, 51, mb_qp);
  (*currMB)->qp       = img->qp = mb_qp;
  (*currMB)->delta_qp = (*currMB)->qp - (*currMB)->prev_qp;

  update_qp (img, *currMB);

  // deblocking filter parameter
  if (active_pps->deblocking_filter_control_present_flag)
  {
    (*currMB)->DFDisableIdc    = img->DFDisableIdc;
    (*currMB)->DFAlphaC0Offset = img->DFAlphaC0Offset;
    (*currMB)->DFBetaOffset    = img->DFBetaOffset;
  }
  else
  {
    (*currMB)->DFDisableIdc    = 0;
    (*currMB)->DFAlphaC0Offset = 0;
    (*currMB)->DFBetaOffset    = 0;
  }

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

  if (curr_slice->symbol_mode == CABAC)
    CheckAvailabilityOfNeighborsCABAC(*currMB);

  reset_macroblock(*currMB, prev_mb);

  if ((params->SearchMode == FAST_FULL_SEARCH) && (!params->IntraProfile))
    ResetFastFullIntegerSearch ();


  // disable writing of trace file
#if TRACE
  for (i=0; i<curr_slice->max_part_nr; i++ )
  {
    curr_slice->partArr[i].bitstream->trace_enabled = FALSE;
  }  
#endif
}

/*!
 ************************************************************************
 * \brief
 *    terminates processing of the current macroblock depending
 *    on the chosen slice mode
 ************************************************************************
 */
void terminate_macroblock(Slice *currSlice,           //!< Current slice
                          Macroblock *currMB,         //!< Current Macroblock
                          Boolean *end_of_slice,      //!< returns true for last macroblock of a slice, otherwise false
                          Boolean *recode_macroblock  //!< returns true if max. slice size is exceeded an macroblock must be recoded in next slice
                          )
{
  int i;
  SyntaxElement se;
  int *partMap = assignSE2partition[params->partition_mode];
  DataPartition *dataPart;
  Bitstream *currStream;
  int rlc_bits=0;
  int use_bitstream_backing = (params->slice_mode == FIXED_RATE || params->slice_mode == CALL_BACK);
  static int skip = FALSE;
  int new_slice = 0;

  // if previous mb in the same slice group has different slice number as the current, it's the
  // the start of new slice
  if ((img->current_mb_nr==0) || (FmoGetPreviousMBNr(img->current_mb_nr)<0) || ( img->mb_data[FmoGetPreviousMBNr(img->current_mb_nr)].slice_nr != img->current_slice_nr ))
    new_slice=1;

  *recode_macroblock=FALSE;

  switch(params->slice_mode)
  {
  case NO_SLICES:
    currSlice->num_mb++;
    *recode_macroblock = FALSE;
    if ((currSlice->num_mb) == (int)img->PicSizeInMbs) // maximum number of MBs reached
      *end_of_slice = TRUE;

    // if it's end of current slice group, slice ends too
    *end_of_slice = (Boolean) (*end_of_slice | (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr))));

    break;
  case FIXED_MB:
    // For slice mode one, check if a new slice boundary follows
    currSlice->num_mb++;
    *recode_macroblock = FALSE;
    //! Check end-of-slice group condition first
    *end_of_slice = (Boolean) (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr)));
    //! Now check maximum # of MBs in slice
    *end_of_slice = (Boolean) (*end_of_slice | (currSlice->num_mb >= params->slice_argument));

    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 CAVLC (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
      se.value1 = img->cod_counter;
      se.value2 = 0;
      se.type = SE_MBTYPE;
      dataPart = &(currSlice->partArr[partMap[se.type]]);

      TRACE_SE (se.tracestring, "mb_skip_run");
      writeSE_UVLC(&se, dataPart);
      rlc_bits=se.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(currSlice, rlc_bits))
      {
        *recode_macroblock = TRUE;
        *end_of_slice      = TRUE;
      }
      else if(!img->cod_counter)
        skip = FALSE;
    }
    // maximum number of MBs

    // check if current slice group is finished
    if ((*recode_macroblock == FALSE) && (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr))))
    {
      *end_of_slice = TRUE;
      if(!img->cod_counter)
        skip = FALSE;
    }

    //! (first MB OR first MB in a slice) AND bigger that maximum size of slice
    if (new_slice && slice_too_big(currSlice, rlc_bits))
    {
      *end_of_slice = TRUE;
      if(!img->cod_counter)
        skip = FALSE;
    }
    if (!*recode_macroblock)
      currSlice->num_mb++;
    break;

  case  CALL_BACK:
    if (img->current_mb_nr > 0 && !new_slice)
    {
      if (currSlice->slice_too_big(rlc_bits))
      {
        *recode_macroblock = TRUE;
        *end_of_slice = TRUE;
      }
    }

    if ( (*recode_macroblock == FALSE) && (img->current_mb_nr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (img->current_mb_nr))))
      *end_of_slice = TRUE;
    break;

  default:
    snprintf(errortext, ET_SIZE, "Slice Mode %d not supported", params->slice_mode);
    error(errortext, 600);
  }

  if (*recode_macroblock == TRUE)
  {
    // Restore everything
    for (i=0; i<currSlice->max_part_nr; i++)
    {
      dataPart = &(currSlice->partArr[i]);
      currStream = dataPart->bitstream;
      currStream->bits_to_go = currStream->stored_bits_to_go;
      currStream->byte_pos  = currStream->stored_byte_pos;
      currStream->byte_buf  = currStream->stored_byte_buf;
      stats->bit_slice      = stats->stored_bit_slice;

      if (currSlice->symbol_mode == CABAC)
      {
        dataPart->ee_cabac = dataPart->ee_recode;
      }
    }
  }

  if (currSlice->symbol_mode == CAVLC)
  {
    // Skip MBs at the end of this slice
    dataPart = &(currSlice->partArr[partMap[SE_MBTYPE]]);
    if(*end_of_slice == TRUE  && skip == TRUE)
    {
      // only for Slice Mode 2 or 3
      // If we still have to write the skip, let's do it!
      if(img->cod_counter && *recode_macroblock == TRUE) // MB that did not fit in this slice
      {
        // If recoding is true and we have had skip,
        // we have to reduce the counter in case of recoding
        img->cod_counter--;
        if(img->cod_counter)
        {
          se.value1 = img->cod_counter;
          se.value2 = 0;
          se.type = SE_MBTYPE;
#if TRACE
          snprintf(se.tracestring, TRACESTRING_SIZE, "Final MB runlength = %3d",img->cod_counter);
#endif
          writeSE_UVLC(&se, dataPart);
          rlc_bits=se.len;
          currMB->bitcounter[BITS_MB_MODE]+=rlc_bits;
          img->cod_counter = 0;
        }
      }
      else //! MB that did not fit in this slice anymore is not a Skip MB
      {
        currStream = dataPart->bitstream;
        // update the bitstream
        currStream->bits_to_go = currStream->bits_to_go_skip;
        currStream->byte_pos  = currStream->byte_pos_skip;
        currStream->byte_buf  = currStream->byte_buf_skip;

        // update the statistics
        img->cod_counter = 0;
        skip = FALSE;
      }
    }

    // Skip MBs at the end of this slice for Slice Mode 0 or 1
    if(*end_of_slice == TRUE && img->cod_counter && !use_bitstream_backing)
    {
      se.value1 = img->cod_counter;
      se.value2 = 0;
      se.type = SE_MBTYPE;

      TRACE_SE (se.tracestring, "mb_skip_run");
      writeSE_UVLC(&se, dataPart);

      rlc_bits=se.len;
      currMB->bitcounter[BITS_MB_MODE]+=rlc_bits;
      img->cod_counter = 0;
    }
  }
}

/*!
 *****************************************************************************
 *
 * \brief
 *    For Slice Mode 2: Checks if one partition of one slice exceeds the
 *    allowed size
 *
 * \return
 *    FALSE if all Partitions of this slice are smaller than the allowed size
 *    TRUE is at least one Partition exceeds the limit
 *
 * \par Side effects
 *    none
 *
 * \date
 *    4 November 2001
 *
 * \author
 *    Tobias Oelbaum      drehvial@gmx.net
 *****************************************************************************/

int slice_too_big(Slice *currSlice, int rlc_bits)
{
  DataPartition *dataPart;
  Bitstream *currStream;
  EncodingEnvironmentPtr eep;
  int i;
  int size_in_bytes;

  //! CAVLC
  if (currSlice->symbol_mode == CAVLC)
  {
    for (i=0; i<currSlice->max_part_nr; i++)
    {
      dataPart = &(currSlice->partArr[i]);
      currStream = dataPart->bitstream;
      size_in_bytes = currStream->byte_pos /*- currStream->tmp_byte_pos*/;

      if (currStream->bits_to_go < 8)
        size_in_bytes++;
      if (currStream->bits_to_go < rlc_bits)
        size_in_bytes++;
      if(size_in_bytes > params->slice_argument)
        return TRUE;
    }
  }

⌨️ 快捷键说明

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