--- bitstream.c 2002/03/08 02:44:34 1.1 +++ bitstream.c 2002/05/09 00:15:51 1.13 @@ -40,7 +40,14 @@ /****************************************************************************** * * * Revision history: * - * * + * * + * 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 * + * 15.04.2002 rewrite log2bin use asm386 By MinChen * + * 26.03.2002 interlacing support * * 03.03.2002 qmatrix writing * * 03.03.2002 merged BITREADER and BITWRITER * * 30.02.2002 intra_dc_threshold support * @@ -52,10 +59,13 @@ #include "bitstream.h" #include "zigzag.h" +#include "../quant/quant_matrix.h" -static int __inline log2bin(int value) +static uint32_t __inline log2bin(uint32_t value) { +/* Changed by Chenm001 */ +#ifndef WIN32 int n = 0; while (value) { @@ -63,6 +73,12 @@ n++; } return n; +#else + __asm{ + bsr eax,value + inc eax + } +#endif } @@ -79,18 +95,39 @@ }; +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; + } +} + /* decode headers returns 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 BitstreamReadHeaders(Bitstream * bs, DECODER * dec, uint32_t * rounding, uint32_t * quant, uint32_t * fcode_forward, uint32_t * fcode_backward, uint32_t * intra_dc_threshold) { uint32_t vol_ver_id; - uint32_t time_inc_resolution; + static uint32_t time_increment_resolution; uint32_t coding_type; uint32_t start_code; - + uint32_t time_incr=0; + int32_t time_increment; + do { BitstreamByteAlign(bs); @@ -152,7 +189,7 @@ // DEBUG("video_object_layer"); BitstreamSkip(bs, 32); // video_object_layer_start_code - BitstreamSkip(bs, 1); // random_accessible_vol + BitstreamSkip(bs, 1); // random_accessible_vol // video_object_type_indication if (BitstreamShowBits(bs, 8) != VIDOBJLAY_TYPE_SIMPLE && @@ -185,11 +222,11 @@ BitstreamSkip(bs, 8); // par_height } - if (BitstreamGetBit(bs)) // vol_control_parameters + if (BitstreamGetBit(bs)) // vol_control_parameters { DEBUG("+ vol_control_parameters"); BitstreamSkip(bs, 2); // chroma_format - BitstreamSkip(bs, 1); // low_delay + dec->low_delay=BitstreamGetBit(bs); // low_delay if (BitstreamGetBit(bs)) // vbv_parameters { DEBUG("+ vbv_parameters"); @@ -218,11 +255,13 @@ READ_MARKER(); - time_inc_resolution = BitstreamGetBits(bs, 16); // vop_time_increment_resolution - time_inc_resolution--; - if (time_inc_resolution > 0) +// *************************** for decode B-frame time *********************** + time_increment_resolution = BitstreamGetBits(bs, 16); // vop_time_increment_resolution + time_increment_resolution--; + //DEBUG1("time_increment_resolution=",time_increment_resolution); + if (time_increment_resolution > 0) { - dec->time_inc_bits = log2bin(time_inc_resolution); + dec->time_inc_bits = log2bin(time_increment_resolution); } else { @@ -263,12 +302,10 @@ } } - - if (BitstreamGetBit(bs)) // interlaced + + if ((dec->interlacing = BitstreamGetBit(bs))) { - DEBUG("TODO: interlaced"); - // TODO - return -1; + DEBUG("vol: interlacing"); } if (!BitstreamGetBit(bs)) // obmc_disable @@ -314,16 +351,21 @@ { if (BitstreamGetBit(bs)) // load_intra_quant_mat { - DEBUG("TODO: load_intra_quant_mat"); - // TODO - return -1; + 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 { - DEBUG("TODO: load_inter_quant_mat"); - // TODO - return -1; + 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) { @@ -331,6 +373,7 @@ DEBUG("TODO: grayscale matrix stuff"); return -1; } + } @@ -382,7 +425,7 @@ } } - if (BitstreamGetBit(bs)) // scalability + if ((dec->scalability=BitstreamGetBit(bs))) // scalability { // TODO DEBUG("TODO: scalability"); @@ -428,7 +471,9 @@ coding_type = BitstreamGetBits(bs, 2); // vop_coding_type //DEBUG1("coding_type", coding_type); - while (BitstreamGetBit(bs) != 0) ; // time_base +// *************************** for decode B-frame time *********************** + while (BitstreamGetBit(bs) != 0) // time_base + time_incr++; READ_MARKER(); @@ -436,8 +481,20 @@ //DEBUG1("vop_time_incr", BitstreamShowBits(bs, dec->time_inc_bits)); if (dec->time_inc_bits) { - BitstreamSkip(bs, dec->time_inc_bits); // vop_time_increment + //BitstreamSkip(bs, dec->time_inc_bits); // vop_time_increment + time_increment = (BitstreamGetBits(bs, dec->time_inc_bits)); // vop_time_increment + } + 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 + time_increment; + dec->time_pp= (uint32_t)(dec->time - dec->last_non_b_time); + dec->last_non_b_time= dec->time; + }else{ + dec->time = (dec->last_time_base + time_incr)*time_increment_resolution + time_increment; + dec->time_bp= (uint32_t)(dec->last_non_b_time - dec->time); } + //DEBUG1("time_increment=",time_increment); READ_MARKER(); @@ -451,7 +508,8 @@ } */ - if (coding_type != I_VOP) + // fix a little bug by MinChen + if ((dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) && (coding_type == P_VOP)) { *rounding = BitstreamGetBit(bs); // rounding_type //DEBUG1("rounding", *rounding); @@ -492,24 +550,37 @@ // intra_dc_vlc_threshold *intra_dc_threshold = intra_dc_threshold_table[ BitstreamGetBits(bs,3) ]; - /* if (interlaced) + if (dec->interlacing) + { + if ((dec->top_field_first = BitstreamGetBit(bs))) { - BitstreamSkip(bs, 1); // top_field_first - BitstreamSkip(bs, 1); // alternative_vertical_scan_flag - */ + DEBUG("vop: top_field_first"); + } + if ((dec->alternate_vertical_scan = BitstreamGetBit(bs))) + { + DEBUG("vop: alternate_vertical_scan"); + } + } } - *quant = BitstreamGetBits(bs, dec->quant_bits); // vop_quant + if((*quant = BitstreamGetBits(bs, dec->quant_bits)) < 1) // vop_quant + *quant = 1; + //DEBUG1("quant", *quant); if (coding_type != I_VOP) { - *fcode = BitstreamGetBits(bs, 3); // fcode_forward + *fcode_forward = BitstreamGetBits(bs, 3); // fcode_forward } if (coding_type == B_VOP) { - // *fcode_backward = BitstreamGetBits(bs, 3); // fcode_backward + *fcode_backward = BitstreamGetBits(bs, 3); // fcode_backward + } + if (!dec->scalability){ + if ((dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR) && (coding_type != I_VOP)){ + BitstreamSkip(bs, 1); // vop_shape_coding_type + } } return coding_type; } @@ -536,7 +607,7 @@ /* write custom quant matrix */ -static void bs_put_matrix(Bitstream * bs, const int16_t * matrix) +static void bs_put_matrix(Bitstream * bs, const int16_t *matrix) { int i, j; const int last = matrix[scan_tables[0][63]]; @@ -559,9 +630,7 @@ write vol header */ void BitstreamWriteVolHeader(Bitstream * const bs, - const int width, - const int height, - const int quant_type) + const MBParam * pParam, const FRAMEINFO * frame) { // video object_start_code & vo_id BitstreamPad(bs); @@ -576,7 +645,23 @@ BitstreamPutBits(bs, 0, 8); // video_object_type_indication BitstreamPutBit(bs, 0); // is_object_layer_identified (0=not given) BitstreamPutBits(bs, 1, 4); // aspect_ratio_info (1=1:1) - BitstreamPutBit(bs, 0); // vol_control_parameters (0=not given) + +#ifdef BFRAMES + 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) + } + + BitstreamPutBits(bs, 0, 2); // video_object_layer_shape (0=rectangular) WRITE_MARKER(); @@ -586,7 +671,11 @@ 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(); @@ -597,40 +686,34 @@ // BitstreamPutBits(bs, 0, 15); WRITE_MARKER(); - BitstreamPutBits(bs, width, 13); // width + BitstreamPutBits(bs, pParam->width, 13); // width WRITE_MARKER(); - BitstreamPutBits(bs, height, 13); // height + BitstreamPutBits(bs, pParam->height, 13); // height WRITE_MARKER(); - BitstreamPutBit(bs, 0); // interlace + 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 // quant_type 0=h.263 1=mpeg4(quantizer tables) - BitstreamPutBit(bs, quant_type); -/* - if (quant_type) + BitstreamPutBit(bs, pParam->m_quant_type); + + if (pParam->m_quant_type) { - BitstreamPutBit(bs, qmatrix->custom_intra); // load_intra_quant_mat - if (qmatrix->custom_intra) + BitstreamPutBit(bs, get_intra_matrix_status()); // load_intra_quant_mat + if (get_intra_matrix_status()) { - bs_put_matrix(bs, qmatrix->intra); + bs_put_matrix(bs, get_intra_matrix()); } - BitstreamPutBit(bs, qmatrix->custom_inter); // load_inter_quant_mat - if (qmatrix->custom_inter) + BitstreamPutBit(bs, get_inter_matrix_status()); // load_inter_quant_mat + if (get_inter_matrix_status()) { - bs_put_matrix(bs, qmatrix->inter); + bs_put_matrix(bs, get_inter_matrix()); } } -*/ - if (quant_type) - { - BitstreamPutBit(bs, 0); // load_intra_quant_mat - BitstreamPutBit(bs, 0); // load_inter_quant_mat - } BitstreamPutBit(bs, 1); // complexity_estimation_disable BitstreamPutBit(bs, 1); // resync_marker_disable @@ -648,35 +731,59 @@ (decoder uses these values to determine precise time since last resync) */ void BitstreamWriteVopHeader(Bitstream * const bs, - VOP_TYPE prediction_type, - const int rounding_type, - const uint32_t quant, - const uint32_t fcode) + const MBParam * pParam, + const FRAMEINFO * frame) { +#ifdef BFRAMES + uint32_t i; +#endif BitstreamPad(bs); BitstreamPutBits(bs, VOP_START_CODE, 32); - BitstreamPutBits(bs, prediction_type, 2); + 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(); BitstreamPutBits(bs, 1, 1); // vop_coded - if (prediction_type != I_VOP) - BitstreamPutBits(bs, rounding_type, 1); + if (frame->coding_type == P_VOP) + BitstreamPutBits(bs, frame->rounding_type, 1); BitstreamPutBits(bs, 0, 3); // intra_dc_vlc_threshold - BitstreamPutBits(bs, quant, 5); // quantizer + if (frame->global_flags & XVID_INTERLACING) + { + BitstreamPutBit(bs, 1); // top field first + BitstreamPutBit(bs, 0); // alternate vertical scan + } + + BitstreamPutBits(bs, frame->quant, 5); // quantizer - if (prediction_type != I_VOP) - BitstreamPutBits(bs, fcode, 3); // fixed_code = [1,4] + if (frame->coding_type != I_VOP) + BitstreamPutBits(bs, frame->fcode, 3); // forward_fixed_code + + if (frame->coding_type == B_VOP) + BitstreamPutBits(bs, frame->bcode, 3); // backward_fixed_code + }