--- bitstream.c 2003/08/26 14:07:11 1.39.2.16 +++ bitstream.c 2005/04/10 00:27:25 1.50 @@ -20,7 +20,7 @@ * 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.c,v 1.39.2.16 2003/08/26 14:07:11 edgomez Exp $ + * $Id: bitstream.c,v 1.50 2005/04/10 00:27:25 suxen_drol Exp $ * ****************************************************************************/ @@ -71,8 +71,10 @@ matrix[scan_tables[0][i++]] = value; } while (value != 0 && i < 64); - i--; /* fix little bug at coeff not full */ + if (value != 0) return; + + i--; while (i < 64) { matrix[scan_tables[0][i++]] = last; } @@ -86,10 +88,10 @@ * returns mbpos */ int -read_video_packet_header(Bitstream *bs, - DECODER * dec, - const int addbits, - int * quant, +read_video_packet_header(Bitstream *bs, + DECODER * dec, + const int addbits, + int * quant, int * fcode_forward, int * fcode_backward, int * intra_dc_threshold) @@ -107,7 +109,7 @@ if (dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR) { hec = BitstreamGetBit(bs); /* header_extension_code */ - if (hec && !(dec->sprite_enable == SPRITE_STATIC /* && current_coding_type = I_VOP */)) + if (hec && !(dec->sprite_enable == SPRITE_STATIC /* && current_coding_type = I_VOP */)) { BitstreamSkip(bs, 13); /* vop_width */ READ_MARKER(); @@ -125,7 +127,7 @@ if (dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) { - *quant = BitstreamGetBits(bs, dec->quant_bits); /* quant_scale */ + *quant = BitstreamGetBits(bs, dec->quant_bits); /* quant_scale */ DPRINTF(XVID_DEBUG_HEADER, "quant %i\n", *quant); } @@ -149,7 +151,7 @@ coding_type = BitstreamGetBits(bs, 2); DPRINTF(XVID_DEBUG_HEADER,"coding_type %i\n", coding_type); - + if (dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR) { BitstreamSkip(bs, 1); /* change_conv_ratio_disable */ @@ -166,7 +168,7 @@ { /* TODO: sprite trajectory */ } - if (dec->reduced_resolution_enable && + if (dec->reduced_resolution_enable && dec->shape == VIDOBJLAY_SHAPE_RECTANGULAR && (coding_type == P_VOP || coding_type == I_VOP)) { @@ -192,7 +194,7 @@ { int vop_id; int vop_id_for_prediction; - + vop_id = BitstreamGetBits(bs, MIN(dec->time_inc_bits + 3, 15)); DPRINTF(XVID_DEBUG_HEADER, "vop_id %i\n", vop_id); if (BitstreamGetBit(bs)) /* vop_id_for_prediction_indication */ @@ -218,7 +220,7 @@ e->method = BitstreamGetBits(bs, 2); /* estimation_method */ DPRINTF(XVID_DEBUG_HEADER,"+ complexity_estimation_header; method=%i\n", e->method); - if (e->method == 0 || e->method == 1) + if (e->method == 0 || e->method == 1) { if (!BitstreamGetBit(bs)) /* shape_complexity_estimation_disable */ { @@ -295,7 +297,7 @@ 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); /* */ @@ -379,7 +381,6 @@ BitstreamReadHeaders(Bitstream * bs, DECODER * dec, uint32_t * rounding, - uint32_t * reduced_resolution, uint32_t * quant, uint32_t * fcode_forward, uint32_t * fcode_backward, @@ -393,7 +394,7 @@ int32_t time_increment = 0; int resize = 0; - do { + while ((BitstreamPos(bs) >> 3) + 4 <= bs->length) { BitstreamByteAlign(bs); start_code = BitstreamShowBits(bs, 32); @@ -506,7 +507,7 @@ READ_MARKER(); bitrate |= BitstreamGetBits(bs,15); /* latter_half_bit_rate */ READ_MARKER(); - + buffer_size = BitstreamGetBits(bs, 15) << 3; /* first_half_vbv_buffer_size */ READ_MARKER(); buffer_size |= BitstreamGetBits(bs, 3); /* latter_half_vbv_buffer_size */ @@ -547,7 +548,7 @@ #endif if (dec->time_inc_resolution > 0) { - dec->time_inc_bits = log2bin(dec->time_inc_resolution-1); + dec->time_inc_bits = MAX(log2bin(dec->time_inc_resolution-1), 1); } else { #if 0 dec->time_inc_bits = 0; @@ -662,20 +663,20 @@ DPRINTF(XVID_DEBUG_HEADER, "load_intra_quant_mat\n"); bs_get_matrix(bs, matrix); - set_intra_matrix(matrix); + set_intra_matrix(dec->mpeg_quant_matrices, matrix); } else - set_intra_matrix(get_default_intra_matrix()); + set_intra_matrix(dec->mpeg_quant_matrices, get_default_intra_matrix()); if (BitstreamGetBit(bs)) /* load_inter_quant_mat */ { uint8_t matrix[64]; - + DPRINTF(XVID_DEBUG_HEADER, "load_inter_quant_mat\n"); bs_get_matrix(bs, matrix); - set_inter_matrix(matrix); + set_inter_matrix(dec->mpeg_quant_matrices, matrix); } else - set_inter_matrix(get_default_inter_matrix()); + set_inter_matrix(dec->mpeg_quant_matrices, get_default_inter_matrix()); if (dec->shape == VIDOBJLAY_SHAPE_GRAYSCALE) { DPRINTF(XVID_DEBUG_ERROR, "greyscale matrix not supported\n"); @@ -691,7 +692,7 @@ } else dec->quarterpel = 0; - + dec->complexity_estimation_disable = BitstreamGetBit(bs); /* complexity estimation disable */ if (!dec->complexity_estimation_disable) @@ -725,7 +726,7 @@ } dec->scalability = BitstreamGetBit(bs); /* scalability */ - if (dec->scalability) + if (dec->scalability) { DPRINTF(XVID_DEBUG_ERROR, "scalability not supported\n"); BitstreamSkip(bs, 1); /* hierarchy_type */ @@ -750,7 +751,7 @@ { if (vol_ver_id != 1) { dec->scalability = BitstreamGetBit(bs); /* scalability */ - if (dec->scalability) + if (dec->scalability) { DPRINTF(XVID_DEBUG_ERROR, "scalability not supported\n"); BitstreamSkip(bs, 4); /* ref_layer_id */ @@ -779,7 +780,7 @@ minutes = BitstreamGetBits(bs, 6); READ_MARKER(); seconds = BitstreamGetBits(bs, 6); - + DPRINTF(XVID_DEBUG_HEADER, "time %ih%im%is\n", hours,minutes,seconds); } BitstreamSkip(bs, 1); /* closed_gov */ @@ -807,30 +808,19 @@ 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", + 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) { dec->last_time_base = dec->time_base; dec->time_base += time_incr; - dec->time = time_increment; - -#if 0 - dec->time_base * dec->time_inc_resolution + - time_increment; -#endif - dec->time_pp = (uint32_t) - (dec->time_inc_resolution + dec->time - dec->last_non_b_time)%dec->time_inc_resolution; + dec->time = dec->time_base*dec->time_inc_resolution + time_increment; + dec->time_pp = (int32_t)(dec->time - dec->last_non_b_time); dec->last_non_b_time = dec->time; } else { - dec->time = time_increment; -#if 0 - (dec->last_time_base + - time_incr) * dec->time_inc_resolution + time_increment; -#endif - dec->time_bp = (uint32_t) - (dec->time_inc_resolution + dec->last_non_b_time - dec->time)%dec->time_inc_resolution; + dec->time = (dec->last_time_base + time_incr)*dec->time_inc_resolution + time_increment; + dec->time_bp = dec->time_pp - (int32_t)(dec->last_non_b_time - dec->time); } DPRINTF(XVID_DEBUG_HEADER,"time_pp=%i\n", dec->time_pp); DPRINTF(XVID_DEBUG_HEADER,"time_bp=%i\n", dec->time_bp); @@ -847,7 +837,7 @@ { int vop_id; int vop_id_for_prediction; - + vop_id = BitstreamGetBits(bs, MIN(dec->time_inc_bits + 3, 15)); DPRINTF(XVID_DEBUG_HEADER, "vop_id %i\n", vop_id); if (BitstreamGetBit(bs)) /* vop_id_for_prediction_indication */ @@ -858,7 +848,7 @@ READ_MARKER(); } - + /* fix a little bug by MinChen */ if ((dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) && @@ -871,12 +861,8 @@ dec->shape == VIDOBJLAY_SHAPE_RECTANGULAR && (coding_type == P_VOP || coding_type == I_VOP)) { - *reduced_resolution = BitstreamGetBit(bs); - DPRINTF(XVID_DEBUG_HEADER, "reduced_resolution %i\n", *reduced_resolution); - } - else - { - *reduced_resolution = 0; + if (BitstreamGetBit(bs)); + DPRINTF(XVID_DEBUG_ERROR, "RRV not supported (anymore)\n"); } if (dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR) { @@ -926,7 +912,7 @@ DPRINTF(XVID_DEBUG_HEADER, "interlace top_field_first %i\n", dec->top_field_first); dec->alternate_vertical_scan = BitstreamGetBit(bs); DPRINTF(XVID_DEBUG_HEADER, "interlace alternate_vertical_scan %i\n", dec->alternate_vertical_scan); - + } } @@ -947,7 +933,7 @@ x = - (x ^ ((1 << length) - 1)); } READ_MARKER(); - + length = bs_get_spritetrajectory(bs); if(length){ y = BitstreamGetBits(bs, length); @@ -1001,14 +987,15 @@ BitstreamSkip(bs, 32); /* user_data_start_code */ + memset(tmp, 0, 256); tmp[0] = BitstreamShowBits(bs, 8); - + for(i = 1; i < 256; i++){ tmp[i] = (BitstreamShowBits(bs, 16) & 0xFF); - - if(tmp[i] == 0) + + if(tmp[i] == 0) break; - + BitstreamSkip(bs, 8); } @@ -1016,15 +1003,21 @@ /* read xvid bitstream version */ if(strncmp(tmp, "XviD", 4) == 0) { - sscanf(tmp, "XviD%d", &dec->bs_version); - DPRINTF(XVID_DEBUG_HEADER, "xvid bitstream version=%i", dec->bs_version); + if (tmp[strlen(tmp)-1] == 'C') { + sscanf(tmp, "XviD%dC", &dec->bs_version); + dec->cartoon_mode = 1; + } + else + sscanf(tmp, "XviD%d", &dec->bs_version); + + DPRINTF(XVID_DEBUG_HEADER, "xvid bitstream version=%i\n", dec->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) { dec->packed_mode = (i == 3 && packed == 'p'); @@ -1040,7 +1033,6 @@ BitstreamSkip(bs, 8); } } - while ((BitstreamPos(bs) >> 3) < bs->length); #if 0 DPRINTF("*** WARNING: no vop_start_code found"); @@ -1053,7 +1045,7 @@ static void bs_put_matrix(Bitstream * bs, - const int16_t * matrix) + const uint16_t * matrix) { int i, j; const int last = matrix[scan_tables[0][63]]; @@ -1075,15 +1067,17 @@ */ void BitstreamWriteVolHeader(Bitstream * const bs, - const MBParam * pParam) + const MBParam * pParam, + const FRAMEINFO * const frame) { static const unsigned int vo_id = 0; static const unsigned int vol_id = 0; int vol_ver_id = 1; int vol_type_ind = VIDOBJLAY_TYPE_SIMPLE; + int vol_profile = pParam->profile; - if ( (pParam->vol_flags & XVID_VOL_QUARTERPEL) || - (pParam->vol_flags & XVID_VOL_GMC) || + if ( (pParam->vol_flags & XVID_VOL_QUARTERPEL) || + (pParam->vol_flags & XVID_VOL_GMC) || (pParam->vol_flags & XVID_VOL_REDUCED_ENABLE)) vol_ver_id = 2; @@ -1091,8 +1085,8 @@ vol_type_ind = VIDOBJLAY_TYPE_ART_SIMPLE; } - if ((pParam->vol_flags & XVID_VOL_QUARTERPEL) || - (pParam->vol_flags & XVID_VOL_GMC)) { + if ((pParam->vol_flags & (XVID_VOL_MPEGQUANT|XVID_VOL_QUARTERPEL|XVID_VOL_GMC|XVID_VOL_INTERLACING)) || + pParam->max_bframes>0) { vol_type_ind = VIDOBJLAY_TYPE_ASP; } @@ -1102,14 +1096,30 @@ #endif /* - * no padding here, anymore. You have to make sure that you are + * no padding here, anymore. You have to make sure that you are * byte aligned, and that always 1-8 padding bits have been written */ - if (pParam->profile) { - BitstreamPutBits(bs, VISOBJSEQ_START_CODE, 32); - BitstreamPutBits(bs, pParam->profile, 8); - } + if (!vol_profile) { + /* Profile was not set by client app, use the more permissive profile + * compatible with the vol_type_id */ + switch(vol_type_ind) { + case VIDOBJLAY_TYPE_ASP: + vol_profile = 0xf5; /* ASP level 5 */ + break; + case VIDOBJLAY_TYPE_ART_SIMPLE: + vol_profile = 0x94; /* ARTS level 4 */ + break; + default: + vol_profile = 0x03; /* Simple level 3 */ + break; + } + } + + /* Write the VOS header */ + BitstreamPutBits(bs, VISOBJSEQ_START_CODE, 32); + BitstreamPutBits(bs, vol_profile, 8); /* profile_and_level_indication */ + /* visual_object_start_code */ BitstreamPad(bs); @@ -1119,7 +1129,7 @@ /* Video type */ BitstreamPutBits(bs, VISOBJ_TYPE_VIDEO, 4); /* visual_object_type */ BitstreamPutBit(bs, 0); /* video_signal_type */ - + /* video object_start_code & vo_id */ BitstreamPadAlways(bs); /* next_start_code() */ BitstreamPutBits(bs, VIDOBJ_START_CODE|(vo_id&0x5), 32); @@ -1172,8 +1182,8 @@ WRITE_MARKER(); if (pParam->fincr>0) { - BitstreamPutBit(bs, 1); /* fixed_vop_rate = 1 */ - BitstreamPutBits(bs, pParam->fincr, log2bin(pParam->fbase)); /* fixed_vop_time_increment */ + BitstreamPutBit(bs, 1); /* fixed_vop_rate = 1 */ + BitstreamPutBits(bs, pParam->fincr, MAX(log2bin(pParam->fbase-1),1)); /* fixed_vop_time_increment */ }else{ BitstreamPutBit(bs, 0); /* fixed_vop_rate = 0 */ } @@ -1187,7 +1197,7 @@ BitstreamPutBit(bs, pParam->vol_flags & XVID_VOL_INTERLACING); /* interlace */ BitstreamPutBit(bs, 1); /* obmc_disable (overlapped block motion compensation) */ - if (vol_ver_id != 1) + if (vol_ver_id != 1) { if ((pParam->vol_flags & XVID_VOL_GMC)) { BitstreamPutBits(bs, 2, 2); /* sprite_enable=='GMC' */ BitstreamPutBits(bs, 3, 6); /* no_of_sprite_warping_points */ @@ -1195,7 +1205,7 @@ BitstreamPutBit(bs, 0); /* sprite_brightness_change (not supported) */ /* - * currently we use no_of_sprite_warping_points==2, sprite_warping_accuracy==3 + * currently we use no_of_sprite_warping_points==2, sprite_warping_accuracy==3 * for DivX5 compatability */ @@ -1211,16 +1221,13 @@ BitstreamPutBit(bs, pParam->vol_flags & XVID_VOL_MPEGQUANT); if ((pParam->vol_flags & XVID_VOL_MPEGQUANT)) { - BitstreamPutBit(bs, get_intra_matrix_status()); /* load_intra_quant_mat */ - if (get_intra_matrix_status()) { - bs_put_matrix(bs, get_intra_matrix()); - } - - BitstreamPutBit(bs, get_inter_matrix_status()); /* load_inter_quant_mat */ - if (get_inter_matrix_status()) { - bs_put_matrix(bs, get_inter_matrix()); - } - + BitstreamPutBit(bs, is_custom_intra_matrix(pParam->mpeg_quant_matrices)); /* load_intra_quant_mat */ + if(is_custom_intra_matrix(pParam->mpeg_quant_matrices)) + bs_put_matrix(bs, get_intra_matrix(pParam->mpeg_quant_matrices)); + + BitstreamPutBit(bs, is_custom_inter_matrix(pParam->mpeg_quant_matrices)); /* load_inter_quant_mat */ + if(is_custom_inter_matrix(pParam->mpeg_quant_matrices)) + bs_put_matrix(bs, get_inter_matrix(pParam->mpeg_quant_matrices)); } if (vol_ver_id != 1) { @@ -1236,23 +1243,32 @@ if (vol_ver_id != 1) { BitstreamPutBit(bs, 0); /* newpred_enable */ - BitstreamPutBit(bs, (pParam->vol_flags & XVID_VOL_REDUCED_ENABLE)?1:0); + BitstreamPutBit(bs, (pParam->vol_flags & XVID_VOL_REDUCED_ENABLE)?1:0); /* reduced_resolution_vop_enabled */ } - + BitstreamPutBit(bs, 0); /* scalability */ BitstreamPadAlways(bs); /* next_start_code(); */ - /* fake divx5 id, to ensure compatibility with divx5 decoder */ -#define DIVX5_ID "DivX000b000p" - if (pParam->max_bframes > 0 && (pParam->global_flags & XVID_GLOBAL_PACKED)) { - BitstreamWriteUserData(bs, DIVX5_ID, strlen(DIVX5_ID)); + /* divx5 userdata string */ +#define DIVX5_ID "DivX503b1393" + if ((pParam->global_flags & XVID_GLOBAL_DIVX5_USERDATA)) { + BitstreamWriteUserData(bs, DIVX5_ID, strlen(DIVX5_ID)); + if (pParam->max_bframes > 0 && (pParam->global_flags & XVID_GLOBAL_PACKED)) + BitstreamPutBits(bs, 'p', 8); } /* xvid id */ -#define XVID_ID "XviD" XVID_BS_VERSION - BitstreamWriteUserData(bs, XVID_ID, strlen(XVID_ID)); + { + const char xvid_user_format[] = "XviD%04d%c"; + char xvid_user_data[100]; + sprintf(xvid_user_data, + xvid_user_format, + XVID_BS_VERSION, + (frame->vop_flags & XVID_VOP_CARTOON)?'C':'\0'); + BitstreamWriteUserData(bs, xvid_user_data, strlen(xvid_user_data)); + } } @@ -1264,7 +1280,8 @@ Bitstream * const bs, const MBParam * pParam, const FRAMEINFO * const frame, - int vop_coded) + int vop_coded, + unsigned int quant) { uint32_t i; @@ -1273,7 +1290,7 @@ #endif /* - * no padding here, anymore. You have to make sure that you are + * no padding here, anymore. You have to make sure that you are * byte aligned, and that always 1-8 padding bits have been written */ @@ -1292,8 +1309,7 @@ WRITE_MARKER(); /* time_increment: value=nth_of_sec, nbits = log2(resolution) */ - - BitstreamPutBits(bs, frame->ticks, log2bin(pParam->fbase)); + BitstreamPutBits(bs, frame->ticks, MAX(log2bin(pParam->fbase-1), 1)); #if 0 DPRINTF("[%i:%i] %c", frame->seconds, frame->ticks, @@ -1323,7 +1339,7 @@ BitstreamPutBits(bs, frame->rounding_type, 1); if ((frame->vol_flags & XVID_VOL_REDUCED_ENABLE)) - BitstreamPutBit(bs, (frame->vop_flags & XVID_VOP_REDUCED)?1:0); + BitstreamPutBit(bs, 0); BitstreamPutBits(bs, 0, 3); /* intra_dc_vlc_threshold */ @@ -1331,7 +1347,7 @@ BitstreamPutBit(bs, (frame->vop_flags & XVID_VOP_TOPFIELDFIRST)); BitstreamPutBit(bs, (frame->vop_flags & XVID_VOP_ALTERNATESCAN)); } - + if (frame->coding_type == S_VOP) { if (1) { /* no_of_sprite_warping_points>=1 (we use 2!) */ int k; @@ -1339,7 +1355,7 @@ { bs_put_spritetrajectory(bs, frame->warp.duv[k].x ); /* du[k] */ WRITE_MARKER(); - + bs_put_spritetrajectory(bs, frame->warp.duv[k].y ); /* dv[k] */ WRITE_MARKER(); @@ -1354,13 +1370,13 @@ } } } - + #if 0 - DPRINTF(XVID_DEBUG_HEADER, "quant = %i\n", frame->quant); + DPRINTF(XVID_DEBUG_HEADER, "quant = %i\n", quant); #endif - BitstreamPutBits(bs, frame->quant, 5); /* quantizer */ + BitstreamPutBits(bs, quant, 5); /* quantizer */ if (frame->coding_type != I_VOP) BitstreamPutBits(bs, frame->fcode, 3); /* forward_fixed_code */ @@ -1370,9 +1386,9 @@ } -void -BitstreamWriteUserData(Bitstream * const bs, - uint8_t * data, +void +BitstreamWriteUserData(Bitstream * const bs, + uint8_t * data, const int length) { int i;