/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - Bitstream reader/writer - * * Copyright (C) 2001-2003 Peter Ross * 2003 Cristoph Lampert * * 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-1307 USA * * $Id: bitstream.cpp,v 1.1.1.1 2005/07/13 14:36:12 jeanlf Exp $ * ****************************************************************************/ #include "bitstream.h" #include "quant_matrix.h" #ifdef WIN32 #include #endif //---------------------------- inline dword ByteSwap(dword a){ return (a<<24) | ((a&0xff00) << 8) | ((a&0xff0000) >> 8) | (a>>24); } //---------------------------- void Bitstream::Init(const void *bitstream, dword _length){ dword adjbitstream = (dword)bitstream; /* * Start the stream on a dword boundary, by rounding down to the * previous dword and skipping the intervening bytes. */ long bitpos = ((sizeof(dword)-1) & (long)bitstream); adjbitstream = adjbitstream - bitpos; start = tail = (dword *) adjbitstream; if(_length){ dword tmp = *start; #ifndef ARCH_IS_BIG_ENDIAN tmp = ByteSwap(tmp); #endif bufa = tmp; if(_length>4){ tmp = *(start + 1); #ifndef ARCH_IS_BIG_ENDIAN tmp = ByteSwap(tmp); #endif bufb = tmp; }else bufb = 0; }else bufa = bufb = 0; buf = 0; pos = initpos = bitpos*8; length = _length; } //--------------------------- /* reads n bits from bitstream without changing the stream pos */ dword Bitstream::ShowBits(dword bits){ int nbit = (bits + pos) - 32; if(nbit > 0) return ((bufa & (0xffffffff >> pos)) << nbit) | (bufb >> (32 - nbit)); return (bufa & (0xffffffff >> pos)) >> (32 - pos - bits); } //--------------------------- // skip n bits forward in bitstream void Bitstream::Skip(dword bits){ pos += bits; if(pos >= 32){ dword tmp; bufa = bufb; tmp = *((dword *) tail + 2); #ifndef ARCH_IS_BIG_ENDIAN tmp = ByteSwap(tmp); #endif bufb = tmp; tail++; pos -= 32; } } //--------------------------- /* show nbits from next byte alignment */ dword Bitstream::ShowBitsFromByteAlign(int bits){ int bspos = pos + NumBitsToByteAlign(); int nbit = (bits + bspos) - 32; if (bspos >= 32) { return bufb >> (32 - nbit); } else if (nbit > 0) { return ((bufa & (0xffffffff >> bspos)) << nbit) | (bufb >> (32 - nbit)); } else { return (bufa & (0xffffffff >> bspos)) >> (32 - bspos - bits); } } //--------------------------- /* read n bits from bitstream */ dword Bitstream::GetBits(dword n){ dword ret = ShowBits(n); Skip(n); return ret; } //--------------------------- static const dword intra_dc_threshold_table[] = { 32, /* never use */ 13, 15, 17, 19, 21, 23, 1, }; //---------------------------- void Bitstream::get_matrix(byte * matrix){ int i = 0; int last, value = 0; do { last = value; value = GetBits(8); matrix[scan_tables[0][i++]] = value; } while (value != 0 && i < 64); i--; /* fix little bug at coeff not full */ while (i < 64) { matrix[scan_tables[0][i++]] = last; } } //---------------------------- /* * for PVOP addbits == fcode - 1 * for BVOP addbits == max(fcode,bcode) - 1 * returns mbpos */ int S_decoder::read_video_packet_header(Bitstream *bs, const int addbits, int *quant, int *fcode_forward, int *fcode_backward, int *intra_dc_threshold){ int startcode_bits = NUMBITS_VP_RESYNC_MARKER + addbits; int mbnum_bits = log2bin(mb_width * mb_height - 1); int mbnum; int hec = 0; bs->Skip(bs->NumBitsToByteAlign()); bs->Skip(startcode_bits); DPRINTF(XVID_DEBUG_STARTCODE, "\n"); if (shape != VIDOBJLAY_SHAPE_RECTANGULAR) { hec = bs->GetBit(); /* header_extension_code */ if (hec && !(sprite_enable == SPRITE_STATIC /* && current_coding_type = I_VOP */)) { bs->Skip(13); /* vop_width */ READ_MARKER(); bs->Skip(13); /* vop_height */ READ_MARKER(); bs->Skip(13); /* vop_horizontal_mc_spatial_ref */ READ_MARKER(); bs->Skip(13); /* vop_vertical_mc_spatial_ref */ READ_MARKER(); } } mbnum = bs->GetBits(mbnum_bits); /* macroblock_number */ DPRINTF(XVID_DEBUG_HEADER, "mbnum %i\n", mbnum); if (shape != VIDOBJLAY_SHAPE_BINARY_ONLY) { *quant = bs->GetBits(quant_bits); /* quant_scale */ DPRINTF(XVID_DEBUG_HEADER, "quant %i\n", *quant); } if (shape == VIDOBJLAY_SHAPE_RECTANGULAR) hec = bs->GetBit(); /* header_extension_code */ DPRINTF(XVID_DEBUG_HEADER, "header_extension_code %i\n", hec); if (hec) { int time_base; int time_increment = 0; int coding_type; for (time_base=0; bs->GetBit()!=0; time_base++); /* modulo_time_base */ READ_MARKER(); if (time_inc_bits) time_increment = (bs->GetBits(time_inc_bits)); /* vop_time_increment */ READ_MARKER(); //DPRINTF(XVID_DEBUG_HEADER,"time %i:%i\n", time_base, time_increment); coding_type = bs->GetBits(2); DPRINTF(XVID_DEBUG_HEADER,"coding_type %i\n", coding_type); if (shape != VIDOBJLAY_SHAPE_RECTANGULAR) { bs->Skip(1); /* change_conv_ratio_disable */ if (coding_type != I_VOP) bs->Skip(1); /* vop_shape_coding_type */ } if (shape != VIDOBJLAY_SHAPE_BINARY_ONLY) { *intra_dc_threshold = intra_dc_threshold_table[bs->GetBits(3)]; if (sprite_enable == SPRITE_GMC && coding_type == S_VOP && sprite_warping_points > 0) { /* TODO: sprite trajectory */ } if(reduced_resolution_enable && shape == VIDOBJLAY_SHAPE_RECTANGULAR && (coding_type == P_VOP || coding_type == I_VOP)){ bs->Skip(1); /* XXX: vop_reduced_resolution */ } if (coding_type != I_VOP && fcode_forward) { *fcode_forward = bs->GetBits(3); DPRINTF(XVID_DEBUG_HEADER,"fcode_forward %i\n", *fcode_forward); } if (coding_type == B_VOP && fcode_backward) { *fcode_backward = bs->GetBits(3); DPRINTF(XVID_DEBUG_HEADER,"fcode_backward %i\n", *fcode_backward); } } } if (newpred_enable) { int vop_id; int vop_id_for_prediction; vop_id = bs->GetBits(MIN(time_inc_bits + 3, 15)); DPRINTF(XVID_DEBUG_HEADER, "vop_id %i\n", vop_id); if (bs->GetBit()) /* vop_id_for_prediction_indication */ { vop_id_for_prediction = bs->GetBits(MIN(time_inc_bits + 3, 15)); DPRINTF(XVID_DEBUG_HEADER, "vop_id_for_prediction %i\n", vop_id_for_prediction); } READ_MARKER(); } return mbnum; } //---------------------------- /* vol estimation header */ void S_decoder::read_vol_complexity_estimation_header(Bitstream * bs){ ESTIMATION * e = &estimation; e->method = bs->GetBits(2); /* estimation_method */ DPRINTF(XVID_DEBUG_HEADER,"+ complexity_estimation_header; method=%i\n", e->method); if (e->method == 0 || e->method == 1){ if(!bs->GetBit()){ //shape_complexity_estimation_disable e->opaque = bs->GetBit(); /* opaque */ e->transparent = bs->GetBit(); /* transparent */ e->intra_cae = bs->GetBit(); /* intra_cae */ e->inter_cae = bs->GetBit(); /* inter_cae */ e->no_update = bs->GetBit(); /* no_update */ e->upsampling = bs->GetBit(); /* upsampling */ } if (!bs->GetBit()) /* texture_complexity_estimation_set_1_disable */ { e->intra_blocks = bs->GetBit(); /* intra_blocks */ e->inter_blocks = bs->GetBit(); /* inter_blocks */ e->inter4v_blocks = bs->GetBit(); /* inter4v_blocks */ e->not_coded_blocks = bs->GetBit(); /* not_coded_blocks */ } } READ_MARKER(); if (!bs->GetBit()){ //texture_complexity_estimation_set_2_disable e->dct_coefs = bs->GetBit(); /* dct_coefs */ e->dct_lines = bs->GetBit(); /* dct_lines */ e->vlc_symbols = bs->GetBit(); /* vlc_symbols */ e->vlc_bits = bs->GetBit(); /* vlc_bits */ } if (!bs->GetBit()){ //motion_compensation_complexity_disable e->apm = bs->GetBit(); /* apm */ e->npm = bs->GetBit(); /* npm */ e->interpolate_mc_q = bs->GetBit(); /* interpolate_mc_q */ e->forw_back_mc_q = bs->GetBit(); /* forw_back_mc_q */ e->halfpel2 = bs->GetBit(); /* halfpel2 */ e->halfpel4 = bs->GetBit(); /* halfpel4 */ } READ_MARKER(); if (e->method == 1){ if (!bs->GetBit()){ //version2_complexity_estimation_disable e->sadct = bs->GetBit(); /* sadct */ e->quarterpel = bs->GetBit(); /* quarterpel */ } } } //---------------------------- /* vop estimation header */ void S_decoder::read_vop_complexity_estimation_header(Bitstream * bs, int coding_type){ ESTIMATION * e = &estimation; if (e->method == 0 || e->method == 1) { if (coding_type == I_VOP) { if (e->opaque) bs->Skip(8); /* dcecs_opaque */ if (e->transparent) bs->Skip(8); /* */ if (e->intra_cae) bs->Skip(8); /* */ if (e->inter_cae) bs->Skip(8); /* */ if (e->no_update) bs->Skip(8); /* */ if (e->upsampling) bs->Skip(8); /* */ if (e->intra_blocks) bs->Skip(8); /* */ if (e->not_coded_blocks) bs->Skip(8); /* */ if (e->dct_coefs) bs->Skip(8); /* */ if (e->dct_lines) bs->Skip(8); /* */ if (e->vlc_symbols) bs->Skip(8); /* */ if (e->vlc_bits) bs->Skip(8); /* */ if (e->sadct) bs->Skip(8); /* */ } if (coding_type == P_VOP) { if (e->opaque) bs->Skip(8); /* */ if (e->transparent) bs->Skip(8); /* */ if (e->intra_cae) bs->Skip(8); /* */ if (e->inter_cae) bs->Skip(8); /* */ if (e->no_update) bs->Skip(8); /* */ if (e->upsampling) bs->Skip(8); /* */ if (e->intra_blocks) bs->Skip(8); /* */ if (e->not_coded_blocks) bs->Skip(8); /* */ if (e->dct_coefs) bs->Skip(8); /* */ if (e->dct_lines) bs->Skip(8); /* */ if (e->vlc_symbols) bs->Skip(8); /* */ if (e->vlc_bits) bs->Skip(8); /* */ if (e->inter_blocks) bs->Skip(8); /* */ if (e->inter4v_blocks) bs->Skip(8); /* */ if (e->apm) bs->Skip(8); /* */ if (e->npm) bs->Skip(8); /* */ if (e->forw_back_mc_q) bs->Skip(8); /* */ if (e->halfpel2) bs->Skip(8); /* */ if (e->halfpel4) bs->Skip(8); /* */ if (e->sadct) bs->Skip(8); /* */ if (e->quarterpel) bs->Skip(8); /* */ } if (coding_type == B_VOP) { if (e->opaque) bs->Skip(8); /* */ if (e->transparent) bs->Skip(8); /* */ if (e->intra_cae) bs->Skip(8); /* */ if (e->inter_cae) bs->Skip(8); /* */ if (e->no_update) bs->Skip(8); /* */ if (e->upsampling) bs->Skip(8); /* */ if (e->intra_blocks) bs->Skip(8); /* */ if (e->not_coded_blocks) bs->Skip(8); /* */ if (e->dct_coefs) bs->Skip(8); /* */ if (e->dct_lines) bs->Skip(8); /* */ if (e->vlc_symbols) bs->Skip(8); /* */ if (e->vlc_bits) bs->Skip(8); /* */ if (e->inter_blocks) bs->Skip(8); /* */ if (e->inter4v_blocks) bs->Skip(8); /* */ if (e->apm) bs->Skip(8); /* */ if (e->npm) bs->Skip(8); /* */ if (e->forw_back_mc_q) bs->Skip(8); /* */ if (e->halfpel2) bs->Skip(8); /* */ if (e->halfpel4) bs->Skip(8); /* */ if (e->interpolate_mc_q) bs->Skip(8); /* */ if (e->sadct) bs->Skip(8); /* */ if (e->quarterpel) bs->Skip(8); /* */ } if (coding_type == S_VOP && sprite_enable == SPRITE_STATIC) { if (e->intra_blocks) bs->Skip(8); /* */ if (e->not_coded_blocks) bs->Skip(8); /* */ if (e->dct_coefs) bs->Skip(8); /* */ if (e->dct_lines) bs->Skip(8); /* */ if (e->vlc_symbols) bs->Skip(8); /* */ if (e->vlc_bits) bs->Skip(8); /* */ if (e->inter_blocks) bs->Skip(8); /* */ if (e->inter4v_blocks) bs->Skip(8); /* */ if (e->apm) bs->Skip(8); /* */ if (e->npm) bs->Skip(8); /* */ if (e->forw_back_mc_q) bs->Skip(8); /* */ if (e->halfpel2) bs->Skip(8); /* */ if (e->halfpel4) bs->Skip(8); /* */ if (e->interpolate_mc_q) bs->Skip(8); /* */ } } } //---------------------------- // decode headers // returns coding_type, or -1 if error #define VIDOBJ_START_CODE_MASK 0x0000001f #define VIDOBJLAY_START_CODE_MASK 0x0000000f int S_decoder::BitstreamReadHeaders(Bitstream * bs, bool &rounding, bool *reduced_resolution, dword *quant, dword *fcode_forward, dword *fcode_backward, dword *intra_dc_threshold, WARPPOINTS *gmc_warp){ dword vol_ver_id; dword coding_type; dword start_code; dword time_incr = 0; int time_increment = 0; int resize = 0; while((bs->Pos() >> 3) < bs->length){ bs->ByteAlign(); start_code = bs->ShowBits(32); switch(start_code){ case VISOBJSEQ_START_CODE: { DPRINTF(XVID_DEBUG_STARTCODE, "\n"); bs->Skip(32); //visual_object_sequence_start_code int profile = bs->GetBits(8); //profile_and_level_indication DPRINTF(XVID_DEBUG_HEADER, "profile_and_level_indication %i\n", profile); } break; case VISOBJSEQ_STOP_CODE: { //visual_object_sequence_stop_code bs->Skip(32); DPRINTF(XVID_DEBUG_STARTCODE, "\n"); } break; case VISOBJ_START_CODE: { DPRINTF(XVID_DEBUG_STARTCODE, "\n"); bs->Skip(32); //visual_object_start_code int visobj_ver_id; //is_visual_object_identified if(bs->GetBit()){ visobj_ver_id = bs->GetBits(4); /* visual_object_ver_id */ DPRINTF(XVID_DEBUG_HEADER,"visobj_ver_id %i\n", visobj_ver_id); bs->Skip(3); //visual_object_priority }else{ visobj_ver_id = 1; } if(bs->ShowBits(4) != VISOBJ_TYPE_VIDEO){ //visual_object_type DPRINTF(XVID_DEBUG_ERROR, "visual_object_type != video\n"); return -1; } bs->Skip(4); //video_signal_type if(bs->GetBit()){ DPRINTF(XVID_DEBUG_HEADER,"+ video_signal_type\n"); bs->Skip(3); /* video_format */ bs->Skip(1); /* video_range */ if (bs->GetBit()) /* color_description */ { DPRINTF(XVID_DEBUG_HEADER,"+ color_description"); bs->Skip(8); /* color_primaries */ bs->Skip(8); /* transfer_characteristics */ bs->Skip(8); /* matrix_coefficients */ } } } break; case GRPOFVOP_START_CODE: { DPRINTF(XVID_DEBUG_STARTCODE, "\n"); bs->Skip(32); { int hours, minutes, seconds; hours = bs->GetBits(5); minutes = bs->GetBits(6); READ_MARKER(); seconds = bs->GetBits(6); //DPRINTF(XVID_DEBUG_HEADER, "time %ih%im%is\n", hours,minutes,seconds); } bs->Skip(1); /* closed_gov */ bs->Skip(1); /* broken_link */ } break; case VOP_START_CODE: { DPRINTF(XVID_DEBUG_STARTCODE, "\n"); bs->Skip(32); /* vop_start_code */ coding_type = bs->GetBits(2); /* vop_coding_type */ DPRINTF(XVID_DEBUG_HEADER, "coding_type %i\n", coding_type); /*********************** for decode B-frame time ***********************/ while (bs->GetBit() != 0) /* time_base */ time_incr++; READ_MARKER(); if (time_inc_bits) { time_increment = (bs->GetBits(time_inc_bits)); /* vop_time_increment */ } DPRINTF(XVID_DEBUG_HEADER, "time_base %i\n", time_incr); DPRINTF(XVID_DEBUG_HEADER, "time_increment %i\n", time_increment); //DPRINTF(XVID_DEBUG_TIMECODE, "%c %i:%i\n", coding_type == I_VOP ? 'I' : coding_type == P_VOP ? 'P' : coding_type == B_VOP ? 'B' : 'S', time_incr, time_increment); if (coding_type != B_VOP) { last_time_base = time_base; time_base += time_incr; time = time_increment; #if 0 time_base * time_inc_resolution + time_increment; #endif time_pp = (dword) (time_inc_resolution + time - last_non_b_time)%time_inc_resolution; last_non_b_time = time; } else { time = time_increment; #if 0 (last_time_base + time_incr) * time_inc_resolution + time_increment; #endif time_bp = (dword) (time_inc_resolution + last_non_b_time - time)%time_inc_resolution; } DPRINTF(XVID_DEBUG_HEADER,"time_pp=%i\n", time_pp); DPRINTF(XVID_DEBUG_HEADER,"time_bp=%i\n", time_bp); READ_MARKER(); if (!bs->GetBit()) /* vop_coded */ { DPRINTF(XVID_DEBUG_HEADER, "vop_coded==false\n"); return N_VOP; } if (newpred_enable) { int vop_id; int vop_id_for_prediction; vop_id = bs->GetBits(MIN(time_inc_bits + 3, 15)); DPRINTF(XVID_DEBUG_HEADER, "vop_id %i\n", vop_id); if (bs->GetBit()) /* vop_id_for_prediction_indication */ { vop_id_for_prediction = bs->GetBits(MIN(time_inc_bits + 3, 15)); DPRINTF(XVID_DEBUG_HEADER, "vop_id_for_prediction %i\n", vop_id_for_prediction); } READ_MARKER(); } //fix a little bug by MinChen if((shape != VIDOBJLAY_SHAPE_BINARY_ONLY) && ((coding_type == P_VOP) || (coding_type == S_VOP && sprite_enable == SPRITE_GMC))){ rounding = !!bs->GetBit(); //rounding_type DPRINTF(XVID_DEBUG_HEADER, "rounding %i\n", rounding); } if(reduced_resolution_enable && shape == VIDOBJLAY_SHAPE_RECTANGULAR && (coding_type == P_VOP || coding_type == I_VOP)) { *reduced_resolution = !!bs->GetBit(); DPRINTF(XVID_DEBUG_HEADER, "reduced_resolution %i\n", *reduced_resolution); }else{ *reduced_resolution = false; } if (shape != VIDOBJLAY_SHAPE_RECTANGULAR) { if(!(sprite_enable == SPRITE_STATIC && coding_type == I_VOP)) { dword width, height; dword horiz_mc_ref, vert_mc_ref; width = bs->GetBits(13); READ_MARKER(); height = bs->GetBits(13); READ_MARKER(); horiz_mc_ref = bs->GetBits(13); READ_MARKER(); vert_mc_ref = bs->GetBits(13); READ_MARKER(); DPRINTF(XVID_DEBUG_HEADER, "width %i\n", width); DPRINTF(XVID_DEBUG_HEADER, "height %i\n", height); DPRINTF(XVID_DEBUG_HEADER, "horiz_mc_ref %i\n", horiz_mc_ref); DPRINTF(XVID_DEBUG_HEADER, "vert_mc_ref %i\n", vert_mc_ref); } bs->Skip(1); /* change_conv_ratio_disable */ if (bs->GetBit()) /* vop_constant_alpha */ { bs->Skip(8); /* vop_constant_alpha_value */ } } if (shape != VIDOBJLAY_SHAPE_BINARY_ONLY) { if (!complexity_estimation_disable) { read_vop_complexity_estimation_header(bs, coding_type); } /* intra_dc_vlc_threshold */ *intra_dc_threshold = intra_dc_threshold_table[bs->GetBits(3)]; top_field_first = 0; alternate_vertical_scan = 0; if(interlacing){ top_field_first = bs->GetBit(); DPRINTF(XVID_DEBUG_HEADER, "interlace top_field_first %i\n", top_field_first); alternate_vertical_scan = bs->GetBit(); DPRINTF(XVID_DEBUG_HEADER, "interlace alternate_vertical_scan %i\n", alternate_vertical_scan); } } if ((sprite_enable == SPRITE_STATIC || sprite_enable== SPRITE_GMC) && coding_type == S_VOP) { int i; for (i = 0 ; i < sprite_warping_points; i++) { int length; int x = 0, y = 0; /* sprite code borowed from ffmpeg; thx Michael Niedermayer */ length = bs->bs_get_spritetrajectory(); if(length){ x= bs->GetBits(length); if ((x >> (length - 1)) == 0) /* if MSB not set it is negative*/ x = - (x ^ ((1 << length) - 1)); } READ_MARKER(); length = bs->bs_get_spritetrajectory(); if(length){ y = bs->GetBits(length); if ((y >> (length - 1)) == 0) /* if MSB not set it is negative*/ y = - (y ^ ((1 << length) - 1)); } READ_MARKER(); gmc_warp->duv[i].x = x; gmc_warp->duv[i].y = y; //DPRINTF(XVID_DEBUG_HEADER,"sprite_warping_point[%i] xy=(%i,%i)\n", i, x, y); } if (sprite_brightness_change) { /* XXX: brightness_change_factor() */ } if (sprite_enable == SPRITE_STATIC) { /* XXX: todo */ } } if ((*quant = bs->GetBits(quant_bits)) < 1) /* vop_quant */ *quant = 1; DPRINTF(XVID_DEBUG_HEADER, "quant %i\n", *quant); if (coding_type != I_VOP) { *fcode_forward = bs->GetBits(3); /* fcode_forward */ DPRINTF(XVID_DEBUG_HEADER, "fcode_forward %i\n", *fcode_forward); } if (coding_type == B_VOP) { *fcode_backward = bs->GetBits(3); /* fcode_backward */ DPRINTF(XVID_DEBUG_HEADER, "fcode_backward %i\n", *fcode_backward); } if(!scalability){ if ((shape != VIDOBJLAY_SHAPE_RECTANGULAR) && (coding_type != I_VOP)) { bs->Skip(1); /* vop_shape_coding_type */ } } return coding_type; } break; case USERDATA_START_CODE: { char tmp[256]; int i; bs->Skip(32); /* user_data_start_code */ tmp[0] = bs->ShowBits(8); for(i = 1; i < 256; i++){ tmp[i] = (bs->ShowBits(16) & 0xFF); if(tmp[i] == 0) break; bs->Skip(8); } //DPRINTF(XVID_DEBUG_STARTCODE, ": %s\n", tmp); /* read xvid bitstream version */ #ifdef WIN32 { char packed; int version, build; if(MemCmp(tmp, "XviD", 4) == 0) { sscanf(tmp, "XviD%d", &bs_version); DPRINTF(XVID_DEBUG_HEADER, "xvid bitstream version=%i", bs_version); } /* divx detection */ i = sscanf(tmp, "DivX%dBuild%d%c", &version, &build, &packed); if (i < 2) i = sscanf(tmp, "DivX%db%d%c", &version, &build, &packed); if (i >= 2){ packed_mode = (i == 3 && packed == 'p'); //DPRINTF(XVID_DEBUG_HEADER, "divx version=%i, build=%i packed=%i\n", version, build, packed_mode); } } #endif } break; default: switch(start_code & ~VIDOBJ_START_CODE_MASK){ case VIDOBJ_START_CODE: { DPRINTF(XVID_DEBUG_STARTCODE, "\n"); DPRINTF(XVID_DEBUG_HEADER, "vo id %i\n", start_code & VIDOBJ_START_CODE_MASK); //video_object_start_code bs->Skip(32); } break; case VIDOBJLAY_START_CODE: { DPRINTF(XVID_DEBUG_STARTCODE, "\n"); DPRINTF(XVID_DEBUG_HEADER, "vol id %i\n", start_code & VIDOBJLAY_START_CODE_MASK); bs->Skip(32); //video_object_layer_start_code bs->Skip(1); //random_accessible_vol bs->Skip(8); //video_object_type_indication if(bs->GetBit()){ //is_object_layer_identifier DPRINTF(XVID_DEBUG_HEADER, "+ is_object_layer_identifier\n"); vol_ver_id = bs->GetBits(4); /* video_object_layer_verid */ DPRINTF(XVID_DEBUG_HEADER,"ver_id %i\n", vol_ver_id); bs->Skip(3); /* video_object_layer_priority */ }else{ vol_ver_id = 1; } aspect_ratio = bs->GetBits(4); if(aspect_ratio == VIDOBJLAY_AR_EXTPAR){ //aspect_ratio_info DPRINTF(XVID_DEBUG_HEADER, "+ aspect_ratio_info\n"); par_width = bs->GetBits(8); /* par_width */ par_height = bs->GetBits(8); /* par_height */ } if(bs->GetBit()){ //vol_control_parameters DPRINTF(XVID_DEBUG_HEADER, "+ vol_control_parameters\n"); bs->Skip(2); /* chroma_format */ low_delay = (bs->GetBit()!=0); DPRINTF(XVID_DEBUG_HEADER, "low_delay %i\n", (int)low_delay); if (bs->GetBit()) /* vbv_parameters */ { unsigned int bitrate; unsigned int buffer_size; unsigned int occupancy; DPRINTF(XVID_DEBUG_HEADER,"+ vbv_parameters\n"); bitrate = bs->GetBits(15) << 15; /* first_half_bit_rate */ READ_MARKER(); bitrate |= bs->GetBits(15); /* latter_half_bit_rate */ READ_MARKER(); buffer_size = bs->GetBits(15) << 3; /* first_half_vbv_buffer_size */ READ_MARKER(); buffer_size |= bs->GetBits(3); /* latter_half_vbv_buffer_size */ occupancy = bs->GetBits(11) << 15; /* first_half_vbv_occupancy */ READ_MARKER(); occupancy |= bs->GetBits(15); /* latter_half_vbv_occupancy */ READ_MARKER(); DPRINTF(XVID_DEBUG_HEADER,"bitrate %d (unit=400 bps)\n", bitrate); DPRINTF(XVID_DEBUG_HEADER,"buffer_size %d (unit=16384 bits)\n", buffer_size); DPRINTF(XVID_DEBUG_HEADER,"occupancy %d (unit=64 bits)\n", occupancy); } }else{ low_delay = low_delay_default; } //video_object_layer_shape shape = bs->GetBits(2); DPRINTF(XVID_DEBUG_HEADER, "shape %i\n", shape); if(shape != VIDOBJLAY_SHAPE_RECTANGULAR){ DPRINTF(XVID_DEBUG_ERROR,"non-rectangular shapes are not supported\n"); } if(shape == VIDOBJLAY_SHAPE_GRAYSCALE && vol_ver_id != 1){ //video_object_layer_shape_extension bs->Skip(4); } READ_MARKER(); /********************** for decode B-frame time ***********************/ time_inc_resolution = bs->GetBits(16); /* vop_time_increment_resolution */ DPRINTF(XVID_DEBUG_HEADER,"vop_time_increment_resolution %i\n", time_inc_resolution); #if 0 time_inc_resolution--; #endif if(time_inc_resolution > 0){ time_inc_bits = log2bin(time_inc_resolution-1); }else{ #if 0 time_inc_bits = 0; #endif /* for "old" xvid compatibility, set time_inc_bits = 1 */ time_inc_bits = 1; } READ_MARKER(); if(bs->GetBit()){ //fixed_vop_rate DPRINTF(XVID_DEBUG_HEADER, "+ fixed_vop_rate\n"); bs->Skip(time_inc_bits); //fixed_vop_time_increment } if(shape != VIDOBJLAY_SHAPE_BINARY_ONLY){ if(shape == VIDOBJLAY_SHAPE_RECTANGULAR){ dword _width, _height; READ_MARKER(); _width = bs->GetBits(13); //video_object_layer_width READ_MARKER(); _height = bs->GetBits(13); //video_object_layer_height READ_MARKER(); DPRINTF(XVID_DEBUG_HEADER, "width %i\n", _width); DPRINTF(XVID_DEBUG_HEADER, "height %i\n", _height); if(width != _width || height != _height){ if(fixed_dimensions){ DPRINTF(XVID_DEBUG_ERROR, "decoder width/height does not match bitstream\n"); return -1; } resize = 1; width = _width; height = _height; } } interlacing = !!bs->GetBit(); DPRINTF(XVID_DEBUG_HEADER, "interlacing %i\n", interlacing); if(!bs->GetBit()){ //obmc_disable DPRINTF(XVID_DEBUG_ERROR, "obmc_disabled==false not supported\n"); /* TODO */ /* fucking divx4.02 has this enabled */ } sprite_enable = bs->GetBits((vol_ver_id == 1 ? 1 : 2)); if(sprite_enable == SPRITE_STATIC || sprite_enable == SPRITE_GMC){ int low_latency_sprite_enable; if(sprite_enable != SPRITE_GMC){ int sprite_width; int sprite_height; int sprite_left_coord; int sprite_top_coord; sprite_width = bs->GetBits(13); /* sprite_width */ READ_MARKER(); sprite_height = bs->GetBits(13); /* sprite_height */ READ_MARKER(); sprite_left_coord = bs->GetBits(13); /* sprite_left_coordinate */ READ_MARKER(); sprite_top_coord = bs->GetBits(13); /* sprite_top_coordinate */ READ_MARKER(); } sprite_warping_points = bs->GetBits(6); /* no_of_sprite_warping_points */ sprite_warping_accuracy = bs->GetBits(2); /* sprite_warping_accuracy */ sprite_brightness_change = bs->GetBits(1); /* brightness_change */ if (sprite_enable != SPRITE_GMC) { low_latency_sprite_enable = bs->GetBits(1); /* low_latency_sprite_enable */ } } if(vol_ver_id != 1 && shape != VIDOBJLAY_SHAPE_RECTANGULAR){ //sadct_disable bs->Skip(1); } if(bs->GetBit()){ //not_8_bit DPRINTF(XVID_DEBUG_HEADER, "not_8_bit==true (ignored)\n"); quant_bits = bs->GetBits(4); /* quant_precision */ bs->Skip(4); /* bits_per_pixel */ }else{ quant_bits = 5; } if(shape == VIDOBJLAY_SHAPE_GRAYSCALE){ bs->Skip(1); /* no_gray_quant_update */ bs->Skip(1); /* composition_method */ bs->Skip(1); /* linear_composition */ } quant_type = bs->GetBit(); DPRINTF(XVID_DEBUG_HEADER, "quant_type %i\n", quant_type); if(quant_type){ if (bs->GetBit()) //load_intra_quant_mat { byte matrix[64]; DPRINTF(XVID_DEBUG_HEADER, "load_intra_quant_mat\n"); bs->get_matrix(matrix); set_intra_matrix(mpeg_quant_matrices, matrix); }else set_intra_matrix(mpeg_quant_matrices, get_default_intra_matrix()); if (bs->GetBit()) /* load_inter_quant_mat */ { byte matrix[64]; DPRINTF(XVID_DEBUG_HEADER, "load_inter_quant_mat\n"); bs->get_matrix(matrix); set_inter_matrix(mpeg_quant_matrices, matrix); }else set_inter_matrix(mpeg_quant_matrices, get_default_inter_matrix()); if (shape == VIDOBJLAY_SHAPE_GRAYSCALE) { DPRINTF(XVID_DEBUG_ERROR, "greyscale matrix not supported\n"); return -1; } } if(vol_ver_id != 1){ quarterpel = bs->GetBit(); DPRINTF(XVID_DEBUG_HEADER,"quarterpel %i\n", quarterpel); }else quarterpel = 0; complexity_estimation_disable = bs->GetBit(); if(!complexity_estimation_disable){ read_vol_complexity_estimation_header(bs); } bs->Skip(1); //resync_marker_disable if(bs->GetBit()){ //data_partitioned DPRINTF(XVID_DEBUG_ERROR, "data_partitioned not supported\n"); bs->Skip(1); /* reversible_vlc */ } if(vol_ver_id != 1){ newpred_enable = !!bs->GetBit(); if (newpred_enable) /* newpred_enable */ { DPRINTF(XVID_DEBUG_HEADER, "+ newpred_enable\n"); bs->Skip(2); /* requested_upstream_message_type */ bs->Skip(1); /* newpred_segment_type */ } reduced_resolution_enable = !!bs->GetBit(); //reduced_resolution_vop_enable DPRINTF(XVID_DEBUG_HEADER, "reduced_resolution_enable %i\n", reduced_resolution_enable); }else{ newpred_enable = false; reduced_resolution_enable = false; } scalability = (bs->GetBit()!=0); if(scalability){ DPRINTF(XVID_DEBUG_ERROR, "scalability not supported\n"); bs->Skip(1); /* hierarchy_type */ bs->Skip(4); /* ref_layer_id */ bs->Skip(1); /* ref_layer_sampling_direc */ bs->Skip(5); /* hor_sampling_factor_n */ bs->Skip(5); /* hor_sampling_factor_m */ bs->Skip(5); /* vert_sampling_factor_n */ bs->Skip(5); /* vert_sampling_factor_m */ bs->Skip(1); /* enhancement_type */ if(shape == VIDOBJLAY_SHAPE_BINARY /* && hierarchy_type==0 */) { bs->Skip(1); /* use_ref_shape */ bs->Skip(1); /* use_ref_texture */ bs->Skip(5); /* shape_hor_sampling_factor_n */ bs->Skip(5); /* shape_hor_sampling_factor_m */ bs->Skip(5); /* shape_vert_sampling_factor_n */ bs->Skip(5); /* shape_vert_sampling_factor_m */ } return -1; } }else{ //shape == BINARY_ONLY if(vol_ver_id != 1){ scalability = (bs->GetBit()!=0); if(scalability){ DPRINTF(XVID_DEBUG_ERROR, "scalability not supported\n"); bs->Skip(4); /* ref_layer_id */ bs->Skip(5); /* hor_sampling_factor_n */ bs->Skip(5); /* hor_sampling_factor_m */ bs->Skip(5); /* vert_sampling_factor_n */ bs->Skip(5); /* vert_sampling_factor_m */ return -1; } } bs->Skip(1); /* resync_marker_disable */ } return (resize ? -3 : -2); //VOL } break; default: { //start_code == ? //if(bs->ShowBits(24) == 0x000001) if((start_code&0x00ffffff) == 0x000001){ DPRINTF(XVID_DEBUG_STARTCODE, "\n", bs->ShowBits(32)); } bs->Skip(8); } } } } #if 0 DPRINTF("*** WARNING: no vop_start_code found"); #endif return -1; //ignore it } //----------------------------