--- bitstream.c 2002/07/12 00:49:59 1.23 +++ bitstream.c 2002/11/02 15:52:30 1.28.2.4 @@ -41,15 +41,17 @@ * * * Revision history: * * * + * 28.10.2002 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 * * 22.05.2002 bs_put_matrix fix * * 20.05.2002 added BitstreamWriteUserData * - * 19.06.2002 Fix a little bug in use custom quant matrix * - * MinChen * - * 08.05.2002 add low_delay support for B_VOP decode * - * MinChen * + * 19.06.2002 Fix a little bug in use custom quant matrix * + * MinChen * + * 08.05.2002 add low_delay support for B_VOP decode * + * MinChen * * 06.05.2002 low_delay * * 06.05.2002 fixed fincr/fbase error * * 01.05.2002 added BVOP support to BitstreamWriteVopHeader * @@ -57,16 +59,17 @@ * 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 * - * + * 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" +#include "mbcoding.h" static uint32_t __inline @@ -330,10 +333,10 @@ DPRINTF(DPRINTF_HEADER,"vop_time_increment_resolution %i", time_increment_resolution); - time_increment_resolution--; +// time_increment_resolution--; if (time_increment_resolution > 0) { - dec->time_inc_bits = log2bin(time_increment_resolution); + dec->time_inc_bits = log2bin(time_increment_resolution-1); } else { // dec->time_inc_bits = 0; // for "old" xvid compatibility, set time_inc_bits = 1 @@ -446,13 +449,12 @@ if (vol_ver_id != 1) { - dec->quarterpel = BitstreamGetBit(bs); // quarter_sampe - if (dec->quarterpel) { - DPRINTF(DPRINTF_ERROR, "quarter_sample not supported"); - } - } else { - dec->quarterpel = 0; + DEBUG("QUARTERPEL BITSTREAM"); + dec->quarterpel = BitstreamGetBit(bs); // quarter_sample } + else + dec->quarterpel = 0; + if (!BitstreamGetBit(bs)) // complexity_estimation_disable { @@ -547,16 +549,21 @@ if (coding_type != B_VOP) { dec->last_time_base = dec->time_base; dec->time_base += time_incr; - dec->time = - dec->time_base * time_increment_resolution + + dec->time = time_increment; + +/* dec->time_base * time_increment_resolution + time_increment; - dec->time_pp = (uint32_t) (dec->time - dec->last_non_b_time); +*/ dec->time_pp = (uint32_t) + (time_increment_resolution + dec->time - dec->last_non_b_time)%time_increment_resolution; dec->last_non_b_time = dec->time; } else { - dec->time = + dec->time = time_increment; +/* (dec->last_time_base + - time_incr) * time_increment_resolution + time_increment; - dec->time_bp = (uint32_t) (dec->last_non_b_time - dec->time); + time_incr) * time_increment_resolution + time_increment; +*/ + dec->time_bp = (uint32_t) + (time_increment_resolution + dec->last_non_b_time - dec->time)%time_increment_resolution; } READ_MARKER(); @@ -574,7 +581,7 @@ // fix a little bug by MinChen if ((dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) && - (coding_type == P_VOP)) { + ( (coding_type == P_VOP) || (coding_type == S_VOP) ) ) { *rounding = BitstreamGetBit(bs); // rounding_type DPRINTF(DPRINTF_HEADER, "rounding %i", *rounding); } @@ -615,6 +622,9 @@ *intra_dc_threshold = intra_dc_threshold_table[BitstreamGetBits(bs, 3)]; + dec->top_field_first = 0; + dec->alternate_vertical_scan = 0; + if (dec->interlacing) { dec->top_field_first = BitstreamGetBit(bs); DPRINTF(DPRINTF_HEADER, "interlace top_field_first %i", dec->top_field_first); @@ -694,8 +704,13 @@ void BitstreamWriteVolHeader(Bitstream * const bs, const MBParam * pParam, - const FRAMEINFO * frame) + const FRAMEINFO * const frame) { + int vol_ver_id=1; + + if ( (pParam->m_quarterpel) || (frame->global_flags & XVID_GMC) ) + vol_ver_id = 2; + // video object_start_code & vo_id BitstreamPad(bs); BitstreamPutBits(bs, VO_START_CODE, 27); @@ -707,22 +722,30 @@ BitstreamPutBit(bs, 0); // random_accessible_vol BitstreamPutBits(bs, 0, 8); // video_object_type_indication - BitstreamPutBit(bs, 0); // is_object_layer_identified (0=not given) + + if (vol_ver_id == 1) + { + BitstreamPutBit(bs, 0); // is_object_layer_identified (0=not given) + } + else + { + BitstreamPutBit(bs, 1); // is_object_layer_identified + BitstreamPutBits(bs, vol_ver_id, 4); // vol_ver_id == 2 + BitstreamPutBits(bs, 4, 3); // vol_ver_priority (1==lowest, 7==highest) ?? + } + BitstreamPutBits(bs, 1, 4); // aspect_ratio_info (1=1:1) -#ifdef BFRAMES + BitstreamPutBit(bs, 1); // vol_control_parameters + BitstreamPutBits(bs, 1, 2); // chroma_format 1="4:2:0" + if (pParam->max_bframes > 0) { - //DPRINTF("low_delay=1"); - BitstreamPutBit(bs, 1); // vol_control_parameters - BitstreamPutBits(bs, 1, 2); // chroma_format 1="4:2:0" BitstreamPutBit(bs, 0); // low_delay - BitstreamPutBit(bs, 0); // vbv_parameters (0=not given) } else -#endif { - BitstreamPutBits(bs, 0, 1); // vol_control_parameters (0=not given) + BitstreamPutBit(bs, 1); // low_delay } - + BitstreamPutBit(bs, 0); // vbv_parameters (0=not given) BitstreamPutBits(bs, 0, 2); // video_object_layer_shape (0=rectangular) @@ -733,20 +756,12 @@ 25fps res=25 inc=1 29.97fps res=30000 inc=1001 */ -#ifdef BFRAMES BitstreamPutBits(bs, pParam->fbase, 16); -#else - BitstreamPutBits(bs, 2, 16); -#endif WRITE_MARKER(); -#ifdef BFRAMES BitstreamPutBit(bs, 1); // fixed_vop_rate = 1 BitstreamPutBits(bs, pParam->fincr, log2bin(pParam->fbase)); // fixed_vop_time_increment -#else - BitstreamPutBit(bs, 0); // fixed_vop_rate = 0 -#endif WRITE_MARKER(); BitstreamPutBits(bs, pParam->width, 13); // width @@ -756,8 +771,24 @@ BitstreamPutBit(bs, frame->global_flags & XVID_INTERLACING); // interlace BitstreamPutBit(bs, 1); // obmc_disable (overlapped block motion compensation) - BitstreamPutBit(bs, 0); // sprite_enable - BitstreamPutBit(bs, 0); // not_in_bit + + if (vol_ver_id != 1) + { if (frame->global_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 + BitstreamPutBit(bs, 0); // sprite_brightness_change (not supported) + +/* currently we use no_of_sprite_warping_points==2, sprite_warping_accuracy==3 + for DivX5 compatability */ + + } else + BitstreamPutBits(bs, 0, 2); // sprite_enable==off + } + else + BitstreamPutBit(bs, 0); // sprite_enable==off + + BitstreamPutBit(bs, 0); // not_8_bit // quant_type 0=h.263 1=mpeg4(quantizer tables) BitstreamPutBit(bs, pParam->m_quant_type); @@ -775,56 +806,57 @@ } + if (vol_ver_id != 1) { + if (pParam->m_quarterpel) + BitstreamPutBit(bs, 1); // quarterpel + else + BitstreamPutBit(bs, 0); // no quarterpel + } + BitstreamPutBit(bs, 1); // complexity_estimation_disable BitstreamPutBit(bs, 1); // resync_marker_disable BitstreamPutBit(bs, 0); // data_partitioned + + if (vol_ver_id != 1) + { + BitstreamPutBit(bs, 0); // newpred_enable + BitstreamPutBit(bs, 0); // reduced_resolution_vop_enabled + } + BitstreamPutBit(bs, 0); // scalability + } /* write vop header - - NOTE: doesnt handle bother with time_base & time_inc - time_base = n seconds since last resync (eg. last iframe) - time_inc = nth of a second since last resync - (decoder uses these values to determine precise time since last resync) */ void BitstreamWriteVopHeader(Bitstream * const bs, const MBParam * pParam, - const FRAMEINFO * frame, + const FRAMEINFO * const frame, int vop_coded) { -#ifdef BFRAMES uint32_t i; -#endif + BitstreamPad(bs); BitstreamPutBits(bs, VOP_START_CODE, 32); BitstreamPutBits(bs, frame->coding_type, 2); - // time_base = 0 write n x PutBit(1), PutBit(0) -#ifdef BFRAMES for (i = 0; i < frame->seconds; i++) { BitstreamPutBit(bs, 1); } BitstreamPutBit(bs, 0); -#else - BitstreamPutBits(bs, 0, 1); -#endif WRITE_MARKER(); // time_increment: value=nth_of_sec, nbits = log2(resolution) -#ifdef BFRAMES + BitstreamPutBits(bs, frame->ticks, log2bin(pParam->fbase)); /*DPRINTF("[%i:%i] %c\n", frame->seconds, frame->ticks, frame->coding_type == I_VOP ? 'I' : frame->coding_type == P_VOP ? 'P' : 'B');*/ -#else - BitstreamPutBits(bs, 1, 1); -#endif WRITE_MARKER(); @@ -835,16 +867,41 @@ BitstreamPutBits(bs, 1, 1); // vop_coded - if (frame->coding_type == P_VOP) + if ( (frame->coding_type == P_VOP) || (frame->coding_type == S_VOP) ) BitstreamPutBits(bs, frame->rounding_type, 1); BitstreamPutBits(bs, 0, 3); // intra_dc_vlc_threshold if (frame->global_flags & XVID_INTERLACING) { - BitstreamPutBit(bs, 1); // top field first - BitstreamPutBit(bs, 0); // alternate vertical scan + BitstreamPutBit(bs, (frame->global_flags & XVID_TOPFIELDFIRST)); + BitstreamPutBit(bs, (frame->global_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 (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(); + } +/* 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! + } + BitstreamPutBits(bs, frame->quant, 5); // quantizer if (frame->coding_type != I_VOP) @@ -855,7 +912,6 @@ } - void BitstreamWriteUserData(Bitstream * const bs, uint8_t * data, @@ -870,4 +926,4 @@ BitstreamPutBits(bs, data[i], 8); } -} \ No newline at end of file +}