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

📄 image.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:

/*!
 *************************************************************************************
 * \file image.c
 *
 * \brief
 *    Code one image/slice
 *
 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *     - Inge Lille-Langoy               <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>
 *     - Byeong-Moon Jeon                <jeonbm@lge.com>
 *     - Yoon-Seong Soh                  <yunsung@lge.com>
 *     - Thomas Stockhammer              <stockhammer@ei.tum.de>
 *     - Detlev Marpe                    <marpe@hhi.de>
 *     - Guido Heising
 *     - Thomas Wedi                     <wedi@tnt.uni-hannover.de>
 *     - Ragip Kurceren                  <ragip.kurceren@nokia.com>
 *     - Antti Hallapuro                 <antti.hallapuro@nokia.com>
 *     - Alexis Michael Tourapis         <alexismt@ieee.org>
 *     - Athanasios Leontaris            <aleon@dolby.com>
 *************************************************************************************
 */
#include "contributors.h"

#include <math.h>
#include <time.h>
#include <sys/timeb.h>

#include "global.h"

#include "filehandle.h"
#include "mbuffer.h"
#include "img_luma.h"
#include "img_chroma.h"
#include "img_distortion.h"
#include "intrarefresh.h"
#include "slice.h"
#include "fmo.h"
#include "sei.h"
#include "memalloc.h"
#include "nalu.h"
#include "ratectl.h"
#include "mb_access.h"
#include "cabac.h"
#include "context_ini.h"
#include "enc_statistics.h"
#include "conformance.h"

#include "q_matrix.h"
#include "q_offsets.h"
#include "wp.h"
#include "input.h"
#include "image.h"
#include "errdo.h"


extern pic_parameter_set_rbsp_t *PicParSet[MAXPPS];

extern void DeblockFrame(ImageParameters *img, imgpel **, imgpel ***);

static void code_a_picture(Picture *pic);
static void field_picture(Picture *top, Picture *bottom);
static void prepare_enc_frame_picture (StorablePicture **stored_pic);
static void writeout_picture(Picture *pic);
static byte picture_structure_decision(Picture *frame, Picture *top, Picture *bot);
static void distortion_fld (Picture *field_pic);
static void field_mode_buffer (ImageParameters *img, InputParameters *params);
static void frame_mode_buffer (ImageParameters *img, InputParameters *params);
static void init_frame(ImageParameters *img);
static void init_field(ImageParameters *img);
static void put_buffer_frame(ImageParameters *img);
static void put_buffer_top(ImageParameters *img);
static void put_buffer_bot(ImageParameters *img);
static void PaddAutoCropBorders (FrameFormat output, int img_size_x, int img_size_y, int img_size_x_cr, int img_size_y_cr);
static void rdPictureCoding(void);

#ifdef _ADAPT_LAST_GROUP_
int *last_P_no;
int *last_P_no_frm;
int *last_P_no_fld;
#endif
int FrameNumberInFile;

static void ReportFirstframe(time_t tmp_time, time_t me_time);
static void ReportIntra(time_t tmp_time, time_t me_time);
static void ReportSP(time_t tmp_time, time_t me_time);
static void ReportP(time_t tmp_time, time_t me_time);
static void ReportB(time_t tmp_time, time_t me_time);
static void ReportNALNonVLCBits(time_t tmp_time, time_t me_time);

StorablePicture *enc_picture;
StorablePicture **enc_frame_picture;
StorablePicture **enc_field_picture;
StorablePicture *enc_frame_picture_JV[MAX_PLANE];  //!< enc_frame_picture to be used during 4:4:4 independent mode encoding

void MbAffPostProc(void)
{
  imgpel temp[32][16];

  imgpel ** imgY  = enc_picture->imgY;
  imgpel ***imgUV = enc_picture->imgUV;
  int i, y, x0, y0, uv;

  if (img->yuv_format != YUV400)
  {
    for (i=0; i<(int)img->PicSizeInMbs; i+=2)
    {
      if (enc_picture->motion.mb_field[i])
      {
        get_mb_pos(i, img->mb_size[IS_LUMA], &x0, &y0);
        for (y=0; y<(2*MB_BLOCK_SIZE);y++)
          memcpy(&temp[y],&imgY[y0+y][x0], MB_BLOCK_SIZE * sizeof(imgpel));

        for (y=0; y<MB_BLOCK_SIZE;y++)
        {
          memcpy(&imgY[y0+(2*y)][x0],temp[y], MB_BLOCK_SIZE * sizeof(imgpel));
          memcpy(&imgY[y0+(2*y + 1)][x0],temp[y+ MB_BLOCK_SIZE], MB_BLOCK_SIZE * sizeof(imgpel));
        }

        x0 = x0 / (16/img->mb_cr_size_x);
        y0 = y0 / (16/img->mb_cr_size_y);

        for (uv=0; uv<2; uv++)
        {
          for (y=0; y < (2 * img->mb_cr_size_y); y++)
            memcpy(&temp[y],&imgUV[uv][y0+y][x0], img->mb_cr_size_x * sizeof(imgpel));

          for (y=0; y<img->mb_cr_size_y;y++)
          {
            memcpy(&imgUV[uv][y0+(2*y)][x0],temp[y], img->mb_cr_size_x * sizeof(imgpel));
            memcpy(&imgUV[uv][y0+(2*y + 1)][x0],temp[y+ img->mb_cr_size_y], img->mb_cr_size_x * sizeof(imgpel));
          }
        }
      }
    }
  }
  else
  {
    for (i=0; i<(int)img->PicSizeInMbs; i+=2)
    {
      if (enc_picture->motion.mb_field[i])
      {
        get_mb_pos(i, img->mb_size[IS_LUMA], &x0, &y0);
        for (y=0; y<(2*MB_BLOCK_SIZE);y++)
          memcpy(&temp[y],&imgY[y0+y][x0], MB_BLOCK_SIZE * sizeof(imgpel));

        for (y=0; y<MB_BLOCK_SIZE;y++)
        {
          memcpy(&imgY[y0+(2*y)][x0],temp[y], MB_BLOCK_SIZE * sizeof(imgpel));
          memcpy(&imgY[y0+(2*y + 1)][x0],temp[y+ MB_BLOCK_SIZE], MB_BLOCK_SIZE * sizeof(imgpel));
        }
      }
    }
  }
}

/*!
 ************************************************************************
 * \brief
 *    Sets slice type
 *
 ************************************************************************
 */
void set_slice_type(int slice_type)
{
  img->type = slice_type;            // set slice type
  img->RCMinQP = params->RCMinQP[img->type];
  img->RCMaxQP = params->RCMaxQP[img->type];
}

void code_a_plane(ImageParameters *img, Picture *pic)
{
  unsigned int NumberOfCodedMBs = 0;
  int SliceGroup = 0;
  // The slice_group_change_cycle can be changed here.
  // FmoInit() is called before coding each picture, frame or field
  img->slice_group_change_cycle=1;
  FmoInit(img, active_pps, active_sps);
  FmoStartPicture ();           //! picture level initialization of FMO

  CalculateQuantParam();
  CalculateOffsetParam();

  if(params->Transform8x8Mode)
  {
    CalculateQuant8Param();
    CalculateOffset8Param();
  }

  reset_pic_bin_count();
  img->bytes_in_picture = 0;

  while (NumberOfCodedMBs < img->PicSizeInMbs)       // loop over slices
  {
    // Encode one SLice Group
    while (!FmoSliceGroupCompletelyCoded (SliceGroup))
    {
      // Encode the current slice
      NumberOfCodedMBs += encode_one_slice (SliceGroup, pic, NumberOfCodedMBs);
      FmoSetLastMacroblockInSlice (img->current_mb_nr);
      // Proceed to next slice
      img->current_slice_nr++;
      stats->bit_slice = 0;
    }
    // Proceed to next SliceGroup
    SliceGroup++;
  }
  FmoEndPicture ();

  if ((params->SkipDeBlockNonRef == 0) || (img->nal_reference_idc != 0))
    DeblockFrame (img, enc_picture->imgY, enc_picture->imgUV); //comment out to disable deblocking filter 
}
/*!
 ************************************************************************
 * \brief
 *    Encodes a picture
 *
 *    This is the main picture coding loop.. It is called by all this
 *    frame and field coding stuff after the img-> elements have been
 *    set up.  Not sure whether it is useful for MB-adaptive frame/field
 *    coding
 ************************************************************************
 */
static void code_a_picture(Picture *pic)
{
  int pl;
  int idr_refresh;

  // currently this code only supports fixed enhancement layer distance
  if ( params->idr_period && !params->adaptive_idr_period )
    idr_refresh = (( ( img->frm_number - img->lastIDRnumber ) % params->idr_period ) == 0);
  else if ( params->idr_period && params->adaptive_idr_period == 1 )
    idr_refresh = (( ( img->frm_number - imax(img->lastIntraNumber, img->lastIDRnumber) ) % params->idr_period ) == 0);
  else
    idr_refresh = (img->frm_number == 0);

  img->currentPicture = pic;

  img->currentPicture->idr_flag = ((!IMG_NUMBER) && (!(img->structure==BOTTOM_FIELD)))
    || (idr_refresh && (img->type == I_SLICE || img->type==SI_SLICE)&& (!(img->structure==BOTTOM_FIELD)));

  pic->no_slices = 0;

  RandomIntraNewPicture ();     //! Allocates forced INTRA MBs (even for fields!)

  if( IS_INDEPENDENT( params ) )
  {
    for( pl=0; pl<MAX_PLANE; pl++ )
    {
      img->current_mb_nr = 0;
      img->current_slice_nr = 0;
      img->SumFrameQP = 0;
      img->colour_plane_id = pl;
      
      code_a_plane(img, pic);
    }
  }
  else
  {
    code_a_plane(img, pic);
  }

  if (img->MbaffFrameFlag)
    MbAffPostProc();
}
void update_global_stats(StatParameters *cur_stats)
{  
  int i, j, k;
  for (i = 0; i < 4; i++)
    stats->intra_chroma_mode[i]    += cur_stats->intra_chroma_mode[i];

  for (i = 0; i < 5; i++)
  {
    stats->quant[i]                += cur_stats->quant[i];
    stats->num_macroblocks[i]      += cur_stats->num_macroblocks[i];
    stats->bit_use_mb_type [i]     += cur_stats->bit_use_mb_type[i];
    stats->bit_use_header  [i]     += cur_stats->bit_use_header[i];
    stats->tmp_bit_use_cbp [i]     += cur_stats->tmp_bit_use_cbp[i];
    stats->bit_use_coeffC  [i]     += cur_stats->bit_use_coeffC[i];
    stats->bit_use_coeff[0][i]     += cur_stats->bit_use_coeff[0][i];
    stats->bit_use_coeff[1][i]     += cur_stats->bit_use_coeff[1][i]; 
    stats->bit_use_coeff[2][i]     += cur_stats->bit_use_coeff[2][i]; 
    stats->bit_use_delta_quant[i]  += cur_stats->bit_use_delta_quant[i];
    stats->bit_use_stuffingBits[i] += cur_stats->bit_use_stuffingBits[i];

    for (k = 0; k < 2; k++)
      stats->b8_mode_0_use[i][k] += cur_stats->b8_mode_0_use[i][k];

    for (j = 0; j < 15; j++)
    {
      stats->mode_use[i][j]     += cur_stats->mode_use[i][j];
      stats->bit_use_mode[i][j] += cur_stats->bit_use_mode[i][j];
      for (k = 0; k < 2; k++)
        stats->mode_use_transform[i][j][k] += cur_stats->mode_use_transform[i][j][k];
    }
  }
}

void free_pictures(int stored_pic)
{
  int i;
  for (i = 0; i < 6; i++)
  {
    if (i != stored_pic)
      free_storable_picture(enc_frame_picture[i]);        
  }
}

/*!
 ************************************************************************
 * \brief
 *    Encodes one frame
 ************************************************************************
 */
int encode_one_frame (void)
{
  static int prev_frame_no = 0; // POC200301
  static int consecutive_non_reference_pictures = 0; // POC200301
  int        i, j;
  int   nplane;

  //Rate control
  int bits = 0;

#ifdef _LEAKYBUCKET_
  //extern long Bit_Buffer[20000];
  extern unsigned long total_frame_buffer;
#endif

  TIME_T start_time;
  TIME_T end_time;
  time_t  tmp_time;

  me_time = 0;
  img->rd_pass = 0;

  if( IS_INDEPENDENT(params) )
  {
    for( nplane=0; nplane<MAX_PLANE; nplane++ ){
      enc_frame_picture_JV[nplane] = NULL;
    }
  }

  for (i = 0; i < 6; i++)
    enc_frame_picture[i]  = NULL;

  gettime(&start_time);          // start time in ms

  //Rate control
  img->write_macroblock = FALSE;
  /*
  //Shankar Regunathan (Oct 2002)
  //Prepare Panscanrect SEI payload
  UpdatePanScanRectInfo ();
  //Prepare Arbitrarydata SEI Payload
  UpdateUser_data_unregistered ();
  //Prepare Registered data SEI Payload
  UpdateUser_data_registered_itu_t_t35 ();
  //Prepare RandomAccess SEI Payload
  UpdateRandomAccess ();
  */

  if ((params->ResendPPS) && (img->frm_number !=0))
  {
    stats->bit_ctr_parametersets_n = write_PPS(0, 0);
    stats->bit_ctr_parametersets  += stats->bit_ctr_parametersets_n;
  }

  put_buffer_frame (img);      // sets the pointers to the frame structures
                               // (and not to one of the field structures)
  init_frame (img);

  ReadOneFrame (FrameNumberInFile, params->infile_header, &params->source, &params->output);
  PaddAutoCropBorders (params->output, img->width, img->height, img->width_cr, img->height_cr);

  // set parameters for direct mode and deblocking filter
  img->direct_spatial_mv_pred_flag = params->direct_spatial_mv_pred_flag;

  img->DFDisableIdc                = params->DFDisableIdc[img->nal_reference_idc > 0][img->type];
  img->DFAlphaC0Offset             = params->DFAlpha     [img->nal_reference_idc > 0][img->type];
  img->DFBetaOffset                = params->DFBeta      [img->nal_reference_idc > 0][img->type];

  img->AdaptiveRounding            = params->AdaptiveRounding; 

  // Following code should consider optimal coding mode. Currently also does not support
  // multiple slices per frame.

⌨️ 快捷键说明

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