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

📄 mbuffer.cpp

📁 h264编解码.用C++实现了图像的编解码功能。
💻 CPP
📖 第 1 页 / 共 3 页
字号:

/*!
 ***********************************************************************
 *  \file
 *      mbuffer.c
 *
 *  \brief
 *      Frame buffer functions
 *
 *  \author
 *      Main contributors (see contributors.h for copyright, address and affiliation details)
 *      - Karsten Suehring          <suehring@hhi.de>
 *      - Alexis Tourapis                 <alexismt@ieee.org>
 ***********************************************************************
 */

#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <string.h>

#include "global.h"
#include "mbuffer.h"
#include "memalloc.h"
#include "output.h"
#include "image.h"

static void insert_picture_in_dpb(FrameStore* fs, StorablePicture* p);
static void output_one_frame_from_dpb();
static int  is_used_for_reference(FrameStore* fs);
static void get_smallest_poc(int *poc,int * pos);
static int  remove_unused_frame_from_dpb();
static int  is_short_term_reference(FrameStore* fs);
static int  is_long_term_reference(FrameStore* fs);

DecodedPictureBuffer dpb;

StorablePicture **listX[2];

extern StorablePicture *dec_picture;
extern int dpb_size;
extern FILE *p_out;
extern seq_parameter_set_rbsp_t *active_sps;

int listXsize[2];

/*!
 ************************************************************************
 * \brief
 *    Allocate memory for decoded picture buffer an initialize with sane values.
 *
 * \param inp
 *    Input Parameters
 *
 ************************************************************************
 */
void init_dpb()
{
  unsigned i,j;

  dpb.size      = dpb_size;
  dpb.used_size = 0;
  dpb.ref_frames_in_buffer = 0;

  dpb.fs =(struct frame_store **) calloc(dpb.size, sizeof (FrameStore*));
  if (NULL==dpb.fs) 
	  error ("init_dpb: Could not allocate dpb->fs memory", 100);

  dpb.fs_ref =(struct frame_store **) calloc(dpb.size, sizeof (FrameStore*));
  if (NULL==dpb.fs_ref) 	  
	  error ("init_dpb: Could not allocate dpb->fs_ref memory", 100);

  dpb.fs_ltref =(struct frame_store **) calloc(dpb.size, sizeof (FrameStore*));
  if (NULL==dpb.fs_ltref) 	  
	  error ("init_dpb: Could not allocate dpb->fs_ltref memory", 100);

  for (i=0; i<dpb.size; i++)
  {
    dpb.fs[i]       = alloc_frame_store();
    dpb.fs_ref[i]   = NULL;
    dpb.fs_ltref[i] = NULL;
  }
  
  for (i=0; i<2; i++)
  {
    listX[i] =(struct storable_picture **) calloc(dpb.size * 2 + 1, sizeof (StorablePicture*)); // +1 for reordering
    if (NULL==listX[i]) 
	  error ("init_dpb: Could not allocate listX[i] memory", 100);
  }

  for (j=0;j<2;j++)
  {
    for (i=0; i<(2*dpb.size)+1; i++)
    {
      listX[j][i] = NULL;
    }
    listXsize[j]=0;
  }

  dpb.last_output_poc = INT_MIN;

  img->last_has_mmco_5 = 0;
}


/*!
 ************************************************************************
 * \brief
 *    Free memory for decoded picture buffer.
 ************************************************************************
 */
void free_dpb()
{
  unsigned i;
  if (dpb.fs)
  {
    for (i=0; i<dpb.size; i++)
    {
      free_frame_store(dpb.fs[i]);
    }
    free (dpb.fs);
    dpb.fs=NULL;
  }
  if (dpb.fs_ref)
  {
    free (dpb.fs_ref);
  }
  if (dpb.fs_ltref)
  {
    free (dpb.fs_ltref);
  }
  dpb.last_output_poc = INT_MIN;

  for (i=0; i<2; i++)
    if (listX[i])
    {
      free (listX[i]);
      listX[i] = NULL;
    }
}


/*!
 ************************************************************************
 * \brief
 *    Allocate memory for decoded picture buffer frame stores an initialize with sane values.
 *
 * \return
 *    the allocated FrameStore structure
 ************************************************************************
 */
FrameStore* alloc_frame_store()
{
  FrameStore *f;

  f =(struct frame_store *) calloc (1, sizeof(FrameStore));
  if (NULL==f) 
	  error ("alloc_frame_store: Could not allocate f memory", 100);

  f->is_used      = 0;
  f->is_reference = 0;
  f->is_long_term = 0;

  f->is_output = 0;

  f->frame        = NULL;
  return f;
}

/*!
 ************************************************************************
 * \brief
 *    Allocate memory for a stored picture. 
 *
 * \param structure
 *    picture structure
 * \param size_x
 *    horizontal luma size
 * \param size_y
 *    vertical luma size
 * \param size_x_cr
 *    horizontal chroma size
 * \param size_y_cr
 *    vertical chroma size
 *
 * \return
 *    the allocated StorablePicture structure
 ************************************************************************
 */
StorablePicture* alloc_storable_picture(/*PictureStructure structure,*/ int size_x, int size_y, int size_x_cr, int size_y_cr)
{
  StorablePicture *s;
  int sizeX,sizeY;
  sizeX = size_x >>2;
  sizeY = size_y >>2;

  s =(struct storable_picture *) calloc (1, sizeof(StorablePicture));
  if (NULL==s) 
	  error ("alloc_storable_picture: Could not allocate s memory", 100);

  get_mem2D (&(s->imgY), size_y, size_x);
  get_mem3D (&(s->imgUV), 2, size_y_cr, size_x_cr );

  get_mem3Dint (&(s->ref_idx), 2, sizeX, sizeY);
  get_mem3Dint64 (&(s->ref_pic_id), 2, sizeX, sizeY);
  get_mem4Dint (&(s->mv), 2, sizeX, sizeY,2 );

  get_mem2D (&(s->moving_block), sizeX, sizeY);

  s->pic_num=0;
  s->long_term_frame_idx=0;
  s->long_term_pic_num=0;
  s->used_for_reference=0;
  s->is_long_term=0;
  s->is_output = 0;

  s->size_x = size_x;
  s->size_y = size_y;
  s->size_x_cr = size_x_cr;
  s->size_y_cr = size_y_cr;
  
  s->frame        = NULL;

  s->mb_adaptive_frame_field_flag  = 0;

  return s;
}

/*!
 ************************************************************************
 * \brief
 *    Free frame store memory.
 *
 * \param f
 *    FrameStore to be freed
 *
 ************************************************************************
 */
void free_frame_store(FrameStore* f)
{
  if (f)
  {
    free_storable_picture(f->frame);
    f->frame=NULL;
    free(f);
  }
}

/*!
 ************************************************************************
 * \brief
 *    Free picture memory.
 *
 * \param p
 *    Picture to be freed
 *
 ************************************************************************
 */
void free_storable_picture(StorablePicture* p)
{
  if (p)
  {
    free_mem3Dint   (p->ref_idx, 2);
    free_mem3Dint64 (p->ref_pic_id, 2);
    free_mem4Dint   (p->mv, 2, p->size_x >>2);

    if (p->moving_block)
    {
      free_mem2D (p->moving_block);
      p->moving_block=NULL;
    }
    
    if (p->imgY)
    {
      free_mem2D (p->imgY);
      p->imgY=NULL;
    }
    if (p->imgUV)
    {
      free_mem3D (p->imgUV, 2);
      p->imgUV=NULL;
    }
    free(p);
  }
}

/*!
 ************************************************************************
 * \brief
 *    mark FrameStore unused for reference
 *
 ************************************************************************
 */
static void unmark_for_reference(FrameStore* fs)
{
  fs->frame->used_for_reference = 0;
  fs->is_reference = 0;
}


/*!
 ************************************************************************
 * \brief
 *    mark FrameStore unused for reference and reset long term flags
 *
 ************************************************************************
 */
static void unmark_for_long_term_reference(FrameStore* fs)
{

  fs->frame->used_for_reference = 0;
  fs->frame->is_long_term = 0;

  fs->is_reference = 0;
  fs->is_long_term = 0;
}


/*!
 ************************************************************************
 * \brief
 *    compares two stored pictures by picture number for qsort in descending order
 *
 ************************************************************************
 */
static int compare_pic_by_pic_num_desc( const void *arg1, const void *arg2 )
{
  if ( (*(StorablePicture**)arg1)->pic_num < (*(StorablePicture**)arg2)->pic_num)
    return 1;
  if ( (*(StorablePicture**)arg1)->pic_num > (*(StorablePicture**)arg2)->pic_num)
    return -1;
  else
    return 0;
}

/*!
 ************************************************************************
 * \brief
 *    compares two stored pictures by picture number for qsort in descending order
 *
 ************************************************************************
 */
static int compare_pic_by_lt_pic_num_asc( const void *arg1, const void *arg2 )
{
  if ( (*(StorablePicture**)arg1)->long_term_pic_num < (*(StorablePicture**)arg2)->long_term_pic_num)
    return -1;
  if ( (*(StorablePicture**)arg1)->long_term_pic_num > (*(StorablePicture**)arg2)->long_term_pic_num)
    return 1;
  else
    return 0;
}

/*!
 ************************************************************************
 * \brief
 *    Initialize listX[0] and list 1 depending on current picture type
 *
 ************************************************************************
 */
void init_lists(int currSliceType)
{
  unsigned i;
  int j;
  int MaxFrameNum = 1 << (active_sps->log2_max_frame_num_minus4 + 4);
  int diff;

  int list0idx = 0;

  StorablePicture *tmp_s;

  for (i=0; i<dpb.ref_frames_in_buffer; i++)
  {
    if (dpb.fs_ref[i]->is_used==3)
    {
      if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
      {
        if( dpb.fs_ref[i]->frame_num > img->frame_num )
        {
          dpb.fs_ref[i]->frame_num_wrap = dpb.fs_ref[i]->frame_num - MaxFrameNum;
        }
        else
        {
          dpb.fs_ref[i]->frame_num_wrap = dpb.fs_ref[i]->frame_num;
        }
        dpb.fs_ref[i]->frame->pic_num = dpb.fs_ref[i]->frame_num_wrap;
        dpb.fs_ref[i]->frame->order_num=list0idx;
      }
    }
  }

  if (currSliceType == I_SLICE)
  {
    listXsize[0] = 0;
    listXsize[1] = 0;
    return;
  }

  else if (currSliceType == P_SLICE)
  {
    // Calculate FrameNumWrap and PicNum
    for (i=0; i<dpb.ref_frames_in_buffer; i++)
    {
      if (dpb.fs_ref[i]->is_used==3)
      {
        if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
        {
          listX[0][list0idx++] = dpb.fs_ref[i]->frame;
        }
      }
    }
      // order list 0 by PicNum
    qsort((void *)listX[0], list0idx, sizeof(StorablePicture*), compare_pic_by_pic_num_desc);
    listXsize[0] = list0idx;

    // long term handling
    for (i=0; i<dpb.ltref_frames_in_buffer; i++)
    {
      if (dpb.fs_ltref[i]->is_used==3)
      {
        // if we have two fields, both must be long-term
        dpb.fs_ltref[i]->frame->long_term_pic_num = dpb.fs_ltref[i]->frame->long_term_frame_idx;
        dpb.fs_ltref[i]->frame->order_num=list0idx;
        listX[0][list0idx++]=dpb.fs_ltref[i]->frame;
      }
    }
    qsort((void *)&listX[0][listXsize[0]], list0idx-listXsize[0], sizeof(StorablePicture*), compare_pic_by_lt_pic_num_asc);
    listXsize[0] = list0idx;
   
    listXsize[1] = 0;
  }

  if ((listXsize[0] == listXsize[1]) && (listXsize[0] > 1))
  {
    // check if lists are identical, if yes swap first two elements of listX[1]
    diff=0;
    for (j = 0; j< listXsize[0]; j++)
    {
      if (listX[0][j]!=listX[1][j])
        diff=1;
    }
    if (!diff)
    {
      tmp_s = listX[1][0];
      listX[1][0]=listX[1][1];
      listX[1][1]=tmp_s;
    }
  }
  // set max size
  listXsize[0] = min (listXsize[0], img->num_ref_idx_l0_active);

  // set the unused list entries to NULL
  for (i=listXsize[0]; i< (2*dpb.size) ; i++)
  {
    listX[0][i] = NULL;
  }
}
 /*!
 ************************************************************************
 * \brief
 *    Returns short term pic with given picNum
 *
 ************************************************************************
 */
static StorablePicture*  get_short_term_pic(int picNum)
{
  unsigned i;

  for (i=0; i<dpb.ref_frames_in_buffer; i++)
  {
    if (dpb.fs_ref[i]->is_reference == 3)
      if ((!dpb.fs_ref[i]->frame->is_long_term)&&(dpb.fs_ref[i]->frame->pic_num == picNum))
        return dpb.fs_ref[i]->frame;
  }
  return NULL;
}

/*!
 ************************************************************************
 * \brief
 *    Returns short term pic with given LongtermPicNum
 *
 ************************************************************************
 */
static StorablePicture*  get_long_term_pic(int LongtermPicNum)
{

⌨️ 快捷键说明

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