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


/*****************************************************************************
 * p264: h264 decoder
 *****************************************************************************
 * Copyright (C) 2003 Laurent Aimar
 * $Id: decoder.c,v 1.1 2004/06/03 19:27:07 fenrir Exp $
 *
 * Authors: Laurent Aimar 
 *
 * Maintained by 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 

#include "core/core.h"
#include "core/cpu.h"
#include "core/vlc.h"

#include "macroblock.h" 
#include "set.h" 
#include "vlc.h"
#include "lists.h"

 
static void p264_slice_idr( p264_t *h ) 
{ 
  int i; 
 
  h->i_poc_msb = 0; 
  h->i_poc_lsb = 0; 
  h->i_frame_offset = 0; 
  h->i_frame_num = 0; 
 
  if( h->sps ) //needed??? 
  { 
    for( i = 0; i < h->sps->i_num_ref_frames + 1; i++ ) 
    { 
      h->frames.reference[i]->i_ref_type=NOT_USED_FOR_REF; 
      h->frames.reference[i]->i_poc = -1; 
    } 
 
    h->fdec = h->frames.reference[0]; 
    h->i_ref0 = 0; 
    h->i_ref1 = 0; 
  } 
} 

/* The slice reading is split in two part:  
*      - part 1 is before ref_pic_list_reordering( ) 
*      - part 2 is after  dec_ref_pic_marking( ) 
*/ 
static int p264_slice_header_part1_read( bs_t *s, 
                                        p264_slice_header_t *sh, p264_sps_t sps_array[32], p264_pps_t pps_array[256], int b_idr ) 
{ 
  sh->i_first_mb = bs_read_ue( s ); 
  sh->i_type = bs_read_ue( s ); 
  if( sh->i_type >= 5 ) 
  { 
    sh->i_type -= 5; //0-4 equal with 5-9 
  } 
  sh->i_pps_id = bs_read_ue( s ); 
  if( bs_eof( s ) || sh->i_pps_id >= 256 || pps_array[sh->i_pps_id].i_id == -1 ) 
  { 
    fprintf( stderr, "invalid pps_id %d in slice header\n", sh->i_pps_id); 
    return -1; 
  } 
 
  sh->pps = &pps_array[sh->i_pps_id]; 
  sh->sps = &sps_array[sh->pps->i_sps_id];    /* valid if pps valid */ 
 
  sh->i_frame_num = bs_read( s, sh->sps->i_log2_max_frame_num ); 
  if( !sh->sps->b_frame_mbs_only ) 
  { 
    sh->b_field_pic = bs_read1( s ); 
    if( sh->b_field_pic ) 
    { 
      sh->b_bottom_field = bs_read1( s ); 
    } 
  } 
 
  if( b_idr ) 
  { 
    sh->i_idr_pic_id = bs_read_ue( s ); 
  } 
  else 
  { 
    sh->i_idr_pic_id = 0; 
  } 
 
  if( sh->sps->i_poc_type == 0 ) 
  { 
    sh->i_poc_lsb = bs_read( s, sh->sps->i_log2_max_poc_lsb ); 
    if( sh->pps->b_pic_order && !sh->b_field_pic ) 
    { 
      sh->i_delta_poc_bottom = bs_read_se( s ); 
    } 
  } 
  else if( sh->sps->i_poc_type == 1 && !sh->sps->b_delta_pic_order_always_zero ) 
  { 
    sh->i_delta_poc[0] = bs_read_se( s ); 
    if( sh->pps->b_pic_order && !sh->b_field_pic ) 
    { 
      sh->i_delta_poc[1] = bs_read_se( s ); 
    } 
  } 
 
  if( sh->pps->b_redundant_pic_cnt ) 
  { 
    sh->i_redundant_pic_cnt = bs_read_ue( s ); 
  } 
 
  if( sh->i_type == SLICE_TYPE_B ) 
  { 
    sh->b_direct_spatial_mv_pred = bs_read1( s ); 
  } 
 
  if( sh->i_type == SLICE_TYPE_P || sh->i_type == SLICE_TYPE_SP || sh->i_type == SLICE_TYPE_B ) 
  { 
    sh->b_num_ref_idx_override = bs_read1( s ); 
 
    sh->i_num_ref_idx_l0_active = sh->pps->i_num_ref_idx_l0_active; /* default */ 
    sh->i_num_ref_idx_l1_active = sh->pps->i_num_ref_idx_l1_active; /* default */ 
 
    if( sh->b_num_ref_idx_override ) 
    { 
      sh->i_num_ref_idx_l0_active = bs_read_ue( s ) + 1; 
      if( sh->i_type == SLICE_TYPE_B ) 
      { 
        sh->i_num_ref_idx_l1_active = bs_read_ue( s ) + 1; 
      } 
    } 
  } 
 
  return bs_eof( s ) ? -1 : 0; 
} 
 
static int p264_slice_header_part2_read( bs_t *s, p264_slice_header_t *sh ) 
{ 
  if( sh->pps->b_cabac && sh->i_type != SLICE_TYPE_I && sh->i_type != SLICE_TYPE_SI ) 
  { 
    sh->i_cabac_init_idc = bs_read_ue( s ); 
  } 
  sh->i_qp_delta = bs_read_se( s ); 
 
  if( sh->i_type == SLICE_TYPE_SI || sh->i_type == SLICE_TYPE_SP ) 
  { 
    if( sh->i_type == SLICE_TYPE_SP ) 
    { 
      sh->b_sp_for_swidth = bs_read1( s ); 
    } 
    sh->i_qs_delta = bs_read_se( s ); 
  } 
 
  if( sh->pps->b_deblocking_filter_control ) 
  { 
    sh->i_disable_deblocking_filter_idc = bs_read_ue( s ); 
    if( sh->i_disable_deblocking_filter_idc != 1 ) 
    { 
      sh->i_alpha_c0_offset = bs_read_se( s ); 
      sh->i_beta_offset = bs_read_se( s ); 
    } 
  } 
  else 
  { 
    sh->i_alpha_c0_offset = 0; 
    sh->i_beta_offset = 0; 
  } 
 
  if( sh->pps->i_num_slice_groups > 1 && sh->pps->i_slice_group_map_type >= 3 && sh->pps->i_slice_group_map_type <= 5 ) 
  { 
    /* FIXME */ 
    return -1; 
  } 
  return 0; 
} 
 
//lspfinish 
static int p264_slice_header_ref_pic_reordering( bs_t *s, p264_slice_header_t *sh )
{
  int b_flag;

  if (sh->i_type!=SLICE_TYPE_I && sh->i_type!=SLICE_TYPE_SI) 
  { 
    b_flag=sh->b_ref_pic_list_reordering_l0=bs_read1(s); 
    if (b_flag) 
    { 
      int i=0; 
      int idc; 
      while (1) 
      { 
        idc=sh->ref_pic_list_order[0][i].idc=bs_read_ue(s); 
        if (3==idc) 
        { 
          break; 
        } 
        else if (idc>3) 
        { 
          fprintf(stderr,"wrong reordering of pic nums idc\n"); 
          return -1; 
        } 
        else 
        { 
          sh->ref_pic_list_order[0][i].arg=bs_read_ue(s); 
        } 
        i++; //!! 
      }//end of while (1) 
    }//end of if (b_flag) 
  }

  if (sh->i_type==SLICE_TYPE_B) 
  { 
    b_flag=sh->b_ref_pic_list_reordering_l1=bs_read1(s); 
    if (b_flag) 
    { 
      int i=0; 
      int idc; 
      while (1) 
      { 
        idc=sh->ref_pic_list_order[1][i].idc=bs_read_ue(s); 
        if (3==idc) 
        { 
          break; 
        } 
        else if (idc>3) 
        { 
          fprintf(stderr,"wrong reordering of pic nums idc\n"); 
          return -1; 
        } 
        else 
        { 
          sh->ref_pic_list_order[1][i].arg=bs_read_ue(s); 
        } 
        i++; //!! 
      }//end of while (1) 
    } 
  }

  return 0;
}

static int p264_slice_header_pred_weight_table( p264_t *h, bs_t *s )
{
  return -1;
} 
 
//lspfinish 
static int p264_slice_header_dec_ref_pic_marking( bs_t *s, p264_slice_header_t *sh, int i_nal_type  ) 
{ 
  if( i_nal_type == NAL_SLICE_IDR ) 
  { 
    sh->b_no_output_of_prior_pics = bs_read1( s ); 
    sh->b_long_term_reference_flag = bs_read1( s ); 
  } 
  else 
  { 
    sh->b_adaptive_ref_pic_marking_mode = bs_read1( s ); 
    if( sh->b_adaptive_ref_pic_marking_mode ) 
    { 
      int i=0; 
      int cmd; 
      while(1)  
      { 
        cmd=sh->ref_pic_marking[i].i_control_operation=bs_read_ue(s); 
        if (cmd==0) 
        { 
          break; 
        } 
        else if (cmd>6) 
        { 
          fprintf(stderr,"wrong memory mangement control operation\n"); 
          return -1; 
        } 
        else if (cmd!=5) 
        { 
          sh->ref_pic_marking[i].arg=bs_read_ue(s); 
        } 
        i++; //!! 
      } 
    }//end of if( sh->b_adaptive_ref_pic_marking_mode ) 
  } 
 
  return 0; 
} 
 
//when param set is NULL or changed 
void p264_decoder_context_init(p264_t *h) 
{ 
    int i; 
 
    h->sps = h->sh.sps; 
    h->pps = h->sh.pps; 
 
    p264_cqm_init( h ); //lsp?? not good 
 
    h->pic_dec->i_width = h->param.i_width = 16 * h->sps->i_mb_width; 
    h->pic_dec->i_height = h->param.i_height= 16 * h->sps->i_mb_height; 
	  //p264_picture_alloc( h->pic_dec, P264_CSP_I420, h->param.i_width, h->param.i_height ); 
 
    h->mb.i_mb_count = h->sps->i_mb_width * h->sps->i_mb_height; 
 
    fprintf( stderr, "p264: %dx%d\n", h->pic_dec->i_width, h->pic_dec->i_height ); 
 
    for( i = 0; i < h->sps->i_num_ref_frames + 1; i++ ) //the additional one for current decode frame 
    { 
      h->frames.reference[i] = p264_frame_new( h ); 
      h->frames.reference[i]->i_ref_type=NOT_USED_FOR_REF; 
      h->frames.reference[i]->i_poc = -1; 
    } 
    h->fdec = h->frames.reference[0]; 
    h->fenc=h->fdec; //be compatible with mb_cache_load function, no actual meaning 
    h->i_ref0 = 0; 
    h->i_ref1 = 0; 
 
    h->i_poc_msb = 0; 
    h->i_poc_lsb = 0; 
    h->i_frame_offset = 0; 
    h->i_frame_num = 0; 
 
    p264_macroblock_cache_init(h); 
    h->mb.mv[0] = h->fdec->mv[0]; //lsp??? is it necessary? 
    h->mb.mv[1] = h->fdec->mv[1]; 
    h->mb.ref[0] = h->fdec->ref[0]; 
    h->mb.ref[1] = h->fdec->ref[1]; 
    h->mb.type = h->fdec->mb_type; 
} 
 
//before param set changed or at the end of the decoder(p264_decoder_close) 
void p264_decoder_context_clean(p264_t *h) 
{ 
	int i; 
 
	p264_macroblock_cache_end(h); 
 
  if( h->pic_dec->i_width != 0 && h->pic_dec->i_height != 0 ) 
  { 
    for( i = 0; i < h->sps->i_num_ref_frames + 1; i++ ) 
    { 
      p264_frame_delete( h->frames.reference[i]); 
    } 
    //p264_picture_clean(h->pic_dec); 
  } 
	 
  h->sps = NULL; 
  h->pps = NULL; 
} 
 
/**************************************************************************** 
* Decode a slice header and setup h for mb decoding. 
****************************************************************************/ 
static int p264_slice_header_decode( p264_t *h, bs_t *s, p264_nal_t *nal ) 
{ 
  //[1] /* read the first part of the slice */ 
  if( p264_slice_header_part1_read( s, &h->sh, 
    h->sps_array, h->pps_array, 
    nal->i_type == NAL_SLICE_IDR ? 1 : 0 ) < 0 ) 
  { 
    fprintf( stderr, "p264_slice_header_part1_read failed\n" ); 
    return -1; 
  } 
 
  //[2] initialize h according to the change of sps and pps 
  do //it's a smart way 
  { 
    //init the decode environment 
    if( h->sps == NULL || h->pps == NULL ) 
    { 
      p264_decoder_context_init(h); 
      break; 
    } 
 
    //free the old context, because picture size may be changed between two sps 
    if( h->sps != h->sh.sps || h->pps != h->sh.pps ) //sh means slice header 
    { 
      p264_decoder_context_clean(h); 
    } 
    else 
    { 
      break;//!! 
    } 
  } while(1); 
 
  //[3] ref list reordering, pred weight table, marking 
  ///* calculate poc for current frame */ 
  //if( h->sps->i_poc_type == 0 ) 
  //{ 
  //  int i_max_poc_lsb = 1 << h->sps->i_log2_max_poc_lsb; 
 
  //  if( h->sh.i_poc_lsb < h->i_poc_lsb && h->i_poc_lsb - h->sh.i_poc_lsb >= i_max_poc_lsb/2 ) 
  //  { 
  //    h->i_poc_msb += i_max_poc_lsb; 
  //  } 
  //  else if( h->sh.i_poc_lsb > h->i_poc_lsb  && h->sh.i_poc_lsb - h->i_poc_lsb > i_max_poc_lsb/2 ) 
  //  { 
  //    h->i_poc_msb -= i_max_poc_lsb; 
  //  } 
  //  h->i_poc_lsb = h->sh.i_poc_lsb; 
 
  //  h->i_poc = h->i_poc_msb + h->sh.i_poc_lsb; 
  //} 
  //else if( h->sps->i_poc_type == 1 ) 
  //{ 
  //  /* FIXME */ 
  //  return -1; 
  //} 
  //else 
  //{ 
  //  if( nal->i_type == NAL_SLICE_IDR ) 
  //  { 
  //    h->i_frame_offset = 0; 
  //    h->i_poc = 0; 
  //  } 
  //  else 
  //  { 
  //    if( h->sh.i_frame_num < h->i_frame_num ) 
  //    { 
  //      h->i_frame_offset += 1 << h->sps->i_log2_max_frame_num; 
  //    } 
  //    if( nal->i_ref_idc > 0 ) 
  //    { 
  //      h->i_poc = 2 * ( h->i_frame_offset + h->sh.i_frame_num ); 
  //    } 
  //    else 
  //    { 
  //      h->i_poc = 2 * ( h->i_frame_offset + h->sh.i_frame_num ) - 1; 
  //    } 
  //  } 
  //  h->i_frame_num = h->sh.i_frame_num; 
  //} 
 
  //fprintf( stderr, "p264: pic type=%s poc:%d\n", 
  //  h->sh.i_type == SLICE_TYPE_I ? "I" : (h->sh.i_type == SLICE_TYPE_P ? "P" : "B?" ), 
  //  h->i_poc ); 
 
  //if( h->sh.i_type != SLICE_TYPE_I && h->sh.i_type != SLICE_TYPE_P ) 
  //{ 
  //  fprintf( stderr, "only SLICE I/P supported\n" ); 
  //  return -1; 
  //} 
 
  //[4] read the ref pic reordering (only read, do after read all the slice header) 
  if( p264_slice_header_ref_pic_reordering( s, &h->sh ) < 0 ) 
  { 
    return -1; 
  } 
 
  //[5] 
  //if( ( (h->sh.i_type == SLICE_TYPE_P || h->sh.i_type == SLICE_TYPE_SP) && h->sh.pps->b_weighted_pred  ) || 
  //  ( h->sh.i_type == SLICE_TYPE_B && h->sh.pps->b_weighted_bipred ) ) 
  //{ 
  //  if( p264_slice_header_pred_weight_table( h, s ) < 0 ) 
  //  { 
  //    return -1; 
  //  } 
  //} 
 
  //[6] read dec_ref_pic_marking (only read, do after decode a picture) 
  if( nal->i_ref_idc != 0 ) 
  { 
    p264_slice_header_dec_ref_pic_marking( s, &h->sh, nal->i_type ); 
  } 
 
  //[7]  
  if( p264_slice_header_part2_read( s, &h->sh ) < 0 ) 
  { 
    fprintf( stderr, "p264_slice_header_part2_read failed\n" ); 
    return -1; 
  } 
 
  return 0; 
} 
 
void p264_macroblock_init(p264_t *h) 
{ 
  memset(&h->dct,0,sizeof(struct dct_t)); 
 
 
  //lsp??? temp way, set a big number, no limit of mv 
  h->mb.mv_min[0]=-9999; 
  h->mb.mv_max[0]=9999; 
  h->mb.mv_min[1]=-9999; 
  h->mb.mv_max[1]=9999; 
} 
 
static int p264_slice_data_decode( p264_t *h, bs_t *s ) 
{ 
  int mb_xy = h->sh.i_first_mb; 
  int i_mb_x, i_mb_y; 
  int i_ret = 0; 
 
  if( h->pps->b_cabac )//lsptodo 
  { 
    /* TODO: alignement and cabac init */ 
  } 
 
  h->b_pic_output=0; 
  h->i_skip_run=-1; 
  /* FIXME field decoding */ 
  for( ;; ) 
  { 
    //lsptodo: support the case a frme have multi-slice 
    if( mb_xy >= h->sps->i_mb_width * h->sps->i_mb_height )//lsp?? temp way 
    { 
      h->b_pic_output=1;  
      break; 
    } 
 
    //if(h->sh.i_frame_num==1 && mb_xy==95)  //lspdebug 
    //{ 
    //  h->b_pic_output=1; 
    //} 
 
    //[0] 
    p264_macroblock_init(h); 
 
 
    //[1] load mb cache 
    i_mb_y = mb_xy / h->sps->i_mb_width;
    i_mb_x = mb_xy % h->sps->i_mb_width; 
    //!note: h->fenc point to f->dec, just want the function work,  
    //in fact, decoder don't need f->fenc 
    //h->param.analyse is used in cache_load and it's no meaning to decoder too. 
    p264_macroblock_cache_load(h, i_mb_x, i_mb_y); 
 
    //[2] mb read 
    if(h->i_skip_run<1) //-1: no skip, 0: skip_run decrease to 0 currently 
    { 
      if( h->pps->b_cabac ) 
      { 
        if( h->sh.i_type != SLICE_TYPE_I && h->sh.i_type != SLICE_TYPE_SI ) 
        { 
          /* TODO */ 
        } 
        i_ret = p264_macroblock_read_cabac( h, s ); 
      } 
      else//CAVLC 
      { 
        i_ret = p264_macroblock_read_cavlc( h, s ); 
      }//end of if( h->pps->b_cabac ) else 
 
      if( i_ret < 0 ) 
      { 
        fprintf( stderr, "p264_macroblock_read failed [%d,%d]\n", h->mb.i_mb_x, h->mb.i_mb_y ); 
        break; 
      } 
    } 
 
    //[3] mb decode 
    if(h->i_skip_run>0) 
    { 
      p264_macroblock_decode_skip(h); 
      h->i_skip_run--; //!! 
    } 
    else 
    { 
      if( p264_macroblock_decode( h ) < 0 ) 
      { 
        fprintf( stderr, "p264_macroblock_decode failed\n" ); 
        /* try to do some error correction ;) */ 
      } 
      h->i_skip_run=-1; //not very good way!! 
    } 
 
    //[4] save the current mb decode info to mb table 
    p264_macroblock_cache_save(h); //lsp 
 
    mb_xy++; //lsptodo: support slice map group 
    //if(h->sh.i_frame_num==1 && mb_xy>100)  //lspdebug 
    //{ 
    //  h->b_pic_output=1; 
    //  break; 
    //} 
  }//end of for( ;; ) 
 
  return i_ret; 
}

/****************************************************************************
* p264_slice_decode: decode one slice
****************************************************************************/
static int p264_slice_decode( p264_t *h, bs_t *s, p264_nal_t *nal )
{
  int i;
  int i_ret;

  //[1] slice header
  if( ( i_ret = p264_slice_header_decode( h, s, nal ) ) < 0 ) 
  { 
    fprintf( stderr, "p264: p264_slice_header_decode failed\n" ); 
    return -1; 
  } 
 
  //lspdebug 
  //if (h->sh.i_frame_num==1) 
  //{ 
  //  printf("ok"); 
  //} 
 
  // slice level init 
  h->fdec->i_frame_num = h->sh.i_frame_num; //lsp?? may be it's better written in header_read 
 
  //[2] lists  
  p264_lists_init(h); 
  p264_lists_reorder(h); 
 
  //[3] slice data decode. important!! 
  if( h->sh.i_redundant_pic_cnt == 0 && i_ret == 0 ) 
  { 
    if( ( i_ret = p264_slice_data_decode( h, s ) ) < 0 ) 
    { 
      fprintf( stderr, "p264: p264_slice_data_decode failed\n" ); 
      return -1; 
    } 
  }

  //[4] 
  //note: if decode a whole picture
  if(h->b_pic_output)
  { 
    /* apply deblocking filter to the current decoded picture */ 
    //note: apply to h->fdec->plane[0,1,2] 
    if( !h->pps->b_deblocking_filter_control || h->sh.i_disable_deblocking_filter_idc != 1 ) 
    { 
      p264_frame_deblocking_filter( h, h->sh.i_type ); 
    } 
    /* expand border for frame reference TODO avoid it when using b-frame */
    p264_frame_expand_border( h->fdec ); 
 
    /* create filtered images */ //half pel interpolation!!
    p264_frame_filter( h->param.cpu, h->fdec ); 
    /* expand border of filtered images */
    p264_frame_expand_border_filtered( h->fdec ); 
	 
    // output recon picture 
    h->pic_dec->img.i_plane = h->fdec->i_plane;
    for( i = 0; i < h->fdec->i_plane; i++ )
    {
      h->pic_dec->img.i_stride[i] = h->fdec->i_stride[i];
      h->pic_dec->img.plane[i]    = h->fdec->plane[i];
    } 
    
    //lists marking
    p264_lists_marking(h); //lsp 
  }

  return 0;
}

/****************************************************************************
 *
 ******************************* p264 libs **********************************
 *
 ****************************************************************************/

/****************************************************************************
 * p264_decoder_open:
 ****************************************************************************/
p264_t *p264_decoder_open   ( p264_param_t *param )
{
    p264_t *h = p264_malloc( sizeof( p264_t ) );
    int i;

    memset( h, 0, sizeof( p264_t ) );

    memcpy( &h->param, param, sizeof( p264_param_t ) );

    /* no SPS and PPS active yet */
    h->sps = NULL;
    h->pps = NULL;

    for( i = 0; i < 32; i++ )
    {
      h->sps_array[i].i_id = -1;  /* invalidate it */
    }
    for( i = 0; i < 256; i++ )
    {
      h->pps_array[i].i_id = -1;  /* invalidate it */
    }

    //note: since there isn't enough info, we can't use p264_picture_alloc()
    h->pic_dec = p264_malloc( sizeof( p264_picture_t ) );
    memset( h->pic_dec, 0, sizeof( p264_picture_t ) );

    /* init predict_XxX */
    p264_predict_16x16_init( h->param.cpu, h->predict_16x16 );
    p264_predict_8x8c_init( h->param.cpu, h->predict_8x8c );
    p264_predict_8x8_init( h->param.cpu, h->predict_8x8 );
    p264_predict_4x4_init( h->param.cpu, h->predict_4x4 );

    p264_pixel_init( h->param.cpu, &h->pixf );
    p264_dct_init( h->param.cpu, &h->dctf );
    p264_mc_init( h->param.cpu, &h->mc );
    p264_quant_init( h, h->param.cpu, &h->quantf );
    p264_deblock_init( h->param.cpu, &h->loopf );

    /* create the vlc table (we could remove it from p264_t but it will need
     * to introduce a p264_init() for global librarie) */
    for( i = 0; i < 5; i++ )
    {
        /* max 2 step */
        h->p264_coeff_token_lookup[i] = p264_vlc_table_lookup_new( p264_coeff_token[i], 17*4, 4 );
    }
    /* max 2 step */
    h->p264_level_prefix_lookup = p264_vlc_table_lookup_new( p264_level_prefix, 16, 8 );

    for( i = 0; i < 15; i++ )
    {
        /* max 1 step */
        h->p264_total_zeros_lookup[i] = p264_vlc_table_lookup_new( p264_total_zeros[i], 16, 9 );
    }
    for( i = 0;i < 3; i++ )
    {
        /* max 1 step */
        h->p264_total_zeros_dc_lookup[i] = p264_vlc_table_lookup_new( p264_total_zeros_dc[i], 4, 3 );
    }
    for( i = 0;i < 7; i++ )
    {
        /* max 2 step */
        h->p264_run_before_lookup[i] = p264_vlc_table_lookup_new( p264_run_before[i], 15, 6 );
    }

    return h;
}

/****************************************************************************
 * p264_decoder_decode: decode one nal unit
 ****************************************************************************/
int     p264_decoder_decode( p264_t *h, 
                            p264_picture_t **pp_pic, p264_nal_t *nal ) 
{ 
  int i_ret = 0; 
  bs_t bs; 
 
  /* no picture */ 
  *pp_pic = NULL; 
  h->b_pic_output=0; 
 
  /* init bitstream reader */ 
  bs_init( &bs, nal->p_payload, nal->i_payload ); 
 
  h->i_nal_type=nal->i_type; //!!! 
 
  switch( nal->i_type ) 
  { 
  case NAL_SPS: 
    if( ( i_ret = p264_sps_read( &bs, h->sps_array ) ) < 0 ) 
    { 
      fprintf( stderr, "p264: p264_sps_read failed\n" ); 
    } 
    break; 
 
  case NAL_PPS: 
    if( ( i_ret = p264_pps_read( &bs, h->pps_array ) ) < 0 ) 
    { 
      fprintf( stderr, "p264: p264_pps_read failed\n" ); 
    } 
    break; 
 
  case NAL_SLICE_IDR: 
    //fprintf( stderr, "p264: NAL_SLICE_IDR\n" ); 
    p264_slice_idr( h ); //note: then do below 
  case NAL_SLICE: 
    if( ( i_ret = p264_slice_decode( h, &bs, nal ) ) < 0 ) 
    { 
      fprintf( stderr, "p264: p264_slice_decode failed\n" ); 
    } 
    else if(h->b_pic_output)
    {
      *pp_pic = h->pic_dec;
    } 
    break; 
 
  case NAL_SLICE_DPA: 
  case NAL_SLICE_DPB: 
  case NAL_SLICE_DPC: 
    fprintf( stderr, "partitioned stream unsupported\n" ); 
    i_ret = -1; 
    break; 
 
  case NAL_SEI: 
  default: 
    break; 
  } 
 
  /* restore CPU state (before using float again) */ 
  p264_cpu_restore( h->param.cpu ); 
 
  return i_ret; 
} 

/****************************************************************************
 * p264_decoder_close:
 ****************************************************************************/ 
//note: free the space init both by p264_slice_header_decode and p264_decoder_open
void    p264_decoder_close  ( p264_t *h )
{
    int i; 
 
	//[0] output decode result info 
	//
 
	//[1] free the space init by p264_slice_header_decode 
	p264_decoder_context_clean(h);
 
	//[2] free the space init by p264_decoder_open
  /* free vlc table */
  for( i = 0; i < 5; i++ )
  {
      p264_vlc_table_lookup_delete( h->p264_coeff_token_lookup[i] );
  }
  p264_vlc_table_lookup_delete( h->p264_level_prefix_lookup );

  for( i = 0; i < 15; i++ )
  {
      p264_vlc_table_lookup_delete( h->p264_total_zeros_lookup[i] );
  }
  for( i = 0;i < 3; i++ )
  {
      p264_vlc_table_lookup_delete( h->p264_total_zeros_dc_lookup[i] );
  }
  for( i = 0;i < 7; i++ )
  {
      p264_vlc_table_lookup_delete( h->p264_run_before_lookup[i] );
  }

	p264_free(h->pic_dec);
  p264_free( h );
}