www.pudn.com > p264decoder.zip > lists.c


/***************************************************************************** 
* lists.c: h264 decoder library 
***************************************************************************** 
* Copyright (C) 2006 p264 project 
* $Id: $ 
* 
* Authors: Peter Lee (lspbeyond@126.com) 
* 2005-2006 at icas of Ningbo university, China 
* p264 Decoder site: http://p264decoder.zj.com 
* 
* This program is free software; you can redistribute it and/or modify 
* it under the terms of the GNU General Public License as published by 
* the Free Software Foundation; either version 2 of the License, or 
* (at your option) any later version. 
* 
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
* GNU General Public License for more details. 
* 
* You should have received a copy of the GNU General Public License 
* along with this program; if not, write to the Free Software 
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. 
*****************************************************************************/ 
 
//#include  
//#include  
//#include  
 
#include "core/core.h" 
#include "lists.h" 
 
//note: when array sequence is short and almost sorted, insert sort is the best choice 
void insert_sort(p264_frame_t **list, int i_list_idx, p264_frame_t *ref) 
{ 
  int j,k; 
 
  //[1] find the position for current ref 
  if (SHORT_TERM_REF==ref->i_ref_type) 
  { 
    for (j=i_list_idx; j>=0; j--) 
    { 
      if (ref->i_pic_num < list[j]->i_pic_num) 
      { 
        break; 
      } 
    } 
  } 
  else if (LONG_TERM_REF==ref->i_ref_type) 
  { 
    for (j=i_list_idx; j=0; j--) 
    { 
      if (ref->i_long_term_pic_num > list[j]->i_long_term_pic_num) 
      { 
        break; 
      } 
    } 
  } 
 
  //[2] adjust the back part of the list 
  for (k=i_list_idx; k>j; k--) 
  { 
    list[k+1]=list[k]; 
  } 
 
  //[3] insert ref into list 
  list[j+1]=ref; 
 
} 
 
//lsptod: support b and field 
int p264_lists_init(p264_t *h) 
{ 
  int i_max_frame_num = 1<< h->sps->i_log2_max_frame_num; 
  int i; 
  int i_short_term_count; 
 
  //i_slice case: no list needed 
  if(h->sh.i_type == SLICE_TYPE_I || h->sh.i_type == SLICE_TYPE_SI) 
  { 
    h->i_ref0=0; 
    h->i_ref1=0; 
    return 0; 
  } 
 
  //[1] compute picture num 
  i_short_term_count=0; 
  for( i = 1; i < h->sps->i_num_ref_frames + 1; i++ ) 
  { 
    p264_frame_t *ref=h->frames.reference[i]; 
    if(SHORT_TERM_REF==ref->i_ref_type) 
    { 
      int i_frame_num_wrap; 
      if(ref->i_frame_num > h->sh.i_frame_num) 
      { 
        i_frame_num_wrap=ref->i_frame_num - i_max_frame_num; 
      } 
      else 
      { 
        i_frame_num_wrap=ref->i_frame_num;  
      } 
      ref->i_pic_num=i_frame_num_wrap; 
      i_short_term_count++; 
    } 
  } 
 
  //[2]Slice P: insert and sort 
  if(h->sh.i_type == SLICE_TYPE_P || h->sh.i_type == SLICE_TYPE_SP) 
  { 
    int i_list0_short_idx=-1; 
    int i_list0_long_idx=-1; 
    //<1> add short term ref to list0 and sort 
    for( i = 1; i < h->sps->i_num_ref_frames + 1; i++ ) 
    { 
      p264_frame_t *ref=h->frames.reference[i]; 
      if (SHORT_TERM_REF==ref->i_ref_type) 
      { 
        insert_sort(h->fref0, i_list0_short_idx, ref); 
        i_list0_short_idx++; 
      } 
    } 
    //<2> add long term ref to list0 and sort 
    for( i = 1; i < h->sps->i_num_ref_frames + 1; i++ ) 
    { 
      p264_frame_t *ref=h->frames.reference[i]; 
      if (LONG_TERM_REF==ref->i_ref_type) 
      { 
        insert_sort(&h->fref0[i_short_term_count], i_list0_long_idx, ref); 
        i_list0_long_idx++; 
      } 
    } 
    //<3> set list0 size 
    h->i_ref0=i_list0_short_idx+i_list0_long_idx+2; 
  }//end of if(h->sh->i_type == SLICE_TYPE_P || h->sh->i_type == SLICE_TYPE_SP) 
 
  //[3]Slice B: //lsptodo 
 
 
  //lspdebug 
  //printf("list_size:%d\n",h->i_ref0); 
 
  return 0; 
} 
 
//lsptodo 
int p264_lists_reorder(p264_t *h) 
{ 
  return 0; 
} 
 
//lsptodo: support adaptive mode and discontinue frame num case 
int p264_lists_marking(p264_t *h) 
{ 
  int i,j; 
  p264_slice_header_t *sh=&h->sh; 
 
  if (NAL_SLICE_IDR==h->i_nal_type) 
  { 
    if (sh->b_no_output_of_prior_pics) //clear all 
    { 
      for( i = 1; i < h->sps->i_num_ref_frames + 1; i++ ) 
      { 
        h->frames.reference[i]->i_ref_type=NOT_USED_FOR_REF; 
      } 
    } 
 
    if (sh->b_long_term_reference_flag) //allow long term  
    { 
      h->fdec->i_ref_type=LONG_TERM_REF; 
    } 
    else 
    { 
      h->fdec->i_ref_type=SHORT_TERM_REF; 
    } 
    //change 
    h->fdec=h->frames.reference[1]; 
    h->frames.reference[1]=h->frames.reference[0]; 
    h->frames.reference[0]=h->fdec; 
    h->frames.i_used_size=2; 
  }//end of if (NAL_SLICE_IDR==h->i_nal_type) 
  else //NON IDR 
  { 
    if(h->sh.b_adaptive_ref_pic_marking_mode)//lsptodo 
    { 
      printf("not support adaptive ref marking yet"); 
      return -1; 
    } 
    else //FIFO, also called sliding window mode 
    { 
      //<0> !!! 
      h->fdec->i_ref_type=SHORT_TERM_REF; 
      //<1> find the min picnum ref 
      if(h->frames.i_used_size < h->sps->i_num_ref_frames+1) 
      { 
        i=h->frames.i_used_size; 
        h->frames.i_used_size++; 
      } 
      else 
      { 
        for( i = h->frames.i_used_size-1; i>=0; i-- ) 
        { 
          if (SHORT_TERM_REF==h->frames.reference[i]->i_ref_type) 
          {  
            h->frames.reference[i]->i_ref_type=NOT_USED_FOR_REF; 
            break; 
          } 
        } 
      } 
      h->fdec=h->frames.reference[i];//!!! 
      //<2> update the list 
      for(j=i; j>0; j--) 
      { 
        h->frames.reference[j]=h->frames.reference[j-1]; 
      } 
      h->frames.reference[0]=h->fdec; 
    }//end of FIFO 
  }//end of non IDR 
 
  //lspdebug 
  //printf("ref_count:%d--",h->sps->i_num_ref_frames); 
  //for( i = 1; i < h->sps->i_num_ref_frames + 1; i++ ) 
  //{ 
  //  printf("%d,",h->frames.reference[i]->i_frame_num); 
  //} 
  //printf("\n"); 
 
  return 0; 
}