📄 bitstream.c
字号:
/****************************************************************************** * * * This file is part of XviD, a free MPEG-4 video encoder/decoder * * * * XviD is an implementation of a part of one or more MPEG-4 Video tools * * as specified in ISO/IEC 14496-2 standard. Those intending to use this * * software module in hardware or software products are advised that its * * use may infringe existing patents or copyrights, and any such use * * would be at such party's own risk. The original developer of this * * software module and his/her company, and subsequent editors and their * * companies, will have no liability for use of this software or * * modifications or derivatives thereof. * * * * XviD 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. * * * * XviD 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-1307 USA * * * ******************************************************************************/ /****************************************************************************** * * * bitstream.c * * * * Copyright (C) 2001 - Peter Ross <pross@cs.rmit.edu.au> * * * * For more information visit the XviD homepage: http://www.xvid.org * * * ******************************************************************************/ /****************************************************************************** * * * Revision history: * * * * 26.03.2002 interlacing support * 03.03.2002 qmatrix writing * * 03.03.2002 merged BITREADER and BITWRITER * * 30.02.2002 intra_dc_threshold support * * 04.12.2001 support for additional headers * * 16.12.2001 inital version * * * ******************************************************************************/#include "bitstream.h"#include "zigzag.h"#include "../quant/quant_matrix.h"static int __inline log2bin(int value){ int n = 0; while (value) { value >>= 1; n++; } return n;}static const uint32_t intra_dc_threshold_table[] ={ 32, /* never use */ 13, 15, 17, 19, 21, 23, 1,};void bs_get_matrix(Bitstream * bs, uint8_t * matrix) { int i = 0; int last, value = 0; do { last = value; value = BitstreamGetBits(bs, 8); matrix[ scan_tables[0][i++] ] = value; } while (value != 0 && i < 64); while (i < 64) { matrix[ scan_tables[0][i++] ] = last; } } // for PVOP addbits == fcode - 1// for BVOP addbits == max(fcode,bcode) - 1// returns mbposint read_video_packet_header(DECODER * dec,int coding_type,Bitstream *bs, const int addbits, int * quant){ uint32_t mbpos; uint32_t hec = 0; int mb_num = 0; int mb_pos_len; int val; int nbits = 0; /* remove ResyncMarker */ nbits = NUMBITS_VP_RESYNC_MARKER + addbits; BitstreamSkip(bs, BitstreamNumBitsToByteAlign(bs)); BitstreamGetBits(bs,nbits); DEBUG("<video_packet_header>"); mb_num = dec->mb_width * dec->mb_height; if (!(mb_num>0)) { DEBUG("video_packet_header : mb_num = 0"); return 0; } /* evaluate LengthOfMBNumber (log(mb_num-1)/log(2)) + 1 */ val = mb_num - 1; mb_pos_len = 0; for(; val; mb_pos_len++) val>>=1; mbpos = 0; if (dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR) { hec = BitstreamGetBits(bs,NUMBITS_VP_HEC); /* warning : do not work with sprite */ if (hec) { int marker; int left; int top; /* width */ BitstreamGetBits(bs,NUMBITS_VOP_WIDTH); marker = BitstreamGetBits(bs,1); // marker bit if (!(marker==1)) { DEBUG("video_packet_header : marker = 0"); return 0; } /* height */ BitstreamGetBits(bs,NUMBITS_VOP_HEIGHT); marker = BitstreamGetBits(bs,1); // marker bit if (!(marker==1)) { DEBUG("video_packet_header : marker = 0"); return 0; } /* left corner */ left = (BitstreamGetBits(bs,1) == 0) ? BitstreamGetBits(bs,NUMBITS_VOP_HORIZONTAL_SPA_REF - 1) : ((int)BitstreamGetBits(bs,NUMBITS_VOP_HORIZONTAL_SPA_REF - 1) - (1 << (NUMBITS_VOP_HORIZONTAL_SPA_REF - 1))); marker = BitstreamGetBits(bs,1); // marker bit if (!(marker==1)) { DEBUG("video_packet_header : marker = 0"); return 0; } /* top corner */ top = (BitstreamGetBits(bs,1) == 0) ? BitstreamGetBits(bs,NUMBITS_VOP_VERTICAL_SPA_REF - 1) : ((int)BitstreamGetBits(bs,NUMBITS_VOP_VERTICAL_SPA_REF - 1) - (1 << (NUMBITS_VOP_VERTICAL_SPA_REF - 1))); marker = BitstreamGetBits(bs,1); // marker bit if (!(marker==1)) { DEBUG("video_packet_header : marker = 0"); return 0; } /* must be even pix unit */ if (!(((left | top)&1)==0)) { DEBUG("video_packet_header : marker = 0"); return 0; } } } /* reading mbpos */ if(mb_num>1) mbpos = BitstreamGetBits(bs,mb_pos_len); /* reading quant */ if(dec->shape!=VIDOBJLAY_SHAPE_BINARY_ONLY) { *quant = BitstreamGetBits(bs,NUMBITS_VP_QUANTIZER); } if (dec->shape == VIDOBJLAY_SHAPE_RECTANGULAR) hec = BitstreamGetBits(bs,NUMBITS_VP_HEC); if (hec){ DEBUG("Time reference and VOP_pred_type not supported"); } return mbpos;}/*decode headersreturns coding_type, or -1 if error*/int BitstreamReadHeaders(Bitstream * bs, DECODER * dec, uint32_t * rounding, uint32_t * quant, uint32_t * fcode, uint32_t * intra_dc_threshold, int findvol){ uint32_t vol_ver_id; uint32_t time_inc_resolution; uint32_t coding_type; uint32_t start_code;#ifdef MPEG4IP uint32_t width, height;#endif do { BitstreamByteAlign(bs); start_code = BitstreamShowBits(bs, 32); if (start_code == VISOBJSEQ_START_CODE) { // DEBUG("visual_object_sequence"); BitstreamSkip(bs, 32); // visual_object_sequence_start_code BitstreamSkip(bs, 8); // profile_and_level_indication } else if (start_code == VISOBJSEQ_STOP_CODE) { BitstreamSkip(bs, 32); // visual_object_sequence_stop_code } else if (start_code == VISOBJ_START_CODE) { // DEBUG("visual_object"); BitstreamSkip(bs,32); // visual_object_start_code if (BitstreamGetBit(bs)) // is_visual_object_identified { vol_ver_id = BitstreamGetBits(bs,4); // visual_object_ver_id BitstreamSkip(bs, 3); // visual_object_priority } else { vol_ver_id = 1; } if (BitstreamShowBits(bs, 4) != VISOBJ_TYPE_VIDEO) // visual_object_type { DEBUG("visual_object_type != video"); return -1; } BitstreamSkip(bs, 4); // video_signal_type if (BitstreamGetBit(bs)) // video_signal_type { DEBUG("+ video_signal_type"); BitstreamSkip(bs, 3); // video_format BitstreamSkip(bs, 1); // video_range if (BitstreamGetBit(bs)) // color_description { DEBUG("+ color_description"); BitstreamSkip(bs, 8); // color_primaries BitstreamSkip(bs, 8); // transfer_characteristics BitstreamSkip(bs, 8); // matrix_coefficients } } } else if ((start_code & ~0x1f) == VIDOBJ_START_CODE) { BitstreamSkip(bs, 32); // video_object_start_code } else if ((start_code & ~0xf) == VIDOBJLAY_START_CODE) { // DEBUG("video_object_layer"); BitstreamSkip(bs, 32); // video_object_layer_start_code BitstreamSkip(bs, 1); // random_accessible_vol // video_object_type_indication if (BitstreamShowBits(bs, 8) != VIDOBJLAY_TYPE_SIMPLE && BitstreamShowBits(bs, 8) != VIDOBJLAY_TYPE_CORE && BitstreamShowBits(bs, 8) != VIDOBJLAY_TYPE_MAIN && BitstreamShowBits(bs, 8) != 0) // BUGGY DIVX { DEBUG1("video_object_type_indication not supported", BitstreamShowBits(bs, 8)); return -1; } BitstreamSkip(bs, 8); if (BitstreamGetBit(bs)) // is_object_layer_identifier { DEBUG("+ is_object_layer_identifier"); vol_ver_id = BitstreamGetBits(bs,4); // video_object_layer_verid BitstreamSkip(bs, 3); // video_object_layer_priority } else { vol_ver_id = 1; } //DEBUGI("vol_ver_id", vol_ver_id); if (BitstreamGetBits(bs, 4) == VIDOBJLAY_AR_EXTPAR) // aspect_ratio_info { DEBUG("+ aspect_ratio_info"); BitstreamSkip(bs, 8); // par_width BitstreamSkip(bs, 8); // par_height } if (BitstreamGetBit(bs)) // vol_control_parameters { DEBUG("+ vol_control_parameters"); BitstreamSkip(bs, 2); // chroma_format BitstreamSkip(bs, 1); // low_delay if (BitstreamGetBit(bs)) // vbv_parameters { DEBUG("+ vbv_parameters"); BitstreamSkip(bs, 15); // first_half_bitrate READ_MARKER(); BitstreamSkip(bs, 15); // latter_half_bitrate READ_MARKER(); BitstreamSkip(bs, 15); // first_half_vbv_buffer_size READ_MARKER(); BitstreamSkip(bs, 3); // latter_half_vbv_buffer_size BitstreamSkip(bs, 11); // first_half_vbv_occupancy READ_MARKER(); BitstreamSkip(bs, 15); // latter_half_vbv_occupancy READ_MARKER(); } } dec->shape = BitstreamGetBits(bs, 2); // video_object_layer_shape // DEBUG1("shape", dec->shape); if (dec->shape == VIDOBJLAY_SHAPE_GRAYSCALE && vol_ver_id != 1) { BitstreamSkip(bs, 4); // video_object_layer_shape_extension } READ_MARKER(); time_inc_resolution = BitstreamGetBits(bs, 16); // vop_time_increment_resolution time_inc_resolution--; if (time_inc_resolution > 0) { dec->time_inc_bits = log2bin(time_inc_resolution); } else { // dec->time_inc_bits = 0; // for "old" xvid compatibility, set time_inc_bits = 1 dec->time_inc_bits = 1; } READ_MARKER(); if (BitstreamGetBit(bs)) // fixed_vop_rate { BitstreamSkip(bs, dec->time_inc_bits); // fixed_vop_time_increment } if (dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) { if (dec->shape == VIDOBJLAY_SHAPE_RECTANGULAR) { uint32_t width, height; READ_MARKER(); width = BitstreamGetBits(bs, 13); // video_object_layer_width //DEBUGI("width", width); READ_MARKER(); height = BitstreamGetBits(bs, 13); // video_object_layer_height //DEBUGI("height", height); READ_MARKER(); if (findvol == 0) { if (width != dec->width || height != dec->height) { DEBUG("FATAL: video dimension discrepancy ***"); DEBUG2("bitstream width/height", width, height); DEBUG2("param width/height", dec->width, dec->height); return -1; } } else { dec->width = width; dec->height = height; } } if ((dec->interlacing = BitstreamGetBit(bs))) { DEBUG("vol: interlacing"); } if (!BitstreamGetBit(bs)) // obmc_disable { DEBUG("IGNORED/TODO: !obmc_disable"); // TODO // fucking divx4.02 has this enabled } if (BitstreamGetBits(bs, (vol_ver_id == 1 ? 1 : 2))) // sprite_enable { DEBUG("sprite_enable; not supported"); return -1; } if (vol_ver_id != 1 && dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR) { BitstreamSkip(bs, 1); // sadct_disable } if (BitstreamGetBit(bs)) // not_8_bit { DEBUG("+ not_8_bit [IGNORED/TODO]"); dec->quant_bits = BitstreamGetBits(bs, 4); // quant_precision BitstreamSkip(bs, 4); // bits_per_pixel } else { dec->quant_bits = 5; } if (dec->shape == VIDOBJLAY_SHAPE_GRAYSCALE) { BitstreamSkip(bs, 1); // no_gray_quant_update BitstreamSkip(bs, 1); // composition_method BitstreamSkip(bs, 1); // linear_composition } dec->quant_type = BitstreamGetBit(bs); // quant_type // DEBUG1("**** quant_type", dec->quant_type); if (dec->quant_type) { if (BitstreamGetBit(bs)) // load_intra_quant_mat { uint8_t matrix[64]; bs_get_matrix(bs, matrix); set_intra_matrix(matrix); } else set_intra_matrix(get_default_intra_matrix()); if (BitstreamGetBit(bs)) // load_inter_quant_mat { uint8_t matrix[64]; bs_get_matrix(bs, matrix); set_inter_matrix(matrix); } else set_inter_matrix(get_default_inter_matrix()); if (dec->shape == VIDOBJLAY_SHAPE_GRAYSCALE) { // TODO DEBUG("TODO: grayscale matrix stuff"); return -1; } } if (vol_ver_id != 1) { dec->quarterpel = BitstreamGetBit(bs); // quarter_sampe if (dec->quarterpel) { DEBUG("IGNORED/TODO: quarter_sample"); } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -