gboolean mpeg4_util_parse_VOL (GstBuffer * buf, Mpeg4VisualObject * vo, Mpeg4VideoObjectLayer * vol) { GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); guint8 video_object_layer_start_code; guint8 aspect_ratio_info; guint8 control_parameters; guint8 not_8_bit; /* set default values */ vol->verid = vo->verid; vol->priority = vo->priority; vol->low_delay = FALSE; vol->chroma_format = 1; vol->vbv_parameters = FALSE; vol->quant_precision = 5; vol->bits_per_pixel = 8; vol->quarter_sample = FALSE; /* start code prefix */ SKIP (&reader, 24); READ_UINT8 (&reader, video_object_layer_start_code, 8); if (!(video_object_layer_start_code >= MPEG4_PACKET_VOL_MIN && video_object_layer_start_code <= MPEG4_PACKET_VOL_MAX)) goto wrong_start_code; READ_UINT8 (&reader, vol->random_accesible_vol, 1); READ_UINT8 (&reader, vol->video_object_type_indication, 8); READ_UINT8 (&reader, vol->is_object_layer_identifier, 1); if (vol->is_object_layer_identifier) { READ_UINT8 (&reader, vol->verid, 4); READ_UINT8 (&reader, vol->priority, 3); } READ_UINT8 (&reader, aspect_ratio_info, 4); if (aspect_ratio_info != 0xff) mpeg4_util_par_from_info (aspect_ratio_info, &vol->par_n, &vol->par_d); else { READ_UINT8 (&reader, vol->par_n, 8); CHECK_ALLOWED (vol->par_n, 1, 255); READ_UINT8 (&reader, vol->par_d, 8); CHECK_ALLOWED (vol->par_d, 1, 255); } READ_UINT8 (&reader, control_parameters, 1); if (control_parameters) { READ_UINT8 (&reader, vol->chroma_format, 2); READ_UINT8 (&reader, vol->low_delay, 1); READ_UINT8 (&reader, vol->vbv_parameters, 1); if (vol->vbv_parameters) { guint16 first_half, latter_half; guint8 latter_part; READ_UINT16 (&reader, first_half, 15); SKIP (&reader, 1); READ_UINT16 (&reader, latter_half, 15); SKIP (&reader, 1); vol->bit_rate = (first_half << 15) | latter_half; READ_UINT16 (&reader, first_half, 15); SKIP (&reader, 1); READ_UINT8 (&reader, latter_part, 3); SKIP (&reader, 1); vol->vbv_buffer_size = (first_half << 15) | latter_part; } } READ_UINT8 (&reader, vol->shape, 2); if (vol->shape != 0x0) goto invalid_shape; /* marker_bit */ SKIP (&reader, 1); READ_UINT16 (&reader, vol->vop_time_increment_resolution, 16); CHECK_ALLOWED (vol->vop_time_increment_resolution, 1, G_MAXUINT16); vol->vop_time_increment_bits = g_bit_storage (vol->vop_time_increment_resolution); /* marker_bit */ SKIP (&reader, 1); READ_UINT8 (&reader, vol->fixed_vop_rate, 1); if (vol->fixed_vop_rate) READ_UINT16 (&reader, vol->fixed_vop_time_increment, vol->vop_time_increment_bits); /* marker bit */ SKIP (&reader, 1); READ_UINT16 (&reader, vol->width, 13); /* marker bit */ SKIP (&reader, 1); READ_UINT16 (&reader, vol->height, 13); /* marker bit */ SKIP (&reader, 1); READ_UINT8 (&reader, vol->interlaced, 1); READ_UINT8 (&reader, vol->obmc_disable, 1); if (vol->verid == 0x1) { READ_UINT8 (&reader, vol->sprite_enable, 1); } else READ_UINT8 (&reader, vol->sprite_enable, 2); if (vol->sprite_enable != 0x0) goto invalid_sprite_enable; READ_UINT8 (&reader, not_8_bit, 1); if (not_8_bit) { READ_UINT8 (&reader, vol->quant_precision, 4); CHECK_ALLOWED (vol->quant_precision, 3, 9); READ_UINT8 (&reader, vol->bits_per_pixel, 4); CHECK_ALLOWED (vol->bits_per_pixel, 4, 12); } READ_UINT8 (&reader, vol->quant_type, 1); if (vol->quant_type) { if (!mpeg4_util_parse_quant (&reader, vol->intra_quant_mat, default_intra_quant_mat)) goto error; if (!mpeg4_util_parse_quant (&reader, vol->non_intra_quant_mat, default_non_intra_quant_mat)) goto error; } else { memset (&vol->intra_quant_mat, 0, 64); memset (&vol->non_intra_quant_mat, 0, 64); } if (vol->verid != 0x1) READ_UINT8 (&reader, vol->quarter_sample, 1); READ_UINT8 (&reader, vol->complexity_estimation_disable, 1); if (!vol->complexity_estimation_disable) goto complexity_estimation_error; READ_UINT8 (&reader, vol->resync_marker_disable, 1); return TRUE; error: GST_WARNING ("error parsing \"Video Object Layer\""); return FALSE; wrong_start_code: GST_WARNING ("got buffer with wrong start code"); goto error; invalid_shape: GST_WARNING ("we only support rectangular shape"); goto error; invalid_sprite_enable: GST_WARNING ("we only support sprite_enable == 0"); goto error; complexity_estimation_error: GST_WARNING ("don't support complexity estimation"); goto error; }
/** * gst_mpeg4_parse_video_object_layer: * @vol: The #GstMpeg4VideoObjectLayer structure to fill * @vo: The #GstMpeg4VisualObject currently being parsed or %NULL * @data: The data to parse * @size: The size of the @data to parse * * Parses @data containing the video object layer packet, and fills * the @vol structure. * * Returns: a #GstMpeg4ParseResult */ GstMpeg4ParseResult gst_mpeg4_parse_video_object_layer (GstMpeg4VideoObjectLayer * vol, GstMpeg4VisualObject * vo, const guint8 * data, gsize size) { guint8 video_object_layer_start_code; /* Used for enums types */ guint8 tmp; GstBitReader br = GST_BIT_READER_INIT (data, size); g_return_val_if_fail (vol != NULL, GST_MPEG4_PARSER_ERROR); GST_DEBUG ("Parsing video object layer"); READ_UINT8 (&br, video_object_layer_start_code, 8); if (!(video_object_layer_start_code >= GST_MPEG4_VIDEO_LAYER_FIRST && video_object_layer_start_code <= GST_MPEG4_VIDEO_LAYER_LAST)) goto wrong_start_code; /* set default values */ if (vo) { vol->verid = vo->verid; vol->priority = vo->priority; } else { vol->verid = 1; vol->priority = 0; } vol->low_delay = FALSE; vol->chroma_format = 1; vol->vbv_parameters = FALSE; vol->quant_precision = 5; vol->bits_per_pixel = 8; vol->quarter_sample = FALSE; vol->newpred_enable = FALSE; vol->interlaced = 0; vol->width = 0; vol->height = 0; READ_UINT8 (&br, vol->random_accessible_vol, 1); READ_UINT8 (&br, vol->video_object_type_indication, 8); READ_UINT8 (&br, vol->is_object_layer_identifier, 1); if (vol->is_object_layer_identifier) { READ_UINT8 (&br, vol->verid, 4); READ_UINT8 (&br, vol->priority, 3); } READ_UINT8 (&br, tmp, 4); vol->aspect_ratio_info = tmp; if (vol->aspect_ratio_info != GST_MPEG4_EXTENDED_PAR) { mpeg4_util_par_from_info (vol->aspect_ratio_info, &vol->par_width, &vol->par_height); } else { gint v; READ_UINT8 (&br, vol->par_width, 8); v = vol->par_width; CHECK_ALLOWED (v, 1, 255); READ_UINT8 (&br, vol->par_height, 8); v = vol->par_height; CHECK_ALLOWED (v, 1, 255); } GST_DEBUG ("Pixel aspect ratio %d/%d", vol->par_width, vol->par_width); READ_UINT8 (&br, vol->control_parameters, 1); if (vol->control_parameters) { guint8 chroma_format; READ_UINT8 (&br, chroma_format, 2); vol->chroma_format = chroma_format; READ_UINT8 (&br, vol->low_delay, 1); READ_UINT8 (&br, vol->vbv_parameters, 1); if (vol->vbv_parameters) { CHECK_REMAINING (&br, 79); vol->first_half_bitrate = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); vol->latter_half_bitrate = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); vol->bit_rate = (vol->first_half_bitrate << 15) | vol->latter_half_bitrate; vol->first_half_vbv_buffer_size = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); vol->latter_half_vbv_buffer_size = gst_bit_reader_get_bits_uint8_unchecked (&br, 3); vol->vbv_buffer_size = (vol->first_half_vbv_buffer_size << 15) | vol->latter_half_vbv_buffer_size; vol->first_half_vbv_occupancy = gst_bit_reader_get_bits_uint16_unchecked (&br, 11); MARKER_UNCHECKED (&br); vol->latter_half_vbv_occupancy = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); } } READ_UINT8 (&br, tmp, 2); vol->shape = tmp; if (vol->shape == GST_MPEG4_GRAYSCALE) { /* TODO support grayscale shapes, for now we just pass */ /* Something the standard starts to define... */ GST_WARNING ("Grayscale shaped not supported"); goto failed; } if (vol->shape == GST_MPEG4_GRAYSCALE && vol->verid != 0x01) READ_UINT8 (&br, vol->shape_extension, 4); CHECK_REMAINING (&br, 19); MARKER_UNCHECKED (&br); vol->vop_time_increment_resolution = gst_bit_reader_get_bits_uint16_unchecked (&br, 16); if (vol->vop_time_increment_resolution < 1) { GST_WARNING ("value not in allowed range. value: %d, range %d-%d", vol->vop_time_increment_resolution, 1, G_MAXUINT16); goto failed; } vol->vop_time_increment_bits = g_bit_storage (vol->vop_time_increment_resolution); MARKER_UNCHECKED (&br); vol->fixed_vop_rate = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); if (vol->fixed_vop_rate) READ_UINT16 (&br, vol->fixed_vop_time_increment, vol->vop_time_increment_bits); if (vol->shape != GST_MPEG4_BINARY_ONLY) { if (vol->shape == GST_MPEG4_RECTANGULAR) { CHECK_REMAINING (&br, 29); MARKER_UNCHECKED (&br); vol->width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); } READ_UINT8 (&br, vol->interlaced, 1); READ_UINT8 (&br, vol->obmc_disable, 1); if (vol->verid == 0x1) READ_UINT8 (&br, tmp, 1); else READ_UINT8 (&br, tmp, 2); vol->sprite_enable = tmp; if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC || vol->sprite_enable == GST_MPEG4_SPRITE_GMG) { if (vol->sprite_enable == GST_MPEG4_SPRITE_GMG) CHECK_REMAINING (&br, 9); else { CHECK_REMAINING (&br, 65); vol->sprite_width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->sprite_height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->sprite_left_coordinate = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->sprite_top_coordinate = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); } vol->no_of_sprite_warping_points = gst_bit_reader_get_bits_uint8_unchecked (&br, 6); vol->sprite_warping_accuracy = gst_bit_reader_get_bits_uint8_unchecked (&br, 2); vol->sprite_brightness_change = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); if (vol->sprite_enable != GST_MPEG4_SPRITE_GMG) vol->low_latency_sprite_enable = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); } if (vol->verid != 0x1 && vol->shape != GST_MPEG4_RECTANGULAR) READ_UINT8 (&br, vol->sadct_disable, 1); READ_UINT8 (&br, vol->not_8_bit, 1); if (vol->not_8_bit) { READ_UINT8 (&br, vol->quant_precision, 4); CHECK_ALLOWED (vol->quant_precision, 3, 9); READ_UINT8 (&br, vol->bits_per_pixel, 4); CHECK_ALLOWED (vol->bits_per_pixel, 4, 12); } if (vol->shape == GST_MPEG4_GRAYSCALE) { /* We don't actually support it */ READ_UINT8 (&br, vol->no_gray_quant_update, 1); READ_UINT8 (&br, vol->composition_method, 1); READ_UINT8 (&br, vol->linear_composition, 1); } READ_UINT8 (&br, vol->quant_type, 1); if (vol->quant_type) { if (!parse_quant (&br, vol->intra_quant_mat, default_intra_quant_mat, &vol->load_intra_quant_mat)) goto failed; if (!parse_quant (&br, vol->non_intra_quant_mat, default_non_intra_quant_mat, &vol->load_non_intra_quant_mat)) goto failed; if (vol->shape == GST_MPEG4_GRAYSCALE) { /* Something the standard starts to define... */ GST_WARNING ("Grayscale shaped not supported"); goto failed; } } else { memset (&vol->intra_quant_mat, 0, 64); memset (&vol->non_intra_quant_mat, 0, 64); } if (vol->verid != 0x1) READ_UINT8 (&br, vol->quarter_sample, 1); READ_UINT8 (&br, vol->complexity_estimation_disable, 1); if (!vol->complexity_estimation_disable) { guint8 estimation_method; guint8 estimation_disable; /* skip unneeded properties */ READ_UINT8 (&br, estimation_method, 2); if (estimation_method < 2) { READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 6); READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 4); CHECK_MARKER (&br); READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 4); READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 6); CHECK_MARKER (&br); if (estimation_method == 1) { READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 2); } } } READ_UINT8 (&br, vol->resync_marker_disable, 1); READ_UINT8 (&br, vol->data_partitioned, 1); if (vol->data_partitioned) READ_UINT8 (&br, vol->reversible_vlc, 1); if (vol->verid != 0x01) { READ_UINT8 (&br, vol->newpred_enable, 1); if (vol->newpred_enable) /* requested_upstream_message_type and newpred_segment_type */ SKIP (&br, 3); READ_UINT8 (&br, vol->reduced_resolution_vop_enable, 1); } READ_UINT8 (&br, vol->scalability, 1); if (vol->scalability) { SKIP (&br, 26); /* Few not needed props */ READ_UINT8 (&br, vol->enhancement_type, 1); } /* More unused infos */ } else if (vol->verid != 0x01) { GST_WARNING ("Binary only shapes not fully supported"); goto failed; } /* ... */ return GST_MPEG4_PARSER_OK; failed: GST_WARNING ("failed parsing \"Video Object Layer\""); return GST_MPEG4_PARSER_ERROR; wrong_start_code: GST_WARNING ("got buffer with wrong start code"); goto failed; }