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

📄 mbuffer.c

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

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

  for (i=0; i<dpb.ltref_frames_in_buffer; i++)
  {
    if (img->structure==FRAME)
    {
      if (dpb.fs_ltref[i]->is_reference == 3)
        if ((dpb.fs_ltref[i]->frame->is_long_term)&&(dpb.fs_ltref[i]->frame->long_term_pic_num == LongtermPicNum))
          return dpb.fs_ltref[i]->frame;
    }
    else
    {
      if (dpb.fs_ltref[i]->is_reference & 1)
        if ((dpb.fs_ltref[i]->top_field->is_long_term)&&(dpb.fs_ltref[i]->top_field->long_term_pic_num == LongtermPicNum))
          return dpb.fs_ltref[i]->top_field;
      if (dpb.fs_ltref[i]->is_reference & 2)
        if ((dpb.fs_ltref[i]->bottom_field->is_long_term)&&(dpb.fs_ltref[i]->bottom_field->long_term_pic_num == LongtermPicNum))
          return dpb.fs_ltref[i]->bottom_field;
    }
  }
  return NULL;
}

/*!
 ************************************************************************
 * \brief
 *    Reordering process for short-term reference pictures
 *
 ************************************************************************
 */
static void reorder_short_term(StorablePicture **RefPicListX, int num_ref_idx_lX_active_minus1, int picNumLX, int *refIdxLX)
{
  int cIdx, nIdx;

  StorablePicture *picLX;

  picLX = get_short_term_pic(picNumLX);

  for( cIdx = num_ref_idx_lX_active_minus1+1; cIdx > *refIdxLX; cIdx-- )
    RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];

  RefPicListX[ (*refIdxLX)++ ] = picLX;

  nIdx = *refIdxLX;

  for( cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1+1; cIdx++ )
    if (RefPicListX[ cIdx ])
      if( (RefPicListX[ cIdx ]->is_long_term ) ||  (RefPicListX[ cIdx ]->pic_num != picNumLX ))
        RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];

}


/*!
 ************************************************************************
 * \brief
 *    Reordering process for short-term reference pictures
 *
 ************************************************************************
 */
static void reorder_long_term(StorablePicture **RefPicListX, int num_ref_idx_lX_active_minus1, int LongTermPicNum, int *refIdxLX)
{
  int cIdx, nIdx;

  StorablePicture *picLX;

  picLX = get_long_term_pic(LongTermPicNum);

  for( cIdx = num_ref_idx_lX_active_minus1+1; cIdx > *refIdxLX; cIdx-- )
    RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];

  RefPicListX[ (*refIdxLX)++ ] = picLX;

  nIdx = *refIdxLX;

  for( cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1+1; cIdx++ )
    if (RefPicListX[ cIdx ])
      if( (!RefPicListX[ cIdx ]->is_long_term ) ||  (RefPicListX[ cIdx ]->long_term_pic_num != LongTermPicNum ))
        RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
}


/*!
 ************************************************************************
 * \brief
 *    Reordering process for reference picture lists
 *
 ************************************************************************
 */
void reorder_ref_pic_list(StorablePicture **list, int *list_size, int num_ref_idx_lX_active_minus1, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx)
{
  int i;

  int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;
  int refIdxLX = 0;

  if (img->structure==FRAME)
  {
    maxPicNum  = img->MaxFrameNum;
    currPicNum = img->frame_num;
  }
  else
  {
    maxPicNum  = 2 * img->MaxFrameNum;
    currPicNum = 2 * img->frame_num + 1;
  }

  picNumLXPred = currPicNum;

  for (i=0; reordering_of_pic_nums_idc[i]!=3; i++)
  {
    if (reordering_of_pic_nums_idc[i]>3)
      error ("Invalid remapping_of_pic_nums_idc command", 500);

    if (reordering_of_pic_nums_idc[i] < 2)
    {
      if (reordering_of_pic_nums_idc[i] == 0)
      {
        if( picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 ) < 0 )
          picNumLXNoWrap = picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 ) + maxPicNum;
        else
          picNumLXNoWrap = picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 );
      }
      else // (remapping_of_pic_nums_idc[i] == 1)
      {
        if( picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 )  >=  maxPicNum )
          picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 ) - maxPicNum;
        else
          picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 );
      }
      picNumLXPred = picNumLXNoWrap;

      if( picNumLXNoWrap > currPicNum )
        picNumLX = picNumLXNoWrap - maxPicNum;
      else
        picNumLX = picNumLXNoWrap;

      reorder_short_term(list, num_ref_idx_lX_active_minus1, picNumLX, &refIdxLX);
    }
    else //(remapping_of_pic_nums_idc[i] == 2)
    {
      reorder_long_term(list, num_ref_idx_lX_active_minus1, long_term_pic_idx[i], &refIdxLX);
    }

  }
  // that's a definition
  *list_size = num_ref_idx_lX_active_minus1 + 1;
}



/*!
 ************************************************************************
 * \brief
 *    Update the list of frame stores that contain reference frames/fields
 *
 ************************************************************************
 */
void update_ref_list(void)
{
  unsigned i, j;
  for (i=0, j=0; i<dpb.used_size; i++)
  {
    if (is_short_term_reference(dpb.fs[i]))
    {
      dpb.fs_ref[j++]=dpb.fs[i];
    }
  }

  dpb.ref_frames_in_buffer = j;

  while (j<dpb.size)
  {
    dpb.fs_ref[j++]=NULL;
  }
}


/*!
 ************************************************************************
 * \brief
 *    Update the list of frame stores that contain long-term reference
 *    frames/fields
 *
 ************************************************************************
 */
void update_ltref_list(void)
{
  unsigned i, j;
  for (i=0, j=0; i<dpb.used_size; i++)
  {
    if (is_long_term_reference(dpb.fs[i]))
    {
      dpb.fs_ltref[j++]=dpb.fs[i];
    }
  }

  dpb.ltref_frames_in_buffer=j;

  while (j<dpb.size)
  {
    dpb.fs_ltref[j++]=NULL;
  }
}

/*!
 ************************************************************************
 * \brief
 *    Perform Memory management for idr pictures
 *
 ************************************************************************
 */
static void idr_memory_management(StorablePicture* p)
{
  unsigned i;

  assert (p->idr_flag);

  if (p->no_output_of_prior_pics_flag)
  {
    // free all stored pictures
    for (i=0; i<dpb.used_size; i++)
    {
      // reset all reference settings
      free_frame_store(dpb.fs[i]);
      dpb.fs[i] = alloc_frame_store();
    }
    for (i=0; i<dpb.ref_frames_in_buffer; i++)
    {
      dpb.fs_ref[i]=NULL;
    }
    for (i=0; i<dpb.ltref_frames_in_buffer; i++)
    {
      dpb.fs_ltref[i]=NULL;
    }
    dpb.used_size=0;
  }
  else
  {
    flush_dpb();
  }
  dpb.last_picture = NULL;

  update_ref_list();
  update_ltref_list();
  dpb.last_output_poc = INT_MIN;

  if (p->long_term_reference_flag)
  {
    dpb.max_long_term_pic_idx = 0;
    p->is_long_term           = 1;
    p->long_term_frame_idx    = 0;
  }
  else
  {
    dpb.max_long_term_pic_idx = -1;
    p->is_long_term           = 0;
  }
}

/*!
 ************************************************************************
 * \brief
 *    Perform Sliding window decoded reference picture marking process
 *
 ************************************************************************
 */
static void sliding_window_memory_management(StorablePicture* p)
{
  unsigned i;

  assert (!p->idr_flag);
  // if this is a reference pic with sliding sliding window, unmark first ref frame
  if (dpb.ref_frames_in_buffer==dpb.num_ref_frames - dpb.ltref_frames_in_buffer)
  {
    for (i=0; i<dpb.used_size;i++)
    {
      if (dpb.fs[i]->is_reference  && (!(dpb.fs[i]->is_long_term)))
      {
        unmark_for_reference(dpb.fs[i]);
        update_ref_list();
        break;
      }
    }
  }

  p->is_long_term = 0;
}

/*!
 ************************************************************************
 * \brief
 *    Calculate picNumX
 ************************************************************************
 */
static int get_pic_num_x (StorablePicture *p, int difference_of_pic_nums_minus1)
{
  int currPicNum;

  if (p->structure == FRAME)
    currPicNum = p->frame_num;
  else
    currPicNum = 2 * p->frame_num + 1;

  return currPicNum - (difference_of_pic_nums_minus1 + 1);
}


/*!
 ************************************************************************
 * \brief
 *    Adaptive Memory Management: Mark short term picture unused
 ************************************************************************
 */
static void mm_unmark_short_term_for_reference(StorablePicture *p, int difference_of_pic_nums_minus1)
{
  int picNumX;

  unsigned i;

  picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);

  for (i=0; i<dpb.ref_frames_in_buffer; i++)
  {
    if (p->structure == FRAME)
    {
      if ((dpb.fs_ref[i]->is_reference==3) && (dpb.fs_ref[i]->is_long_term==0))
      {
        if (dpb.fs_ref[i]->frame->pic_num == picNumX)
        {
          unmark_for_reference(dpb.fs_ref[i]);
          return;
        }
      }
    }
    else
    {
      if ((dpb.fs_ref[i]->is_reference & 1) && (!(dpb.fs_ref[i]->is_long_term & 1)))
      {
        if (dpb.fs_ref[i]->top_field->pic_num == picNumX)
        {
          dpb.fs_ref[i]->top_field->used_for_reference = 0;
          dpb.fs_ref[i]->is_reference &= 2;
          if (dpb.fs_ref[i]->is_used == 3)
          {
            dpb.fs_ref[i]->frame->used_for_reference = 0;
          }
          return;
        }
      }
      if ((dpb.fs_ref[i]->is_reference & 2) && (!(dpb.fs_ref[i]->is_long_term & 2)))
      {
        if (dpb.fs_ref[i]->bottom_field->pic_num == picNumX)
        {
          dpb.fs_ref[i]->bottom_field->used_for_reference = 0;
          dpb.fs_ref[i]->is_reference &= 1;
          if (dpb.fs_ref[i]->is_used == 3)
          {
            dpb.fs_ref[i]->frame->used_for_reference = 0;
          }
          return;
        }
      }
    }
  }
}


/*!
 ************************************************************************
 * \brief
 *    Adaptive Memory Management: Mark long term picture unused
 ************************************************************************
 */
static void mm_unmark_long_term_for_reference(StorablePicture *p, int long_term_pic_num)
{
  unsigned i;
  for (i=0; i<dpb.ltref_frames_in_buffer; i++)
  {
    if (p->structure == FRAME)
    {
      if ((dpb.fs_ltref[i]->is_reference==3) && (dpb.fs_ltref[i]->is_long_term==3))
      {
        if (dpb.fs_ltref[i]->frame->long_term_pic_num == long_term_pic_num)
        {
          unmark_for_long_term_reference(dpb.fs_ltref[i]);
        }
      }
    }
    else
    {
      if ((dpb.fs_ltref[i]->is_reference & 1) && ((dpb.fs_ltref[i]->is_long_term & 1)))
      {
        if (dpb.fs_ltref[i]->top_field->long_term_pic_num == long_term_pic_num)
        {
          dpb.fs_ltref[i]->top_field->used_for_reference = 0;
          dpb.fs_ltref[i]->top_field->is_long_term = 0;
          dpb.fs_ltref[i]->is_reference &= 2;
          dpb.fs_ltref[i]->is_long_term &= 2;
          if (dpb.fs_ltref[i]->is_used == 3)
          {
            dpb.fs_ltref[i]->frame->used_for_reference = 0;
            dpb.fs_ltref[i]->frame->is_long_term = 0;
          }
          return;
        }
      }
      if ((dpb.fs_ltref[i]->is_reference & 2) && ((dpb.fs_ltref[i]->is_long_term & 2)))
      {
        if (dpb.fs_ltref[i]->bottom_field->long_term_pic_num == long_term_pic_num)
        {
          dpb.fs_ltref[i]->bottom_field->used_for_reference = 0;
          dpb.fs_ltref[i]->bottom_field->is_long_term = 0;
          dpb.fs_ltref[i]->is_reference &= 1;
          dpb.fs_ltref[i]->is_long_term &= 1;
          if (dpb.fs_ltref[i]->is_used == 3)
          {
            dpb.fs_ltref[i]->frame->used_for_reference = 0;
            dpb.fs_ltref[i]->frame->is_long_term = 0;
          }
          return;
        }
      }
    }
  }
}


/*!
 ************************************************************************
 * \brief
 *    Mark a long-term reference frame or complementary field pair unused for referemce
 ************************************************************************
 */
static void unmark_long_term_frame_for_reference_by_frame_idx(int long_term_frame_idx)
{
  unsigned i;
  for(i=0; i<dpb.ltref_frames_in_buffer; i++)
  {
    if (dpb.fs_ltref[i]->long_term_frame_idx == long_term_frame_idx)
      unmark_for_long_term_reference(dpb.fs_ltref[i]);
  }
}

/*!
 ************************************************************************
 * \brief
 *    Mark a long-term reference field unused for reference only if it's not
 *    the complementary field of the picture indicated by picNumX
 ************************************************************************
 */
static void unmark_long_term_field_for_reference_by_frame_idx(PictureStructure structure, int long_term_frame_idx, int mark_current, unsigned curr_frame_num, int curr_pic_num)

⌨️ 快捷键说明

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