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

📄 image.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:
 ************************************************************************
 */
static void writeout_picture(Picture *pic)
{
  int partition, slice;
  Slice  *currSlice;

  img->currentPicture = pic;

  // loop over all slices of the picture
  for (slice=0; slice < pic->no_slices; slice++)
  {
    currSlice = pic->slices[slice];

    // loop over the partitions
    for (partition=0; partition < currSlice->max_part_nr; partition++)
    {
      // write only if the partition has content
      if (currSlice->partArr[partition].bitstream->write_flag )
      {
        stats->bit_ctr += WriteNALU (currSlice->partArr[partition].nal_unit);
      }
    }
  }
}


void copy_params(StorablePicture *enc_picture, seq_parameter_set_rbsp_t *active_sps)
{
  enc_picture->frame_mbs_only_flag = active_sps->frame_mbs_only_flag;
  enc_picture->frame_cropping_flag = active_sps->frame_cropping_flag;
  enc_picture->chroma_format_idc   = active_sps->chroma_format_idc;

  if (active_sps->frame_cropping_flag)
  {
    enc_picture->frame_cropping_rect_left_offset   = active_sps->frame_cropping_rect_left_offset;
    enc_picture->frame_cropping_rect_right_offset  = active_sps->frame_cropping_rect_right_offset;
    enc_picture->frame_cropping_rect_top_offset    = active_sps->frame_cropping_rect_top_offset;
    enc_picture->frame_cropping_rect_bottom_offset = active_sps->frame_cropping_rect_bottom_offset;
  }
  else
  {
    enc_picture->frame_cropping_rect_left_offset   = 0;
    enc_picture->frame_cropping_rect_right_offset  = 0;
    enc_picture->frame_cropping_rect_top_offset    = 0;
    enc_picture->frame_cropping_rect_bottom_offset = 0;
  }
}

/*!
 ************************************************************************
 * \brief
 *    Prepare and allocate an encoded frame picture structure
 ************************************************************************
 */
static void prepare_enc_frame_picture (StorablePicture **stored_pic)
{
  (*stored_pic)              = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
  
  img->ThisPOC               = img->framepoc;
  (*stored_pic)->poc         = img->framepoc;
  (*stored_pic)->top_poc     = img->toppoc;
  (*stored_pic)->bottom_poc  = img->bottompoc;
  (*stored_pic)->frame_poc   = img->framepoc;
  (*stored_pic)->pic_num     = img->frame_num;
  (*stored_pic)->frame_num   = img->frame_num;
  (*stored_pic)->coded_frame = 1;
  (*stored_pic)->MbaffFrameFlag = img->MbaffFrameFlag = (params->MbInterlace != FRAME_CODING);
  
  get_mb_block_pos           = img->MbaffFrameFlag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal;
  getNeighbour               = img->MbaffFrameFlag ? getAffNeighbour : getNonAffNeighbour;
  enc_picture                = *stored_pic;

  copy_params(enc_picture, active_sps);
}

static void calc_picture_bits(Picture *frame)
{
  int i, j;
  Slice *thisSlice = NULL;

  frame->bits_per_picture = 0;

  for ( i = 0; i < frame->no_slices; i++ )
  {
    thisSlice = frame->slices[i];

    for ( j = 0; j < thisSlice->max_part_nr; j++ )
      frame->bits_per_picture += 8 * ((thisSlice->partArr[j]).bitstream)->byte_pos;
  }
}
/*!
 ************************************************************************
 * \brief
 *    Encodes a frame picture
 ************************************************************************
 */
void frame_picture (Picture *frame, int rd_pass)
{
  int nplane;
  img->SumFrameQP = 0;
  img->structure = FRAME;
  img->PicSizeInMbs = img->FrameSizeInMbs;
  //set mv limits to frame type
  update_mv_limits(img, FALSE);


  if( IS_INDEPENDENT(params) )
  {
    for( nplane=0; nplane<MAX_PLANE; nplane++ )
    {
      prepare_enc_frame_picture( &enc_frame_picture_JV[nplane] );      
    }
  }
  else
  {
    prepare_enc_frame_picture( &enc_frame_picture[rd_pass] );
  }


  img->fld_flag = FALSE;
  code_a_picture(frame);

  if( IS_INDEPENDENT(params) )
  {
    make_frame_picture_JV();
  }

  calc_picture_bits(frame);

  if (img->structure==FRAME)
  {
    find_distortion ();
    frame->distortion = dist->metric[SSE];
  }
}


/*!
 ************************************************************************
 * \brief
 *    Encodes a field picture, consisting of top and bottom field
 ************************************************************************
 */
static void field_picture (Picture *top, Picture *bottom)
{
  //Rate control
  int old_pic_type;              // picture type of top field used for rate control
  int TopFieldBits;
  img->SumFrameQP = 0;
  //set mv limits to field type
  update_mv_limits(img, TRUE);

  //Rate control
  old_pic_type = img->type;

  img->number *= 2;
  img->buf_cycle *= 2;
  img->height    = (params->output.height + img->auto_crop_bottom) / 2;
  img->height_cr = img->height_cr_frame / 2;
  img->fld_flag  = TRUE;
  img->PicSizeInMbs = img->FrameSizeInMbs/2;
  // Top field

  enc_field_picture[0]              = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
  enc_field_picture[0]->poc         = img->toppoc;
  enc_field_picture[0]->frame_poc   = img->toppoc;
  enc_field_picture[0]->pic_num     = img->frame_num;
  enc_field_picture[0]->frame_num   = img->frame_num;
  enc_field_picture[0]->coded_frame = 0;
  enc_field_picture[0]->MbaffFrameFlag = img->MbaffFrameFlag = FALSE;
  get_mb_block_pos = get_mb_block_pos_normal;
  getNeighbour = getNonAffNeighbour;
  img->ThisPOC = img->toppoc;

  img->structure = TOP_FIELD;
  enc_picture = enc_field_picture[0];
  copy_params(enc_picture, active_sps);

  put_buffer_top (img);
  init_field (img);
  if (img->type == B_SLICE)       //all I- and P-frames
    nextP_tr_fld--;


  img->fld_flag = TRUE;

  //Rate control
  if(params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE)
    rc_init_top_field();

  code_a_picture(field_pic[0]);
  enc_picture->structure = TOP_FIELD;

  store_picture_in_dpb(enc_field_picture[0]);

  calc_picture_bits(top);

  //Rate control
  TopFieldBits=top->bits_per_picture;

  //  Bottom field
  enc_field_picture[1]  = alloc_storable_picture ((PictureStructure) img->structure, img->width, img->height, img->width_cr, img->height_cr);
  enc_field_picture[1]->poc=img->bottompoc;
  enc_field_picture[1]->frame_poc = img->bottompoc;
  enc_field_picture[1]->pic_num = img->frame_num;
  enc_field_picture[1]->frame_num = img->frame_num;
  enc_field_picture[1]->coded_frame = 0;
  enc_field_picture[1]->MbaffFrameFlag = img->MbaffFrameFlag = FALSE;
  get_mb_block_pos = get_mb_block_pos_normal;
  getNeighbour = getNonAffNeighbour;

  img->ThisPOC = img->bottompoc;
  img->structure = BOTTOM_FIELD;
  enc_picture = enc_field_picture[1];
  copy_params(enc_picture, active_sps);
  put_buffer_bot (img);
  img->number++;

  init_field (img);

  if (img->type == B_SLICE)       //all I- and P-frames
    nextP_tr_fld++;             //check once coding B field

 if (img->type == I_SLICE && params->IntraBottom!=1)
   set_slice_type((params->BRefPictures == 2) ? B_SLICE : P_SLICE);

  img->fld_flag = TRUE;

  //Rate control
  if(params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE)
    rc_init_bottom_field( TopFieldBits );

  enc_picture->structure = BOTTOM_FIELD;
  code_a_picture(field_pic[1]);

  calc_picture_bits(bottom);

  // the distortion for a field coded frame (consisting of top and bottom field)
  // lives in the top->distortion variables, the bottom-> are dummies
  distortion_fld (top);
}

/*!
 ************************************************************************
 * \brief
 *    form frame picture from two field pictures
 ************************************************************************
 */
static void combine_field(void)
{
  int i, k;

  for (i = 0; i < (img->height >> 1); i++)
  {
    memcpy(imgY_com[i*2],     enc_field_picture[0]->imgY[i], img->width*sizeof(imgpel));     // top field
    memcpy(imgY_com[i*2 + 1], enc_field_picture[1]->imgY[i], img->width*sizeof(imgpel)); // bottom field
  }

  if (img->yuv_format != YUV400)
  {
    for (k = 0; k < 2; k++)
    {
      for (i = 0; i < (img->height_cr >> 1); i++)
      {
        memcpy(imgUV_com[k][i*2],     enc_field_picture[0]->imgUV[k][i], img->width_cr*sizeof(imgpel));
        memcpy(imgUV_com[k][i*2 + 1], enc_field_picture[1]->imgUV[k][i], img->width_cr*sizeof(imgpel));
      }
    }
  }
}

/*!
 ************************************************************************
 * \brief
 *    Distortion Field
 ************************************************************************
 */
static void distortion_fld (Picture *field_pic)
{

  img->number /= 2;
  img->buf_cycle /= 2;
  img->height    = (params->output.height + img->auto_crop_bottom);
  img->height_cr = img->height_cr_frame;

  combine_field ();

  pCurImg   = img_org_frm[0];
  pImgOrg[0] = img_org_frm[0];

  if (params->yuv_format != YUV400)
  {
    pImgOrg[1] = img_org_frm[1];
    pImgOrg[2] = img_org_frm[2];
  }

  find_distortion ();   // find snr from original frame picture
  field_pic->distortion = dist->metric[SSE];
}


/*!
 ************************************************************************
 * \brief
 *    RD decision of frame and field coding
 ************************************************************************
 */
static byte decide_fld_frame(float snr_frame_Y, float snr_field_Y, int bit_field, int bit_frame, double lambda_picture)
{
  double cost_frame, cost_field;

  cost_frame = bit_frame * lambda_picture + snr_frame_Y;
  cost_field = bit_field * lambda_picture + snr_field_Y;

  if (cost_field > cost_frame)
    return FALSE;
  else
    return TRUE;
}

/*!
 ************************************************************************
 * \brief
 *    Picture Structure Decision
 ************************************************************************
 */
static byte picture_structure_decision (Picture *frame, Picture *top, Picture *bot)
{
  double lambda_picture;
  int bframe = (img->type == B_SLICE);
  float sse_frame, sse_field;
  int bit_frame, bit_field;

  lambda_picture = 0.68 * pow (2, img->bitdepth_lambda_scale + ((img->qp - SHIFT_QP) / 3.0)) * (bframe ? 1 : 1);

  sse_frame = frame->distortion.value[0] + frame->distortion.value[1] + frame->distortion.value[2];
  //! all distrortions of a field picture are accumulated in the top field
  sse_field = top->distortion.value[0] + top->distortion.value[1] + top->distortion.value[2];

  bit_field = top->bits_per_picture + bot->bits_per_picture;
  bit_frame = frame->bits_per_picture;
  return decide_fld_frame (sse_frame, sse_field, bit_field, bit_frame, lambda_picture);
}


/*!
 ************************************************************************
 * \brief
 *    Field Mode Buffer
 ************************************************************************
 */
static void field_mode_buffer (ImageParameters *img, InputParameters *params)
{
  put_buffer_frame (img);
}


/*!
 ************************************************************************
 * \brief
 *    Frame Mode Buffer
 ************************************************************************
 */
static void frame_mode_buffer (ImageParameters *img, InputParameters *params)
{
  put_buffer_frame (img);

  if ((params->PicInterlace != FRAME_CODING)||(params->MbInterlace != FRAME_CODING))
  {
    img->height = img->height / 2;
    img->height_cr = img->height_cr / 2;
    img->number *= 2;

    put_buffer_top (img);

    img->number++;
    put_buffer_bot (img);

    img->number /= 2;         // reset the img->number to field
    img->height = (params->output.height + img->auto_crop_bottom);
    img->height_cr = img->height_cr_frame;

    put_buffer_frame (img);
  }
}


/*!
 ************************************************************************

⌨️ 快捷键说明

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