int S_decoder::BitstreamReadHeaders()

in modules/xvid_dec/xvid_wce/bitstream.cpp [439:1101]


int S_decoder::BitstreamReadHeaders(Bitstream * bs, bool &rounding, bool *reduced_resolution, dword *quant, dword *fcode_forward,
                                    dword *fcode_backward, dword *intra_dc_threshold, WARPPOINTS *gmc_warp) {

	dword vol_ver_id;
	dword coding_type;
	dword start_code;
	dword time_incr = 0;
	int time_increment = 0;
	int resize = 0;

	while((bs->Pos() >> 3) < bs->length) {
		bs->ByteAlign();
		start_code = bs->ShowBits(32);

		switch(start_code) {
		case VISOBJSEQ_START_CODE:
		{
			DPRINTF(XVID_DEBUG_STARTCODE, "<visual_object_sequence>\n");

			bs->Skip(32);     //visual_object_sequence_start_code
			int profile = bs->GetBits(8);  //profile_and_level_indication

			DPRINTF(XVID_DEBUG_HEADER, "profile_and_level_indication %i\n", profile);
		}
		break;
		case VISOBJSEQ_STOP_CODE:
		{
			//visual_object_sequence_stop_code
			bs->Skip(32);
			DPRINTF(XVID_DEBUG_STARTCODE, "</visual_object_sequence>\n");

		}
		break;
		case VISOBJ_START_CODE:
		{
			DPRINTF(XVID_DEBUG_STARTCODE, "<visual_object>\n");

			bs->Skip(32);  //visual_object_start_code

			int visobj_ver_id;
			//is_visual_object_identified
			if(bs->GetBit()) {
				visobj_ver_id = bs->GetBits(4);  /* visual_object_ver_id */
				DPRINTF(XVID_DEBUG_HEADER,"visobj_ver_id %i\n", visobj_ver_id);
				bs->Skip(3);   //visual_object_priority
			} else {
				visobj_ver_id = 1;
			}

			if(bs->ShowBits(4) != VISOBJ_TYPE_VIDEO) {
				//visual_object_type
				DPRINTF(XVID_DEBUG_ERROR, "visual_object_type != video\n");
				return -1;
			}
			bs->Skip(4);
			//video_signal_type

			if(bs->GetBit()) {
				DPRINTF(XVID_DEBUG_HEADER,"+ video_signal_type\n");
				bs->Skip(3);   /* video_format */
				bs->Skip(1);   /* video_range */
				if (bs->GetBit()) /* color_description */
				{
					DPRINTF(XVID_DEBUG_HEADER,"+ color_description");
					bs->Skip(8);   /* color_primaries */
					bs->Skip(8);   /* transfer_characteristics */
					bs->Skip(8);   /* matrix_coefficients */
				}
			}
		}
		break;
		case GRPOFVOP_START_CODE:
		{
			DPRINTF(XVID_DEBUG_STARTCODE, "<group_of_vop>\n");

			bs->Skip(32);
			{
				int hours, minutes, seconds;

				hours = bs->GetBits(5);
				minutes = bs->GetBits(6);
				READ_MARKER();
				seconds = bs->GetBits(6);
				//DPRINTF(XVID_DEBUG_HEADER, "time %ih%im%is\n", hours,minutes,seconds);
			}
			bs->Skip(1);   /* closed_gov */
			bs->Skip(1);   /* broken_link */
		}
		break;
		case VOP_START_CODE:
		{

			DPRINTF(XVID_DEBUG_STARTCODE, "<vop>\n");

			bs->Skip(32);  /* vop_start_code */

			coding_type = bs->GetBits(2); /* vop_coding_type */
			DPRINTF(XVID_DEBUG_HEADER, "coding_type %i\n", coding_type);

			/*********************** for decode B-frame time ***********************/
			while (bs->GetBit() != 0)  /* time_base */
				time_incr++;

			READ_MARKER();

			if (time_inc_bits) {
				time_increment = (bs->GetBits(time_inc_bits));  /* vop_time_increment */
			}

			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", 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) {
				last_time_base = time_base;
				time_base += time_incr;
				time = time_increment;

#if 0
				time_base * time_inc_resolution +
				time_increment;
#endif
				time_pp = (dword)
				          (time_inc_resolution + time - last_non_b_time)%time_inc_resolution;
				last_non_b_time = time;
			} else {
				time = time_increment;
#if 0
				(last_time_base +
				 time_incr) * time_inc_resolution + time_increment;
#endif
				time_bp = (dword)
				          (time_inc_resolution + last_non_b_time - time)%time_inc_resolution;
			}
			DPRINTF(XVID_DEBUG_HEADER,"time_pp=%i\n", time_pp);
			DPRINTF(XVID_DEBUG_HEADER,"time_bp=%i\n", time_bp);

			READ_MARKER();

			if (!bs->GetBit())   /* vop_coded */
			{
				DPRINTF(XVID_DEBUG_HEADER, "vop_coded==false\n");
				return N_VOP;
			}

			if (newpred_enable) {
				int vop_id;
				int vop_id_for_prediction;

				vop_id = bs->GetBits(MIN(time_inc_bits + 3, 15));
				DPRINTF(XVID_DEBUG_HEADER, "vop_id %i\n", vop_id);
				if (bs->GetBit()) /* vop_id_for_prediction_indication */
				{
					vop_id_for_prediction = bs->GetBits(MIN(time_inc_bits + 3, 15));
					DPRINTF(XVID_DEBUG_HEADER, "vop_id_for_prediction %i\n", vop_id_for_prediction);
				}
				READ_MARKER();
			}

			//fix a little bug by MinChen <chenm002@163.com>
			if((shape != VIDOBJLAY_SHAPE_BINARY_ONLY) &&
			        ((coding_type == P_VOP) || (coding_type == S_VOP && sprite_enable == SPRITE_GMC))) {
				rounding = !!bs->GetBit();  //rounding_type
				DPRINTF(XVID_DEBUG_HEADER, "rounding %i\n", rounding);
			}

			if(reduced_resolution_enable && shape == VIDOBJLAY_SHAPE_RECTANGULAR && (coding_type == P_VOP || coding_type == I_VOP)) {

				*reduced_resolution = !!bs->GetBit();
				DPRINTF(XVID_DEBUG_HEADER, "reduced_resolution %i\n", *reduced_resolution);
			} else {
				*reduced_resolution = false;
			}

			if (shape != VIDOBJLAY_SHAPE_RECTANGULAR) {
				if(!(sprite_enable == SPRITE_STATIC && coding_type == I_VOP)) {

					dword width, height;
					dword horiz_mc_ref, vert_mc_ref;

					width = bs->GetBits(13);
					READ_MARKER();
					height = bs->GetBits(13);
					READ_MARKER();
					horiz_mc_ref = bs->GetBits(13);
					READ_MARKER();
					vert_mc_ref = bs->GetBits(13);
					READ_MARKER();

					DPRINTF(XVID_DEBUG_HEADER, "width %i\n", width);
					DPRINTF(XVID_DEBUG_HEADER, "height %i\n", height);
					DPRINTF(XVID_DEBUG_HEADER, "horiz_mc_ref %i\n", horiz_mc_ref);
					DPRINTF(XVID_DEBUG_HEADER, "vert_mc_ref %i\n", vert_mc_ref);
				}

				bs->Skip(1);   /* change_conv_ratio_disable */
				if (bs->GetBit()) /* vop_constant_alpha */
				{
					bs->Skip(8);   /* vop_constant_alpha_value */
				}
			}

			if (shape != VIDOBJLAY_SHAPE_BINARY_ONLY) {

				if (!complexity_estimation_disable)
				{
					read_vop_complexity_estimation_header(bs, coding_type);
				}

				/* intra_dc_vlc_threshold */
				*intra_dc_threshold =
				    intra_dc_threshold_table[bs->GetBits(3)];

				top_field_first = 0;
				alternate_vertical_scan = 0;

				if(interlacing) {
					top_field_first = bs->GetBit();
					DPRINTF(XVID_DEBUG_HEADER, "interlace top_field_first %i\n", top_field_first);
					alternate_vertical_scan = bs->GetBit();
					DPRINTF(XVID_DEBUG_HEADER, "interlace alternate_vertical_scan %i\n", alternate_vertical_scan);

				}
			}

			if ((sprite_enable == SPRITE_STATIC || sprite_enable== SPRITE_GMC) && coding_type == S_VOP) {

				int i;

				for (i = 0 ; i < sprite_warping_points; i++)
				{
					int length;
					int x = 0, y = 0;

					/* sprite code borowed from ffmpeg; thx Michael Niedermayer <michaelni@gmx.at> */
					length = bs->bs_get_spritetrajectory();
					if(length) {
						x= bs->GetBits(length);
						if ((x >> (length - 1)) == 0) /* if MSB not set it is negative*/
							x = - (x ^ ((1 << length) - 1));
					}
					READ_MARKER();

					length = bs->bs_get_spritetrajectory();
					if(length) {
						y = bs->GetBits(length);
						if ((y >> (length - 1)) == 0) /* if MSB not set it is negative*/
							y = - (y ^ ((1 << length) - 1));
					}
					READ_MARKER();

					gmc_warp->duv[i].x = x;
					gmc_warp->duv[i].y = y;

					//DPRINTF(XVID_DEBUG_HEADER,"sprite_warping_point[%i] xy=(%i,%i)\n", i, x, y);
				}

				if (sprite_brightness_change)
				{
					/* XXX: brightness_change_factor() */
				}
				if (sprite_enable == SPRITE_STATIC)
				{
					/* XXX: todo */
				}

			}

			if ((*quant = bs->GetBits(quant_bits)) < 1)  /* vop_quant */
				*quant = 1;
			DPRINTF(XVID_DEBUG_HEADER, "quant %i\n", *quant);

			if (coding_type != I_VOP) {
				*fcode_forward = bs->GetBits(3); /* fcode_forward */
				DPRINTF(XVID_DEBUG_HEADER, "fcode_forward %i\n", *fcode_forward);
			}

			if (coding_type == B_VOP) {
				*fcode_backward = bs->GetBits(3);   /* fcode_backward */
				DPRINTF(XVID_DEBUG_HEADER, "fcode_backward %i\n", *fcode_backward);
			}
			if(!scalability) {
				if ((shape != VIDOBJLAY_SHAPE_RECTANGULAR) &&
				        (coding_type != I_VOP)) {
					bs->Skip(1);   /* vop_shape_coding_type */
				}
			}
			return coding_type;

		}
		break;
		case USERDATA_START_CODE:
		{
			char tmp[256];
			int i;

			bs->Skip(32);  /* user_data_start_code */

			tmp[0] = bs->ShowBits(8);

			for(i = 1; i < 256; i++) {
				tmp[i] = (bs->ShowBits(16) & 0xFF);

				if(tmp[i] == 0)
					break;

				bs->Skip(8);
			}

			//DPRINTF(XVID_DEBUG_STARTCODE, "<user_data>: %s\n", tmp);

			/* read xvid bitstream version */
#ifdef WIN32
			{
				char packed;
				int version, build;
				if(MemCmp(tmp, "XviD", 4) == 0) {
					sscanf(tmp, "XviD%d", &bs_version);
					DPRINTF(XVID_DEBUG_HEADER, "xvid bitstream version=%i", 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) {
					packed_mode = (i == 3 && packed == 'p');
					//DPRINTF(XVID_DEBUG_HEADER, "divx version=%i, build=%i packed=%i\n", version, build, packed_mode);
				}
			}
#endif
		}
		break;
		default:
			switch(start_code & ~VIDOBJ_START_CODE_MASK) {
			case VIDOBJ_START_CODE:
			{

				DPRINTF(XVID_DEBUG_STARTCODE, "<video_object>\n");
				DPRINTF(XVID_DEBUG_HEADER, "vo id %i\n", start_code & VIDOBJ_START_CODE_MASK);
				//video_object_start_code
				bs->Skip(32);
			}
			break;
			case VIDOBJLAY_START_CODE:
			{

				DPRINTF(XVID_DEBUG_STARTCODE, "<video_object_layer>\n");
				DPRINTF(XVID_DEBUG_HEADER, "vol id %i\n", start_code & VIDOBJLAY_START_CODE_MASK);

				bs->Skip(32);  //video_object_layer_start_code
				bs->Skip(1);   //random_accessible_vol

				bs->Skip(8);   //video_object_type_indication

				if(bs->GetBit()) {
					//is_object_layer_identifier
					DPRINTF(XVID_DEBUG_HEADER, "+ is_object_layer_identifier\n");
					vol_ver_id = bs->GetBits(4);  /* video_object_layer_verid */
					DPRINTF(XVID_DEBUG_HEADER,"ver_id %i\n", vol_ver_id);
					bs->Skip(3);   /* video_object_layer_priority */
				} else {
					vol_ver_id = 1;
				}

				aspect_ratio = bs->GetBits(4);

				if(aspect_ratio == VIDOBJLAY_AR_EXTPAR) {
					//aspect_ratio_info
					DPRINTF(XVID_DEBUG_HEADER, "+ aspect_ratio_info\n");
					par_width = bs->GetBits(8);   /* par_width */
					par_height = bs->GetBits(8);  /* par_height */
				}

				if(bs->GetBit()) {
					//vol_control_parameters
					DPRINTF(XVID_DEBUG_HEADER, "+ vol_control_parameters\n");
					bs->Skip(2);   /* chroma_format */
					low_delay = (bs->GetBit()!=0);
					DPRINTF(XVID_DEBUG_HEADER, "low_delay %i\n", (int)low_delay);
					if (bs->GetBit()) /* vbv_parameters */
					{
						unsigned int bitrate;
						unsigned int buffer_size;
						unsigned int occupancy;

						DPRINTF(XVID_DEBUG_HEADER,"+ vbv_parameters\n");

						bitrate = bs->GetBits(15) << 15; /* first_half_bit_rate */
						READ_MARKER();
						bitrate |= bs->GetBits(15);      /* latter_half_bit_rate */
						READ_MARKER();

						buffer_size = bs->GetBits(15) << 3; /* first_half_vbv_buffer_size */
						READ_MARKER();
						buffer_size |= bs->GetBits(3);      /* latter_half_vbv_buffer_size */

						occupancy = bs->GetBits(11) << 15;  /* first_half_vbv_occupancy */
						READ_MARKER();
						occupancy |= bs->GetBits(15); /* latter_half_vbv_occupancy */
						READ_MARKER();

						DPRINTF(XVID_DEBUG_HEADER,"bitrate %d (unit=400 bps)\n", bitrate);
						DPRINTF(XVID_DEBUG_HEADER,"buffer_size %d (unit=16384 bits)\n", buffer_size);
						DPRINTF(XVID_DEBUG_HEADER,"occupancy %d (unit=64 bits)\n", occupancy);
					}
				} else {
					low_delay = low_delay_default;
				}

				//video_object_layer_shape
				shape = bs->GetBits(2);

				DPRINTF(XVID_DEBUG_HEADER, "shape %i\n", shape);
				if(shape != VIDOBJLAY_SHAPE_RECTANGULAR) {
					DPRINTF(XVID_DEBUG_ERROR,"non-rectangular shapes are not supported\n");
				}

				if(shape == VIDOBJLAY_SHAPE_GRAYSCALE && vol_ver_id != 1) {
					//video_object_layer_shape_extension
					bs->Skip(4);
				}

				READ_MARKER();

				/********************** for decode B-frame time ***********************/
				time_inc_resolution = bs->GetBits(16); /* vop_time_increment_resolution */
				DPRINTF(XVID_DEBUG_HEADER,"vop_time_increment_resolution %i\n", time_inc_resolution);

#if 0
				time_inc_resolution--;
#endif

				if(time_inc_resolution > 0) {
					time_inc_bits = log2bin(time_inc_resolution-1);
				} else {
#if 0
					time_inc_bits = 0;
#endif
					/* for "old" xvid compatibility, set time_inc_bits = 1 */
					time_inc_bits = 1;
				}

				READ_MARKER();

				if(bs->GetBit()) {
					//fixed_vop_rate
					DPRINTF(XVID_DEBUG_HEADER, "+ fixed_vop_rate\n");
					bs->Skip(time_inc_bits);   //fixed_vop_time_increment
				}

				if(shape != VIDOBJLAY_SHAPE_BINARY_ONLY) {

					if(shape == VIDOBJLAY_SHAPE_RECTANGULAR) {
						dword _width, _height;

						READ_MARKER();
						_width = bs->GetBits(13);  //video_object_layer_width
						READ_MARKER();
						_height = bs->GetBits(13); //video_object_layer_height
						READ_MARKER();

						DPRINTF(XVID_DEBUG_HEADER, "width %i\n", _width);
						DPRINTF(XVID_DEBUG_HEADER, "height %i\n", _height);

						if(width != _width || height != _height) {
							if(fixed_dimensions) {
								DPRINTF(XVID_DEBUG_ERROR, "decoder width/height does not match bitstream\n");
								return -1;
							}
							resize = 1;
							width = _width;
							height = _height;
						}
					}

					interlacing = !!bs->GetBit();
					DPRINTF(XVID_DEBUG_HEADER, "interlacing %i\n", interlacing);

					if(!bs->GetBit()) {
						//obmc_disable
						DPRINTF(XVID_DEBUG_ERROR, "obmc_disabled==false not supported\n");
						/* TODO */
						/* fucking divx4.02 has this enabled */
					}

					sprite_enable = bs->GetBits((vol_ver_id == 1 ? 1 : 2));

					if(sprite_enable == SPRITE_STATIC || sprite_enable == SPRITE_GMC) {
						int low_latency_sprite_enable;

						if(sprite_enable != SPRITE_GMC) {
							int sprite_width;
							int sprite_height;
							int sprite_left_coord;
							int sprite_top_coord;
							sprite_width = bs->GetBits(13);     /* sprite_width */
							READ_MARKER();
							sprite_height = bs->GetBits(13); /* sprite_height */
							READ_MARKER();
							sprite_left_coord = bs->GetBits(13);   /* sprite_left_coordinate */
							READ_MARKER();
							sprite_top_coord = bs->GetBits(13); /* sprite_top_coordinate */
							READ_MARKER();
						}
						sprite_warping_points = bs->GetBits(6);      /* no_of_sprite_warping_points */
						sprite_warping_accuracy = bs->GetBits(2);    /* sprite_warping_accuracy */
						sprite_brightness_change = bs->GetBits(1);      /* brightness_change */
						if (sprite_enable != SPRITE_GMC)
						{
							low_latency_sprite_enable = bs->GetBits(1);     /* low_latency_sprite_enable */
						}
					}

					if(vol_ver_id != 1 && shape != VIDOBJLAY_SHAPE_RECTANGULAR) {
						//sadct_disable
						bs->Skip(1);
					}

					if(bs->GetBit()) {
						//not_8_bit
						DPRINTF(XVID_DEBUG_HEADER, "not_8_bit==true (ignored)\n");
						quant_bits = bs->GetBits(4);  /* quant_precision */
						bs->Skip(4);   /* bits_per_pixel */
					} else {
						quant_bits = 5;
					}

					if(shape == VIDOBJLAY_SHAPE_GRAYSCALE) {
						bs->Skip(1);   /* no_gray_quant_update */
						bs->Skip(1);   /* composition_method */
						bs->Skip(1);   /* linear_composition */
					}

					quant_type = bs->GetBit();
					DPRINTF(XVID_DEBUG_HEADER, "quant_type %i\n", quant_type);

					if(quant_type) {
						if (bs->GetBit()) //load_intra_quant_mat
						{
							byte matrix[64];

							DPRINTF(XVID_DEBUG_HEADER, "load_intra_quant_mat\n");

							bs->get_matrix(matrix);
							set_intra_matrix(mpeg_quant_matrices, matrix);
						} else
							set_intra_matrix(mpeg_quant_matrices, get_default_intra_matrix());

						if (bs->GetBit()) /* load_inter_quant_mat */
						{
							byte matrix[64];

							DPRINTF(XVID_DEBUG_HEADER, "load_inter_quant_mat\n");

							bs->get_matrix(matrix);
							set_inter_matrix(mpeg_quant_matrices, matrix);
						} else
							set_inter_matrix(mpeg_quant_matrices, get_default_inter_matrix());

						if (shape == VIDOBJLAY_SHAPE_GRAYSCALE) {
							DPRINTF(XVID_DEBUG_ERROR, "greyscale matrix not supported\n");
							return -1;
						}

					}

					if(vol_ver_id != 1) {
						quarterpel = bs->GetBit();
						DPRINTF(XVID_DEBUG_HEADER,"quarterpel %i\n", quarterpel);
					} else
						quarterpel = 0;


					complexity_estimation_disable = bs->GetBit();
					if(!complexity_estimation_disable) {
						read_vol_complexity_estimation_header(bs);
					}

					bs->Skip(1);   //resync_marker_disable

					if(bs->GetBit()) {
						//data_partitioned
						DPRINTF(XVID_DEBUG_ERROR, "data_partitioned not supported\n");
						bs->Skip(1);   /* reversible_vlc */
					}

					if(vol_ver_id != 1) {
						newpred_enable = !!bs->GetBit();
						if (newpred_enable)  /* newpred_enable */
						{
							DPRINTF(XVID_DEBUG_HEADER, "+ newpred_enable\n");
							bs->Skip(2);   /* requested_upstream_message_type */
							bs->Skip(1);   /* newpred_segment_type */
						}
						reduced_resolution_enable = !!bs->GetBit(); //reduced_resolution_vop_enable
						DPRINTF(XVID_DEBUG_HEADER, "reduced_resolution_enable %i\n", reduced_resolution_enable);
					} else {
						newpred_enable = false;
						reduced_resolution_enable = false;
					}

					scalability = (bs->GetBit()!=0);
					if(scalability) {
						DPRINTF(XVID_DEBUG_ERROR, "scalability not supported\n");
						bs->Skip(1);   /* hierarchy_type */
						bs->Skip(4);   /* ref_layer_id */
						bs->Skip(1);   /* ref_layer_sampling_direc */
						bs->Skip(5);   /* hor_sampling_factor_n */
						bs->Skip(5);   /* hor_sampling_factor_m */
						bs->Skip(5);   /* vert_sampling_factor_n */
						bs->Skip(5);   /* vert_sampling_factor_m */
						bs->Skip(1);   /* enhancement_type */
						if(shape == VIDOBJLAY_SHAPE_BINARY /* && hierarchy_type==0 */) {
							bs->Skip(1);   /* use_ref_shape */
							bs->Skip(1);   /* use_ref_texture */
							bs->Skip(5);   /* shape_hor_sampling_factor_n */
							bs->Skip(5);   /* shape_hor_sampling_factor_m */
							bs->Skip(5);   /* shape_vert_sampling_factor_n */
							bs->Skip(5);   /* shape_vert_sampling_factor_m */
						}
						return -1;
					}
				} else {
					//shape == BINARY_ONLY
					if(vol_ver_id != 1) {
						scalability = (bs->GetBit()!=0);
						if(scalability) {
							DPRINTF(XVID_DEBUG_ERROR, "scalability not supported\n");
							bs->Skip(4);   /* ref_layer_id */
							bs->Skip(5);   /* hor_sampling_factor_n */
							bs->Skip(5);   /* hor_sampling_factor_m */
							bs->Skip(5);   /* vert_sampling_factor_n */
							bs->Skip(5);   /* vert_sampling_factor_m */
							return -1;
						}
					}
					bs->Skip(1);   /* resync_marker_disable */

				}

				return (resize ? -3 : -2);   //VOL

			}
			break;
			default:
			{
				//start_code == ?
				//if(bs->ShowBits(24) == 0x000001)
				if((start_code&0x00ffffff) == 0x000001) {
					DPRINTF(XVID_DEBUG_STARTCODE, "<unknown: %x>\n", bs->ShowBits(32));
				}
				bs->Skip(8);
			}
			}
		}
	}

#if 0
	DPRINTF("*** WARNING: no vop_start_code found");
#endif
	return -1;                 //ignore it
}