--- bitstream.c 2002/11/12 15:53:23 1.28.2.6 +++ bitstream.c 2003/02/22 08:49:45 1.39.2.1 @@ -41,8 +41,8 @@ * * * Revision history: * * * - * 28.10.2002 GMC support - gruel * - * 04.10.2002 qpel support - Isibaar * + * 05.01.2003 GMC support - gruel * + * 04.10.2002 qpel support - Isibaar * * 11.07.2002 add VOP width & height return to dec when dec->width * * or dec->height is 0 (for use in examples/ex1.c) * * MinChen * @@ -67,6 +67,8 @@ #include +#include + #include "bitstream.h" #include "zigzag.h" #include "../quant/quant_matrix.h" @@ -77,7 +79,7 @@ log2bin(uint32_t value) { /* Changed by Chenm001 */ -#ifndef WIN32 +#if !defined(_MSC_VER) int n = 0; while (value) { @@ -171,7 +173,7 @@ if (dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) { - *quant = BitstreamGetBits(bs, 5); /* quant_scale */ + *quant = BitstreamGetBits(bs, dec->quant_bits); /* quant_scale */ DPRINTF(DPRINTF_HEADER, "quant %i", *quant); } @@ -216,7 +218,7 @@ dec->shape == VIDOBJLAY_SHAPE_RECTANGULAR && (coding_type == P_VOP || coding_type == I_VOP)) { - BitstreamSkip(bs, 1); /* vop_reduced_resolution */ + BitstreamSkip(bs, 1); /* XXX: vop_reduced_resolution */ } if (coding_type != I_VOP && fcode_forward) @@ -228,7 +230,7 @@ if (coding_type == B_VOP && fcode_backward) { *fcode_backward = BitstreamGetBits(bs, 3); - DPRINTF(DPRINTF_HEADER,"fcode_backward %i", fcode_backward); + DPRINTF(DPRINTF_HEADER,"fcode_backward %i", *fcode_backward); } } @@ -254,6 +256,165 @@ + +/* vol estimation header */ +static void +read_vol_complexity_estimation_header(Bitstream * bs, DECODER * dec) +{ + ESTIMATION * e = &dec->estimation; + + e->method = BitstreamGetBits(bs, 2); /* estimation_method */ + DPRINTF(DPRINTF_HEADER,"+ complexity_estimation_header; method=%i", e->method); + + if (e->method == 0 || e->method == 1) + { + if (!BitstreamGetBit(bs)) /* shape_complexity_estimation_disable */ + { + e->opaque = BitstreamGetBit(bs); /* opaque */ + e->transparent = BitstreamGetBit(bs); /* transparent */ + e->intra_cae = BitstreamGetBit(bs); /* intra_cae */ + e->inter_cae = BitstreamGetBit(bs); /* inter_cae */ + e->no_update = BitstreamGetBit(bs); /* no_update */ + e->upsampling = BitstreamGetBit(bs); /* upsampling */ + } + + if (!BitstreamGetBit(bs)) /* texture_complexity_estimation_set_1_disable */ + { + e->intra_blocks = BitstreamGetBit(bs); /* intra_blocks */ + e->inter_blocks = BitstreamGetBit(bs); /* inter_blocks */ + e->inter4v_blocks = BitstreamGetBit(bs); /* inter4v_blocks */ + e->not_coded_blocks = BitstreamGetBit(bs); /* not_coded_blocks */ + } + } + + READ_MARKER(); + + if (!BitstreamGetBit(bs)) /* texture_complexity_estimation_set_2_disable */ + { + e->dct_coefs = BitstreamGetBit(bs); /* dct_coefs */ + e->dct_lines = BitstreamGetBit(bs); /* dct_lines */ + e->vlc_symbols = BitstreamGetBit(bs); /* vlc_symbols */ + e->vlc_bits = BitstreamGetBit(bs); /* vlc_bits */ + } + + if (!BitstreamGetBit(bs)) /* motion_compensation_complexity_disable */ + { + e->apm = BitstreamGetBit(bs); /* apm */ + e->npm = BitstreamGetBit(bs); /* npm */ + e->interpolate_mc_q = BitstreamGetBit(bs); /* interpolate_mc_q */ + e->forw_back_mc_q = BitstreamGetBit(bs); /* forw_back_mc_q */ + e->halfpel2 = BitstreamGetBit(bs); /* halfpel2 */ + e->halfpel4 = BitstreamGetBit(bs); /* halfpel4 */ + } + + READ_MARKER(); + + if (e->method == 1) + { + if (!BitstreamGetBit(bs)) /* version2_complexity_estimation_disable */ + { + e->sadct = BitstreamGetBit(bs); /* sadct */ + e->quarterpel = BitstreamGetBit(bs); /* quarterpel */ + } + } +} + + +/* vop estimation header */ +static void +read_vop_complexity_estimation_header(Bitstream * bs, DECODER * dec, int coding_type) +{ + ESTIMATION * e = &dec->estimation; + + if (e->method == 0 || e->method == 1) + { + if (coding_type == I_VOP) { + if (e->opaque) BitstreamSkip(bs, 8); /* dcecs_opaque */ + if (e->transparent) BitstreamSkip(bs, 8); /* */ + if (e->intra_cae) BitstreamSkip(bs, 8); /* */ + if (e->inter_cae) BitstreamSkip(bs, 8); /* */ + if (e->no_update) BitstreamSkip(bs, 8); /* */ + if (e->upsampling) BitstreamSkip(bs, 8); /* */ + if (e->intra_blocks) BitstreamSkip(bs, 8); /* */ + if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */ + if (e->dct_coefs) BitstreamSkip(bs, 8); /* */ + if (e->dct_lines) BitstreamSkip(bs, 8); /* */ + if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */ + if (e->vlc_bits) BitstreamSkip(bs, 8); /* */ + if (e->sadct) BitstreamSkip(bs, 8); /* */ + } + + if (coding_type == P_VOP) { + if (e->opaque) BitstreamSkip(bs, 8); /* */ + if (e->transparent) BitstreamSkip(bs, 8); /* */ + if (e->intra_cae) BitstreamSkip(bs, 8); /* */ + if (e->inter_cae) BitstreamSkip(bs, 8); /* */ + if (e->no_update) BitstreamSkip(bs, 8); /* */ + if (e->upsampling) BitstreamSkip(bs, 8); /* */ + if (e->intra_blocks) BitstreamSkip(bs, 8); /* */ + if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */ + if (e->dct_coefs) BitstreamSkip(bs, 8); /* */ + if (e->dct_lines) BitstreamSkip(bs, 8); /* */ + if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */ + if (e->vlc_bits) BitstreamSkip(bs, 8); /* */ + if (e->inter_blocks) BitstreamSkip(bs, 8); /* */ + if (e->inter4v_blocks) BitstreamSkip(bs, 8); /* */ + if (e->apm) BitstreamSkip(bs, 8); /* */ + if (e->npm) BitstreamSkip(bs, 8); /* */ + if (e->forw_back_mc_q) BitstreamSkip(bs, 8); /* */ + if (e->halfpel2) BitstreamSkip(bs, 8); /* */ + if (e->halfpel4) BitstreamSkip(bs, 8); /* */ + if (e->sadct) BitstreamSkip(bs, 8); /* */ + if (e->quarterpel) BitstreamSkip(bs, 8); /* */ + } + if (coding_type == B_VOP) { + if (e->opaque) BitstreamSkip(bs, 8); /* */ + if (e->transparent) BitstreamSkip(bs, 8); /* */ + if (e->intra_cae) BitstreamSkip(bs, 8); /* */ + if (e->inter_cae) BitstreamSkip(bs, 8); /* */ + if (e->no_update) BitstreamSkip(bs, 8); /* */ + if (e->upsampling) BitstreamSkip(bs, 8); /* */ + if (e->intra_blocks) BitstreamSkip(bs, 8); /* */ + if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */ + if (e->dct_coefs) BitstreamSkip(bs, 8); /* */ + if (e->dct_lines) BitstreamSkip(bs, 8); /* */ + if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */ + if (e->vlc_bits) BitstreamSkip(bs, 8); /* */ + if (e->inter_blocks) BitstreamSkip(bs, 8); /* */ + if (e->inter4v_blocks) BitstreamSkip(bs, 8); /* */ + if (e->apm) BitstreamSkip(bs, 8); /* */ + if (e->npm) BitstreamSkip(bs, 8); /* */ + if (e->forw_back_mc_q) BitstreamSkip(bs, 8); /* */ + if (e->halfpel2) BitstreamSkip(bs, 8); /* */ + if (e->halfpel4) BitstreamSkip(bs, 8); /* */ + if (e->interpolate_mc_q) BitstreamSkip(bs, 8); /* */ + if (e->sadct) BitstreamSkip(bs, 8); /* */ + if (e->quarterpel) BitstreamSkip(bs, 8); /* */ + } + + if (coding_type == S_VOP && dec->sprite_enable == SPRITE_STATIC) { + if (e->intra_blocks) BitstreamSkip(bs, 8); /* */ + if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */ + if (e->dct_coefs) BitstreamSkip(bs, 8); /* */ + if (e->dct_lines) BitstreamSkip(bs, 8); /* */ + if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */ + if (e->vlc_bits) BitstreamSkip(bs, 8); /* */ + if (e->inter_blocks) BitstreamSkip(bs, 8); /* */ + if (e->inter4v_blocks) BitstreamSkip(bs, 8); /* */ + if (e->apm) BitstreamSkip(bs, 8); /* */ + if (e->npm) BitstreamSkip(bs, 8); /* */ + if (e->forw_back_mc_q) BitstreamSkip(bs, 8); /* */ + if (e->halfpel2) BitstreamSkip(bs, 8); /* */ + if (e->halfpel4) BitstreamSkip(bs, 8); /* */ + if (e->interpolate_mc_q) BitstreamSkip(bs, 8); /* */ + } + } +} + + + + + /* decode headers returns coding_type, or -1 if error @@ -271,13 +432,13 @@ uint32_t * fcode_forward, uint32_t * fcode_backward, uint32_t * intra_dc_threshold, - VECTOR * gmc_mv) + WARPPOINTS *gmc_warp) { uint32_t vol_ver_id; uint32_t coding_type; uint32_t start_code; uint32_t time_incr = 0; - int32_t time_increment; + int32_t time_increment = 0; int resize = 0; do { @@ -303,17 +464,18 @@ DPRINTF(DPRINTF_STARTCODE, ""); } else if (start_code == VISOBJ_START_CODE) { + int visobj_ver_id; DPRINTF(DPRINTF_STARTCODE, ""); BitstreamSkip(bs, 32); // visual_object_start_code if (BitstreamGetBit(bs)) // is_visual_object_identified { - vol_ver_id = BitstreamGetBits(bs, 4); // visual_object_ver_id - DPRINTF(DPRINTF_HEADER,"ver_id %i", vol_ver_id); + visobj_ver_id = BitstreamGetBits(bs, 4); // visual_object_ver_id + DPRINTF(DPRINTF_HEADER,"visobj_ver_id %i", visobj_ver_id); BitstreamSkip(bs, 3); // visual_object_priority } else { - vol_ver_id = 1; + visobj_ver_id = 1; } if (BitstreamShowBits(bs, 4) != VISOBJ_TYPE_VIDEO) // visual_object_type @@ -396,19 +558,32 @@ DPRINTF(DPRINTF_HEADER, "low_delay %i", dec->low_delay); if (BitstreamGetBit(bs)) // vbv_parameters { + unsigned int bitrate; + unsigned int buffer_size; + unsigned int occupancy; + DPRINTF(DPRINTF_HEADER,"+ vbv_parameters"); - BitstreamSkip(bs, 15); // first_half_bitrate + + bitrate = BitstreamGetBits(bs,15) << 15; // first_half_bit_rate READ_MARKER(); - BitstreamSkip(bs, 15); // latter_half_bitrate + bitrate |= BitstreamGetBits(bs,15); // latter_half_bit_rate READ_MARKER(); - BitstreamSkip(bs, 15); // first_half_vbv_buffer_size + + buffer_size = BitstreamGetBits(bs, 15) << 3; // first_half_vbv_buffer_size READ_MARKER(); - BitstreamSkip(bs, 3); // latter_half_vbv_buffer_size - BitstreamSkip(bs, 11); // first_half_vbv_occupancy + buffer_size |= BitstreamGetBits(bs, 3); // latter_half_vbv_buffer_size + + occupancy = BitstreamGetBits(bs, 11) << 15; // first_half_vbv_occupancy READ_MARKER(); - BitstreamSkip(bs, 15); // latter_half_vbv_occupancy + occupancy |= BitstreamGetBits(bs, 15); // latter_half_vbv_occupancy READ_MARKER(); + + DPRINTF(DPRINTF_HEADER,"bitrate %d (unit=400 bps)", bitrate); + DPRINTF(DPRINTF_HEADER,"buffer_size %d (unit=16384 bits)", buffer_size); + DPRINTF(DPRINTF_HEADER,"occupancy %d (unit=64 bits)", occupancy); } + }else{ + dec->low_delay = dec->low_delay_default; } dec->shape = BitstreamGetBits(bs, 2); // video_object_layer_shape @@ -465,7 +640,7 @@ { if (dec->fixed_dimensions) { - DPRINTF(DPRINTF_ERROR, "XVID_DEC_PARAM width/height does not match bitstream"); + DPRINTF(DPRINTF_ERROR, "decoder width/height does not match bitstream"); return -1; } resize = 1; @@ -576,10 +751,10 @@ dec->quarterpel = 0; - if (!BitstreamGetBit(bs)) // complexity_estimation_disable + dec->complexity_estimation_disable = BitstreamGetBit(bs); /* complexity estimation disable */ + if (!dec->complexity_estimation_disable) { - DPRINTF(DPRINTF_ERROR, "complexity_estimation not supported"); - return -1; + read_vol_complexity_estimation_header(bs, dec); } BitstreamSkip(bs, 1); // resync_marker_disable @@ -598,12 +773,8 @@ BitstreamSkip(bs, 2); // requested_upstream_message_type BitstreamSkip(bs, 1); // newpred_segment_type } - dec->reduced_resolution_enable = BitstreamGetBit(bs); - if (dec->reduced_resolution_enable) // reduced_resolution_vop_enable - { - DPRINTF(DPRINTF_ERROR, "reduced_resolution_vop not supported"); - //return -1; - } + dec->reduced_resolution_enable = BitstreamGetBit(bs); /* reduced_resolution_vop_enable */ + DPRINTF(DPRINTF_HEADER, "reduced_resolution_enable %i", dec->reduced_resolution_enable); } else { @@ -611,17 +782,40 @@ dec->reduced_resolution_enable = 0; } - if ((dec->scalability = BitstreamGetBit(bs))) // scalability + dec->scalability = BitstreamGetBit(bs); /* scalability */ + if (dec->scalability) { DPRINTF(DPRINTF_ERROR, "scalability not supported"); + BitstreamSkip(bs, 1); /* hierarchy_type */ + BitstreamSkip(bs, 4); /* ref_layer_id */ + BitstreamSkip(bs, 1); /* ref_layer_sampling_direc */ + BitstreamSkip(bs, 5); /* hor_sampling_factor_n */ + BitstreamSkip(bs, 5); /* hor_sampling_factor_m */ + BitstreamSkip(bs, 5); /* vert_sampling_factor_n */ + BitstreamSkip(bs, 5); /* vert_sampling_factor_m */ + BitstreamSkip(bs, 1); /* enhancement_type */ + if(dec->shape == VIDOBJLAY_SHAPE_BINARY /* && hierarchy_type==0 */) { + BitstreamSkip(bs, 1); /* use_ref_shape */ + BitstreamSkip(bs, 1); /* use_ref_texture */ + BitstreamSkip(bs, 5); /* shape_hor_sampling_factor_n */ + BitstreamSkip(bs, 5); /* shape_hor_sampling_factor_m */ + BitstreamSkip(bs, 5); /* shape_vert_sampling_factor_n */ + BitstreamSkip(bs, 5); /* shape_vert_sampling_factor_m */ + } return -1; } } else // dec->shape == BINARY_ONLY { if (vol_ver_id != 1) { - if (BitstreamGetBit(bs)) // scalability + dec->scalability = BitstreamGetBit(bs); /* scalability */ + if (dec->scalability) { - DPRINTF(DPRINTF_ERROR, "scalability not supported"); + DPRINTF(DPRINTF_ERROR, "scalability not supported"); + BitstreamSkip(bs, 4); /* ref_layer_id */ + BitstreamSkip(bs, 5); /* hor_sampling_factor_n */ + BitstreamSkip(bs, 5); /* hor_sampling_factor_m */ + BitstreamSkip(bs, 5); /* vert_sampling_factor_n */ + BitstreamSkip(bs, 5); /* vert_sampling_factor_m */ return -1; } } @@ -644,7 +838,7 @@ READ_MARKER(); seconds = BitstreamGetBits(bs, 6); - DPRINTF(DPRINTF_HEADER, "time %ih%im%is", hours); + DPRINTF(DPRINTF_HEADER, "time %ih%im%is", hours,minutes,seconds); } BitstreamSkip(bs, 1); // closed_gov BitstreamSkip(bs, 1); // broken_link @@ -694,6 +888,8 @@ dec->time_bp = (uint32_t) (dec->time_inc_resolution + dec->last_non_b_time - dec->time)%dec->time_inc_resolution; } + DPRINTF(DPRINTF_HEADER,"time_pp=%i", dec->time_pp); + DPRINTF(DPRINTF_HEADER,"time_bp=%i", dec->time_bp); READ_MARKER(); @@ -732,6 +928,7 @@ (coding_type == P_VOP || coding_type == I_VOP)) { *reduced_resolution = BitstreamGetBit(bs); + DPRINTF(DPRINTF_HEADER, "reduced_resolution %i", *reduced_resolution); } else { @@ -767,6 +964,12 @@ } if (dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) { + + if (!dec->complexity_estimation_disable) + { + read_vop_complexity_estimation_header(bs, dec, coding_type); + } + // intra_dc_vlc_threshold *intra_dc_threshold = intra_dc_threshold_table[BitstreamGetBits(bs, 3)]; @@ -809,8 +1012,8 @@ } READ_MARKER(); - gmc_mv[i].x = x; - gmc_mv[i].y = y; + gmc_warp->duv[i].x = x; + gmc_warp->duv[i].y = y; DPRINTF(DPRINTF_HEADER,"sprite_warping_point[%i] xy=(%i,%i)", i, x, y); } @@ -849,7 +1052,8 @@ } else if (start_code == USERDATA_START_CODE) { char tmp[256]; - int i; + int i, version, build; + char packed; BitstreamSkip(bs, 32); // user_data_start_code @@ -866,11 +1070,18 @@ DPRINTF(DPRINTF_STARTCODE, ": %s\n", tmp); - if(strncmp(tmp, "DivX501b481p", 12) == 0) { - dec->packed_mode = 1; - DPRINTF(DPRINTF_STARTCODE, "packed_mode = %d\n", dec->packed_mode); - + /* 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) + { + dec->packed_mode = (i == 3 && packed == 'p'); + DPRINTF(DPRINTF_HEADER, "divx version=%i, build=%i packed=%i", + version, build, dec->packed_mode); } + } else // start_code == ? { if (BitstreamShowBits(bs, 24) == 0x000001) { @@ -912,22 +1123,46 @@ */ void BitstreamWriteVolHeader(Bitstream * const bs, - const MBParam * pParam, - const FRAMEINFO * const frame) + const MBParam * pParam) { + static const unsigned int vo_id = 0; + static const unsigned int vol_id = 0; int vol_ver_id=1; + int profile = 0x03; /* simple profile/level 3 */ - if ( (pParam->m_quarterpel) || (frame->global_flags & XVID_GMC) ) + if ( (pParam->vol_flags & XVID_QUARTERPEL) || + (pParam->vol_flags & XVID_GMC) || + (pParam->vol_flags & XVID_REDUCED_ENABLE)) vol_ver_id = 2; + + if ((pParam->vol_flags & XVID_REDUCED_ENABLE)) + profile = 0x93; /* advanced realtime simple profile/level 3 */ + + if ((pParam->vol_flags & XVID_QUARTERPEL) || + (pParam->vol_flags & XVID_GMC)) + profile = 0xf3; /* advanced simple profile/level 2 */ + + // visual_object_sequence_start_code +// BitstreamPad(bs); +/* no padding here, anymore. You have to make sure that you are + byte aligned, and that always 1-8 padding bits have been written */ + + BitstreamPutBits(bs, VISOBJSEQ_START_CODE, 32); + BitstreamPutBits(bs, profile, 8); + + // visual_object_start_code + BitstreamPad(bs); + BitstreamPutBits(bs, VISOBJ_START_CODE, 32); + BitstreamPutBits(bs, 0, 1); // is_visual_object_identifier + BitstreamPutBits(bs, VISOBJ_TYPE_VIDEO, 4); // visual_object_type // video object_start_code & vo_id BitstreamPad(bs); - BitstreamPutBits(bs, VO_START_CODE, 27); - BitstreamPutBits(bs, 0, 5); + BitstreamPutBits(bs, VIDOBJ_START_CODE|(vo_id&0x5), 32); // video_object_layer_start_code & vol_id - BitstreamPutBits(bs, VOL_START_CODE, 28); - BitstreamPutBits(bs, 0, 4); + BitstreamPad(bs); + BitstreamPutBits(bs, VIDOBJLAY_START_CODE|(vol_id&0x4), 32); BitstreamPutBit(bs, 0); // random_accessible_vol BitstreamPutBits(bs, 0, 8); // video_object_type_indication @@ -978,11 +1213,11 @@ BitstreamPutBits(bs, pParam->height, 13); // height WRITE_MARKER(); - BitstreamPutBit(bs, frame->global_flags & XVID_INTERLACING); // interlace + BitstreamPutBit(bs, pParam->vol_flags & XVID_INTERLACING); // interlace BitstreamPutBit(bs, 1); // obmc_disable (overlapped block motion compensation) if (vol_ver_id != 1) - { if (frame->global_flags & XVID_GMC) + { if ((pParam->vol_flags & XVID_GMC)) { BitstreamPutBits(bs, 2, 2); // sprite_enable=='GMC' BitstreamPutBits(bs, 2, 6); // no_of_sprite_warping_points BitstreamPutBits(bs, 3, 2); // sprite_warping_accuracy 0==1/2, 1=1/4, 2=1/8, 3=1/16 @@ -1000,9 +1235,9 @@ BitstreamPutBit(bs, 0); // not_8_bit // quant_type 0=h.263 1=mpeg4(quantizer tables) - BitstreamPutBit(bs, pParam->m_quant_type); + BitstreamPutBit(bs, pParam->vol_flags & XVID_MPEGQUANT); - if (pParam->m_quant_type) { + if ((pParam->vol_flags & XVID_MPEGQUANT)) { BitstreamPutBit(bs, get_intra_matrix_status()); // load_intra_quant_mat if (get_intra_matrix_status()) { bs_put_matrix(bs, get_intra_matrix()); @@ -1016,7 +1251,7 @@ } if (vol_ver_id != 1) { - if (pParam->m_quarterpel) + if ((pParam->vol_flags & XVID_QUARTERPEL)) BitstreamPutBit(bs, 1); // quarterpel else BitstreamPutBit(bs, 0); // no quarterpel @@ -1029,11 +1264,22 @@ if (vol_ver_id != 1) { BitstreamPutBit(bs, 0); // newpred_enable - BitstreamPutBit(bs, 0); // reduced_resolution_vop_enabled + + BitstreamPutBit(bs, (pParam->vol_flags & XVID_REDUCED_ENABLE)?1:0); + /* reduced_resolution_vop_enabled */ } BitstreamPutBit(bs, 0); // scalability + /* fake divx5 id, to ensure compatibility with divx5 decoder */ +#define DIVX5_ID "DivX000b000p" + if (pParam->max_bframes > 0 && (pParam->global_flags & XVID_PACKED)) { + BitstreamWriteUserData(bs, DIVX5_ID, strlen(DIVX5_ID)); + } + + /* xvid id */ +#define XVID_ID "XviD" XVID_BS_VERSION + BitstreamWriteUserData(bs, XVID_ID, strlen(XVID_ID)); } @@ -1041,14 +1287,18 @@ write vop header */ void -BitstreamWriteVopHeader(Bitstream * const bs, +BitstreamWriteVopHeader( + Bitstream * const bs, const MBParam * pParam, const FRAMEINFO * const frame, int vop_coded) { uint32_t i; - BitstreamPad(bs); +// BitstreamPad(bs); +/* no padding here, anymore. You have to make sure that you are + byte aligned, and that always 1-8 padding bits have been written */ + BitstreamPutBits(bs, VOP_START_CODE, 32); BitstreamPutBits(bs, frame->coding_type, 2); @@ -1080,49 +1330,42 @@ if ( (frame->coding_type == P_VOP) || (frame->coding_type == S_VOP) ) BitstreamPutBits(bs, frame->rounding_type, 1); + if ((frame->vol_flags & XVID_REDUCED_ENABLE)) + BitstreamPutBit(bs, (frame->vop_flags & XVID_REDUCED)?1:0); + BitstreamPutBits(bs, 0, 3); // intra_dc_vlc_threshold - if (frame->global_flags & XVID_INTERLACING) { - BitstreamPutBit(bs, (frame->global_flags & XVID_TOPFIELDFIRST)); - BitstreamPutBit(bs, (frame->global_flags & XVID_ALTERNATESCAN)); + if ((frame->vol_flags & XVID_INTERLACING)) { + BitstreamPutBit(bs, (frame->vop_flags & XVID_TOPFIELDFIRST)); + BitstreamPutBit(bs, (frame->vop_flags & XVID_ALTERNATESCAN)); } if (frame->coding_type == S_VOP) { - if (1) { // no_of_sprite_warping_points>=1 - if (pParam->m_quarterpel) - bs_put_spritetrajectory(bs, frame->GMC_MV.x/2 ); // du[0] - else - bs_put_spritetrajectory(bs, frame->GMC_MV.x ); // du[0] - WRITE_MARKER(); + if (1) { // no_of_sprite_warping_points>=1 (we use 2!) + int k; + for (k=0;k<2;k++) + { + bs_put_spritetrajectory(bs, frame->warp.duv[k].x ); // du[k] + WRITE_MARKER(); - if (pParam->m_quarterpel) - bs_put_spritetrajectory(bs, frame->GMC_MV.y/2 ); // dv[0] - else - bs_put_spritetrajectory(bs, frame->GMC_MV.y ); // dv[0] - WRITE_MARKER(); - + bs_put_spritetrajectory(bs, frame->warp.duv[k].y ); // dv[k] + WRITE_MARKER(); - if (pParam->m_quarterpel) + if ((frame->vol_flags & XVID_QUARTERPEL)) { - DPRINTF(DPRINTF_HEADER,"sprite_warping_point[%i] xy=(%i,%i) *QPEL*", 0, frame->GMC_MV.x/2, frame->GMC_MV.y/2); + DPRINTF(DPRINTF_HEADER,"sprite_warping_point[%i] xy=(%i,%i) *QPEL*", k, frame->warp.duv[k].x/2, frame->warp.duv[k].y/2); } else { - DPRINTF(DPRINTF_HEADER,"sprite_warping_point[%i] xy=(%i,%i)", 0, frame->GMC_MV.x, frame->GMC_MV.y); + DPRINTF(DPRINTF_HEADER,"sprite_warping_point[%i] xy=(%i,%i)", k, frame->warp.duv[k].x, frame->warp.duv[k].y); + } } - - } -/* GMC is halfpel in bitstream, even though GMC_MV was pseudo-qpel (2*halfpel) */ - - if (2) { // no_of_sprite_warping_points>=2 (for DivX5 compat) - bs_put_spritetrajectory(bs, 0 ); - WRITE_MARKER(); - bs_put_spritetrajectory(bs, 0 ); - WRITE_MARKER(); } - // no support for brightness_change! } + + DPRINTF(DPRINTF_HEADER, "quant = %i", frame->quant); + BitstreamPutBits(bs, frame->quant, 5); // quantizer if (frame->coding_type != I_VOP)