--- bitstream.c 2003/06/09 01:17:09 1.39.2.10 +++ bitstream.c 2005/04/10 00:27:25 1.50 @@ -1,70 +1,28 @@ - /****************************************************************************** - * * - * This file is part of XviD, a free MPEG-4 video encoder/decoder * - * * - * XviD is an implementation of a part of one or more MPEG-4 Video tools * - * as specified in ISO/IEC 14496-2 standard. Those intending to use this * - * software module in hardware or software products are advised that its * - * use may infringe existing patents or copyrights, and any such use * - * would be at such party's own risk. The original developer of this * - * software module and his/her company, and subsequent editors and their * - * companies, will have no liability for use of this software or * - * modifications or derivatives thereof. * - * * - * XviD 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. * - * * - * XviD 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 * - * * - ******************************************************************************/ - - /****************************************************************************** - * * - * bitstream.c * - * * - * Copyright (C) 2001 - Peter Ross * - * * - * For more information visit the XviD homepage: http://www.xvid.org * - * * - ******************************************************************************/ - - /****************************************************************************** - * * - * Revision history: * - * * - * 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 * - * 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 * - * 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 * - * 04.12.2001 support for additional headers * - * 16.12.2001 inital version * - * * - ******************************************************************************/ - +/***************************************************************************** + * + * 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.c,v 1.50 2005/04/10 00:27:25 suxen_drol Exp $ + * + ****************************************************************************/ #include #include @@ -78,8 +36,6 @@ static uint32_t __inline log2bin(uint32_t value) { -/* Changed by Chenm001 */ -#if !defined(_MSC_VER) int n = 0; while (value) { @@ -87,12 +43,6 @@ n++; } return n; -#else - __asm { - bsr eax, value - inc eax - } -#endif } @@ -121,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; } @@ -136,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) @@ -157,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(); @@ -175,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); } @@ -199,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 */ @@ -216,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)) { @@ -242,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 */ @@ -268,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 */ { @@ -345,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); /* */ @@ -429,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, @@ -443,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); @@ -556,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 */ @@ -597,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; @@ -712,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"); @@ -741,7 +692,7 @@ } else dec->quarterpel = 0; - + dec->complexity_estimation_disable = BitstreamGetBit(bs); /* complexity estimation disable */ if (!dec->complexity_estimation_disable) @@ -775,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 */ @@ -800,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 */ @@ -829,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 */ @@ -857,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); @@ -897,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 */ @@ -908,7 +848,7 @@ READ_MARKER(); } - + /* fix a little bug by MinChen */ if ((dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY) && @@ -921,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) { @@ -976,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); - + } } @@ -997,7 +933,7 @@ x = - (x ^ ((1 << length) - 1)); } READ_MARKER(); - + length = bs_get_spritetrajectory(bs); if(length){ y = BitstreamGetBits(bs, length); @@ -1051,24 +987,37 @@ 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); } DPRINTF(XVID_DEBUG_STARTCODE, ": %s\n", tmp); + /* read xvid bitstream version */ + if(strncmp(tmp, "XviD", 4) == 0) { + 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'); @@ -1084,7 +1033,6 @@ BitstreamSkip(bs, 8); } } - while ((BitstreamPos(bs) >> 3) < bs->length); #if 0 DPRINTF("*** WARNING: no vop_start_code found"); @@ -1097,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]]; @@ -1119,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_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; @@ -1135,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; } @@ -1146,23 +1096,42 @@ #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); BitstreamPutBits(bs, VISOBJ_START_CODE, 32); BitstreamPutBits(bs, 0, 1); /* is_visual_object_identifier */ + + /* Video type */ BitstreamPutBits(bs, VISOBJ_TYPE_VIDEO, 4); /* visual_object_type */ - + BitstreamPutBit(bs, 0); /* video_signal_type */ + /* video object_start_code & vo_id */ - BitstreamPad(bs); + BitstreamPadAlways(bs); /* next_start_code() */ BitstreamPutBits(bs, VIDOBJ_START_CODE|(vo_id&0x5), 32); /* video_object_layer_start_code & vol_id */ @@ -1172,18 +1141,20 @@ BitstreamPutBit(bs, 0); /* random_accessible_vol */ BitstreamPutBits(bs, vol_type_ind, 8); /* video_object_type_indication */ - if (vol_ver_id == 1) - { + if (vol_ver_id == 1) { BitstreamPutBit(bs, 0); /* is_object_layer_identified (0=not given) */ - } - else - { + } 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, 4, 3); /* vol_ver_priority (1==highest, 7==lowest) */ } - BitstreamPutBits(bs, 1, 4); /* aspect_ratio_info (1=1:1) */ + /* Aspect ratio */ + BitstreamPutBits(bs, pParam->par, 4); /* aspect_ratio_info (1=1:1) */ + if(pParam->par == XVID_PAR_EXT) { + BitstreamPutBits(bs, pParam->par_width, 8); + BitstreamPutBits(bs, pParam->par_height, 8); + } BitstreamPutBit(bs, 1); /* vol_control_parameters */ BitstreamPutBits(bs, 1, 2); /* chroma_format 1="4:2:0" */ @@ -1211,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 */ } @@ -1226,15 +1197,15 @@ 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, 2, 6); /* no_of_sprite_warping_points */ + BitstreamPutBits(bs, 3, 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 + * currently we use no_of_sprite_warping_points==2, sprite_warping_accuracy==3 * for DivX5 compatability */ @@ -1250,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) { @@ -1273,25 +1241,34 @@ BitstreamPutBit(bs, 1); /* resync_marker_disable */ BitstreamPutBit(bs, 0); /* data_partitioned */ - if (vol_ver_id != 1) - { + 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 */ - /* 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)); + BitstreamPadAlways(bs); /* next_start_code(); */ + + /* 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)); + } } @@ -1303,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; @@ -1312,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 */ @@ -1331,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, @@ -1345,6 +1322,14 @@ if (!vop_coded) { BitstreamPutBits(bs, 0, 1); +#if 0 + BitstreamPadAlways(bs); /* next_start_code() */ +#endif + /* NB: It's up to the function caller to write the next_start_code(). + * At the moment encoder.c respects that requisite because a VOP + * always ends with a next_start_code either if it's coded or not + * and encoder.c terminates a frame with a next_start_code in whatever + * case */ return; } @@ -1354,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 */ @@ -1362,15 +1347,15 @@ 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; - for (k=0;k<2;k++) + for (k=0;k<3;k++) { 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(); @@ -1385,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 */ @@ -1401,9 +1386,9 @@ } -void -BitstreamWriteUserData(Bitstream * const bs, - uint8_t * data, +void +BitstreamWriteUserData(Bitstream * const bs, + uint8_t * data, const int length) { int i;