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

📄 image.c

📁 包含了从MPEG4的视频解码到H.264的视频编码部分的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
***********************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2001, International Telecommunications Union, Geneva
*
* DISCLAIMER OF WARRANTY
*
* These software programs are available to the user without any
* license fee or royalty on an "as is" basis. The ITU disclaims
* any and all warranties, whether express, implied, or
* statutory, including any implied warranties of merchantability
* or of fitness for a particular purpose.  In no event shall the
* contributor or the ITU be liable for any incidental, punitive, or
* consequential damages of any kind whatsoever arising from the
* use of these programs.
*
* This disclaimer of warranty extends to the user of these programs
* and user's customers, employees, agents, transferees, successors,
* and assigns.
*
* The ITU does not represent or warrant that the programs furnished
* hereunder are free of infringement of any third-party patents.
* Commercial implementations of ITU-T Recommendations, including
* shareware, may be subject to royalty fees to patent holders.
* Information regarding the ITU-T patent policy is available from
* the ITU Web site at http://www.itu.int.
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE ITU-T PATENT POLICY.
************************************************************************
*/

/*!
 *************************************************************************************
 * \file image.c
 *
 * \brief
 *    Code one image/slice
 *
 * \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>
 *     - 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                   <heising@hhi.de>
 *     - Thomas Wedi                     <wedi@tnt.uni-hannover.de>
 *     - Ragip Kurceren                  <ragip.kurceren@nokia.com>
 *     - Antti Hallapuro                 <antti.hallapuro@nokia.com>
 *************************************************************************************
 */
#include "contributors.h"

#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/timeb.h>
#include <string.h>
#include <memory.h>
#include <assert.h>

#include "global.h"
#include "image.h"
#include "refbuf.h"
#include "mbuffer.h"
#include "encodeiff.h"
#include "header.h"
#include "intrarefresh.h"
#include "fmo.h"
#include "sei.h"
#include "memalloc.h"
#include "nalu.h"

#define TO_SAVE 4711
#define FROM_SAVE 4712
static void copy_mv_to_or_from_save (int direction);

static void code_a_picture(Picture *pic);
static void frame_picture (Picture *frame);
static void field_picture(Picture *top, Picture *bottom);

static void write_reconstructed_image();
static int  writeout_picture(Picture *pic);

static int  picture_structure_decision(Picture *frame, Picture *top, Picture *bot);
static void distortion_fld (float *dis_fld_y, float *dis_fld_u, float *dis_fld_v);
static void find_snr();
static void find_distortion();

static void field_mode_buffer(int bit_field, float snr_field_y, float snr_field_u, float snr_field_v);
static void frame_mode_buffer (int bit_frame, float snr_frame_y, float snr_frame_u, float snr_frame_v);

static void init_frame();
static void init_field();

static void put_buffer_frame();
static void put_buffer_top();
static void put_buffer_bot();

static void interpolate_frame();
static void interpolate_frame_to_fb();

static void estimate_weighting_factor ();

static void rotate_buffer();
static void store_field_MV(int frame_number);
static void store_direct_moving_flag (int frame_number);
static void copy_motion_vectors_MB(int bot_block); //!< For MB level field/frame coding tools

static void CopyFrameToOldImgOrgVariables (Sourceframe *sf);
static void CopyTopFieldToOldImgOrgVariables (Sourceframe *sf);
static void CopyBottomFieldToOldImgOrgVariables (Sourceframe *sf);
static Sourceframe *AllocSourceframe (int xs, int ys);
static void FreeSourceframe (Sourceframe *sf);
static void ReadOneFrame (int FrameNoInFile, int HeaderSize, int xs, int ys, Sourceframe *sf);
static void writeUnit(Bitstream* currStream);



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

static void UnifiedOneForthPix (pel_t ** imgY, pel_t ** imgU, pel_t ** imgV,
                                pel_t ** out4Y, pel_t ** outU, pel_t ** outV,
                                pel_t ** ref11);
static void ReportFirstframe(int tmp_time);
static void ReportIntra(int tmp_time);
static void ReportSP(int tmp_time);
static void ReportBS(int tmp_time);
static void ReportP(int tmp_time);
static void ReportB(int tmp_time);

static int CalculateFrameNumber();  // Calculates the next frame number
static int FrameNumberInFile;       // The current frame number in the input file

static Sourceframe *srcframe;

const int ONE_FOURTH_TAP[3][2] =
{
  {20,20},
  {-5,-4},
  { 1, 0},
};


/*!
 ************************************************************************
 * \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 NumberOfCodedMBs = 0;
  int SliceGroup = 0;
  int j;

  img->currentPicture = pic;

  pic->no_slices = 0;
  pic->distortion_u = pic->distortion_v = pic->distortion_y = 0.0;

  RandomIntraNewPicture ();     //! Allocates forced INTRA MBs (even for fields!)
  FmoStartPicture ();           //! picture level initialization of FMO
  while (NumberOfCodedMBs < img->total_number_mb)       // loop over slices
    {
      // Encode one SLice Group
      while (!FmoSliceGroupCompletelyCoded (SliceGroup))
        {
          // Encode the current slice
          NumberOfCodedMBs += encode_one_slice (SliceGroup, pic);
          FmoSetLastMacroblockInSlice (img->current_mb_nr);
          // Proceed to next slice
          img->current_slice_nr++;
          stat->bit_slice = 0;
        }
      // Proceed to next SliceGroup
      SliceGroup++;
    }
  FmoEndPicture ();
  if (input->rdopt == 2 && (img->type != B_IMG))
    for (j = 0; j < input->NoOfDecoders; j++)
      DeblockFrame (img, decs->decY_best[j], NULL);
  DeblockFrame (img, imgY, imgUV);
}



/*!
 ************************************************************************
 * \brief
 *    Encodes one frame
 ************************************************************************
 */
int encode_one_frame ()
{
  static int prev_frame_no = 0; // POC200301
  static int consecutive_non_reference_pictures = 0; // POC200301
#ifdef _LEAKYBUCKET_
  extern long Bit_Buffer[10000];
  extern unsigned long total_frame_buffer;
#endif
//  Bitstream *tmp_bitstream;

//  int i, j;

  time_t ltime1;
  time_t ltime2;

#ifdef WIN32
  struct _timeb tstruct1;
  struct _timeb tstruct2;
#else
  struct timeb tstruct1;
  struct timeb tstruct2;
#endif

  int tmp_time;
  int bits_frm = 0, bits_fld = 0;
  float dis_frm = 0, dis_frm_y = 0, dis_frm_u = 0, dis_frm_v = 0;
  float dis_fld = 0, dis_fld_y = 0, dis_fld_u = 0, dis_fld_v = 0;


#ifdef WIN32
  _ftime (&tstruct1);           // start time ms
#else
  ftime (&tstruct1);
#endif
  time (&ltime1);               // start time s

/*
  //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 ();
*/

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

  srcframe = AllocSourceframe (img->width, img->height);
  ReadOneFrame (FrameNumberInFile, input->infile_header, img->width, img->height, srcframe);

  if (img->type == B_IMG)
    Bframe_ctr++;         // Bframe_ctr only used for statistics, should go to stat->

  if (input->InterlaceCodingOption == FIELD_CODING)
  {
    CopyFrameToOldImgOrgVariables (srcframe);
    img->field_picture = 1;  // we encode fields
    field_picture (top_pic, bottom_pic);
    img->fld_flag = 1;
  }
  else
  {
    // For frame coding, turn MB level field/frame coding flag on
    if (input->InterlaceCodingOption >= MB_CODING)
      mb_adaptive = 1;
    img->field_picture = 0; // we encode a frame
    frame_picture (frame_pic);
    // For field coding, turn MB level field/frame coding flag off
    if (input->InterlaceCodingOption >= MB_CODING)
      mb_adaptive = 0;
    
    if (input->InterlaceCodingOption != FRAME_CODING)
    {
      img->field_picture = 1;  // we encode fields
      field_picture (top_pic, bottom_pic);
      
      //! Note: the distortion for a field coded picture is stored in the top field
      //! the distortion values in the bottom field are dummies
      dis_fld = top_pic->distortion_y + top_pic->distortion_u + top_pic->distortion_v;
      dis_frm = frame_pic->distortion_y + frame_pic->distortion_u + frame_pic->distortion_v;
      
      img->fld_flag = picture_structure_decision (frame_pic, top_pic, bottom_pic);

      update_field_frame_contexts (img->fld_flag);
    }
    else
      img->fld_flag = 0;
  }

  if (img->fld_flag)
    stat->bit_ctr_emulationprevention += stat->em_prev_bits_fld;
  else
    stat->bit_ctr_emulationprevention += stat->em_prev_bits_frm;

  if (img->type != B_IMG)
  {
    img->pstruct_next_P = img->fld_flag;
  }

  // Here, img->pstruct 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 (bits_fld, dis_fld_y, dis_fld_u, dis_fld_v);
    writeout_picture (top_pic);
    writeout_picture (bottom_pic);
  }
  else                          //frame mode
  {
    frame_mode_buffer (bits_frm, dis_frm_y, dis_frm_u, dis_frm_v);
    writeout_picture (frame_pic);
  }

  if (frame_pic)
    free_slice_list(frame_pic);
  if (top_pic)
    free_slice_list(top_pic);
  if (bottom_pic)
    free_slice_list(bottom_pic);

  /*
  // 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 (input->InterlaceCodingOption == FRAME_CODING
      && input->SparePictureOption && img->type != B_IMG)
    CalculateSparePicture ();
*/

  if (input->InterlaceCodingOption != FRAME_CODING)
    {
      store_field_MV (IMG_NUMBER);      // assume that img->number = frame_number
    }
  else
    store_direct_moving_flag (IMG_NUMBER);

  if (input->InterlaceCodingOption >= MB_CODING && img->number != 0 && input->successive_Bframe != 0 && img->type != B_IMG)
  {
    copy_mv_to_or_from_save (FROM_SAVE);
  }
  if (input->InterlaceCodingOption == FRAME_CODING)
    {
      if (input->rdopt == 2 && img->type != B_IMG)
        UpdateDecoders ();      // simulate packet losses and move decoded image to reference buffers

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

  find_snr ();

  time (&ltime2);               // end time sec
#ifdef WIN32
  _ftime (&tstruct2);           // end time ms
#else
  ftime (&tstruct2);            // end time ms
#endif

  tmp_time = (ltime2 * 1000 + tstruct2.millitm) - (ltime1 * 1000 + tstruct1.millitm);
  tot_time = tot_time + tmp_time;

  // Write reconstructed images
  write_reconstructed_image ();

#ifdef _LEAKYBUCKET_
  // Store bits used for this frame and increment counter of no. of coded frames
  Bit_Buffer[total_frame_buffer] = stat->bit_ctr - stat->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->disposable_flag) 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;
  }

  if (IMG_NUMBER == 0)
    ReportFirstframe(tmp_time);
  else
  {
    switch (img->type)
    {
    case INTRA_IMG:
      stat->bit_ctr_P += stat->bit_ctr - stat->bit_ctr_n;
      ReportIntra(tmp_time);
      break;
    case SP_IMG:
      stat->bit_ctr_P += stat->bit_ctr - stat->bit_ctr_n;
      ReportSP(tmp_time);
      break;
    case BS_IMG:
      stat->bit_ctr_P += stat->bit_ctr - stat->bit_ctr_n;
      ReportBS(tmp_time);
      break;
    case B_IMG:
      stat->bit_ctr_B += stat->bit_ctr - stat->bit_ctr_n;
      ReportB(tmp_time);
      break;
    default:      // P, P_MULTPRED?
      stat->bit_ctr_P += stat->bit_ctr - stat->bit_ctr_n;
      ReportP(tmp_time);
    }
  }
  stat->bit_ctr_n = stat->bit_ctr;

  FreeSourceframe (srcframe);

  if (IMG_NUMBER == 0)
    return 0;
  else
    return 1;
}


/*!
 ************************************************************************
 * \brief
 *    This function write out a picture
 * \return
 *    0 if OK,                                                         \n
 *    1 in case of error
 *
 ************************************************************************
 */
static int writeout_picture(Picture *pic)
{
  Bitstream *currStream;
  int partition, slice;
  Slice *currSlice;

  for (slice=0; slice<pic->no_slices; slice++)
  {
    currSlice = pic->slices[slice];
    for (partition=0; partition<currSlice->max_part_nr; partition++)
    {
      currStream = (currSlice->partArr[partition]).bitstream;
      assert (currStream->bits_to_go == 8);    //! should always be the case, the 
                                              //! byte alignment is done in terminate_slice
      writeUnit (currSlice->partArr[partition].bitstream);

    }           // partition loop
  }           // slice loop
  return 0;   
}


/*!
 ************************************************************************
 * \brief
 *    Encodes a frame picture
 ************************************************************************
 */
static void frame_picture (Picture *frame)
{
//  int i;

  // if more than one B pictures, they will overwrite refFrArr_top, refFrArr_bot
  if (input->InterlaceCodingOption != FRAME_CODING && mb_adaptive && img->type == B_IMG)
  {
    copy_mv_to_or_from_save (TO_SAVE);
  }

  stat->em_prev_bits_frm = 0;
  stat->em_prev_bits = &stat->em_prev_bits_frm;

  // Initialize frame with all stat and img variables
//  img->total_number_mb =
//    (img->width * img->height) / (MB_BLOCK_SIZE * MB_BLOCK_SIZE);
//  init_frame ();

  init_mref ();
  init_Refbuf (img);
  copy_mref (img);


  CopyFrameToOldImgOrgVariables (srcframe);

  if (input->InterlaceCodingOption >= MB_CODING && mb_adaptive)
  {
    CopyTopFieldToOldImgOrgVariables (srcframe);
    CopyBottomFieldToOldImgOrgVariables (srcframe);
  }

  if (img->type != INTRA_IMG && (input->WeightedPrediction == 1 || (input->WeightedBiprediction > 0 && (img->type == B_IMG || img->type == BS_IMG))))
  {
    estimate_weighting_factor ();

⌨️ 快捷键说明

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