www.pudn.com > jm74.zip > mbuffer.c


 
/*! 
 *********************************************************************** 
 *  \file 
 *      mbuffer.c 
 * 
 *  \brief 
 *      Frame buffer functions 
 * 
 *  \author 
 *      Main contributors (see contributors.h for copyright, address and affiliation details) 
 *      - Karsten Sühring           
 *      - Alexis Tourapis                  
 *********************************************************************** 
 */ 
 
#include  
#include  
#include  
#include  
 
#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[6]; 
 
extern StorablePicture *dec_picture; 
 
int listXsize[6]; 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Print out list of pictures in DPB. Used for debug purposes. 
 ************************************************************************ 
 */ 
void dump_dpb() 
{ 
  unsigned i; 
 
  return; 
   
  for (i=0; iframe_num); 
    if (dpb.fs[i]->is_used & 1) 
      printf("T: poc=%d  ", dpb.fs[i]->top_field->poc); 
    if (dpb.fs[i]->is_used & 2) 
      printf("B: poc=%d  ", dpb.fs[i]->bottom_field->poc); 
    if (dpb.fs[i]->is_used == 3) 
      printf("F: poc=%d  ", dpb.fs[i]->frame->poc); 
    printf("G: poc=%d)  ", dpb.fs[i]->poc); 
    if (dpb.fs[i]->is_reference) printf ("ref  "); 
    if (dpb.fs[i]->is_output) printf ("out  "); 
    printf ("\n"); 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Allocate memory for decoded picture buffer an initialize with sane values. 
 * 
 * \param inp 
 *    Input Parameters 
 * 
 ************************************************************************ 
 */ 
void init_dpb(struct inp_par *inp) 
{ 
  unsigned i,j; 
 
  dpb.size      = inp->dpb_size; 
  dpb.used_size = 0; 
 
  dpb.fs = calloc(dpb.size, sizeof (FrameStore*)); 
  if (NULL==dpb.fs)  
    no_mem_exit("init_dpb: dpb->fs"); 
 
  dpb.fs_ref = calloc(dpb.size, sizeof (FrameStore*)); 
  if (NULL==dpb.fs_ref)  
    no_mem_exit("init_dpb: dpb->fs_ref"); 
 
  dpb.fs_ltref = calloc(dpb.size, sizeof (FrameStore*)); 
  if (NULL==dpb.fs_ltref)  
    no_mem_exit("init_dpb: dpb->fs_ltref"); 
 
  for (i=0; ilast_has_mmco_5 = 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Free memory for decoded picture buffer. 
 ************************************************************************ 
 */ 
void free_dpb() 
{ 
  unsigned i; 
  if (dpb.fs) 
  { 
    for (i=0; iis_used      = 0; 
  f->is_reference = 0; 
 
  f->is_output = 0; 
 
  f->frame        = NULL;; 
  f->top_field    = NULL; 
  f->bottom_field = 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; 
 
  //printf ("Allocating (%s) picture (x=%d, y=%d, x_cr=%d, y_cr=%d)\n", (type == FRAME)?"FRAME":(type == TOP_FIELD)?"TOP_FIELD":"BOTTOM_FIELD", size_x, size_y, size_x_cr, size_y_cr); 
 
  s = calloc (1, sizeof(StorablePicture)); 
  if (NULL==s)  
    no_mem_exit("alloc_storable_picture: s"); 
 
  get_mem2D (&(s->imgY), size_y, size_x); 
  get_mem3D (&(s->imgUV), 2, size_y_cr, size_x_cr ); 
 
  s->mb_field = calloc (img->PicSizeInMbs, sizeof(int)); 
 
  get_mem3Dint (&(s->ref_idx), 2, size_x / BLOCK_SIZE, size_y / BLOCK_SIZE); 
  get_mem3Dint64 (&(s->ref_pic_id), 2, size_x / BLOCK_SIZE, size_y / BLOCK_SIZE); 
  get_mem4Dint (&(s->mv), 2, size_x / BLOCK_SIZE, size_y / BLOCK_SIZE,2 ); 
 
  get_mem2D (&(s->moving_block), size_x / BLOCK_SIZE, size_y / BLOCK_SIZE); 
 
  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->non_existing=0; 
  s->is_output = 0; 
 
  s->structure=structure; 
 
  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->top_field    = NULL; 
  s->bottom_field = NULL; 
  s->frame        = NULL; 
 
  s->coded_frame                   = 0; 
  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) 
  { 
    if (f->frame) 
    { 
      free_storable_picture(f->frame); 
      f->frame=NULL; 
    } 
    if (f->top_field) 
    { 
      free_storable_picture(f->top_field); 
      f->top_field=NULL; 
    } 
    if (f->bottom_field) 
    { 
      free_storable_picture(f->bottom_field); 
      f->bottom_field=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 / BLOCK_SIZE); 
 
    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->mb_field); 
 
    free(p); 
  } 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    mark FrameStore unused for reference 
 * 
 ************************************************************************ 
 */ 
static void unmark_for_reference(FrameStore* fs) 
{ 
 
  if (fs->is_used & 1) 
  { 
    fs->top_field->used_for_reference = 0; 
  } 
  if (fs->is_used & 2) 
  { 
    fs->bottom_field->used_for_reference = 0; 
  } 
  if (fs->is_used == 3) 
  { 
    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) 
{ 
 
  if (fs->is_used & 1) 
  { 
    fs->top_field->used_for_reference = 0; 
    fs->top_field->is_long_term = 0; 
  } 
  if (fs->is_used & 2) 
  { 
    fs->bottom_field->used_for_reference = 0; 
    fs->bottom_field->is_long_term = 0; 
  } 
  if (fs->is_used == 3) 
  { 
    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 
 *    compares two frame stores by pic_num for qsort in descending order 
 * 
 ************************************************************************ 
 */ 
static int compare_fs_by_frame_num_desc( const void *arg1, const void *arg2 ) 
{ 
  if ( (*(FrameStore**)arg1)->frame_num_wrap < (*(FrameStore**)arg2)->frame_num_wrap) 
    return 1; 
  if ( (*(FrameStore**)arg1)->frame_num_wrap > (*(FrameStore**)arg2)->frame_num_wrap) 
    return -1; 
  else 
    return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    compares two frame stores by lt_pic_num for qsort in descending order 
 * 
 ************************************************************************ 
 */ 
static int compare_fs_by_lt_pic_idx_asc( const void *arg1, const void *arg2 ) 
{ 
  if ( (*(FrameStore**)arg1)->long_term_frame_idx < (*(FrameStore**)arg2)->long_term_frame_idx) 
    return -1; 
  if ( (*(FrameStore**)arg1)->long_term_frame_idx > (*(FrameStore**)arg2)->long_term_frame_idx) 
    return 1; 
  else 
    return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    compares two stored pictures by poc for qsort in ascending order 
 * 
 ************************************************************************ 
 */ 
static int compare_pic_by_poc_asc( const void *arg1, const void *arg2 ) 
{ 
  if ( (*(StorablePicture**)arg1)->poc < (*(StorablePicture**)arg2)->poc) 
    return -1; 
  if ( (*(StorablePicture**)arg1)->poc > (*(StorablePicture**)arg2)->poc) 
    return 1; 
  else 
    return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    compares two stored pictures by poc for qsort in descending order 
 * 
 ************************************************************************ 
 */ 
static int compare_pic_by_poc_desc( const void *arg1, const void *arg2 ) 
{ 
  if ( (*(StorablePicture**)arg1)->poc < (*(StorablePicture**)arg2)->poc) 
    return 1; 
  if ( (*(StorablePicture**)arg1)->poc > (*(StorablePicture**)arg2)->poc) 
    return -1; 
  else 
    return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    compares two frame stores by poc for qsort in ascending order 
 * 
 ************************************************************************ 
 */ 
static int compare_fs_by_poc_asc( const void *arg1, const void *arg2 ) 
{ 
  if ( (*(FrameStore**)arg1)->poc < (*(FrameStore**)arg2)->poc) 
    return -1; 
  if ( (*(FrameStore**)arg1)->poc > (*(FrameStore**)arg2)->poc) 
    return 1; 
  else 
    return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    compares two frame stores by poc for qsort in descending order 
 * 
 ************************************************************************ 
 */ 
static int compare_fs_by_poc_desc( const void *arg1, const void *arg2 ) 
{ 
  if ( (*(FrameStore**)arg1)->poc < (*(FrameStore**)arg2)->poc) 
    return 1; 
  if ( (*(FrameStore**)arg1)->poc > (*(FrameStore**)arg2)->poc) 
    return -1; 
  else 
    return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    returns true, if picture is short term reference picture 
 * 
 ************************************************************************ 
 */ 
int is_short_ref(StorablePicture *s) 
{ 
  return ((s->used_for_reference) && (!(s->is_long_term))); 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    returns true, if picture is long term reference picture 
 * 
 ************************************************************************ 
 */ 
int is_long_ref(StorablePicture *s) 
{ 
  return ((s->used_for_reference) && (s->is_long_term)); 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Generates a alternating field list from a given FrameStore list 
 * 
 ************************************************************************ 
 */ 
static void gen_pic_list_from_frame_list(PictureStructure currStrcture, FrameStore **fs_list, int list_idx, StorablePicture **list, int *list_size, int long_term) 
{ 
  int top_idx = 0; 
  int bot_idx = 0; 
 
  int (*is_ref)(StorablePicture *s); 
 
  if (long_term) 
    is_ref=is_long_ref; 
  else 
    is_ref=is_short_ref; 
 
  if (currStrcture == TOP_FIELD) 
  { 
    while ((top_idxis_used & 1) 
        { 
          if(is_ref(fs_list[top_idx]->top_field)) 
          { 
            // short term ref pic 
            list[*list_size] = fs_list[top_idx]->top_field; 
            (*list_size)++; 
            top_idx++; 
            break; 
          } 
        } 
      } 
      for ( ; bot_idxis_used & 2) 
        { 
          if(is_ref(fs_list[bot_idx]->bottom_field)) 
          { 
            // short term ref pic 
            list[*list_size] = fs_list[bot_idx]->bottom_field; 
            (*list_size)++; 
            bot_idx++; 
            break; 
          } 
        } 
      } 
    } 
  } 
  if (currStrcture == BOTTOM_FIELD) 
  { 
    while ((top_idxis_used & 2) 
        { 
          if(is_ref(fs_list[bot_idx]->bottom_field)) 
          { 
            // short term ref pic 
            list[*list_size] = fs_list[bot_idx]->bottom_field; 
            (*list_size)++; 
            bot_idx++; 
            break; 
          } 
        } 
      } 
      for ( ; top_idxis_used & 1) 
        { 
          if(is_ref(fs_list[top_idx]->top_field)) 
          { 
            // short term ref pic 
            list[*list_size] = fs_list[top_idx]->top_field; 
            (*list_size)++; 
            top_idx++; 
            break; 
          } 
        } 
      } 
    } 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Initialize listX[0] and list 1 depending on current picture type 
 * 
 ************************************************************************ 
 */ 
void init_lists(int currSliceType, PictureStructure currPicStructure) 
{ 
  int add_top, add_bottom; 
  unsigned i; 
  int j; 
  int MaxFrameNum = 1 << (active_sps->log2_max_frame_num_minus4 + 4); 
  int diff; 
 
  int list0idx = 0; 
  int list0idx_1 = 0; 
  int listltidx = 0; 
 
  FrameStore **fs_list0; 
  FrameStore **fs_list1; 
  FrameStore **fs_listlt; 
 
  StorablePicture *tmp_s; 
 
  if ((currSliceType == I_SLICE)||(currSliceType == SI_SLICE)) 
  { 
    listXsize[0] = 0; 
    listXsize[1] = 0; 
    return; 
  } 
 
  if ((currSliceType == P_SLICE)||(currSliceType == SP_SLICE)) 
  { 
    // Calculate FrameNumWrap and PicNum 
    if (currPicStructure == FRAME)   
    { 
      for (i=0; iis_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; 
            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; 
//      printf("listX[0] (PicNum): "); for (i=0; ipic_num);} printf("\n"); 
 
      // long term handling 
      for (i=0; iis_used==3) 
        { 
          dpb.fs_ltref[i]->frame->long_term_pic_num = dpb.fs_ltref[i]->frame->long_term_frame_idx; 
          // if we have two fields, both must be long-term 
          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; 
    } 
    else 
    { 
      fs_list0 = calloc(dpb.size, sizeof (FrameStore*)); 
      if (NULL==fs_list0)  
         no_mem_exit("init_lists: fs_list0"); 
      fs_listlt = calloc(dpb.size, sizeof (FrameStore*)); 
      if (NULL==fs_listlt)  
         no_mem_exit("init_lists: fs_listlt"); 
 
      if (currPicStructure == TOP_FIELD) 
      { 
        add_top    = 1; 
        add_bottom = 0; 
      } 
      else 
      { 
        add_top    = 0; 
        add_bottom = 1; 
      } 
       
      for (i=0; iis_reference) 
        { 
          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; 
          } 
          if (dpb.fs_ref[i]->is_reference & 1) 
          { 
            dpb.fs_ref[i]->top_field->pic_num = (2 * dpb.fs_ref[i]->frame_num_wrap) + add_top; 
          } 
          if (dpb.fs_ref[i]->is_reference & 2) 
          { 
            dpb.fs_ref[i]->bottom_field->pic_num = (2 * dpb.fs_ref[i]->frame_num_wrap) + add_bottom; 
          } 
          fs_list0[list0idx++] = dpb.fs_ref[i]; 
        } 
      } 
 
      qsort((void *)fs_list0, list0idx, sizeof(FrameStore*), compare_fs_by_frame_num_desc); 
 
//      printf("fs_list0 (FrameNum): "); for (i=0; iframe_num_wrap);} printf("\n"); 
 
      listXsize[0] = 0; 
      gen_pic_list_from_frame_list(currPicStructure, fs_list0, list0idx, listX[0], &listXsize[0], 0); 
 
//      printf("listX[0] (PicNum): "); for (i=0; ipic_num);} printf("\n"); 
 
      // long term handling 
      for (i=0; iis_long_term & 1) 
        { 
          dpb.fs_ltref[i]->top_field->long_term_pic_num = 2 * dpb.fs_ltref[i]->top_field->long_term_frame_idx + add_top; 
        } 
        if (dpb.fs_ltref[i]->is_long_term & 2) 
        { 
          dpb.fs_ltref[i]->bottom_field->long_term_pic_num = 2 * dpb.fs_ltref[i]->bottom_field->long_term_frame_idx + add_bottom; 
        } 
      } 
 
      qsort((void *)fs_listlt, listltidx, sizeof(FrameStore*), compare_fs_by_lt_pic_idx_asc); 
 
      gen_pic_list_from_frame_list(currPicStructure, fs_listlt, listltidx, listX[0], &listXsize[0], 1); 
 
      free(fs_list0); 
      free(fs_listlt); 
    } 
    listXsize[1] = 0; 
  } 
  else 
  { 
    // B-Slice 
    if (currPicStructure == FRAME)   
    { 
      for (i=0; iis_used==3) 
        { 
          if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term)) 
          { 
            if (img->framepoc >= dpb.fs_ref[i]->frame->poc) 
            { 
              dpb.fs_ref[i]->frame->order_num=list0idx; 
              listX[0][list0idx++] = dpb.fs_ref[i]->frame; 
            } 
          } 
        } 
      } 
      qsort((void *)listX[0], list0idx, sizeof(StorablePicture*), compare_pic_by_poc_desc); 
      list0idx_1 = list0idx; 
      for (i=0; iis_used==3) 
        { 
          if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term)) 
          { 
            if (img->framepoc < dpb.fs_ref[i]->frame->poc) 
            { 
              dpb.fs_ref[i]->frame->order_num=list0idx; 
              listX[0][list0idx++] = dpb.fs_ref[i]->frame; 
            } 
          } 
        } 
      } 
      qsort((void *)&listX[0][list0idx_1], list0idx-list0idx_1, sizeof(StorablePicture*), compare_pic_by_poc_asc); 
 
      for (j=0; jframepoc); for (i=0; ipoc);} printf("\n"); 
//      printf("listX[1] currPoc=%d (Poc): ", img->framepoc); for (i=0; ipoc);} printf("\n"); 
 
      // long term handling 
      for (i=0; iis_used==3) 
        { 
          // if we have two fields, both must be long-term 
          listX[0][list0idx]  =dpb.fs_ltref[i]->frame; 
          listX[1][list0idx++]=dpb.fs_ltref[i]->frame; 
        } 
      } 
      qsort((void *)&listX[0][listXsize[0]], list0idx-listXsize[0], sizeof(StorablePicture*), compare_pic_by_lt_pic_num_asc); 
      qsort((void *)&listX[1][listXsize[0]], list0idx-listXsize[0], sizeof(StorablePicture*), compare_pic_by_lt_pic_num_asc); 
      listXsize[0] = listXsize[1] = list0idx; 
    } 
    else 
    { 
      fs_list0 = calloc(dpb.size, sizeof (FrameStore*)); 
      if (NULL==fs_list0)  
         no_mem_exit("init_lists: fs_list0"); 
      fs_list1 = calloc(dpb.size, sizeof (FrameStore*)); 
      if (NULL==fs_list1)  
         no_mem_exit("init_lists: fs_list1"); 
      fs_listlt = calloc(dpb.size, sizeof (FrameStore*)); 
      if (NULL==fs_listlt)  
         no_mem_exit("init_lists: fs_listlt"); 
 
      listXsize[0] = 0; 
      listXsize[1] = 1; 
 
      for (i=0; iis_used) 
        { 
          if (img->ThisPOC >= dpb.fs_ref[i]->poc) 
          { 
            fs_list0[list0idx++] = dpb.fs_ref[i]; 
          } 
        } 
      } 
      qsort((void *)fs_list0, list0idx, sizeof(FrameStore*), compare_fs_by_poc_desc); 
      list0idx_1 = list0idx; 
      for (i=0; iis_used) 
        { 
          if (img->ThisPOC < dpb.fs_ref[i]->poc) 
          { 
            fs_list0[list0idx++] = dpb.fs_ref[i]; 
          } 
        } 
      } 
      qsort((void *)&fs_list0[list0idx_1], list0idx-list0idx_1, sizeof(FrameStore*), compare_fs_by_poc_asc); 
 
      for (j=0; jThisPOC); for (i=0; ipoc);} printf("\n"); 
//      printf("fs_list1 currPoc=%d (Poc): ", img->ThisPOC); for (i=0; ipoc);} printf("\n"); 
 
      listXsize[0] = 0; 
      listXsize[1] = 0; 
      gen_pic_list_from_frame_list(currPicStructure, fs_list0, list0idx, listX[0], &listXsize[0], 0); 
      gen_pic_list_from_frame_list(currPicStructure, fs_list1, list0idx, listX[1], &listXsize[1], 0); 
 
//      printf("listX[0] currPoc=%d (Poc): ", img->framepoc); for (i=0; ipoc);} printf("\n"); 
//      printf("listX[1] currPoc=%d (Poc): ", img->framepoc); for (i=0; ipoc);} printf("\n"); 
 
      // long term handling 
      for (i=0; i 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); 
  listXsize[1] = min (listXsize[1], img->num_ref_idx_l1_active); 
 
  // set the unused list entries to NULL 
  for (i=listXsize[0]; i< (2*dpb.size) ; i++) 
  { 
    listX[0][i] = NULL; 
  } 
  for (i=listXsize[1]; i< (2*dpb.size) ; i++) 
  { 
    listX[1][i] = NULL; 
  } 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Initilaize listX[2..5] from lists 0 and 1 
 *    listX[2]: list0 for current_field==top 
 *    listX[3]: list1 for current_field==top 
 *    listX[4]: list0 for current_field==bottom 
 *    listX[5]: list1 for current_field==bottom 
 * 
 ************************************************************************ 
 */ 
void init_mbaff_lists() 
{ 
  unsigned j; 
  int i; 
 
  for (i=2;i<6;i++) 
  { 
    for (j=0; j<(2*dpb.size)+1; j++) 
    { 
      listX[i][j] = NULL; 
    } 
    listXsize[i]=0; 
  } 
 
  for (i=0; itop_field; 
    listX[2][2*i+1]=listX[0][i]->bottom_field; 
    listX[4][2*i]  =listX[0][i]->bottom_field; 
    listX[4][2*i+1]=listX[0][i]->top_field; 
  } 
  listXsize[2]=listXsize[4]=listXsize[0] * 2; 
 
  for (i=0; itop_field; 
    listX[3][2*i+1]=listX[1][i]->bottom_field; 
    listX[5][2*i]  =listX[1][i]->bottom_field; 
    listX[5][2*i+1]=listX[1][i]->top_field; 
  } 
  listXsize[3]=listXsize[5]=listXsize[1] * 2; 
} 
  
 /*! 
 ************************************************************************ 
 * \brief 
 *    Returns short term pic with given picNum 
 * 
 ************************************************************************ 
 */ 
static StorablePicture*  get_short_term_pic(int picNum) 
{ 
  unsigned i; 
 
  for (i=0; itype==FRAME) 
    { 
      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; 
    } 
    else 
    { 
      if (dpb.fs_ref[i]->is_reference & 1) 
        if ((!dpb.fs_ref[i]->top_field->is_long_term)&&(dpb.fs_ref[i]->top_field->pic_num == picNum)) 
          return dpb.fs_ref[i]->top_field; 
      if (dpb.fs_ref[i]->is_reference & 2) 
        if ((!dpb.fs_ref[i]->bottom_field->is_long_term)&&(dpb.fs_ref[i]->bottom_field->pic_num == picNum)) 
          return dpb.fs_ref[i]->bottom_field; 
    } 
  } 
  return NULL; 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Returns short term pic with given LongtermPicNum 
 * 
 ************************************************************************ 
 */ 
static StorablePicture*  get_long_term_pic(int LongtermPicNum) 
{ 
  unsigned i; 
 
  for (i=0; itype==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 ]->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 *remapping_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; 
  } 
 
  picNumLXPred = currPicNum; 
 
  for (i=0; remapping_of_pic_nums_idc[i]!=3; i++) 
  { 
    if (remapping_of_pic_nums_idc[i]>3) 
      error ("Invalid remapping_of_pic_nums_idc command", 500); 
 
    if (remapping_of_pic_nums_idc[i] < 2) 
    { 
      if (remapping_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() 
{ 
  unsigned i, j; 
  for (i=0, j=0; iidr_flag); 
 
  if (img->no_output_of_prior_pics_flag) 
  { 
    // free all stored pictures 
    for (i=0; ilong_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 (!img->idr_flag); 
  // if this is a reference pic with sliding sliding window, unmark first ref frame 
  if (dpb.ref_frames_in_buffer==active_sps->num_ref_frames - dpb.ltref_frames_in_buffer) 
  { 
    for (i=0; iis_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 = img->frame_num; 
  else  
    currPicNum = 2 * img->frame_num; 
   
  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; istructure == 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; istructure == 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; ilong_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 referemce 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(StorablePicture *p, int long_term_frame_idx, int picNumX) 
{ 
  unsigned i; 
  for(i=0; ilong_term_frame_idx == long_term_frame_idx) 
    { 
      if (p->structure == TOP_FIELD) 
      { 
        if (!(dpb.fs_ltref[i]->is_reference == 3)) 
        { 
          unmark_for_long_term_reference(dpb.fs_ltref[i]); 
        } 
        else 
        { 
          if (!(dpb.fs_ltref[i]->is_long_term == 2)) 
          { 
            unmark_for_long_term_reference(dpb.fs_ltref[i]); 
          } 
          else 
          { 
            if (!(dpb.fs_ltref[i]->top_field->pic_num==picNumX)) 
              unmark_for_long_term_reference(dpb.fs_ltref[i]); 
          } 
        } 
      } 
      if (p->structure == BOTTOM_FIELD) 
      { 
        if (!(dpb.fs_ltref[i]->is_reference == 3)) 
        { 
          unmark_for_long_term_reference(dpb.fs_ltref[i]); 
        } 
        else 
        { 
          if (!(dpb.fs_ltref[i]->is_long_term == 1)) 
          { 
            unmark_for_long_term_reference(dpb.fs_ltref[i]); 
          } 
          else 
          { 
            if (!(dpb.fs_ltref[i]->bottom_field->pic_num==picNumX)) 
            { 
              unmark_for_long_term_reference(dpb.fs_ltref[i]); 
            } 
          } 
        } 
      } 
    } 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    mark a picture as long-term reference 
 ************************************************************************ 
 */ 
static void mark_pic_long_term(StorablePicture* p, int long_term_frame_idx, int picNumX) 
{ 
  unsigned i; 
  int add_top, add_bottom; 
 
  if (p->structure == FRAME) 
  { 
    for (i=0; iis_reference == 3) 
      { 
        if ((!dpb.fs_ref[i]->frame->is_long_term)&&(dpb.fs_ref[i]->frame->pic_num == picNumX)) 
        { 
          dpb.fs_ref[i]->long_term_frame_idx = dpb.fs_ref[i]->frame->long_term_frame_idx 
                                             = dpb.fs_ref[i]->top_field->long_term_frame_idx 
                                             = dpb.fs_ref[i]->bottom_field->long_term_frame_idx 
                                             = long_term_frame_idx; 
          dpb.fs_ref[i]->frame->long_term_pic_num = dpb.fs_ref[i]->top_field->long_term_pic_num 
                                                  = dpb.fs_ref[i]->bottom_field->long_term_pic_num 
                                                  = long_term_frame_idx; 
          dpb.fs_ref[i]->frame->is_long_term = dpb.fs_ref[i]->top_field->is_long_term 
                                             = dpb.fs_ref[i]->bottom_field->is_long_term 
                                             = 1; 
          dpb.fs_ref[i]->is_long_term = 3; 
          return; 
        } 
      } 
    } 
    printf ("Warning: reference frame for long term marking not found\n"); 
  } 
  else 
  { 
    if (p->structure == TOP_FIELD) 
    { 
      add_top    = 1; 
      add_bottom = 0; 
    } 
    else 
    { 
      add_top    = 0; 
      add_bottom = 1; 
    } 
    for (i=0; iis_reference & 1) 
      { 
        if ((!dpb.fs_ref[i]->top_field->is_long_term)&&(dpb.fs_ref[i]->top_field->pic_num == picNumX)) 
        { 
          if ((dpb.fs_ref[i]->is_long_term) && (dpb.fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) 
          { 
              printf ("Warning: assigning long_term_frame_idx different from other field\n"); 
          } 
 
          dpb.fs_ref[i]->long_term_frame_idx = dpb.fs_ref[i]->top_field->long_term_frame_idx  
                                             = long_term_frame_idx; 
          dpb.fs_ref[i]->top_field->long_term_pic_num = 2 * long_term_frame_idx + add_top; 
          dpb.fs_ref[i]->top_field->is_long_term = 1; 
          dpb.fs_ref[i]->is_long_term |= 1; 
          if (dpb.fs_ref[i]->is_long_term == 3) 
          { 
            dpb.fs_ref[i]->frame->is_long_term = 1; 
            dpb.fs_ref[i]->frame->long_term_frame_idx = dpb.fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; 
          } 
          return; 
        } 
      } 
      if (dpb.fs_ref[i]->is_reference & 2) 
      { 
        if ((!dpb.fs_ref[i]->bottom_field->is_long_term)&&(dpb.fs_ref[i]->bottom_field->pic_num == picNumX)) 
        { 
          if ((dpb.fs_ref[i]->is_long_term) && (dpb.fs_ref[i]->long_term_frame_idx != long_term_frame_idx)) 
          { 
              printf ("Warning: assigning long_term_frame_idx different from other field\n"); 
          } 
 
          dpb.fs_ref[i]->long_term_frame_idx = dpb.fs_ref[i]->bottom_field->long_term_frame_idx  
                                             = long_term_frame_idx; 
          dpb.fs_ref[i]->bottom_field->long_term_pic_num = 2 * long_term_frame_idx + add_top; 
          dpb.fs_ref[i]->bottom_field->is_long_term = 1; 
          dpb.fs_ref[i]->is_long_term |= 2; 
          if (dpb.fs_ref[i]->is_long_term == 3) 
          { 
            dpb.fs_ref[i]->frame->is_long_term = 1; 
            dpb.fs_ref[i]->frame->long_term_frame_idx = dpb.fs_ref[i]->frame->long_term_pic_num = long_term_frame_idx; 
          } 
          return; 
        } 
      } 
    } 
    printf ("Warning: reference field for long term marking not found\n"); 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Assign a long term frame index to a short term picture 
 ************************************************************************ 
 */ 
static void mm_assign_long_term_frame_idx(StorablePicture* p, int difference_of_pic_nums_minus1, int long_term_frame_idx) 
{ 
  int picNumX; 
 
  picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1); 
 
  // remove frames/fields with same long_term_frame_idx 
  if (p->structure == FRAME) 
  { 
    unmark_long_term_frame_for_reference_by_frame_idx(long_term_frame_idx); 
  } 
  else 
  { 
    unmark_long_term_field_for_reference_by_frame_idx(p, long_term_frame_idx, picNumX); 
  } 
 
  mark_pic_long_term(p, long_term_frame_idx, picNumX); 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Set new max long_term_frame_idx 
 ************************************************************************ 
 */ 
void mm_update_max_long_term_frame_idx(int max_long_term_frame_idx_plus1) 
{ 
  unsigned i; 
 
  dpb.max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1; 
 
  // check for invalid frames 
  for (i=0; ilong_term_frame_idx > dpb.max_long_term_pic_idx) 
    { 
      unmark_for_long_term_reference(dpb.fs_ltref[i]); 
    } 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Mark all long term reference pictures unused for reference 
 ************************************************************************ 
 */ 
static void mm_unmark_all_long_term_for_reference () 
{ 
  mm_update_max_long_term_frame_idx(0); 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Mark all short term reference pictures unused for reference 
 ************************************************************************ 
 */ 
static void mm_unmark_all_short_term_for_reference () 
{ 
  unsigned int i; 
  for (i=0; istructure == FRAME) 
  { 
    unmark_long_term_frame_for_reference_by_frame_idx(long_term_frame_idx); 
  } 
  else 
  { 
    unmark_long_term_field_for_reference_by_frame_idx(p, long_term_frame_idx, 2 * p->pic_num + 1); 
  } 
 
  p->is_long_term = 1; 
  p->long_term_frame_idx = long_term_frame_idx; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Perform Adaptive memory control decoded reference picture marking process 
 ************************************************************************ 
 */ 
static void adaptive_memory_management(StorablePicture* p) 
{ 
  DecRefPicMarking_t *tmp_drpm; 
   
  img->last_has_mmco_5 = 0; 
 
  assert (!img->idr_flag); 
  assert (img->adaptive_ref_pic_buffering_flag); 
 
  while (img->dec_ref_pic_marking_buffer) 
  { 
    tmp_drpm = img->dec_ref_pic_marking_buffer; 
    switch (tmp_drpm->memory_management_control_operation) 
    { 
      case 0: 
        if (tmp_drpm->Next != NULL) 
        { 
          error ("memory_management_control_operation = 0 not last operation in buffer", 500); 
        } 
        break; 
      case 1: 
        mm_unmark_short_term_for_reference(p, tmp_drpm->difference_of_pic_nums_minus1); 
        update_ref_list(); 
        break; 
      case 2: 
        mm_unmark_long_term_for_reference(p, tmp_drpm->long_term_pic_num); 
        update_ltref_list(); 
        break; 
      case 3: 
        mm_assign_long_term_frame_idx(p, tmp_drpm->difference_of_pic_nums_minus1, tmp_drpm->long_term_frame_idx); 
        update_ref_list(); 
        update_ltref_list(); 
        break; 
      case 4: 
        mm_update_max_long_term_frame_idx (tmp_drpm->max_long_term_frame_idx_plus1); 
        update_ltref_list(); 
        break; 
      case 5: 
        mm_unmark_all_short_term_for_reference(); 
        mm_unmark_all_long_term_for_reference(); 
       img->last_has_mmco_5 = 1; 
        break; 
      case 6: 
        mm_mark_current_picture_long_term(p, tmp_drpm->long_term_frame_idx); 
        break; 
      default: 
        error ("invalid memory_management_control_operation in buffer", 500); 
    } 
    img->dec_ref_pic_marking_buffer = tmp_drpm->Next; 
    free (tmp_drpm); 
  } 
  if ( img->last_has_mmco_5 ) 
  { 
    img->frame_num = p->pic_num = 0; 
    p->poc = 0; 
    flush_dpb(); 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Store a picture in DPB. This includes cheking for space in DPB and  
 *    flushing frames. 
 *    If we received a frame, we need to check for a new store, if we 
 *    got a field, check if it's the second field of an already allocated 
 *    store. 
 * 
 * \param p 
 *    Picture to be stored 
 * 
 ************************************************************************ 
 */ 
void store_picture_in_dpb(StorablePicture* p) 
{ 
  unsigned i; 
  int found; 
  int poc, pos; 
  // diagnostics 
  //printf ("Storing (%s) non-ref pic with frame_num #%d\n", (p->type == FRAME)?"FRAME":(p->type == TOP_FIELD)?"TOP_FIELD":"BOTTOM_FIELD", img->frame_num); 
  // if frame, check for new store,  
  assert (p!=NULL); 
 
  p->used_for_reference = (img->nal_reference_idc != 0); 
   
  img->last_has_mmco_5=0; 
  img->last_pic_bottom_field = img->bottom_field_flag; 
 
  if (img->idr_flag) 
    idr_memory_management(p); 
  else 
  { 
    // adaptive memory management 
    if (p->used_for_reference && (img->adaptive_ref_pic_buffering_flag)) 
      adaptive_memory_management(p); 
  } 
 
  if ((p->structure==TOP_FIELD)||(p->structure==BOTTOM_FIELD)) 
  { 
    // check for frame store with same pic_number 
    found = 0; 
    for (i=0;iframe_num == img->frame_num)&&(dpb.fs[i]->is_used<3)) 
      { 
        found=1; 
        break; 
      } 
    } 
    if (found) 
    { 
      if (!(((p->structure==TOP_FIELD)&&(dpb.fs[i]->is_used&1))||((p->structure==BOTTOM_FIELD)&&(dpb.fs[i]->is_used&2)))) 
      { 
//        printf ("store second field at pos %d\n",i); 
 
        insert_picture_in_dpb(dpb.fs[i], p); 
        update_ref_list(); 
        update_ltref_list(); 
        dump_dpb(); 
        return; 
      } 
    } 
  } 
   
  // this is a frame or a field which has no stored complementatry field 
 
  // sliding window, if necessary 
  if ((!img->idr_flag)&&(p->used_for_reference && (!img->adaptive_ref_pic_buffering_flag))) 
  { 
    sliding_window_memory_management(p); 
  }  
 
  // first try to remove unused frames 
  if (dpb.used_size==dpb.size) 
  { 
    remove_unused_frame_from_dpb(); 
  } 
   
  // then output frames until one can be removed 
  while (dpb.used_size==dpb.size) 
  { 
    // non-reference frames may be output directly 
    if (!p->used_for_reference) 
    { 
      get_smallest_poc(&poc, &pos); 
      if ((-1==pos) || (p->poc < poc)) 
      { 
        direct_output(p, p_out); 
        return; 
      } 
    } 
    // flush a frame 
    output_one_frame_from_dpb(); 
  } 
   
  // check for duplicate frame number in short term reference buffer 
  if ((p->used_for_reference)&&(!p->is_long_term)) 
  { 
    for (i=0; iframe_num == img->frame_num) 
      { 
        error("duplicate frame_num im short-term reference picture buffer", 500); 
      } 
    } 
 
  } 
  // store at end of buffer 
//  printf ("store frame/field at pos %d\n",dpb.used_size); 
  insert_picture_in_dpb(dpb.fs[dpb.used_size],p); 
  dpb.used_size++; 
 
  update_ref_list(); 
  update_ltref_list(); 
  dump_dpb(); 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Insert the picture into the DPB. A free DPB position is necessary 
 *    for frames, . 
 * 
 * \param fs 
 *    FrameStore into which the picture will be inserted 
 * \param p 
 *    StorablePicture to be inserted 
 * 
 ************************************************************************ 
 */ 
static void insert_picture_in_dpb(FrameStore* fs, StorablePicture* p) 
{ 
//  printf ("insert (%s) pic with frame_num #%d, poc %d\n", (p->structure == FRAME)?"FRAME":(p->structure == TOP_FIELD)?"TOP_FIELD":"BOTTOM_FIELD", img->frame_num, p->poc); 
  assert (p!=NULL); 
  assert (fs!=NULL); 
  switch (p->structure) 
  { 
  case FRAME:  
    fs->frame = p; 
    fs->is_used = 3; 
   
    if (p->used_for_reference) 
    { 
      fs->is_reference = 3; 
      if (p->is_long_term) 
      { 
        fs->is_long_term = 3; 
      } 
    } 
    // generate field views 
    dpb_split_field(fs); 
    break; 
  case TOP_FIELD: 
    fs->top_field = p; 
    fs->is_used |= 1; 
    if (p->used_for_reference) 
    { 
      fs->is_reference |= 1; 
      if (p->is_long_term) 
      { 
        fs->is_long_term |= 1; 
        fs->long_term_frame_idx = p->long_term_frame_idx; 
      } 
    } 
    if (fs->is_used == 3) 
    { 
      // generate frame view 
      dpb_combine_field(fs); 
    } else 
    { 
      fs->poc = p->poc; 
    } 
    break; 
  case BOTTOM_FIELD: 
    fs->bottom_field = p; 
    fs->is_used |= 2; 
    if (p->used_for_reference) 
    { 
      fs->is_reference |= 2; 
      if (p->is_long_term) 
      { 
        fs->is_long_term |= 2; 
        fs->long_term_frame_idx = p->long_term_frame_idx; 
      } 
    } 
    if (fs->is_used == 3) 
    { 
      // generate frame view 
      dpb_combine_field(fs); 
    } else 
    { 
      fs->poc = p->poc; 
    } 
    break; 
  } 
  fs->frame_num = p->pic_num; 
  fs->is_output = p->is_output; 
 
  if (fs->is_used==3) 
  { 
    if (p_ref) 
      find_snr(snr, fs->frame, p_ref); 
  } 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Check if one of the frames/fields in frame store is used for reference 
 ************************************************************************ 
 */ 
static int is_used_for_reference(FrameStore* fs) 
{ 
  if (fs->is_reference) 
  { 
    return 1; 
  } 
   
  if (fs->is_used==3) // frame 
  { 
    if (fs->frame->used_for_reference) 
    { 
      return 1; 
    } 
  } 
 
  if (fs->is_used&1) // top field 
  { 
    if (fs->top_field->used_for_reference) 
    { 
      return 1; 
    } 
  } 
 
  if (fs->is_used&2) // bottom field 
  { 
    if (fs->bottom_field->used_for_reference) 
    { 
      return 1; 
    } 
  } 
  return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Check if one of the frames/fields in frame store is used for short-term reference 
 ************************************************************************ 
 */ 
static int is_short_term_reference(FrameStore* fs) 
{ 
 
  if (fs->is_used==3) // frame 
  { 
    if ((fs->frame->used_for_reference)&&(!fs->frame->is_long_term)) 
    { 
      return 1; 
    } 
  } 
 
  if (fs->is_used&1) // top field 
  { 
    if ((fs->top_field->used_for_reference)&&(!fs->top_field->is_long_term)) 
    { 
      return 1; 
    } 
  } 
 
  if (fs->is_used&2) // bottom field 
  { 
    if ((fs->bottom_field->used_for_reference)&&(!fs->top_field->is_long_term)) 
    { 
      return 1; 
    } 
  } 
  return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Check if one of the frames/fields in frame store is used for short-term reference 
 ************************************************************************ 
 */ 
static int is_long_term_reference(FrameStore* fs) 
{ 
 
  if (fs->is_used==3) // frame 
  { 
    if ((fs->frame->used_for_reference)&&(fs->frame->is_long_term)) 
    { 
      return 1; 
    } 
  } 
 
  if (fs->is_used&1) // top field 
  { 
    if ((fs->top_field->used_for_reference)&&(fs->top_field->is_long_term)) 
    { 
      return 1; 
    } 
  } 
 
  if (fs->is_used&2) // bottom field 
  { 
    if ((fs->bottom_field->used_for_reference)&&(fs->top_field->is_long_term)) 
    { 
      return 1; 
    } 
  } 
  return 0; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    remove one frame from DPB 
 ************************************************************************ 
 */ 
static void remove_frame_from_dpb(int pos) 
{ 
  FrameStore* fs = dpb.fs[pos]; 
  FrameStore* tmp; 
  unsigned i; 
   
//  printf ("remove frame with frame_num #%d\n", fs->frame_num); 
  switch (fs->is_used) 
  { 
  case 3: 
    free_storable_picture(fs->frame); 
    free_storable_picture(fs->top_field); 
    free_storable_picture(fs->bottom_field); 
    fs->frame=NULL; 
    fs->top_field=NULL; 
    fs->bottom_field=NULL; 
    break; 
  case 2: 
    free_storable_picture(fs->bottom_field); 
    fs->bottom_field=NULL; 
    break; 
  case 1: 
    free_storable_picture(fs->top_field); 
    fs->top_field=NULL; 
    break; 
  case 0: 
    break; 
  default: 
    error("invalid frame store type",500); 
  } 
  fs->is_used = 0; 
 
  // move empty framestore to end of buffer 
  tmp = dpb.fs[pos]; 
 
  for (i=pos; idpb.fs[i]->poc)&&(!dpb.fs[i]->is_output)) 
    { 
      *poc = dpb.fs[i]->poc; 
      *pos=i; 
    } 
  } 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Remove a picture from DPB which is no longer needed. 
 ************************************************************************ 
 */ 
static int remove_unused_frame_from_dpb() 
{ 
  unsigned i; 
 
  // check for frames that were already output and no longer used for reference 
  for (i=0; iis_output && (!is_used_for_reference(dpb.fs[i]))) 
    { 
      remove_frame_from_dpb(i); 
      return 1; 
    } 
  } 
  return 0; 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Output one picture stored in the DPB. 
 ************************************************************************ 
 */ 
static void output_one_frame_from_dpb() 
{ 
  int poc, pos; 
  //diagnostics 
  if (dpb.used_size<1) 
  { 
    error("Cannot output frame, DPB empty.",150); 
  } 
 
  // find smallest POC 
  get_smallest_poc(&poc, &pos); 
 
  if(pos==-1) 
  { 
    error("no frames for output available", 150); 
  } 
 
  // call the output function 
//  printf ("output frame with frame_num #%d, poc %d (dpb. dpb.size=%d, dpb.used_size=%d)\n", dpb.fs[pos]->frame_num, dpb.fs[pos]->frame->poc, dpb.size, dpb.used_size); 
 
  write_stored_frame(dpb.fs[pos], p_out); 
 
  if (dpb.last_output_poc >= poc) 
  { 
    error ("output POC must be in ascending order", 150); 
  }  
  dpb.last_output_poc = poc; 
  // free frame store and move empty store to end of buffer 
  if (!is_used_for_reference(dpb.fs[pos])) 
  { 
    remove_frame_from_dpb(pos); 
  } 
} 
 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    All stored picture are output. Should be called to empty the buffer 
 ************************************************************************ 
 */ 
void flush_dpb() 
{ 
  unsigned i; 
 
  //diagnostics 
//  printf("Flush remaining frames from dpb. dpb.size=%d, dpb.used_size=%d\n",dpb.size,dpb.used_size); 
 
  // mark all frames unused 
  for (i=0; itop_field    = alloc_storable_picture(TOP_FIELD,    fs->frame->size_x, fs->frame->size_y/2, fs->frame->size_x_cr, fs->frame->size_y_cr/2); 
  fs->bottom_field = alloc_storable_picture(BOTTOM_FIELD, fs->frame->size_x, fs->frame->size_y/2, fs->frame->size_x_cr, fs->frame->size_y_cr/2); 
 
  for (i=0; iframe->size_y/2; i++) 
  { 
    memcpy(fs->top_field->imgY[i], fs->frame->imgY[i*2], fs->frame->size_x); 
  } 
 
  for (i=0; iframe->size_y_cr/2; i++) 
  { 
    memcpy(fs->top_field->imgUV[0][i], fs->frame->imgUV[0][i*2], fs->frame->size_x_cr); 
    memcpy(fs->top_field->imgUV[1][i], fs->frame->imgUV[1][i*2], fs->frame->size_x_cr); 
  } 
 
  for (i=0; iframe->size_y/2; i++) 
  { 
    memcpy(fs->bottom_field->imgY[i], fs->frame->imgY[i*2 + 1], fs->frame->size_x); 
  } 
 
  for (i=0; iframe->size_y_cr/2; i++) 
  { 
    memcpy(fs->bottom_field->imgUV[0][i], fs->frame->imgUV[0][i*2 + 1], fs->frame->size_x_cr); 
    memcpy(fs->bottom_field->imgUV[1][i], fs->frame->imgUV[1][i*2 + 1], fs->frame->size_x_cr); 
  } 
 
  fs->poc = fs->top_field->poc  
          = fs->frame->poc; 
 
  fs->bottom_field->poc =  fs->frame->bottom_poc; 
 
  fs->top_field->used_for_reference = fs->bottom_field->used_for_reference  
                                    = fs->frame->used_for_reference; 
  fs->top_field->is_long_term = fs->bottom_field->is_long_term  
                              = fs->frame->is_long_term; 
  fs->long_term_frame_idx = fs->top_field->long_term_frame_idx  
                          = fs->bottom_field->long_term_frame_idx  
                          = fs->frame->long_term_frame_idx; 
 
  fs->top_field->coded_frame = fs->bottom_field->coded_frame = 1; 
  fs->top_field->mb_adaptive_frame_field_flag = fs->bottom_field->mb_adaptive_frame_field_flag 
                                              = fs->frame->mb_adaptive_frame_field_flag; 
 
  fs->frame->top_field    = fs->top_field; 
  fs->frame->bottom_field = fs->bottom_field; 
  if (!active_sps->frame_mbs_only_flag) 
  { 
  for (i=0;itop_field->ref_pic_num[LIST_1][2*i]     =fs->frame->ref_pic_num[2 + LIST_1][2*i]; 
    fs->top_field->ref_pic_num[LIST_1][2*i + 1] =fs->frame->ref_pic_num[2 + LIST_1][2*i+1]; 
    fs->bottom_field->ref_pic_num[LIST_1][2*i]  =fs->frame->ref_pic_num[4 + LIST_1][2*i]; 
    fs->bottom_field->ref_pic_num[LIST_1][2*i+1]=fs->frame->ref_pic_num[4 + LIST_1][2*i+1] ; 
/*    fs->top_field->ref_pic_num[LIST_1][2*i]     =fs->frame->ref_pic_num[LIST_1][i]; 
    fs->top_field->ref_pic_num[LIST_1][2*i + 1] =fs->frame->ref_pic_num[LIST_1][i] + 1; 
    fs->bottom_field->ref_pic_num[LIST_1][2*i]  =fs->frame->ref_pic_num[LIST_1][i] + 1; 
    fs->bottom_field->ref_pic_num[LIST_1][2*i+1]=fs->frame->ref_pic_num[LIST_1][i] ; 
    */ 
  } 
 
  for (i=0;itop_field->ref_pic_num[LIST_0][2*i]     =fs->frame->ref_pic_num[2 + LIST_0][2*i]; 
    fs->top_field->ref_pic_num[LIST_0][2*i + 1] =fs->frame->ref_pic_num[2 + LIST_0][2*i+1]; 
    fs->bottom_field->ref_pic_num[LIST_0][2*i]  =fs->frame->ref_pic_num[4 + LIST_0][2*i]; 
    fs->bottom_field->ref_pic_num[LIST_0][2*i+1]=fs->frame->ref_pic_num[4 + LIST_0][2*i+1] ; 
/*    fs->top_field->ref_pic_num[LIST_0][2*i]=fs->frame->ref_pic_num[LIST_0][i]; 
    fs->top_field->ref_pic_num[LIST_0][2*i + 1]=fs->frame->ref_pic_num[LIST_0][i] + 1; 
    fs->bottom_field->ref_pic_num[LIST_0][2*i]=fs->frame->ref_pic_num[LIST_0][i] + 1; 
    fs->bottom_field->ref_pic_num[LIST_0][2*i+1]=fs->frame->ref_pic_num[LIST_0][i] ; 
    */ 
  } 
  } 
 
  if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)       
  {     
  for (i=0 ; iframe->size_x/4 ; i++) 
    {                 
      for (j=0 ; jframe->size_y/8; j++)       
      {  
        int idiv4=i/4,jdiv4=j/2; 
 
        int currentmb=2*(fs->frame->size_x/16)*(jdiv4/2)+ (idiv4)*2 + (jdiv4%2); 
        // Assign field mvs attached to MB-Frame buffer to the proper buffer 
        if (img->MbaffFrameFlag && img->mb_data[currentmb].mb_field) 
          { 
          fs->bottom_field->mv[LIST_0][i][j][0] = fs->frame->mv[LIST_0][i][(j/4)*8 + j%4 + 4][0]; 
          fs->bottom_field->mv[LIST_0][i][j][1] = fs->frame->mv[LIST_0][i][(j/4)*8 + j%4 + 4][1]; 
          fs->bottom_field->mv[LIST_1][i][j][0] = fs->frame->mv[LIST_1][i][(j/4)*8 + j%4 + 4][0]; 
          fs->bottom_field->mv[LIST_1][i][j][1] = fs->frame->mv[LIST_1][i][(j/4)*8 + j%4 + 4][1]; 
          fs->bottom_field->ref_idx[LIST_0][i][j] = fs->frame->ref_idx[LIST_0][i][(j/4)*8 + j%4 + 4]; 
          fs->bottom_field->ref_idx[LIST_1][i][j] = fs->frame->ref_idx[LIST_1][i][(j/4)*8 + j%4 + 4]; 
             
          fs->top_field->mv[LIST_0][i][j][0] = fs->frame->mv[LIST_0][i][(j/4)*8 + j%4][0]; 
          fs->top_field->mv[LIST_0][i][j][1] = fs->frame->mv[LIST_0][i][(j/4)*8 + j%4][1]; 
          fs->top_field->mv[LIST_1][i][j][0] = fs->frame->mv[LIST_1][i][(j/4)*8 + j%4][0]; 
          fs->top_field->mv[LIST_1][i][j][1] = fs->frame->mv[LIST_1][i][(j/4)*8 + j%4][1]; 
          fs->top_field->ref_idx[LIST_0][i][j] = fs->frame->ref_idx[LIST_0][i][(j/4)*8 + j%4]; 
          fs->top_field->ref_idx[LIST_1][i][j] = fs->frame->ref_idx[LIST_1][i][(j/4)*8 + j%4]; 
        } 
      } 
    }              
  } 
           
  if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)       
  { 
  for (j=0 ; jframe->size_y/4 ; j++)       
  {                 
    for (i=0 ; iframe->size_x/4 ; i++)           
    {                 
      int idiv4=i/4,jdiv4=j/4; 
      int currentmb=2*(fs->frame->size_x/16)*(jdiv4/2)+ (idiv4)*2 + (jdiv4%2); 
        if (img->MbaffFrameFlag && img->mb_data[currentmb].mb_field) 
        {  
          //! Assign frame buffers for field MBs            
          fs->frame->mv[LIST_0][i][j][0]    = fs->top_field->mv[LIST_0][i][j/2][0]; 
          fs->frame->mv[LIST_0][i][j][1]    = fs->top_field->mv[LIST_0][i][j/2][1] ;           
          fs->frame->mv[LIST_1][i][j][0]    = fs->top_field->mv[LIST_1][i][j/2][0]; 
          fs->frame->mv[LIST_1][i][j][1]    = fs->top_field->mv[LIST_1][i][j/2][1] ;            
          fs->frame->ref_idx[LIST_0][i][j]  = fs->top_field->ref_idx[LIST_0][i][j/2];          
          fs->frame->ref_idx[LIST_1][i][j]  = fs->top_field->ref_idx[LIST_1][i][j/2];                    
          } 
      } 
    }              
  } 
     
  //! Generate field MVs from Frame MVs 
  for (i=0 ; iframe->size_x/4 ; i++) 
  { 
    for (j=0 ; jframe->size_y/8 ; j++) 
    { 
      int idiv4=i/4,jdiv4=j/2; 
       
      int currentmb=2*(fs->frame->size_x/16)*(jdiv4/2)+ (idiv4)*2 + (jdiv4%2); 
      //! Do nothing if macroblock as field coded in MB-AFF 
      if (!img->MbaffFrameFlag || !img->mb_data[currentmb].mb_field)     
      { 
        fs->top_field->mv[LIST_0][i][j][0] = fs->bottom_field->mv[LIST_0][i][j][0] = fs->frame->mv[LIST_0][RSD(i)][2*RSD(j)][0]; 
        fs->top_field->mv[LIST_0][i][j][1] = fs->bottom_field->mv[LIST_0][i][j][1] = (fs->frame->mv[LIST_0][RSD(i)][2*RSD(j)][1]); 
        fs->top_field->mv[LIST_1][i][j][0] = fs->bottom_field->mv[LIST_1][i][j][0] = fs->frame->mv[LIST_1][RSD(i)][2*RSD(j)][0]; 
        fs->top_field->mv[LIST_1][i][j][1] = fs->bottom_field->mv[LIST_1][i][j][1] = (fs->frame->mv[LIST_1][RSD(i)][2*RSD(j)][1]); 
         
        // Scaling of references is done here since it will not affect spatial direct (2*0 =0) 
        if (fs->frame->ref_idx[LIST_0][RSD(i)][2*RSD(j)] == -1)       
          fs->top_field->ref_idx[LIST_0][i][j] = fs->bottom_field->ref_idx[LIST_0][i][j] = - 1; 
        else 
          fs->top_field->ref_idx[LIST_0][i][j] = fs->bottom_field->ref_idx[LIST_0][i][j] = fs->frame->ref_idx[LIST_0][RSD(i)][2*RSD(j)] * 2; 
         
        if (fs->frame->ref_idx[LIST_1][RSD(i)][2*RSD(j)] == -1)       
          fs->top_field->ref_idx[LIST_1][i][j] = fs->bottom_field->ref_idx[LIST_1][i][j] = - 1; 
        else 
          fs->top_field->ref_idx[LIST_1][i][j] = fs->bottom_field->ref_idx[LIST_1][i][j] = fs->frame->ref_idx[LIST_1][RSD(i)][2*RSD(j)]*2; 
 
        fs->top_field->moving_block[i][j] = fs->bottom_field->moving_block[i][j]=  
          !(((fs->top_field->ref_idx[LIST_0][i][j] == 0) &&  
          (abs(fs->top_field->mv[LIST_0][i][j][0])>>1 == 0) &&  
          (abs(fs->top_field->mv[LIST_0][i][j][1])>>1 == 0)) ||  
          ((fs->top_field->ref_idx[LIST_0][i][j] == -1) &&  
          (fs->top_field->ref_idx[LIST_1][i][j] == 0) &&  
          (abs(fs->top_field->mv[LIST_1][i][j][0])>>1 == 0) &&  
          (abs(fs->top_field->mv[LIST_1][i][j][1])>>1 == 0))); 
 
        fs->top_field->mv[LIST_0][i][j][1] /= 2; 
        fs->top_field->mv[LIST_1][i][j][1] /= 2; 
        fs->bottom_field->mv[LIST_0][i][j][1] /= 2; 
        fs->bottom_field->mv[LIST_1][i][j][1] /= 2; 
    } 
      else 
    { 
        fs->bottom_field->mv[LIST_0][i][j][0] = fs->bottom_field->mv[LIST_0][RSD(i)][RSD(j)][0]; 
        fs->bottom_field->mv[LIST_0][i][j][1] = fs->bottom_field->mv[LIST_0][RSD(i)][RSD(j)][1]; 
        fs->bottom_field->mv[LIST_1][i][j][0] = fs->bottom_field->mv[LIST_1][RSD(i)][RSD(j)][0]; 
        fs->bottom_field->mv[LIST_1][i][j][1] = fs->bottom_field->mv[LIST_1][RSD(i)][RSD(j)][1]; 
        fs->bottom_field->ref_idx[LIST_0][i][j] = fs->bottom_field->ref_idx[LIST_0][RSD(i)][RSD(j)];  
        fs->bottom_field->ref_idx[LIST_1][i][j] = fs->bottom_field->ref_idx[LIST_0][RSD(i)][RSD(j)];  
       
        fs->bottom_field->moving_block[i][j] =  
          !(((fs->bottom_field->ref_idx[LIST_0][i][j] == 0) &&  
          (abs(fs->bottom_field->mv[LIST_0][i][j][0])>>1 == 0) &&  
          (abs(fs->bottom_field->mv[LIST_0][i][j][1])>>1 == 0)) ||  
          ((fs->bottom_field->ref_idx[LIST_0][i][j] == -1) &&  
          (fs->bottom_field->ref_idx[LIST_1][i][j] == 0) &&  
          (abs(fs->bottom_field->mv[LIST_1][i][j][0])>>1 == 0) &&  
          (abs(fs->bottom_field->mv[LIST_1][i][j][1])>>1 == 0))); 
         
        fs->top_field->mv[LIST_0][i][j][0] = fs->top_field->mv[LIST_0][RSD(i)][RSD(j)][0]; 
        fs->top_field->mv[LIST_0][i][j][1] = fs->top_field->mv[LIST_0][RSD(i)][RSD(j)][1]; 
        fs->top_field->mv[LIST_1][i][j][0] = fs->top_field->mv[LIST_1][RSD(i)][RSD(j)][0]; 
        fs->top_field->mv[LIST_1][i][j][1] = fs->top_field->mv[LIST_1][RSD(i)][RSD(j)][1]; 
        fs->top_field->ref_idx[LIST_0][i][j] = fs->top_field->ref_idx[LIST_0][RSD(i)][RSD(j)];  
        fs->top_field->ref_idx[LIST_1][i][j] = fs->top_field->ref_idx[LIST_0][RSD(i)][RSD(j)];  
         
        fs->top_field->moving_block[i][j] =  
          !(((fs->top_field->ref_idx[LIST_0][i][j] == 0) &&  
          (abs(fs->top_field->mv[LIST_0][i][j][0])>>1 == 0) &&  
          (abs(fs->top_field->mv[LIST_0][i][j][1])>>1 == 0)) ||  
          ((fs->top_field->ref_idx[LIST_0][i][j] == -1) &&  
          (fs->top_field->ref_idx[LIST_1][i][j] == 0) &&  
          (abs(fs->top_field->mv[LIST_1][i][j][0])>>1 == 0) &&  
          (abs(fs->top_field->mv[LIST_1][i][j][1])>>1 == 0))); 
    } 
  } 
  } 
 
 
   
    for (j=0 ; jframe->size_y/4 ; j++)       
    {                 
    for (i=0 ; iframe->size_x/4 ; i++)           
    {                 
      if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)       
      { 
          //! Use inference flag to remap mvs/references 
          fs->frame->mv[LIST_0][i][j][0]=fs->frame->mv[LIST_0][RSD(i)][RSD(j)][0]; 
          fs->frame->mv[LIST_0][i][j][1]=fs->frame->mv[LIST_0][RSD(i)][RSD(j)][1]; 
          fs->frame->mv[LIST_1][i][j][0]=fs->frame->mv[LIST_1][RSD(i)][RSD(j)][0]; 
          fs->frame->mv[LIST_1][i][j][1]=fs->frame->mv[LIST_1][RSD(i)][RSD(j)][1];         
           
          fs->frame->ref_idx[LIST_0][i][j]=fs->frame->ref_idx[LIST_0][RSD(i)][RSD(j)] ;      
          fs->frame->ref_idx[LIST_1][i][j]=fs->frame->ref_idx[LIST_1][RSD(i)][RSD(j)] ;      
      } 
      fs->frame->moving_block[i][j]=  
        !(((fs->frame->ref_idx[LIST_0][i][j] == 0) &&  
        (abs(fs->frame->mv[LIST_0][i][j][0])>>1 == 0) &&  
        (abs(fs->frame->mv[LIST_0][i][j][1])>>1 == 0)) ||  
        ((fs->frame->ref_idx[LIST_0][i][j] == -1) &&  
        (fs->frame->ref_idx[LIST_1][i][j] == 0) &&  
        (abs(fs->frame->mv[LIST_1][i][j][0])>>1 == 0) &&  
        (abs(fs->frame->mv[LIST_1][i][j][1])>>1 == 0))); 
    }       
  } 
   
  if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)       
  { 
  for (j=0 ; jframe->size_y/4 ; j++)       
  {                 
    for (i=0 ; iframe->size_x/4 ; i++)           
    {                 
      int idiv4=i/4,jdiv4=j/4; 
      int currentmb=2*(fs->frame->size_x/16)*(jdiv4/2)+ (idiv4)*2 + (jdiv4%2); 
 
      if (img->MbaffFrameFlag && img->mb_data[currentmb].mb_field) 
      { 
        fs->frame->mv[LIST_0][i][j][1] *= 2; 
        fs->frame->mv[LIST_1][i][j][1] *= 2; 
        if (fs->frame->ref_idx[LIST_0][i][j] != -1) 
            fs->frame->ref_idx[LIST_0][i][j] >>= 1; 
        if (fs->frame->ref_idx[LIST_1][i][j] != -1) 
            fs->frame->ref_idx[LIST_1][i][j] >>= 1; 
      } 
    } 
  } 
} 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Generate a frame from top and bottom fields 
 ************************************************************************ 
 */ 
void dpb_combine_field(FrameStore *fs) 
{ 
  int i,j; 
 
  fs->frame = alloc_storable_picture(FRAME, fs->top_field->size_x, fs->top_field->size_y*2, fs->top_field->size_x_cr, fs->top_field->size_y_cr*2); 
 
  for (i=0; itop_field->size_y; i++) 
  { 
    memcpy(fs->frame->imgY[i*2],     fs->top_field->imgY[i]   , fs->top_field->size_x);     // top field 
    memcpy(fs->frame->imgY[i*2 + 1], fs->bottom_field->imgY[i], fs->bottom_field->size_x); // bottom field 
  } 
 
  for (i=0; itop_field->size_y_cr; i++) 
  { 
    memcpy(fs->frame->imgUV[0][i*2],     fs->top_field->imgUV[0][i],    fs->top_field->size_x_cr); 
    memcpy(fs->frame->imgUV[0][i*2 + 1], fs->bottom_field->imgUV[0][i], fs->bottom_field->size_x_cr); 
    memcpy(fs->frame->imgUV[1][i*2],     fs->top_field->imgUV[1][i],    fs->top_field->size_x_cr); 
    memcpy(fs->frame->imgUV[1][i*2 + 1], fs->bottom_field->imgUV[1][i], fs->bottom_field->size_x_cr); 
  } 
 
  fs->poc=fs->frame->poc = min (fs->top_field->poc, fs->bottom_field->poc); 
  fs->frame->top_poc=fs->top_field->poc; 
  fs->frame->bottom_poc=fs->bottom_field->poc; 
 
  fs->frame->used_for_reference = (fs->top_field->used_for_reference && fs->bottom_field->used_for_reference ); 
  fs->frame->is_long_term = (fs->top_field->is_long_term && fs->bottom_field->is_long_term ); 
 
  if (fs->frame->is_long_term)  
    fs->frame->long_term_frame_idx = fs->long_term_frame_idx; 
 
  fs->frame->top_field    = fs->top_field; 
  fs->frame->bottom_field = fs->bottom_field; 
   
  fs->top_field->frame = fs->bottom_field->frame = fs->frame; 
   
  for (i=0;i<(listXsize[LIST_1]+1)/2;i++) 
  { 
//    fs->frame->ref_pic_num[LIST_1][i]=   (fs->top_field->ref_pic_num[LIST_1][2*i]/2)*2; 
    fs->frame->ref_pic_num[LIST_1][i]=   min ((fs->top_field->ref_pic_num[LIST_1][2*i]/2)*2, (fs->bottom_field->ref_pic_num[LIST_1][2*i]/2)*2); 
  } 
 
  for (i=0;i<(listXsize[LIST_0]+1)/2;i++) 
  { 
//    fs->frame->ref_pic_num[LIST_0][i]=(fs->top_field->ref_pic_num[LIST_0][2*i]/2)*2; 
    fs->frame->ref_pic_num[LIST_0][i]=   min ((fs->top_field->ref_pic_num[LIST_0][2*i]/2)*2, (fs->bottom_field->ref_pic_num[LIST_0][2*i]/2)*2); 
  } 
   
  //! Use inference flag to remap mvs/references  
   
    //! Generate Frame parameters from field information. 
    for (i=0 ; itop_field->size_x/4 ; i++) 
    { 
      for (j=0 ; jtop_field->size_y/2 ; j++) 
      {         
        fs->frame->mv[LIST_0][i][j][0] = fs->top_field->mv[LIST_0][i][j/2][0]; 
        fs->frame->mv[LIST_0][i][j][1] = fs->top_field->mv[LIST_0][i][j/2][1] ; 
        fs->frame->mv[LIST_1][i][j][0] = fs->top_field->mv[LIST_1][i][j/2][0]; 
        fs->frame->mv[LIST_1][i][j][1] = fs->top_field->mv[LIST_1][i][j/2][1] ;  
         
        fs->frame->ref_idx[LIST_0][i][j]  = fs->top_field->ref_idx[LIST_0][i][j/2]; 
        fs->frame->ref_idx[LIST_1][i][j]  = fs->top_field->ref_idx[LIST_1][i][j/2]; 
      }      
    } 
 
    for (i=0 ; itop_field->size_x/4 ; i++) 
    { 
      for (j=0 ; jtop_field->size_y/2 ; j++) 
      { 
          //! Use inference flag to remap mvs/references 
          fs->frame->mv[LIST_0][i][j][0]=fs->frame->mv[LIST_0][RSD(i)][RSD(j)][0]; 
          fs->frame->mv[LIST_0][i][j][1]=fs->frame->mv[LIST_0][RSD(i)][RSD(j)][1]; 
          fs->frame->mv[LIST_1][i][j][0]=fs->frame->mv[LIST_1][RSD(i)][RSD(j)][0]; 
          fs->frame->mv[LIST_1][i][j][1]=fs->frame->mv[LIST_1][RSD(i)][RSD(j)][1];         
         
          fs->frame->ref_idx[LIST_0][i][j]=fs->frame->ref_idx[LIST_0][RSD(i)][RSD(j)] ;      
          fs->frame->ref_idx[LIST_1][i][j]=fs->frame->ref_idx[LIST_1][RSD(i)][RSD(j)] ;      
         
        fs->frame->moving_block[i][j]=  
          !(((fs->frame->ref_idx[LIST_0][i][j] == 0) &&  
          (abs(fs->frame->mv[LIST_0][i][j][0])>>1 == 0) &&  
          (abs(fs->frame->mv[LIST_0][i][j][1])>>1 == 0)) ||  
          ((fs->frame->ref_idx[LIST_0][i][j] == -1) &&  
          (fs->frame->ref_idx[LIST_1][i][j] == 0) &&  
          (abs(fs->frame->mv[LIST_1][i][j][0])>>1 == 0) &&  
          (abs(fs->frame->mv[LIST_1][i][j][1])>>1 == 0))); 
      }       
    } 
 
    //scaling of mvs/references needs to be done separately  
    for (i=0 ; itop_field->size_x/4 ; i++) 
    { 
      for (j=0 ; jtop_field->size_y/2 ; j++) 
      {                 
        fs->frame->mv[LIST_0][i][j][1] *= 2;         
        fs->frame->mv[LIST_1][i][j][1] *= 2; 
        if (fs->frame->ref_idx[LIST_0][i][j] != -1) 
        fs->frame->ref_idx[LIST_0][i][j] >>= 1; 
        if (fs->frame->ref_idx[LIST_1][i][j] != -1) 
        fs->frame->ref_idx[LIST_1][i][j] >>= 1; 
      }      
    } 
 
 
  if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)       
  {         
    for (i=0 ; itop_field->size_x/4 ; i++) 
    { 
      for (j=0 ; jtop_field->size_y/4 ; j++) 
      {         
        fs->top_field->mv[LIST_0][i][j][0]=fs->top_field->mv[LIST_0][RSD(i)][RSD(j)][0]; 
        fs->top_field->mv[LIST_0][i][j][1]=fs->top_field->mv[LIST_0][RSD(i)][RSD(j)][1]; 
        fs->top_field->mv[LIST_1][i][j][0]=fs->top_field->mv[LIST_1][RSD(i)][RSD(j)][0]; 
        fs->top_field->mv[LIST_1][i][j][1]=fs->top_field->mv[LIST_1][RSD(i)][RSD(j)][1]; 
         
        fs->bottom_field->mv[LIST_0][i][j][0]=fs->bottom_field->mv[LIST_0][RSD(i)][RSD(j)][0]; 
        fs->bottom_field->mv[LIST_0][i][j][1]=fs->bottom_field->mv[LIST_0][RSD(i)][RSD(j)][1]; 
        fs->bottom_field->mv[LIST_1][i][j][0]=fs->bottom_field->mv[LIST_1][RSD(i)][RSD(j)][0]; 
        fs->bottom_field->mv[LIST_1][i][j][1]=fs->bottom_field->mv[LIST_1][RSD(i)][RSD(j)][1]; 
         
        fs->top_field->ref_idx[LIST_0][i][j]=fs->top_field->ref_idx[LIST_0][RSD(i)][RSD(j)] ;      
        fs->top_field->ref_idx[LIST_1][i][j]=fs->top_field->ref_idx[LIST_1][RSD(i)][RSD(j)] ;      
         
        fs->bottom_field->ref_idx[LIST_0][i][j]=fs->bottom_field->ref_idx[LIST_0][RSD(i)][RSD(j)] ;      
        fs->bottom_field->ref_idx[LIST_1][i][j]=fs->bottom_field->ref_idx[LIST_1][RSD(i)][RSD(j)] ;      
 
      fs->top_field->moving_block[i][j] =   
        !(((fs->top_field->ref_idx[LIST_0][i][j] == 0) &&  
        (abs(fs->top_field->mv[LIST_0][i][j][0])>>1 == 0) &&  
        (abs(fs->top_field->mv[LIST_0][i][j][1])>>1 == 0)) ||  
        ((fs->top_field->ref_idx[LIST_0][i][j] == -1) &&  
        (fs->top_field->ref_idx[LIST_1][i][j] == 0) &&  
        (abs(fs->top_field->mv[LIST_1][i][j][0])>>1 == 0) &&  
        (abs(fs->top_field->mv[LIST_1][i][j][1])>>1 == 0))); 
 
      fs->bottom_field->moving_block[i][j]=  
        !(((fs->bottom_field->ref_idx[LIST_0][i][j] == 0) &&  
        (abs(fs->bottom_field->mv[LIST_0][i][j][0])>>1 == 0) &&  
        (abs(fs->bottom_field->mv[LIST_0][i][j][1])>>1 == 0)) ||  
        ((fs->bottom_field->ref_idx[LIST_0][i][j] == -1) &&  
        (fs->bottom_field->ref_idx[LIST_1][i][j] == 0) &&  
        (abs(fs->bottom_field->mv[LIST_1][i][j][0])>>1 == 0) &&  
        (abs(fs->bottom_field->mv[LIST_1][i][j][1])>>1 == 0))); 
      } 
    }     
     
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Allocate memory for buffering of reference picture reordering commands 
 ************************************************************************ 
 */ 
void alloc_ref_pic_list_reordering_buffer(Slice *currSlice) 
{ 
  int size = img->num_ref_idx_l0_active+1; 
 
  if (img->type!=I_SLICE && img->type!=SI_SLICE) 
  { 
    if ((currSlice->remapping_of_pic_nums_idc_l0 = calloc(size,sizeof(int)))==NULL) no_mem_exit("alloc_ref_pic_list_reordering_buffer: remapping_of_pic_nums_idc_l0"); 
    if ((currSlice->abs_diff_pic_num_minus1_l0 = calloc(size,sizeof(int)))==NULL) no_mem_exit("alloc_ref_pic_list_reordering_buffer: abs_diff_pic_num_minus1_l0"); 
    if ((currSlice->long_term_pic_idx_l0 = calloc(size,sizeof(int)))==NULL) no_mem_exit("alloc_ref_pic_list_reordering_buffer: long_term_pic_idx_l0"); 
  } 
  else 
  { 
    currSlice->remapping_of_pic_nums_idc_l0 = NULL; 
    currSlice->abs_diff_pic_num_minus1_l0 = NULL; 
    currSlice->long_term_pic_idx_l0 = NULL; 
  } 
   
  size = img->num_ref_idx_l1_active+1; 
 
  if (img->type==B_SLICE) 
  { 
    if ((currSlice->remapping_of_pic_nums_idc_l1 = calloc(size,sizeof(int)))==NULL) no_mem_exit("alloc_ref_pic_list_reordering_buffer: remapping_of_pic_nums_idc_l1"); 
    if ((currSlice->abs_diff_pic_num_minus1_l1 = calloc(size,sizeof(int)))==NULL) no_mem_exit("alloc_ref_pic_list_reordering_buffer: abs_diff_pic_num_minus1_l1"); 
    if ((currSlice->long_term_pic_idx_l1 = calloc(size,sizeof(int)))==NULL) no_mem_exit("alloc_ref_pic_list_reordering_buffer: long_term_pic_idx_l1"); 
  } 
  else 
  { 
    currSlice->remapping_of_pic_nums_idc_l1 = NULL; 
    currSlice->abs_diff_pic_num_minus1_l1 = NULL; 
    currSlice->long_term_pic_idx_l1 = NULL; 
  } 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Free memory for buffering of reference picture reordering commands 
 ************************************************************************ 
 */ 
void free_ref_pic_list_reordering_buffer(Slice *currSlice) 
{ 
 
  if (currSlice->remapping_of_pic_nums_idc_l0)  
    free(currSlice->remapping_of_pic_nums_idc_l0); 
  if (currSlice->abs_diff_pic_num_minus1_l0) 
    free(currSlice->abs_diff_pic_num_minus1_l0); 
  if (currSlice->long_term_pic_idx_l0) 
    free(currSlice->long_term_pic_idx_l0); 
 
  currSlice->remapping_of_pic_nums_idc_l0 = NULL; 
  currSlice->abs_diff_pic_num_minus1_l0 = NULL; 
  currSlice->long_term_pic_idx_l0 = NULL; 
   
  if (currSlice->remapping_of_pic_nums_idc_l1) 
    free(currSlice->remapping_of_pic_nums_idc_l1); 
  if (currSlice->abs_diff_pic_num_minus1_l1) 
    free(currSlice->abs_diff_pic_num_minus1_l1); 
  if (currSlice->long_term_pic_idx_l1) 
    free(currSlice->long_term_pic_idx_l1); 
   
  currSlice->remapping_of_pic_nums_idc_l1 = NULL; 
  currSlice->abs_diff_pic_num_minus1_l1 = NULL; 
  currSlice->long_term_pic_idx_l1 = NULL; 
} 
 
/*! 
 ************************************************************************ 
 * \brief 
 *      Tian Dong 
 *          June 13, 2002, Modifed on July 30, 2003 
 * 
 *      If a gap in frame_num is found, try to fill the gap 
 * \param img 
 *       
 ************************************************************************ 
 */ 
void fill_frame_num_gap(ImageParameters *img) 
{ 
  int CurrFrameNum; 
  int UnusedShortTermFrameNum; 
  StorablePicture *picture = NULL; 
  int nal_ref_idc_bak; 
 
//  printf("A gap in frame number is found, try to fill it.\n"); 
 
  nal_ref_idc_bak = img->nal_reference_idc; 
  img->nal_reference_idc = 1; 
 
  UnusedShortTermFrameNum = (img->pre_frame_num + 1) % img->MaxFrameNum; 
  CurrFrameNum = img->frame_num; 
 
  while (CurrFrameNum != UnusedShortTermFrameNum) 
  { 
    picture = alloc_storable_picture (FRAME, img->width, img->height, img->width_cr, img->height_cr); 
    picture->coded_frame = 1; 
    picture->pic_num = UnusedShortTermFrameNum; 
    picture->non_existing = 1; 
    picture->is_output = 1; 
     
    img->adaptive_ref_pic_buffering_flag = 0; 
 
    store_picture_in_dpb(picture); 
 
    picture=NULL; 
    UnusedShortTermFrameNum = (UnusedShortTermFrameNum + 1) % img->MaxFrameNum; 
  } 
 
  img->nal_reference_idc = nal_ref_idc_bak; 
}