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

📄 image.c

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

  dist->frame_ctr++;

  if(img->type == SP_SLICE)
  {
    if(params->sp2_frame_indicator)
    { // switching SP frame encoding
      sp2_frame_indicator=1;
      read_SP_coefficients();
    }
  }
  else
  {
    sp2_frame_indicator=0;
  }
  if ( params->WPMCPrecision )
  {
    wpxInitWPXPasses(params);
    pWPX->curr_wp_rd_pass = pWPX->wp_rd_passes;
    pWPX->curr_wp_rd_pass->algorithm = WP_REGULAR;
  }


  if (params->PicInterlace == FIELD_CODING)
  {
    //Rate control
    if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
      generic_RC->FieldControl = 1;

    img->field_picture = 1;  // we encode fields
    field_picture (field_pic[0], field_pic[1]);
    img->fld_flag = TRUE;
  }
  else
  {
    int tmpFrameQP;
    //Rate control
    if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
      generic_RC->FieldControl = 0;

    img->field_picture = 0; // we encode a frame

    //Rate control
    if(params->RCEnable)
      rc_init_frame(FrameNumberInFile);

    if (params->GenerateMultiplePPS)
      active_pps = PicParSet[0];

    frame_picture (frame_pic[0], 0);

    if ((params->RDPictureIntra || img->type!=I_SLICE) && params->RDPictureDecision)
    {
      rdPictureCoding();
    }

    tmpFrameQP = img->SumFrameQP; // call it here since rdPictureCoding buffers it and may modify it

    if ((img->type==SP_SLICE) && (si_frame_indicator==0) && (params->si_frame_indicator))
    {
      // once the picture has been encoded as a primary SP frame encode as an SI frame
      si_frame_indicator=1;
      frame_picture (frame_pic_si, 0);
    }
    if ((img->type == SP_SLICE) && (params->sp_output_indicator))
    {
      // output the transformed and quantized coefficients (useful for switching SP frames)
      output_SP_coefficients();
    }

    if (params->PicInterlace == ADAPTIVE_CODING)
    {
      //Rate control
      if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
        generic_RC->FieldControl=1;
      img->write_macroblock = FALSE;
      img->bot_MB = FALSE;

      img->field_picture = 1;  // we encode fields
      field_picture (field_pic[0], field_pic[1]);

      if(img->rd_pass == 0)
        img->fld_flag = picture_structure_decision (frame_pic[0], field_pic[0], field_pic[1]);
      else if(img->rd_pass == 1)
        img->fld_flag = picture_structure_decision (frame_pic[1], field_pic[0], field_pic[1]);
      else
        img->fld_flag = picture_structure_decision (frame_pic[2], field_pic[0], field_pic[1]);

      if ( img->fld_flag )
        tmpFrameQP = img->SumFrameQP;

      update_field_frame_contexts (img->fld_flag);

      //Rate control
      if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE )
        generic_RC->FieldFrame = !(img->fld_flag) ? 1 : 0;
    }
    else
      img->fld_flag = FALSE;

    img->SumFrameQP = tmpFrameQP;
  }

  stats->frame_counter++;
  stats->frame_ctr[img->type]++;


  // Here, img->structure may be either FRAME or BOTTOM FIELD depending on whether AFF coding is used
  // The picture structure decision changes really only the fld_flag

  if (img->fld_flag)            // field mode (use field when fld_flag=1 only)
  {
    field_mode_buffer (img, params);
    writeout_picture (field_pic[0]);
    writeout_picture (field_pic[1]);
  }
  else                          //frame mode
  {
    frame_mode_buffer (img, params);

    if (img->type==SP_SLICE && si_frame_indicator == 1)
    {
      writeout_picture (frame_pic_si);
      si_frame_indicator=0;
    }
    else
    {
      writeout_picture (frame_pic[img->rd_pass]);
    }
  }

  if (frame_pic_si)
  {
    free_slice_list(frame_pic_si);
  }

  for (i = 0; i < img->frm_iter; i++)
  {
    if (frame_pic[i])
    {
      free_slice_list(frame_pic[i]);
    }
  }

  if (field_pic)
  {
    for (i = 0; i < 2; i++)
    {
      if (field_pic[i])
        free_slice_list(field_pic[i]);
    }
  }

  /*
  // Tian Dong (Sept 2002)
  // in frame mode, the newly reconstructed frame has been inserted to the mem buffer
  // and it is time to prepare the spare picture SEI payload.
  if (params->InterlaceCodingOption == FRAME_CODING
  && params->SparePictureOption && img->type != B_SLICE)
  CalculateSparePicture ();
  */

  //Rate control
  if(params->RCEnable)
  {
    // we could add here a function pointer!
    bits = (int) (stats->bit_ctr - stats->bit_ctr_n);
    if ( params->RCUpdateMode <= MAX_RC_MODE )
      rc_update_pict_frame_ptr(quadratic_RC, bits);
  }

  if (params->PicInterlace == FRAME_CODING)
  {
    if ((params->rdopt == 3) && (img->nal_reference_idc != 0))
    {
      UpdateDecoders (params, img, enc_picture);      // simulate packet losses and move decoded image to reference buffers
    }

    if (params->RestrictRef)
      UpdatePixelMap ();
  }

  compute_distortion();

  // redundant pictures: save reconstruction to calculate SNR and replace reference picture

  if(params->redundant_pic_flag)
  {
    int k;
    if(key_frame)
    {
      for(j=0; j<img->height; j++)
      {
        memcpy(imgY_tmp[j], enc_frame_picture[0]->imgY[j], img->width * sizeof(imgpel));
      }

      for (k = 0; k < 2; k++)
      {
        for(j=0; j<img->height_cr; j++)
        {
          memcpy(imgUV_tmp[k][j], enc_frame_picture[0]->imgUV[k][j], img->width_cr * sizeof(imgpel));
        }
      }
    }

    if(redundant_coding)
    {
      for(j=0; j<img->height; j++)
      {
        memcpy(enc_frame_picture[0]->imgY[j], imgY_tmp[j], img->width * sizeof(imgpel));
      }
      for (k = 0; k < 2; k++)
      {
        for(j=0; j<img->height_cr; j++)
        {
          memcpy(enc_frame_picture[0]->imgUV[k][j], imgUV_tmp[k][j], img->width_cr * sizeof(imgpel));
        }
      }
    }
  }

 
  if (params->PicInterlace == ADAPTIVE_CODING)
  {
    if (img->fld_flag)
    {
      // store bottom field
      store_picture_in_dpb(enc_field_picture[1]);
      free_storable_picture(enc_frame_picture[0]);
      free_storable_picture(enc_frame_picture[1]);
      free_storable_picture(enc_frame_picture[2]);
      update_global_stats(&enc_field_picture[0]->stats);
      update_global_stats(&enc_field_picture[1]->stats);
    }
    else
    {
      // replace top with frame
      if (img->rd_pass==2)
      {
        replace_top_pic_with_frame(enc_frame_picture[2]);
        free_storable_picture(enc_frame_picture[0]);
        free_storable_picture(enc_frame_picture[1]);
      }
      else if (img->rd_pass==1)
      {
        replace_top_pic_with_frame(enc_frame_picture[1]);
        free_storable_picture(enc_frame_picture[0]);
        free_storable_picture(enc_frame_picture[2]);
      }
      else
      {
        if(params->redundant_pic_flag==0 || (key_frame==0))
        {
          replace_top_pic_with_frame(enc_frame_picture[0]);
          free_storable_picture(enc_frame_picture[1]);
          free_storable_picture(enc_frame_picture[2]);
        }
      }
      free_storable_picture(enc_field_picture[1]);
      update_global_stats(&enc_frame_picture[img->rd_pass]->stats);
    }
  }
  else
  {
    if (img->fld_flag)
    {
      store_picture_in_dpb(enc_field_picture[1]);
      update_global_stats(&enc_field_picture[0]->stats);
      update_global_stats(&enc_field_picture[1]->stats);
    }
    else
    {
      if ((params->redundant_pic_flag != 1) || (key_frame == 0))
      {
        store_picture_in_dpb (enc_frame_picture[img->rd_pass]);
        update_global_stats(&enc_frame_picture[img->rd_pass]->stats);
        free_pictures(img->rd_pass);
      }
    }
  }

  img->AverageFrameQP = isign(img->SumFrameQP) * ((iabs(img->SumFrameQP) + (int) (img->FrameSizeInMbs >> 1))/ (int) img->FrameSizeInMbs);

  if ( params->RCEnable && params->RCUpdateMode <= MAX_RC_MODE && img->type != B_SLICE && params->basicunit < img->FrameSizeInMbs )
    quadratic_RC->CurrLastQP = img->AverageFrameQP;

#ifdef _LEAKYBUCKET_
  // Store bits used for this frame and increment counter of no. of coded frames
  Bit_Buffer[total_frame_buffer] = (int) (stats->bit_ctr - stats->bit_ctr_n);
  total_frame_buffer++;
#endif

  // POC200301: Verify that POC coding type 2 is not used if more than one consecutive
  // non-reference frame is requested or if decoding order is different from output order
  if (img->pic_order_cnt_type == 2)
  {
    if (!img->nal_reference_idc) consecutive_non_reference_pictures++;
    else consecutive_non_reference_pictures = 0;

    if (frame_no < prev_frame_no || consecutive_non_reference_pictures>1)
      error("POC type 2 cannot be applied for the coding pattern where the encoding /decoding order of pictures are different from the output order.\n", -1);
    prev_frame_no = frame_no;
  }

  gettime(&end_time);    // end time in ms
  tmp_time  = timediff(&start_time, &end_time);
  tot_time += tmp_time;

  if (stats->bit_ctr_parametersets_n!=0)
    ReportNALNonVLCBits(tmp_time, me_time);

  if (img->frm_number == 0)
    ReportFirstframe(tmp_time,me_time);
  else
  {
    //Rate control
    if(params->RCEnable)
    {
      if ((!params->PicInterlace) && (!params->MbInterlace))
        bits = (int) (stats->bit_ctr - stats->bit_ctr_n);
      else if ( params->RCUpdateMode <= MAX_RC_MODE )
      {
        bits = (int)(stats->bit_ctr - (quadratic_RC->Pprev_bits)); // used for rate control update
        quadratic_RC->Pprev_bits = stats->bit_ctr;
      }
    }

    stats->bit_counter[img->type] += stats->bit_ctr - stats->bit_ctr_n;

    switch (img->type)
    {
    case I_SLICE:
    case SI_SLICE:
      ReportIntra(tmp_time,me_time);
      break;
    case SP_SLICE:
      ReportSP(tmp_time,me_time);
      break;
    case B_SLICE:
      ReportB(tmp_time,me_time);
      break;
    default:      // P
      ReportP(tmp_time,me_time);
    }
  }

  if (params->Verbose == 0)
  {
    //for (i = 0; i <= (img->number & 0x0F); i++)
    //printf(".");
    //printf("                              \r");
    printf("Completed Encoding Frame %05d.\r",frame_no);
  }
  // Flush output statistics
  fflush(stdout);

  //Rate control
  if(params->RCEnable)
    rc_update_picture_ptr( bits );
  stats->bit_ctr_n = stats->bit_ctr;

  stats->bit_ctr_parametersets_n = 0;

  if ( img->type == I_SLICE && img->nal_reference_idc)
  {
    //img->lastINTRA = frame_no;
    // Lets also handle the possibility of backward GOPs and hierarchical structures 
    if ( !(img->b_frame_to_code) )
    {
      img->lastINTRA       = imax(img->lastINTRA, frame_no);
      img->lastIntraNumber = img->frm_number;
    }
    if ( img->currentPicture->idr_flag )
    {
      img->lastIDRnumber = img->frm_number;
    }
  }

  return ((IMG_NUMBER == 0)? 0 : 1);
}


/*!
 ************************************************************************
 * \brief
 *    This function write out a picture
 * \return
 *    0 if OK,                                                         \n
 *    1 in case of error
 *

⌨️ 快捷键说明

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