/*!
 **************************************************************************************
 * \file
 *    slice.c
 * \brief
 *    generate the slice header, setup the bit buffer for slices,
 *    and generates the slice NALU(s)

 * \author
 *    Main contributors (see contributors.h for copyright, address and affiliation details)
 *     - Athanasios Leontaris            <aleon@dolby.com>
 *     - Karsten Suehring
 *     - Alexis Michael Tourapis         <alexismt@ieee.org> 
 ***************************************************************************************
 */

#include "contributors.h"

#include <math.h>
#include <float.h>

#include "global.h"
#include "image.h"
#include "wp.h"
#include "list_reorder.h"

/*!
 ************************************************************************
 * \brief
 *    init_ref_pic_list_reordering initializations should go here
 ************************************************************************
 */
void init_ref_pic_list_reordering(Slice* currSlice, int refReorderMethod)
{
  currSlice->ref_pic_list_reordering_flag[LIST_0] = 0;
  currSlice->ref_pic_list_reordering_flag[LIST_1] = 0;

  if (refReorderMethod == 2)
    currSlice->poc_ref_pic_reorder_frame = tlyr_ref_pic_reorder_frame_default;
  else
    currSlice->poc_ref_pic_reorder_frame = poc_ref_pic_reorder_frame_default;


}

/*!
************************************************************************
* \brief
*    decide reference picture reordering, Frame only
************************************************************************
*/
void poc_ref_pic_reorder_frame_default(Slice *currSlice, unsigned num_ref_idx_lX_active, int list_no)
{
  StorablePicture **list = currSlice->listX[list_no];
  int *reordering_of_pic_nums_idc = currSlice->reordering_of_pic_nums_idc[list_no]; 
  int *abs_diff_pic_num_minus1 = currSlice->abs_diff_pic_num_minus1[list_no]; 
  VideoParameters *p_Vid = currSlice->p_Vid;
  InputParameters *p_Inp = currSlice->p_Inp;
  StorablePicture *p_Enc_Pic = p_Vid->enc_picture;
  DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;

  unsigned int i,j,k;

  int currPicNum, picNumLXPred;

  int default_order[32];
  int re_order[32];
  int tmp_reorder[32];
  int list_sign[32];
  int reorder_stop, no_reorder;
  int poc_diff[32];
  int tmp_value, diff;

  int abs_poc_dist;
  int maxPicNum;
  unsigned int num_refs;

  maxPicNum  = p_Vid->max_frame_num;
  currPicNum = p_Vid->frame_num;

  picNumLXPred = currPicNum;

  // First assign default list order.
  for (i=0; i<num_ref_idx_lX_active; i++)
  {
    default_order[i] = list[i]->pic_num;
  }

  // Now access all references in buffer and assign them
  // to a potential reordering list. For each one of these
  // references compute the poc distance compared to current
  // frame.
  num_refs = currSlice->p_Dpb->ref_frames_in_buffer;
  for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++)
  {
    poc_diff[i] = 0xFFFF;
    re_order[i] = p_Dpb->fs_ref[i]->frame->pic_num;

#if (MVC_EXTENSION_ENABLE)
    if (p_Dpb->fs_ref[i]->is_used==3 && (p_Dpb->fs_ref[i]->frame->used_for_reference)&&(!p_Dpb->fs_ref[i]->frame->is_long_term)
      && (p_Inp->num_of_views==1 || p_Dpb->fs_ref[i]->view_id==p_Vid->view_id))
#else
    if (p_Dpb->fs_ref[i]->is_used==3 && (p_Dpb->fs_ref[i]->frame->used_for_reference)&&(!p_Dpb->fs_ref[i]->frame->is_long_term))
#endif
    {
      abs_poc_dist = iabs(p_Dpb->fs_ref[i]->frame->poc - p_Enc_Pic->poc) ;
      poc_diff[i] = abs_poc_dist;
      if (list_no == LIST_0)
      {
        list_sign[i] = (p_Enc_Pic->poc < p_Dpb->fs_ref[i]->frame->poc) ? +1 : -1;
      }
      else
      {
        list_sign[i] = (p_Enc_Pic->poc > p_Dpb->fs_ref[i]->frame->poc) ? +1 : -1;
      }
    }
  }

  // now sort these references based on poc (temporal) distance
  for (i = 0; i < (num_refs - 1); i++)
  {
    for (j = i + 1; j < num_refs; j++)
    {
      if (poc_diff[i]>poc_diff[j] || (poc_diff[i] == poc_diff[j] && list_sign[j] > list_sign[i]))
      {

        tmp_value = poc_diff[i];
        poc_diff[i] = poc_diff[j];
        poc_diff[j] = tmp_value;
        tmp_value  = re_order[i];
        re_order[i] = re_order[j];
        re_order[j] = tmp_value ;
        tmp_value  = list_sign[i];
        list_sign[i] = list_sign[j];
        list_sign[j] = tmp_value;
      }
    }
  }

  // populate list with selections from the pre-analysis stage
  if ( p_Inp->WPMCPrecision 
    && p_Vid->pWPX->curr_wp_rd_pass->algorithm != WP_REGULAR
    && p_Vid->pWPX->num_wp_ref_list[list_no] )
  {
    for (i=0; i<num_ref_idx_lX_active; i++)
    {
      re_order[i] = p_Vid->pWPX->wp_ref_list[list_no][i].PicNum;
    }
  }

  // Check versus default list to see if any
  // change has happened
  no_reorder = 1;
  for (i=0; i<num_ref_idx_lX_active; i++)
  {
    if (default_order[i] != re_order[i])
    {
      no_reorder = 0;
    }
  }

  // If different, then signal reordering
  if (no_reorder==0)
  {
    for (i=0; i<num_ref_idx_lX_active; i++)
    {
      diff = re_order[i]-picNumLXPred;
      if (diff <= 0)
      {
        reordering_of_pic_nums_idc[i] = 0;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
        if (abs_diff_pic_num_minus1[i] < 0)
          abs_diff_pic_num_minus1[i] = maxPicNum -1;
      }
      else
      {
        reordering_of_pic_nums_idc[i] = 1;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
      }
      picNumLXPred = re_order[i];

      tmp_reorder[i] = re_order[i];

      k = i;
      for (j=i; j<num_ref_idx_lX_active; j++)
      {
        if (default_order[j] != re_order[i])
        {
          ++k;
          tmp_reorder[k] = default_order[j];
        }
      }
      reorder_stop = 1;
      for(j=i+1; j<num_ref_idx_lX_active; j++)
      {
        if (tmp_reorder[j] != re_order[j])
        {
          reorder_stop = 0;
          break;
        }
      }

      if (reorder_stop==1)
      {
        ++i;
        break;
      }
      memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));

    }
    reordering_of_pic_nums_idc[i] = 3;

    memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));

    if (list_no==0)
    {
      currSlice->ref_pic_list_reordering_flag[LIST_0] = 1;
    }
    else
    {
      currSlice->ref_pic_list_reordering_flag[LIST_1] = 1;
    }
  }
}

/*!
************************************************************************
* \brief
*    decide reference picture reordering, Field only
************************************************************************
*/
void poc_ref_pic_reorder_field(Slice *currSlice, unsigned num_ref_idx_lX_active, int list_no)
{
  StorablePicture **list = currSlice->listX[list_no];
  int *reordering_of_pic_nums_idc = currSlice->reordering_of_pic_nums_idc[list_no]; 
  int *abs_diff_pic_num_minus1 = currSlice->abs_diff_pic_num_minus1[list_no]; 

  VideoParameters *p_Vid = currSlice->p_Vid;
  //InputParameters *p_Inp = currSlice->p_Inp;
  StorablePicture *p_Enc_Pic = p_Vid->enc_picture;
  DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;

  unsigned int i,j,k;

  int currPicNum, picNumLXPred;

  int default_order[32];
  int re_order[32];
  int tmp_reorder[32];
  int list_sign[32];  
  int poc_diff[32];
  int fld_type[32];

  int reorder_stop, no_reorder;
  int tmp_value, diff;

  int abs_poc_dist;
  int maxPicNum;
  unsigned int num_refs;

  int field_used[2] = {1, 2};
  int fld, idx, num_flds;

  unsigned int top_idx = 0;
  unsigned int bot_idx = 0;
  unsigned int list_size = 0;

  StorablePicture *pField[2]; // 0: TOP_FIELD, 1: BOTTOM_FIELD
  FrameStore      *pFrameStore; 

  maxPicNum  = 2 * p_Vid->max_frame_num;
  currPicNum = 2 * p_Vid->frame_num + 1;

  picNumLXPred = currPicNum;

  // First assign default list order.
  for (i=0; i<num_ref_idx_lX_active; i++)
  {
    default_order[i] = list[i]->pic_num;
  }

  // Now access all references in buffer and assign them
  // to a potential reordering list. For each one of these
  // references compute the poc distance compared to current
  // frame.  
  // look for eligible fields
  idx = 0;

  for (i=0; i<p_Dpb->ref_frames_in_buffer; i++)
  {
    pFrameStore = p_Dpb->fs_ref[i];
    pField[0]   = pFrameStore->top_field;
    pField[1]   = pFrameStore->bottom_field;
    num_flds    = (currSlice->structure == BOTTOM_FIELD && (p_Enc_Pic->poc == (pField[0]->poc + 1) ) ) ? 1 : 2;

    poc_diff[2*i    ] = 0xFFFF;
    poc_diff[2*i + 1] = 0xFFFF;

    for ( fld = 0; fld < num_flds; fld++ )
    {
#if (MVC_EXTENSION_ENABLE)
      if ( (pFrameStore->is_used & field_used[fld]) && pField[fld]->used_for_reference && !(pField[fld]->is_long_term) 
        && (p_Vid->p_Inp->num_of_views==1 || pField[fld]->view_id==p_Vid->view_id))
#else
      if ( (pFrameStore->is_used & field_used[fld]) && pField[fld]->used_for_reference && !(pField[fld]->is_long_term))
#endif
      {
        abs_poc_dist = iabs(pField[fld]->poc - p_Enc_Pic->poc) ;
        poc_diff[idx] = abs_poc_dist;
        re_order[idx] = pField[fld]->pic_num;
        fld_type[idx] = fld + 1;

        if (list_no == LIST_0)
        {
          list_sign[idx] = (p_Enc_Pic->poc < pField[fld]->poc) ? +1 : -1;
        }
        else
        {
          list_sign[idx] = (p_Enc_Pic->poc > pField[fld]->poc) ? +1 : -1;
        }
        idx++;
      }
    }
  }
  num_refs = idx;

  // now sort these references based on poc (temporal) distance
  for (i=0; i < num_refs-1; i++)
  {
    for (j = (i + 1); j < num_refs; j++)
    {
      if (poc_diff[i] > poc_diff[j] || (poc_diff[i] == poc_diff[j] && list_sign[j] > list_sign[i]))
      {
        // poc_diff
        tmp_value   = poc_diff[i];
        poc_diff[i] = poc_diff[j];
        poc_diff[j] = tmp_value;
        // re_order (PicNum)
        tmp_value   = re_order[i];
        re_order[i] = re_order[j];
        re_order[j] = tmp_value;
        // list_sign
        tmp_value    = list_sign[i];
        list_sign[i] = list_sign[j];
        list_sign[j] = tmp_value;
        // fld_type
        tmp_value   = fld_type[i];
        fld_type[i] = fld_type[j];
        fld_type[j] = tmp_value ;
      }
    }
  }

  if (currSlice->structure == TOP_FIELD)
  {
    while ((top_idx < num_refs)||(bot_idx < num_refs))
    {
      for ( ; top_idx < num_refs; top_idx++)
      {
        if ( fld_type[top_idx] == TOP_FIELD )
        {
          tmp_reorder[list_size] = re_order[top_idx];
          list_size++;
          top_idx++;
          break;
        }
      }
      for ( ; bot_idx < num_refs; bot_idx++)
      {
        if ( fld_type[bot_idx] == BOTTOM_FIELD )
        {
          tmp_reorder[list_size] = re_order[bot_idx];
          list_size++;
          bot_idx++;
          break;
        }
      }
    }
  }
  if (currSlice->structure == BOTTOM_FIELD)
  {
    while ((top_idx < num_refs)||(bot_idx < num_refs))
    {
      for ( ; bot_idx < num_refs; bot_idx++)
      {
        if ( fld_type[bot_idx] == BOTTOM_FIELD )
        {
          tmp_reorder[list_size] = re_order[bot_idx];
          list_size++;
          bot_idx++;
          break;
        }
      }
      for ( ; top_idx < num_refs; top_idx++)
      {
        if ( fld_type[top_idx] == TOP_FIELD )
        {
          tmp_reorder[list_size] = re_order[top_idx];
          list_size++;
          top_idx++;
          break;
        }
      }
    }
  }

  // copy to final matrix
  list_size = imin( list_size, 32 );
  for ( i = 0; i < list_size; i++ )
  {
    re_order[i] = tmp_reorder[i];
  }

  // Check versus default list to see if any
  // change has happened
  no_reorder = 1;
  for (i=0; i<num_ref_idx_lX_active; i++)
  {
    if (default_order[i] != re_order[i])
    {
      no_reorder = 0;
    }
  }

  // If different, then signal reordering
  if (no_reorder == 0)
  {
    for (i=0; i<num_ref_idx_lX_active; i++)
    {
      diff = re_order[i] - picNumLXPred;
      if (diff <= 0)
      {
        reordering_of_pic_nums_idc[i] = 0;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
        if (abs_diff_pic_num_minus1[i] < 0)
          abs_diff_pic_num_minus1[i] = maxPicNum -1;
      }
      else
      {
        reordering_of_pic_nums_idc[i] = 1;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
      }
      picNumLXPred = re_order[i];

      tmp_reorder[i] = re_order[i];

      k = i;
      for (j = i; j < num_ref_idx_lX_active; j++)
      {
        if (default_order[j] != re_order[i])
        {
          ++k;
          tmp_reorder[k] = default_order[j];
        }
      }
      reorder_stop = 1;
      for(j=i+1; j<num_ref_idx_lX_active; j++)
      {
        if (tmp_reorder[j] != re_order[j])
        {
          reorder_stop = 0;
          break;
        }
      }

      if (reorder_stop==1)
      {
        ++i;
        break;
      }

      memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));
    }
    reordering_of_pic_nums_idc[i] = 3;

    memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));

    if (list_no==0)
    {
      currSlice->ref_pic_list_reordering_flag[LIST_0] = 1;
    }
    else
    {
      currSlice->ref_pic_list_reordering_flag[LIST_1] = 1;
    }
  }
}


/*!
************************************************************************
* \brief
*    decide reference picture reordering based on temporal layer, Frame only
************************************************************************
*/
void tlyr_ref_pic_reorder_frame_default(Slice *currSlice, unsigned num_ref_idx_lX_active, int list_no)
{
  StorablePicture **list = currSlice->listX[list_no];
  int *reordering_of_pic_nums_idc = currSlice->reordering_of_pic_nums_idc[list_no]; 
  int *abs_diff_pic_num_minus1 = currSlice->abs_diff_pic_num_minus1[list_no]; 

  VideoParameters *p_Vid = currSlice->p_Vid;
  InputParameters *p_Inp = currSlice->p_Inp;
  StorablePicture *p_Enc_Pic = p_Vid->enc_picture;
  struct decoded_picture_buffer *p_Dpb = currSlice->p_Dpb;

  unsigned int i,j,k;

  int currPicNum, picNumLXPred;

  int default_order[32];
  int re_order[32];
  int tmp_reorder[32];
  int list_sign[32];
  int reorder_stop, no_reorder;
  int poc_diff[32];

  int temporal_layer[32];

  int diff;

  int abs_poc_dist;
  int maxPicNum;
  unsigned int num_refs;

  int tmp_poc_diff, tmp_re_order, tmp_list_sign, tmp_temporal_layer;
  unsigned int beginIdx = 0;
  char newSize = 0;


  maxPicNum  = p_Vid->max_frame_num;
  currPicNum = p_Vid->frame_num;

  picNumLXPred = currPicNum;

  // First assign default list order.
  for (i=0; i<num_ref_idx_lX_active; i++)
  {
    default_order[i] = list[i]->pic_num;
  }

  // Now access all references in buffer and assign them
  // to a potential reordering list. For each one of these
  // references compute the poc distance compared to current
  // frame.
  num_refs = p_Dpb->ref_frames_in_buffer;
  for (i=0; i<p_Dpb->ref_frames_in_buffer; i++)
  {
    poc_diff[i] = 0xFFFF;
    re_order[i] = p_Dpb->fs_ref[i]->frame->pic_num;
    
    temporal_layer[i] = p_Dpb->fs_ref[i]->frame->temporal_layer; 

    if (p_Dpb->fs_ref[i]->is_used==3 && (p_Dpb->fs_ref[i]->frame->used_for_reference)&&(!p_Dpb->fs_ref[i]->frame->is_long_term))
    {
      abs_poc_dist = iabs(p_Dpb->fs_ref[i]->frame->poc - p_Enc_Pic->poc) ;
      poc_diff[i] = abs_poc_dist;
      if (list_no == LIST_0)
      {
        list_sign[i] = (p_Enc_Pic->poc < p_Dpb->fs_ref[i]->frame->poc) ? +1 : -1;
      }
      else
      {
        list_sign[i] = (p_Enc_Pic->poc > p_Dpb->fs_ref[i]->frame->poc) ? +1 : -1;
      }
    }
  }

  // first, sort the references based on poc (temporal) distance 
  for (i = 0; i < (num_refs - 1); i++)
  {
    for (j = i + 1; j < num_refs; j++)
    {
      if (list_sign[i] == list_sign[j] && poc_diff[i] > poc_diff[j])
      {
        tmp_poc_diff = poc_diff[i];
        tmp_re_order = re_order[i];
        tmp_list_sign = list_sign[i];
        tmp_temporal_layer = temporal_layer[i];
        poc_diff[i] = poc_diff[j];
        re_order[i] = re_order[j];
        list_sign[i] = list_sign[j];
        temporal_layer[i] = temporal_layer[j];
        poc_diff[j] = tmp_poc_diff;
        re_order[j] = tmp_re_order ;
        list_sign[j] = tmp_list_sign;
        temporal_layer[j] = tmp_temporal_layer;
      }
    }
  }

  // use the closest valid reference frame + 3 temporal layer 0 frames
  for (i = 0; i < num_refs; i++)
  {  
    /*
    if ( (i == 0 && temporal_layer[i] <= p_Enc_Pic->temporal_layer) ||
         (i && !temporal_layer[i]) ) // valid reference pic
    */
    if (temporal_layer[i] <= p_Enc_Pic->temporal_layer) 
    {
      tmp_poc_diff = poc_diff[i];
      tmp_re_order = re_order[i];
      tmp_list_sign = list_sign[i];
      tmp_temporal_layer = temporal_layer[i];
      for (j = i; j > beginIdx; j--) 
      {
        poc_diff[j] = poc_diff[j-1];
        re_order[j] = re_order[j-1];
        list_sign[j] = list_sign[j-1];
        temporal_layer[j] = temporal_layer[j-1];
      }                   
      poc_diff[beginIdx] = tmp_poc_diff;
      re_order[beginIdx] = tmp_re_order;
      list_sign[beginIdx] = tmp_list_sign;
      temporal_layer[beginIdx] = tmp_temporal_layer;
      beginIdx += 1;

      newSize++;
    }
  }
  currSlice->listXsize[0] = newSize; // update with valid size

  // populate list with selections from the pre-analysis stage
  if ( p_Inp->WPMCPrecision 
    && p_Vid->pWPX->curr_wp_rd_pass->algorithm != WP_REGULAR
    && p_Vid->pWPX->num_wp_ref_list[list_no] )
  {
    for (i=0; i<num_ref_idx_lX_active; i++)
    {
      re_order[i] = p_Vid->pWPX->wp_ref_list[list_no][i].PicNum;
    }
  }

  // Check versus default list to see if any
  // change has happened
  no_reorder = 1;
  for (i=0; i<num_ref_idx_lX_active; i++)
  {
    if (default_order[i] != re_order[i])
    {
      no_reorder = 0;
    }
  }

  // If different, then signal reordering
  if (no_reorder==0)
  {
    for (i=0; i<num_ref_idx_lX_active; i++)
    {
      diff = re_order[i]-picNumLXPred;
      if (diff <= 0)
      {
        reordering_of_pic_nums_idc[i] = 0;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
        if (abs_diff_pic_num_minus1[i] < 0)
          abs_diff_pic_num_minus1[i] = maxPicNum -1;
      }
      else
      {
        reordering_of_pic_nums_idc[i] = 1;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
      }
      picNumLXPred = re_order[i];

      tmp_reorder[i] = re_order[i];

      k = i;
      for (j=i; j<num_ref_idx_lX_active; j++)
      {
        if (default_order[j] != re_order[i])
        {
          ++k;
          tmp_reorder[k] = default_order[j];
        }
      }
      reorder_stop = 1;
      for(j=i+1; j<num_ref_idx_lX_active; j++)
      {
        if (tmp_reorder[j] != re_order[j])
        {
          reorder_stop = 0;
          break;
        }
      }

      if (reorder_stop==1)
      {
        ++i;
        break;
      }
      memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));

    }
    reordering_of_pic_nums_idc[i] = 3;

    memcpy ( default_order, tmp_reorder, num_ref_idx_lX_active * sizeof(int));

    if (list_no==0)
    {
      currSlice->ref_pic_list_reordering_flag[LIST_0] = 1;
    }
    else
    {
      currSlice->ref_pic_list_reordering_flag[LIST_1] = 1;
    }
  }
}

/*!
************************************************************************
* \brief
*    Reorder lists
************************************************************************
*/

void reorder_lists( Slice *currSlice )
{
  InputParameters *p_Inp = currSlice->p_Inp;

  // Perform reordering based on poc distances for HierarchicalCoding
  if ( p_Inp->ReferenceReorder && currSlice->slice_type == P_SLICE )
  {
    int i, num_ref;

    alloc_ref_pic_list_reordering_buffer(currSlice);

    for (i = 0; i < currSlice->num_ref_idx_active[LIST_0] + 1; i++)
    {
      currSlice->reordering_of_pic_nums_idc[LIST_0][i] = 3;
      currSlice->abs_diff_pic_num_minus1[LIST_0][i] = 0;
      currSlice->long_term_pic_idx[LIST_0][i] = 0;
    }

    num_ref = currSlice->num_ref_idx_active[LIST_0];

    if ( p_Inp->ReferenceReorder == 2 ) 
    { // temporal layer based
      if ( currSlice->structure == FRAME )
        currSlice->poc_ref_pic_reorder_frame(currSlice, num_ref, LIST_0);
    }
    else
    {
      if ( currSlice->structure == FRAME )
        currSlice->poc_ref_pic_reorder_frame(currSlice, num_ref, LIST_0);
      else
      {
        poc_ref_pic_reorder_field(currSlice, num_ref, LIST_0);
      }
    }

    currSlice->num_ref_idx_active[LIST_0] = currSlice->listXsize[0]; 
    //reference picture reordering
    reorder_ref_pic_list ( currSlice, LIST_0);
  }
   currSlice->num_ref_idx_active[LIST_0] = currSlice->listXsize[0]; 
}

/*!
************************************************************************
* \brief
*    Reorder lists
************************************************************************
*/

void wp_mcprec_reorder_lists( Slice *currSlice )
{

  int i, num_ref;

  wpxModifyRefPicList( currSlice );

  alloc_ref_pic_list_reordering_buffer(currSlice);

  for (i = 0; i < currSlice->num_ref_idx_active[LIST_0] + 1; i++)
  {
    currSlice->reordering_of_pic_nums_idc[LIST_0][i] = 3;
    currSlice->abs_diff_pic_num_minus1[LIST_0][i] = 0;
    currSlice->long_term_pic_idx[LIST_0][i] = 0;
  }

  if (currSlice->slice_type == B_SLICE) // type should be part of currSlice not p_Vid
  {
    for (i = 0; i < currSlice->num_ref_idx_active[LIST_1] + 1; i++)
    {
      currSlice->reordering_of_pic_nums_idc[LIST_1][i] = 3;
      currSlice->abs_diff_pic_num_minus1[LIST_1][i] = 0;
      currSlice->long_term_pic_idx[LIST_1][i] = 0;
    }
  }

  // LIST_0
  num_ref = currSlice->num_ref_idx_active[LIST_0];

  currSlice->poc_ref_pic_reorder_frame(currSlice, num_ref, LIST_0);
  // reference picture reordering
  reorder_ref_pic_list ( currSlice, LIST_0);

  if ( currSlice->slice_type == B_SLICE )
  {
    // LIST_1
    num_ref = currSlice->num_ref_idx_active[LIST_1];

    currSlice->poc_ref_pic_reorder_frame(currSlice, num_ref, LIST_1);
    // reference picture reordering
    reorder_ref_pic_list ( currSlice, LIST_1);
  }
}

void set_default_ref_pic_lists(Slice *currSlice)
{
  int list, ref;

  for(list = LIST_0; list <= (currSlice->slice_type == P_SLICE ? LIST_0:LIST_1); list++)
  {
    for(ref = 0; ref < currSlice->listXsize[list]; ref++)
    {
      currSlice->default_pic_num[list][ref] = currSlice->listX[list][ref]->pic_num;
#if MVC_EXTENSION_ENABLE
      currSlice->default_view_id[list][ref] = currSlice->listX[list][ref]->view_id;
#endif
    }
  }
}
#if MVC_EXTENSION_ENABLE
void reorder_against_default_ref_pic_lists(Slice *currSlice, int cur_list)
{
  VideoParameters *p_Vid = currSlice->p_Vid;
  int *reordering_of_pic_nums_idc = currSlice->reordering_of_pic_nums_idc[cur_list];
  int *abs_diff_pic_num_minus1 = currSlice->abs_diff_pic_num_minus1[cur_list];
  int *abs_diff_view_idx_minus1 = currSlice->abs_diff_view_idx_minus1[cur_list];
  int i;

  int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred;
  int picViewIdxLX;
  int maxViewIdx =0;
  int currViewIdx = -1;
  int picViewIdxLXPred=-1;
  
  int diff;

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

  currViewIdx = p_Vid->view_id;
  maxViewIdx = 1;
  picViewIdxLXPred=-1;

  picNumLXPred = currPicNum/2;

  currSlice->ref_pic_list_reordering_flag[cur_list] = 0;
  for (i = 0; i < currSlice->listXsize[cur_list]; i++)
  {
    if(currSlice->default_view_id[cur_list][i] != currSlice->listX[cur_list][i]->view_id || 
       currSlice->default_pic_num[cur_list][i] != currSlice->listX[cur_list][i]->pic_num)
    {
      currSlice->ref_pic_list_reordering_flag[cur_list] = 1;
      break;
    }
  }
  if(!currSlice->ref_pic_list_reordering_flag[cur_list])
    return;

  // initialization
  for (i = 0; i < currSlice->listXsize[cur_list]+1; i++)
    reordering_of_pic_nums_idc[i] = 3;

  for (i=0; i < currSlice->listXsize[cur_list]; i++)
  {
    StorablePicture *ref_pic = currSlice->listX[cur_list][i];
    // inter_view ref reordering
    if(ref_pic->view_id != currViewIdx)
    {
      diff = 1;
      
      reordering_of_pic_nums_idc[i] = 5;
      abs_diff_view_idx_minus1[i] = iabs(diff)-1;
    }
    // temporal ref reordering
    else
    {
      diff = (ref_pic->pic_num-ref_pic->view_id)/2-picNumLXPred;
      if (diff <= 0)
      {
        reordering_of_pic_nums_idc[i] = 0;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
        if (abs_diff_pic_num_minus1[i] < 0)
          abs_diff_pic_num_minus1[i] = maxPicNum-1;
      }
      else
      {
        reordering_of_pic_nums_idc[i] = 1;
        abs_diff_pic_num_minus1[i] = iabs(diff)-1;
      }
    }

    if (reordering_of_pic_nums_idc[i] == 0 || reordering_of_pic_nums_idc[i] == 1)
    {
      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;
    }
    else if (reordering_of_pic_nums_idc[i] == 4 || reordering_of_pic_nums_idc[i] == 5)
    {
      if(reordering_of_pic_nums_idc[i] == 4) 
      {
        picViewIdxLX = picViewIdxLXPred - (abs_diff_view_idx_minus1[i] + 1);
        if( picViewIdxLX <0)
          picViewIdxLX += maxViewIdx;
      }
      else //if(reordering_of_pic_nums_idc[i] == 5)
      {
        picViewIdxLX = picViewIdxLXPred + (abs_diff_view_idx_minus1[i] + 1);
        if( picViewIdxLX >= maxViewIdx)
          picViewIdxLX -= maxViewIdx;
      }
      picViewIdxLXPred = picViewIdxLX;
    }
  }
}
#endif
