📄 decoder.c.svn-base
字号:
/***************************************************************************** * 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.h>#include "common/common.h"#include "common/cpu.h"#include "common/vlc.h"#include "macroblock.h"#include "set.h"#include "vlc.h"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; if( h->sps ) { for( i = 0; i < h->sps->i_num_ref_frames + 1; i++ ) { h->freference[i]->i_poc = -1; } h->fdec = h->freference[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 b_ok; int i; /* use the no more use frame */ h->fdec = h->freference[0]; h->fdec->i_poc = h->i_poc; /* build ref list 0/1 */ h->i_ref0 = 0; h->i_ref1 = 0; for( i = 1; i < h->sps->i_num_ref_frames + 1; i++ ) { if( h->freference[i]->i_poc >= 0 ) { if( h->freference[i]->i_poc < h->fdec->i_poc ) { h->fref0[h->i_ref0++] = h->freference[i]; } else if( h->freference[i]->i_poc > h->fdec->i_poc ) { h->fref1[h->i_ref1++] = h->freference[i]; } } } /* Order ref0 from higher to lower poc */ do { b_ok = 1; for( i = 0; i < h->i_ref0 - 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 ); /* Order ref1 from lower to higher poc (bubble sort) for B-frame */ do { b_ok = 1; for( i = 0; i < h->i_ref1 - 1; i++ ) { if( h->fref1[i]->i_poc > h->fref1[i+1]->i_poc ) { x264_frame_t *tmp = h->fref1[i+1]; h->fref1[i+1] = h->fref1[i]; h->fref1[i] = tmp; b_ok = 0; break; } } } while( !b_ok ); if( h->i_ref0 > h->pps->i_num_ref_idx_l0_active ) { h->i_ref0 = h->pps->i_num_ref_idx_l0_active; } if( h->i_ref1 > h->pps->i_num_ref_idx_l1_active ) { h->i_ref1 = h->pps->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 ); /* Now parse the stream and change the default order */ if( h->sh.i_type != SLICE_TYPE_I && h->sh.i_type != SLICE_TYPE_SI ) { int b_reorder = bs_read1( s ); if( b_reorder ) { /* FIXME */ return -1; } } if( h->sh.i_type == SLICE_TYPE_B ) { int b_reorder = bs_read1( s ); if( b_reorder ) { /* FIXME */ return -1; } } return 0;}static int x264_slice_header_pred_weight_table( x264_t *h, bs_t *s ){ return -1;}static int x264_slice_header_dec_ref_pic_marking( x264_t *h, bs_t *s, int i_nal_type ){ if( i_nal_type == NAL_SLICE_IDR ) { int b_no_output_of_prior_pics = bs_read1( s ); int b_long_term_reference_flag = bs_read1( s ); /* TODO */ if( b_no_output_of_prior_pics ) { } if( b_long_term_reference_flag ) { } } else { int b_adaptive_ref_pic_marking_mode = bs_read1( s ); if( b_adaptive_ref_pic_marking_mode ) { return -1; } } return 0;}/**************************************************************************** * Decode a slice header and setup h for mb decoding. ****************************************************************************/static int x264_slice_header_decode( x264_t *h, bs_t *s, x264_nal_t *nal ){ /* read the first part of the slice */ if( x264_slice_header_part1_read( s, &h->sh, h->sps_array, h->pps_array, nal->i_type == NAL_SLICE_IDR ? 1 : 0 ) < 0 ) { fprintf( stderr, "x264_slice_header_part1_read failed\n" ); return -1; } /* now reset h if needed for this frame */ if( h->sps != h->sh.sps || h->pps != h->sh.pps ) { int i; /* TODO */ h->sps = NULL; h->pps = NULL; if( h->picture->i_width != 0 && h->picture->i_height != 0 ) { for( i = 0; i < h->sps->i_num_ref_frames + 1; i++ ) { x264_frame_delete( h->freference[i]); } free( h->mb ); } h->picture->i_width = 0; h->picture->i_height = 0; } /* and init if needed */ if( h->sps == NULL || h->pps == NULL ) { int i; h->sps = h->sh.sps; h->pps = h->sh.pps; h->param.i_width = h->picture->i_width = 16 * h->sps->i_mb_width; h->param.i_height= h->picture->i_height= 16 * h->sps->i_mb_height; fprintf( stderr, "x264: %dx%d\n", h->picture->i_width, h->picture->i_height ); h->mb = x264_macroblocks_new( h->sps->i_mb_width, h->sps->i_mb_height ); for( i = 0; i < h->sps->i_num_ref_frames + 1; i++ ) { h->freference[i] = x264_frame_new( h ); h->freference[i]->i_poc = -1; } h->fdec = h->freference[0]; 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; } /* calculate poc for current frame */ if( h->sps->i_poc_type == 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -