?? decoder_new.c
字號:
/***************************************************************************** * x264: h264 decoder ***************************************************************************** * Copyright (C) 2003 Laurent Aimar * $Id: decoder.c,v 1.1 2004/06/03 19:27:07 fenrir Exp $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * 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 <stdlib.h>#include <stdio.h>#include <string.h>#include "stdint_x264.h"#include <limits.h>#include "common.h"#include "set.h"#include "macroblock.h"#include "vlc.h"#include "assert.h"static void x264_update_ref_list( x264_t *h ){int i, j; for( i = 0, j = 0; i < h->dpb.used_size; i++ ) { if (h->dpb.fs[i]->is_reference && !h->dpb.fs[i]->is_long_ref) { h->short_ref[j++] = h->dpb.fs[i]; } } h->short_ref_count = j; while ( j < h->dpb.size ) { h->short_ref[j++] = NULL; } for( i = 0, j = 0; i < h->dpb.used_size; i++ ) { if (h->dpb.fs[i]->is_reference && h->dpb.fs[i]->is_long_ref) { h->long_ref[j++] = h->dpb.fs[i]; } } h->long_ref_count = j; while ( j < h->dpb.size ) { h->long_ref[j++] = NULL; }}/*! ************************************************************************ * \brief * Perform Sliding window decoded reference picture marking process * ************************************************************************ */static void sliding_window_memory_management( x264_t *h ){ int i; // if this is a reference pic with sliding sliding window, unmark first ref frame if (h->short_ref_count == h->sps->i_num_ref_frames - h->long_ref_count) { for (i = 0; i < h->dpb.used_size; i++) { if (h->dpb.fs[i]->is_reference && (!(h->dpb.fs[i]->is_long_ref))) { h->dpb.fs[i]->is_reference = 0; x264_update_ref_list( h ); break; } } }}static int x264_bulid_ref_list( x264_t *h ){ int b_ok; int i, list0idx; int ref_num = 0; /* build ref list 0/1 */ h->i_ref0 = 0; h->i_ref1 = 0; if( h->sh.i_type == SLICE_TYPE_P ) { for( i = 0; i < h->short_ref_count; i++ ) { if( h->short_ref[i]->i_poc >= 0 ) { h->fref0[ref_num++] = h->short_ref[i]; } } /* Order ref0 from higher to lower poc */ do { b_ok = 1; for( i = 0; i < ref_num - 1; i++ ) { if( h->fref0[i]->i_poc < h->fref0[i+1]->i_poc ) { x264_frame_t *tmp = h->fref0[i+1]; h->fref0[i+1] = h->fref0[i]; h->fref0[i] = tmp; b_ok = 0; break; } } } while( !b_ok ); h->i_ref0 = ref_num; } else if( h->sh.i_type == SLICE_TYPE_B ) { for( i = 0; i < h->short_ref_count; i++ ) { if( h->short_ref[i]->i_poc >= 0 ) { if( h->short_ref[i]->i_poc < h->fdec->i_poc ) { h->fref0[ref_num++] = h->short_ref[i]; } } } list0idx = ref_num; for( i = 0; i < h->short_ref_count; i++ ) { if( h->short_ref[i]->i_poc >= 0 ) { if( h->short_ref[i]->i_poc > h->fdec->i_poc ) { h->fref0[ref_num++] = h->short_ref[i]; } } } /* Order ref0 from higher to lower poc for pictures with POC smaller than current POC then order ref0 from lower to higher poc for pictures with POC larger than current POC*/ do { b_ok = 1; for( i = 0; i < list0idx - 1; i++ ) { if( h->fref0[i]->i_poc < h->fref0[i+1]->i_poc ) { x264_frame_t *tmp = h->fref0[i+1]; h->fref0[i+1] = h->fref0[i]; h->fref0[i] = tmp; b_ok = 0; break; } } } while( !b_ok ); do { b_ok = 1; for( i = list0idx; i < ref_num - 1; i++ ) { if( h->fref0[i]->i_poc > h->fref0[i+1]->i_poc ) { x264_frame_t *tmp = h->fref0[i+1]; h->fref0[i+1] = h->fref0[i]; h->fref0[i] = tmp; b_ok = 0; break; } } } while( !b_ok ); /* initial ref1 */ for (i = 0; i < list0idx; i++) { h->fref1[ref_num - list0idx + i] = h->fref0[i]; } for (i = list0idx; i < ref_num; i++) { h->fref1[i - list0idx] = h->fref0[i]; } h->i_ref0 = ref_num; h->i_ref1 = ref_num; } if( h->i_ref0 > h->sh.i_num_ref_idx_l0_active ) { h->i_ref0 = h->sh.i_num_ref_idx_l0_active; } if( h->i_ref1 > h->sh.i_num_ref_idx_l1_active ) { h->i_ref1 = h->sh.i_num_ref_idx_l1_active; } //fprintf( stderr,"POC:%d ref0=%d POC0=%d\n", h->fdec->i_poc, h->i_ref0, h->i_ref0 > 0 ? h->fref0[0]->i_poc : -1 ); return 0;}static void x264_slice_idr( x264_t *h ){ int i; h->i_poc_msb = 0; h->i_poc_lsb = 0; h->i_frame_offset = 0; h->i_frame_num = 0; for( i = 0; i < 16; i++){ if (h->long_ref[i] != NULL) { h->long_ref[i] = NULL; } if (h->short_ref[i] != NULL) { h->short_ref[i] = NULL; } } h->long_ref_count = 0; h->short_ref_count = 0; if( h->sps ) { for( i = 0; i < h->dpb.used_size; i++ ) { h->dpb.fs[i]->i_poc = -1; } h->dpb.used_size = 0; h->fdec = h->dpb.fs[0]; h->i_ref0 = 0; h->i_ref1 = 0; }}/* The slice reading is split in two part: * - before ref_pic_list_reordering( ) * - after dec_ref_pic_marking( ) */static int x264_slice_header_part1_read( bs_t *s, x264_slice_header_t *sh, x264_sps_t sps_array[32], x264_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; } 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 in slice header\n" ); 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 x264_slice_header_part2_read( bs_t *s, x264_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;}static int x264_slice_header_ref_pic_reordering( x264_t *h, bs_t *s ){ int ref_pic_list_reordering_flag_10;int ref_pic_list_reordering_flag_11;uint8_t reordering_of_pic_nums_idc;uint8_t abs_diff_pic_num;uint8_t long_term_pic_num;int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;int refIdxLX = 0;int i;x264_frame_t *picLx;int cIdx;int nIdx; h->i_max_frame_num = 2 * h->sps->i_log2_max_frame_num; maxPicNum = h->i_max_frame_num; currPicNum = h->i_frame_num; picNumLXPred = currPicNum; /* Now parse the stream and change the default order */ if( h->sh.i_type != SLICE_TYPE_I && h->sh.i_type != SLICE_TYPE_SI ) { ref_pic_list_reordering_flag_10 = bs_read1( s ); if( ref_pic_list_reordering_flag_10 ) do{ reordering_of_pic_nums_idc = bs_read_ue(s); if(reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) { abs_diff_pic_num = bs_read_ue(s) + 1 ; } else if ( reordering_of_pic_nums_idc == 2) { long_term_pic_num = bs_read_ue(s); } } while( reordering_of_pic_nums_idc != 3); if (reordering_of_pic_nums_idc < 2) { if (reordering_of_pic_nums_idc == 0) { if( picNumLXPred - ( abs_diff_pic_num ) < 0 ) picNumLXNoWrap = picNumLXPred - abs_diff_pic_num + maxPicNum; else picNumLXNoWrap = picNumLXPred - abs_diff_pic_num; } else // (remapping_of_pic_nums_idc[i] == 1) { if( picNumLXPred + abs_diff_pic_num >= maxPicNum ) picNumLXNoWrap = picNumLXPred + abs_diff_pic_num - maxPicNum; else picNumLXNoWrap = picNumLXPred + abs_diff_pic_num; } picNumLXPred = picNumLXNoWrap; if( picNumLXNoWrap > currPicNum ) picNumLX = picNumLXNoWrap - maxPicNum; else picNumLX = picNumLXNoWrap; for ( i=0; i < h->dpb.used_size; i++) { if(( !h->dpb.fs[i]->is_long_ref )&&( h->dpb.fs[i]->i_frame_num == picNumLX)) { picLx = h->dpb.fs[i]; break; } } for( cIdx = h->sh.i_num_ref_idx_l0_active; cIdx > refIdxLX; cIdx-- ) h->fref0[cIdx] = h->fref0[cIdx-1]; h->fref0[ (refIdxLX)++ ] = picLx; nIdx = refIdxLX; for( cIdx = refIdxLX; cIdx <= h->sh.i_num_ref_idx_l0_active; cIdx++ ) if (h->fref0[ cIdx ]) if( (h->fref0[ cIdx ]->is_long_ref ) || (h->fref0[ cIdx ]->i_frame_num != picNumLX )) h->fref0[ nIdx++ ] = h->fref0[ cIdx ]; } if (reordering_of_pic_nums_idc == 2) { for ( i=0; i < h->dpb.used_size; i++) { if(( h->dpb.fs[i]->is_long_ref )&&( h->dpb.fs[i]->longtermpicnum == long_term_pic_num)) { picLx = h->dpb.fs[i]; break; } } for( cIdx = h->sh.i_num_ref_idx_l0_active; cIdx > refIdxLX; cIdx-- ) h->fref0[cIdx] = h->fref0[cIdx-1]; h->fref0[ (refIdxLX)++ ] = picLx; nIdx = refIdxLX; for( cIdx = refIdxLX; cIdx <= h->sh.i_num_ref_idx_l0_active; cIdx++ ) if (h->fref0[ cIdx ]) if( (!h->fref0[ cIdx ]->is_long_ref ) || (h->fref0[ cIdx ]->longtermpicnum != long_term_pic_num )) h->fref0[ nIdx++ ] = h->fref0[ cIdx ]; } } if( h->sh.i_type == SLICE_TYPE_B ) { ref_pic_list_reordering_flag_11 = bs_read1( s ); refIdxLX = 0; if( ref_pic_list_reordering_flag_11 ) do{ reordering_of_pic_nums_idc = bs_read_ue(s); if(reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) { abs_diff_pic_num = bs_read_ue(s) + 1 ; } else if ( reordering_of_pic_nums_idc == 2) { long_term_pic_num = bs_read_ue(s); } } while( reordering_of_pic_nums_idc != 3); if (reordering_of_pic_nums_idc < 2) { if (reordering_of_pic_nums_idc == 0) { if( picNumLXPred - ( abs_diff_pic_num ) < 0 ) picNumLXNoWrap = picNumLXPred - abs_diff_pic_num + maxPicNum; else picNumLXNoWrap = picNumLXPred - abs_diff_pic_num; } else // (remapping_of_pic_nums_idc[i] == 1) { if( picNumLXPred + abs_diff_pic_num >= maxPicNum ) picNumLXNoWrap = picNumLXPred + abs_diff_pic_num - maxPicNum; else picNumLXNoWrap = picNumLXPred + abs_diff_pic_num; } picNumLXPred = picNumLXNoWrap; if( picNumLXNoWrap > currPicNum ) picNumLX = picNumLXNoWrap - maxPicNum; else picNumLX = picNumLXNoWrap; for ( i=0; i < h->dpb.used_size; i++) { if(( !h->dpb.fs[i]->is_long_ref )&&( h->dpb.fs[i]->i_frame_num == picNumLX)) { picLx = h->dpb.fs[i]; break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -