diff --git a/docs/libs/gst-plugins-bad-libs-docs.sgml b/docs/libs/gst-plugins-bad-libs-docs.sgml index 0c9994160e..cf6885b44a 100644 --- a/docs/libs/gst-plugins-bad-libs-docs.sgml +++ b/docs/libs/gst-plugins-bad-libs-docs.sgml @@ -30,6 +30,7 @@ + diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt index 09a395dab4..b949137dfe 100644 --- a/docs/libs/gst-plugins-bad-libs-sections.txt +++ b/docs/libs/gst-plugins-bad-libs-sections.txt @@ -117,6 +117,41 @@ gst_mpeg_video_parse_quant_matrix_extension +
+gstmpeg4parser +mpeg4parser +gst/codecparsers/gstmpeg4parser.h +GstMpeg4StartCode +GstMpeg4VisualObjectType +GstMpeg4AspectRatioInfo +GstMpeg4ParseResult +GstMpeg4VideoObjectCodingType +GstMpeg4ChromaFormat +GstMpeg4VideoObjectLayerShape +GstMpeg4SpriteEnable +GstMpeg4Profile +GstMpeg4Level +GstMpeg4VisualObjectSequence +GstMpeg4VisualObject +GstMpeg4VideoSignalType +GstMpeg4VideoPlaneShortHdr +GstMpeg4VideoObjectLayer +GstMpeg4SpriteTrajectory +GstMpeg4GroupOfVOP +GstMpeg4VideoObjectPlane +GstMpeg4Packet +GstMpeg4VideoPacketHdr +gst_mpeg4_parse +gst_mpeg4_parse_video_object_plane +gst_mpeg4_parse_group_of_vop +gst_mpeg4_parse_video_object_layer +gst_mpeg4_parse_visual_object +gst_mpeg4_parse_visual_object_sequence +gst_mpeg4_parse_video_packet_header + + +
+
gstphotography GST_PHOTOGRAPHY_AUTOFOCUS_DONE diff --git a/gst-libs/gst/codecparsers/Makefile.am b/gst-libs/gst/codecparsers/Makefile.am index f65311dade..2593f85c51 100644 --- a/gst-libs/gst/codecparsers/Makefile.am +++ b/gst-libs/gst/codecparsers/Makefile.am @@ -1,7 +1,8 @@ lib_LTLIBRARIES = libgstcodecparsers-@GST_MAJORMINOR@.la libgstcodecparsers_@GST_MAJORMINOR@_la_SOURCES = \ - gstmpegvideoparser.c gsth264parser.c gstvc1parser.c parserutils.c + gstmpegvideoparser.c gsth264parser.c gstvc1parser.c gstmpeg4parser.c \ + parserutils.c libgstcodecparsers_@GST_MAJORMINOR@includedir = \ $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/codecparsers @@ -9,7 +10,7 @@ libgstcodecparsers_@GST_MAJORMINOR@includedir = \ noinst_HEADERS = parserutils.h libgstcodecparsers_@GST_MAJORMINOR@include_HEADERS = \ - gstmpegvideoparser.h gsth264parser.h gstvc1parser.h + gstmpegvideoparser.h gsth264parser.h gstvc1parser.h gstmpeg4parser.h libgstcodecparsers_@GST_MAJORMINOR@_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) \ diff --git a/gst-libs/gst/codecparsers/gstmpeg4parser.c b/gst-libs/gst/codecparsers/gstmpeg4parser.c new file mode 100644 index 0000000000..6181a5b7e9 --- /dev/null +++ b/gst-libs/gst/codecparsers/gstmpeg4parser.c @@ -0,0 +1,1666 @@ +/* Gstreamer + * Copyright (C) <2011> Intel + * Copyright (C) <2011> Collabora Ltd. + * Copyright (C) <2011> Thibault Saunier + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:gstmpeg4parser + * @short_description: Convenience library for parsing mpeg4 part 2 video + * bitstream. + * + * For more details about the structures, you can refer to the + * specifications: ISO-IEC-14496-2_2004_MPEG4_VISUAL.pdf + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + + +#include "gstmpeg4parser.h" +#include "parserutils.h" + +#ifndef GST_DISABLE_GST_DEBUG + +#define GST_CAT_DEFAULT ensure_debug_category() + +static GstDebugCategory * +ensure_debug_category (void) +{ + static gsize cat_gonce = 0; + + if (g_once_init_enter (&cat_gonce)) { + gsize cat_done; + + cat_done = (gsize) _gst_debug_category_new ("codecparsers_mpeg4", 0, + "GstMpeg4 codec parsing library"); + + g_once_init_leave (&cat_gonce, cat_done); + } + + return (GstDebugCategory *) cat_gonce; +} + +#else + +#define ensure_debug_category() /* NOOP */ + +#endif /* GST_DISABLE_GST_DEBUG */ + +#define CHECK_MARKER(br) G_STMT_START { \ + guint8 marker;\ + if (!gst_bit_reader_get_bits_uint8 (br, &marker, 1)) { \ + GST_WARNING ("failed to read marker bit"); \ + goto failed; \ + } else if (!marker) {\ + GST_WARNING ("Wrong marker bit"); \ + goto failed;\ + }\ +} G_STMT_END + +#define MARKER_UNCHECKED(br) G_STMT_START { \ + if (!gst_bit_reader_get_bits_uint8_unchecked (br, 1)) { \ + GST_WARNING ("Wrong marker bit"); \ + goto failed; \ + } \ +} G_STMT_END + +#define CHECK_REMAINING(br, needed) G_STMT_START { \ + if (gst_bit_reader_get_remaining (br) < needed) \ + goto failed; \ +} G_STMT_END + +const guint8 default_intra_quant_mat[64] = { + 8, 17, 18, 19, 21, 23, 25, 27, + 17, 18, 19, 21, 23, 25, 27, 28, + 20, 21, 22, 23, 24, 26, 28, 30, + 21, 22, 23, 24, 26, 28, 30, 32, + 22, 23, 24, 26, 28, 30, 32, 35, + 23, 24, 26, 28, 30, 32, 35, 38, + 25, 26, 28, 30, 32, 35, 38, 41, + 27, 28, 30, 32, 35, 38, 41, 45 +}; + +const guint8 default_non_intra_quant_mat[64] = { + 16, 17, 18, 19, 20, 21, 22, 23, + 17, 18, 19, 20, 21, 22, 23, 24, + 18, 19, 20, 21, 22, 23, 24, 25, + 19, 20, 21, 22, 23, 24, 26, 27, + 20, 21, 22, 23, 25, 26, 27, 28, + 21, 22, 23, 24, 26, 27, 28, 30, + 22, 23, 24, 26, 27, 28, 30, 31, + 23, 24, 25, 27, 28, 30, 31, 33, +}; + +const guint8 mpeg4_zigzag_8x8[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +static VLCTable mpeg4_dmv_size_vlc_table[] = { + {0x00, 2, 0}, + {0x02, 3, 1}, + {0x03, 3, 2}, + {0x04, 3, 3}, + {0x05, 3, 4}, + {0x06, 3, 5}, + {0x0e, 4, 6}, + {0x1e, 5, 7}, + {0x3e, 6, 8}, + {0x7e, 7, 9}, + {0xfe, 8, 10}, + {0x1fe, 9, 11}, + {0x3fe, 10, 12}, + {0x7fe, 11, 13}, + {0xffe, 12, 14} +}; + +static void +mpeg4_util_par_from_info (guint8 aspect_ratio_info, guint8 * par_width, + guint8 * par_height) +{ + switch (aspect_ratio_info) { + case 0x02: + *par_width = 12; + *par_height = 11; + break; + case 0x03: + *par_width = 10; + *par_height = 11; + break; + case 0x04: + *par_width = 16; + *par_height = 11; + break; + case 0x05: + *par_width = 40; + *par_height = 33; + break; + + case 0x01: + default: + *par_width = 1; + *par_height = 1; + } +} + +static gboolean +parse_quant (GstBitReader * br, guint8 quant_mat[64], + const guint8 default_quant_mat[64], guint8 * load_quant_mat) +{ + READ_UINT8 (br, *load_quant_mat, 1); + if (*load_quant_mat) { + guint i; + guint8 val; + + val = 1; + for (i = 0; i < 64; i++) { + + if (val != 0) + READ_UINT8 (br, val, 8); + + if (val == 0) { + if (i == 0) + goto invalid_quant_mat; + quant_mat[mpeg4_zigzag_8x8[i]] = quant_mat[mpeg4_zigzag_8x8[i - 1]]; + } else + quant_mat[mpeg4_zigzag_8x8[i]] = val; + } + } else + memcpy (quant_mat, default_quant_mat, 64); + + return TRUE; + +failed: + GST_WARNING ("failed parsing quant matrix"); + return FALSE; + +invalid_quant_mat: + GST_WARNING ("the first value should be non zero"); + goto failed; +} + +static gboolean +parse_signal_type (GstBitReader * br, GstMpeg4VideoSignalType * signal_type) +{ + READ_UINT8 (br, signal_type->type, 1); + + if (signal_type->type) { + + READ_UINT8 (br, signal_type->format, 3); + READ_UINT8 (br, signal_type->range, 1); + READ_UINT8 (br, signal_type->color_description, 1); + + if (signal_type->color_description) { + READ_UINT8 (br, signal_type->color_primaries, 8); + READ_UINT8 (br, signal_type->transfer_characteristics, 8); + READ_UINT8 (br, signal_type->matrix_coefficients, 8); + } + } + + return TRUE; + +failed: + GST_WARNING ("failed parsing \"Video Signal Type\""); + + return FALSE; +} + +static gboolean +parse_sprite_trajectory (GstBitReader * br, + GstMpeg4SpriteTrajectory * sprite_traj, guint no_of_sprite_warping_points) +{ + guint i, length; + + for (i = 0; i < no_of_sprite_warping_points; i++) { + + if (!decode_vlc (br, &length, mpeg4_dmv_size_vlc_table, + G_N_ELEMENTS (mpeg4_dmv_size_vlc_table))) + goto failed; + + if (length) + READ_UINT16 (br, sprite_traj->vop_ref_points[i], length); + CHECK_MARKER (br); + + if (!decode_vlc (br, &length, mpeg4_dmv_size_vlc_table, + G_N_ELEMENTS (mpeg4_dmv_size_vlc_table))) + goto failed; + + if (length) + READ_UINT16 (br, sprite_traj->sprite_ref_points[i], length); + CHECK_MARKER (br); + } + + return TRUE; + +failed: + GST_WARNING ("Could not parse the sprite trajectory"); + return FALSE; +} + +static guint +find_psc (GstByteReader * br) +{ + guint psc_pos = -1, psc; + + if (!gst_byte_reader_peek_uint24_be (br, &psc)) + goto failed; + + /* Scan for the picture start code (22 bits - 0x0020) */ + while ((gst_byte_reader_get_remaining (br) >= 3)) { + if (gst_byte_reader_peek_uint24_be (br, &psc) && + ((psc & 0xffffc0) == 0x000080)) { + psc_pos = gst_byte_reader_get_pos (br); + break; + } else + gst_byte_reader_skip (br, 1); + } + +failed: + + return psc_pos; +} + +static inline guint8 +compute_resync_marker_size (const GstMpeg4VideoObjectPlane * vop) +{ + guint8 off; + /* FIXME handle the binary only shape case */ + switch (vop->coding_type) { + case (GST_MPEG4_I_VOP): + off = 16; + + break; + case (GST_MPEG4_S_VOP): + case (GST_MPEG4_P_VOP): + off = 15 + vop->fcode_forward; + + break; + case (GST_MPEG4_B_VOP): + off = MAX (15 + MAX (vop->fcode_forward, vop->fcode_backward), 17); + + break; + default: + return -1; + } + + return off++; /* Take the following 1 into account */ +} + +/********** API **********/ + +/** + * gst_mpeg4_parse: + * @packet: The #GstMpeg4Packet to fill + * @skip_user_data: %TRUE to skip user data packet %FALSE otherwize + * @offset: offset from which to start the parsing + * @data: The data to parse + * @size: The size of the @data to parse + * + * Parses @data and fills @packet with the information of the next packet + * found. + * + * Returns: a #GstMpeg4ParseResult + */ +GstMpeg4ParseResult +gst_mpeg4_parse (GstMpeg4Packet * packet, gboolean skip_user_data, + const guint8 * data, guint offset, gsize size) +{ + gint off1, off2; + GstByteReader br; + + gst_byte_reader_init (&br, data, size); + + g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR); + + ensure_debug_category (); + + if (size - offset <= 4) { + GST_DEBUG ("Can't parse, buffer is to small size %d at offset %d", size, + offset); + return GST_MPEG4_PARSER_ERROR; + } + + off1 = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100, + offset, size - offset); + + if (off1 < 0) { + GST_DEBUG ("No start code prefix in this buffer"); + return GST_MPEG4_PARSER_NO_PACKET; + } + + /* Recursively skip user data if needed */ + if (skip_user_data && data[off1 + 3] == GST_MPEG4_USER_DATA) + return gst_mpeg4_parse (packet, skip_user_data, data, off1 + 3, + size - off1 - 3); + + packet->offset = off1 + 3; + packet->data = data; + packet->type = (GstMpeg4StartCode) (data[off1 + 3]); + + off2 = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100, + off1 + 4, size - off1 - 4); + + if (off2 < 0) { + GST_DEBUG ("Packet start %d, No end found", off1 + 4); + + packet->size = G_MAXUINT; + return GST_MPEG4_PARSER_NO_PACKET_END; + } + + packet->size = (gsize) off2 - off1 - 3; + + GST_DEBUG ("Complete packet of type %x found at: %d, Size: %d", + packet->type, packet->offset, packet->size); + return GST_MPEG4_PARSER_OK; + +} + +/** + * gst_h263_parse: + * @packet: The #GstMpeg4Packet to fill + * @offset: offset from which to start the parsing + * @data: The data to parse + * @size: The size of the @data to parse + * + * Parses @data and fills @packet with the information of the next packet + * found. + * + * Note that the type of the packet is meaningless in this case. + * + * Returns: a #GstMpeg4ParseResult + */ +GstMpeg4ParseResult +gst_h263_parse (GstMpeg4Packet * packet, + const guint8 * data, guint offset, gsize size) +{ + gint off1, off2; + GstByteReader br; + + gst_byte_reader_init (&br, data, size); + + g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR); + + ensure_debug_category (); + + if (size - offset < 3) { + GST_DEBUG ("Can't parse, buffer is to small size %d at offset %d", size, + offset); + return GST_MPEG4_PARSER_ERROR; + } + + off1 = find_psc (&br); + + if (off1 < 0) { + GST_DEBUG ("No start code prefix in this buffer"); + return GST_MPEG4_PARSER_NO_PACKET; + } + + packet->offset = off1; + packet->data = data; + + off2 = find_psc (&br); + + if (off2 < 0) { + GST_DEBUG ("Packet start %d, No end found", off1); + + packet->size = G_MAXUINT; + return GST_MPEG4_PARSER_NO_PACKET_END; + } + + packet->size = (gsize) off2 - off1; + + GST_DEBUG ("Complete packet found at: %d, Size: %d", + packet->offset, packet->size); + + return GST_MPEG4_PARSER_OK; +} + +/** + * gst_mpeg4_parse_visual_object_sequence: + * @vos: The #GstMpeg4VisualObjectSequence structure to fill + * @data: The data to parse, should contain the visual_object_sequence_start_code + * but not the start code prefix + * @size: The size of the @data to parse + * + * Parses @data containing the visual object sequence packet, and fills + * the @vos structure. + * + * Returns: a #GstMpeg4ParseResult + */ +GstMpeg4ParseResult +gst_mpeg4_parse_visual_object_sequence (GstMpeg4VisualObjectSequence * vos, + const guint8 * data, gsize size) +{ + guint8 vos_start_code; + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (vos != NULL, GST_MPEG4_PARSER_ERROR); + + READ_UINT8 (&br, vos_start_code, 8); + if (vos_start_code != GST_MPEG4_VISUAL_OBJ_SEQ_START) + goto wrong_start_code; + + READ_UINT8 (&br, vos->profile_and_level_indication, 8); + + switch (vos->profile_and_level_indication) { + case 0x01: + vos->profile = GST_MPEG4_PROFILE_SIMPLE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x02: + vos->profile = GST_MPEG4_PROFILE_SIMPLE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x03: + vos->profile = GST_MPEG4_PROFILE_SIMPLE; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0x08: + vos->profile = GST_MPEG4_PROFILE_SIMPLE; + vos->level = GST_MPEG4_LEVEL0; + break; + case 0x10: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_SCALABLE; + vos->level = GST_MPEG4_LEVEL0; + break; + case 0x11: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_SCALABLE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x12: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_SCALABLE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x21: + vos->profile = GST_MPEG4_PROFILE_CORE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x22: + vos->profile = GST_MPEG4_PROFILE_CORE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x32: + vos->profile = GST_MPEG4_PROFILE_MAIN; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x33: + vos->profile = GST_MPEG4_PROFILE_MAIN; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0x34: + vos->profile = GST_MPEG4_PROFILE_MAIN; + vos->level = GST_MPEG4_LEVEL4; + break; + case 0x42: + vos->profile = GST_MPEG4_PROFILE_N_BIT; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x51: + vos->profile = GST_MPEG4_PROFILE_SCALABLE_TEXTURE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x61: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_FACE_ANIMATION; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x62: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_FACE_ANIMATION; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x63: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_FBA; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x64: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_FBA; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x71: + vos->profile = GST_MPEG4_PROFILE_BASIC_ANIMATED_TEXTURE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x72: + vos->profile = GST_MPEG4_PROFILE_BASIC_ANIMATED_TEXTURE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x81: + vos->profile = GST_MPEG4_PROFILE_HYBRYD; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x82: + vos->profile = GST_MPEG4_PROFILE_HYBRYD; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x91: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_REALTIME_SIMPLE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0x92: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_REALTIME_SIMPLE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0x93: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_REALTIME_SIMPLE; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0x94: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_REALTIME_SIMPLE; + vos->level = GST_MPEG4_LEVEL4; + break; + case 0xa1: + vos->profile = GST_MPEG4_PROFILE_CORE_SCALABLE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xa2: + vos->profile = GST_MPEG4_PROFILE_CORE_SCALABLE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xa3: + vos->profile = GST_MPEG4_PROFILE_CORE_SCALABLE; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xb1: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xb2: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xb3: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xb4: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY; + vos->level = GST_MPEG4_LEVEL4; + break; + case 0xc1: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_CORE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xc2: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_CORE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xc3: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_CORE; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xd1: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SCALABLE_TEXTURE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xd2: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SCALABLE_TEXTURE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xd3: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SCALABLE_TEXTURE; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xe1: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_STUDIO; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xe2: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_STUDIO; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xe3: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_STUDIO; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xe4: + vos->profile = GST_MPEG4_PROFILE_SIMPLE_STUDIO; + vos->level = GST_MPEG4_LEVEL4; + break; + case 0xe5: + vos->profile = GST_MPEG4_PROFILE_CORE_STUDIO; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xe6: + vos->profile = GST_MPEG4_PROFILE_CORE_STUDIO; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xe7: + vos->profile = GST_MPEG4_PROFILE_CORE_STUDIO; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xe8: + vos->profile = GST_MPEG4_PROFILE_CORE_STUDIO; + vos->level = GST_MPEG4_LEVEL4; + break; + case 0xf0: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SIMPLE; + vos->level = GST_MPEG4_LEVEL0; + break; + case 0xf1: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SIMPLE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xf2: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SIMPLE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xf3: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SIMPLE; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xf4: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SIMPLE; + vos->level = GST_MPEG4_LEVEL4; + break; + case 0xf5: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SIMPLE; + vos->level = GST_MPEG4_LEVEL5; + break; + case 0xf7: + vos->profile = GST_MPEG4_PROFILE_ADVANCED_SIMPLE; + vos->level = GST_MPEG4_LEVEL3b; + break; + case 0xf8: + vos->profile = GST_MPEG4_PROFILE_FINE_GRANULARITY_SCALABLE; + vos->level = GST_MPEG4_LEVEL0; + break; + case 0xf9: + vos->profile = GST_MPEG4_PROFILE_FINE_GRANULARITY_SCALABLE; + vos->level = GST_MPEG4_LEVEL1; + break; + case 0xfa: + vos->profile = GST_MPEG4_PROFILE_FINE_GRANULARITY_SCALABLE; + vos->level = GST_MPEG4_LEVEL2; + break; + case 0xfb: + vos->profile = GST_MPEG4_PROFILE_FINE_GRANULARITY_SCALABLE; + vos->level = GST_MPEG4_LEVEL3; + break; + case 0xfc: + vos->profile = GST_MPEG4_PROFILE_FINE_GRANULARITY_SCALABLE; + vos->level = GST_MPEG4_LEVEL4; + break; + case 0xfd: + vos->profile = GST_MPEG4_PROFILE_FINE_GRANULARITY_SCALABLE; + vos->level = GST_MPEG4_LEVEL5; + break; + default: + vos->profile = GST_MPEG4_PROFILE_RESERVED; + vos->level = GST_MPEG4_LEVEL_RESERVED; + break; + } + + return GST_MPEG4_PARSER_OK; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + return GST_MPEG4_PARSER_ERROR; + +failed: + GST_WARNING ("failed parsing \"Visual Object\""); + return GST_MPEG4_PARSER_ERROR; +} + +/** + * gst_mpeg4_parse_visual_object: + * @vo: The #GstMpeg4VisualObject structure to fill + * @signal_type: The #GstMpeg4VideoSignalType to fill or %NULL + * @data: The data to parse, should contain the vo_start_code + * but not the start code prefix + * @size: The size of the @data to parse + * + * Parses @data containing the visual object packet, and fills + * the @vo structure. + * + * Returns: a #GstMpeg4ParseResult + */ +GstMpeg4ParseResult +gst_mpeg4_parse_visual_object (GstMpeg4VisualObject * vo, + GstMpeg4VideoSignalType * signal_type, const guint8 * data, gsize size) +{ + guint8 vo_start_code, type; + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (vo != NULL, GST_MPEG4_PARSER_ERROR); + + GST_DEBUG ("Parsing visual object"); + + READ_UINT8 (&br, vo_start_code, 8); + if (vo_start_code != GST_MPEG4_VISUAL_OBJ) + goto wrong_start_code; + + /* set default values */ + vo->verid = 0x1; + vo->priority = 1; + + READ_UINT8 (&br, vo->is_identifier, 1); + if (vo->is_identifier) { + READ_UINT8 (&br, vo->verid, 4); + READ_UINT8 (&br, vo->priority, 3); + } + + READ_UINT8 (&br, type, 4); + vo->type = type; + + if ((type == GST_MPEG4_VIDEO_ID || + type == GST_MPEG4_STILL_TEXTURE_ID) && signal_type) { + + if (!parse_signal_type (&br, signal_type)) + goto failed; + + } else if (signal_type) { + signal_type->type = 0; + } + + return GST_MPEG4_PARSER_OK; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + return GST_MPEG4_PARSER_ERROR; + +failed: + GST_WARNING ("failed parsing \"Visual Object\""); + return GST_MPEG4_PARSER_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; + } + + 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 { + READ_UINT8 (&br, vol->par_width, 8); + CHECK_ALLOWED (vol->par_width, 1, 255); + READ_UINT8 (&br, vol->par_height, 8); + CHECK_ALLOWED (vol->par_height, 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); + MARKER_UNCHECKED (&br); + + 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); + CHECK_ALLOWED (vol->vop_time_increment_resolution, 1, G_MAXUINT16); + 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); + vol->sprite_enable = tmp; + } 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->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) + goto complexity_estimation_error; + + + 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; + +complexity_estimation_error: + GST_WARNING ("don't support complexity estimation"); + goto failed; +} + +/** + * gst_mpeg4_parse_group_of_vop: + * @gov: The #GstMpeg4GroupOfVOP structure to fill + * @data: The data to parse + * @size: The size of the @data to parse + * + * Parses @data containing the group of video object plane packet, and fills + * the @gov structure. + * + * Returns: a #GstMpeg4ParseResult + */ +GstMpeg4ParseResult +gst_mpeg4_parse_group_of_vop (GstMpeg4GroupOfVOP * + gov, const guint8 * data, gsize size) +{ + guint8 gov_start_code; + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (gov != NULL, GST_MPEG4_PARSER_ERROR); + + READ_UINT8 (&br, gov_start_code, 8); + if (gov_start_code != GST_MPEG4_GROUP_OF_VOP) + goto wrong_start_code; + + CHECK_REMAINING (&br, 65); + + gov->hours = gst_bit_reader_get_bits_uint8_unchecked (&br, 5); + gov->minutes = gst_bit_reader_get_bits_uint8_unchecked (&br, 6); + /* marker bit */ + MARKER_UNCHECKED (&br); + gov->seconds = gst_bit_reader_get_bits_uint8_unchecked (&br, 6); + + gov->closed = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + gov->broken_link = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + + return GST_MPEG4_PARSER_OK; + +failed: + GST_WARNING ("failed parsing \"Group of Video Object Plane\""); + return GST_MPEG4_PARSER_ERROR; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + goto failed; +} + +/** + * gst_mpeg4_parse_video_object_plane: + * @vop: The #GstMpeg4VideoObjectPlane currently being parsed + * @sprite_trajectory: A #GstMpeg4SpriteTrajectory to fill or %NULL + * @vol: The #GstMpeg4VideoObjectLayer structure to fill + * @data: The data to parse + * @size: The size of the @data to parse + * + * Parses @data containing the video object plane packet, and fills the @vol + * structure. + * + * Returns: a #GstMpeg4ParseResult + */ +GstMpeg4ParseResult +gst_mpeg4_parse_video_object_plane (GstMpeg4VideoObjectPlane * vop, + GstMpeg4SpriteTrajectory * sprite_trajectory, + GstMpeg4VideoObjectLayer * vol, const guint8 * data, gsize size) +{ + guint8 vop_start_code, coding_type, modulo_time_base; + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (vop != NULL, GST_MPEG4_PARSER_ERROR); + + if (vol->shape == GST_MPEG4_BINARY_ONLY) { + /* TODO: implement binary only shapes */ + GST_WARNING ("Binary only shapes not supported"); + goto failed; + } + + READ_UINT8 (&br, vop_start_code, 8); + if (vop_start_code != GST_MPEG4_VIDEO_OBJ_PLANE) + goto wrong_start_code; + + + /* set default values */ + vop->modulo_time_base = 0; + vop->rounding_type = 0; + vop->top_field_first = 1; + vop->alternate_vertical_scan_flag = 0; + vop->fcode_forward = 1; + vop->fcode_backward = 1; + + /* Compute macroblock informations */ + if (vol->interlaced) + vop->mb_height = (2 * (vol->height + 31) / 32); + else + vop->mb_height = (vol->height + 15) / 16; + + vop->mb_width = (vol->width + 15) / 16; + vop->mb_num = vop->mb_height * vop->mb_width; + + READ_UINT8 (&br, coding_type, 2); + vop->coding_type = coding_type; + + READ_UINT8 (&br, modulo_time_base, 1); + while (modulo_time_base) { + vop->modulo_time_base++; + + READ_UINT8 (&br, modulo_time_base, 1); + } + + CHECK_REMAINING (&br, vol->vop_time_increment_bits + 3); + + MARKER_UNCHECKED (&br); + vop->time_increment = + gst_bit_reader_get_bits_uint16_unchecked (&br, + vol->vop_time_increment_bits); + MARKER_UNCHECKED (&br); + + vop->coded = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + if (!vop->coded) + return GST_MPEG4_PARSER_OK; + + if (vol->newpred_enable) { + guint16 nbbits = + vop->time_increment + 3 < 15 ? vop->time_increment + 3 : 15; + + READ_UINT16 (&br, vop->id, nbbits); + READ_UINT8 (&br, vop->id_for_prediction_indication, 1); + if (vop->id_for_prediction_indication) { + /* Would be nice if the standard actually told us... */ + READ_UINT16 (&br, vop->id, nbbits); + CHECK_MARKER (&br); + } + } + + if (vol->shape != GST_MPEG4_BINARY_ONLY && + (vop->coding_type == GST_MPEG4_P_VOP || + (vop->coding_type == GST_MPEG4_S_VOP && + vol->sprite_enable == GST_MPEG4_SPRITE_GMG))) + READ_UINT8 (&br, vop->rounding_type, 1); + + if ((vol->reduced_resolution_vop_enable) && + (vol->shape == GST_MPEG4_RECTANGULAR || + (vop->coding_type = GST_MPEG4_P_VOP || + vop->coding_type == GST_MPEG4_I_VOP))) + READ_UINT8 (&br, vop->reduced_resolution, 1); + + if (vol->shape != GST_MPEG4_RECTANGULAR) { + if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC && + vop->coding_type == GST_MPEG4_I_VOP) { + CHECK_REMAINING (&br, 55); + + vop->width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); + MARKER_UNCHECKED (&br); + + vop->height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); + MARKER_UNCHECKED (&br); + + vop->horizontal_mc_spatial_ref = + gst_bit_reader_get_bits_uint16_unchecked (&br, 13); + MARKER_UNCHECKED (&br); + + vop->vertical_mc_spatial_ref = + gst_bit_reader_get_bits_uint16_unchecked (&br, 13); + MARKER_UNCHECKED (&br); + + /* Recompute the Macroblock informations + * accordingly to the new values */ + if (vol->interlaced) + vop->mb_height = (2 * (vol->height + 31) / 32); + else + vop->mb_height = (vol->height + 15) / 16; + + vop->mb_width = (vol->width + 15) / 16; + vop->mb_num = vop->mb_height * vop->mb_width; + } + + if ((vol->shape != GST_MPEG4_BINARY_ONLY) && + vol->scalability && vol->enhancement_type) + READ_UINT8 (&br, vop->background_composition, 1); + + READ_UINT8 (&br, vop->change_conv_ratio_disable, 1); + + READ_UINT8 (&br, vop->constant_alpha, 1); + if (vop->constant_alpha) + READ_UINT8 (&br, vop->constant_alpha_value, 1); + } + + if (vol->shape != GST_MPEG4_BINARY_ONLY) { + if (!vol->complexity_estimation_disable) { + GST_WARNING ("Complexity estimation not supported"); + goto failed; + } + + READ_UINT8 (&br, vop->intra_dc_vlc_thr, 3); + + if (vol->interlaced) { + READ_UINT8 (&br, vop->top_field_first, 1); + READ_UINT8 (&br, vop->alternate_vertical_scan_flag, 1); + } + } + + if ((vol->sprite_enable == GST_MPEG4_SPRITE_STATIC || + vol->sprite_enable == GST_MPEG4_SPRITE_GMG) && + vop->coding_type == GST_MPEG4_S_VOP) { + + /* only if @sprite_trajectory is not NULL we parse it */ + if (sprite_trajectory && vol->no_of_sprite_warping_points) + parse_sprite_trajectory (&br, sprite_trajectory, + vol->no_of_sprite_warping_points); + + if (vol->sprite_brightness_change) { + GST_WARNING ("sprite_brightness_change not supported"); + goto failed; + } + + if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC) { + GST_WARNING ("sprite enable static not supported"); + goto failed; + } + } + + if (vol->shape != GST_MPEG4_BINARY_ONLY) { + READ_UINT16 (&br, vop->quant, vol->quant_precision); + + if (vol->shape == GST_MPEG4_GRAYSCALE) { + /* TODO implement grayscale support */ + GST_WARNING ("Grayscale shapes no supported"); + + /* TODO implement me */ + goto failed; + } + + if (vop->coding_type != GST_MPEG4_I_VOP) { + READ_UINT8 (&br, vop->fcode_forward, 3); + CHECK_ALLOWED (vop->fcode_forward, 1, 7); + } + + if (vop->coding_type == GST_MPEG4_B_VOP) { + READ_UINT8 (&br, vop->fcode_backward, 3); + CHECK_ALLOWED (vop->fcode_backward, 1, 7); + } + } + + if (!vol->scalability) { + if (vol->shape != GST_MPEG4_RECTANGULAR) + READ_UINT8 (&br, vop->shape_coding_type, 1); + + } else { + if (vol->enhancement_type) { + READ_UINT8 (&br, vop->load_backward_shape, 1); + + if (vop->load_backward_shape) { + GST_WARNING ("Load backward shape not supported"); + goto failed; + } + + READ_UINT8 (&br, vop->ref_select_code, 2); + } + } + + vop->size = gst_bit_reader_get_pos (&br); + /* More things to possibly parse ... */ + + return GST_MPEG4_PARSER_OK; + +failed: + GST_WARNING ("failed parsing \"Video Object Plane\""); + return GST_MPEG4_PARSER_ERROR; + +wrong_start_code: + GST_WARNING ("got buffer with wrong start code"); + goto failed; +} + +/** + * gst_mpeg4_parse_video_plane_with_short_header: + * @shorthdr: The #GstMpeg4VideoPlaneShortHdr to parse + * @data: The data to parse + * @size: The size of the @data to parse + */ +GstMpeg4ParseResult +gst_mpeg4_parse_video_plane_short_header (GstMpeg4VideoPlaneShortHdr * + shorthdr, const guint8 * data, gsize size) +{ + guint8 zero_bits; + guint32 gob_resync; + + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (shorthdr != NULL, GST_MPEG4_PARSER_ERROR); + + if (gst_bit_reader_get_remaining (&br) < 26) + goto failed; + + shorthdr->temporal_reference = + gst_bit_reader_get_bits_uint8_unchecked (&br, 8); + CHECK_MARKER (&br); + shorthdr->split_screen_indicator = + gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + shorthdr->document_camera_indicator = + gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + shorthdr->full_picture_freeze_release = + gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + shorthdr->source_format = gst_bit_reader_get_bits_uint8_unchecked (&br, 3); + + /* Set parameters/Table 6-25 */ + switch (shorthdr->source_format) { + case 0x01: + shorthdr->vop_width = 128; + shorthdr->vop_height = 96; + shorthdr->num_macroblocks_in_gob = 8; + shorthdr->num_gobs_in_vop = 6; + case 0x02: + shorthdr->vop_width = 176; + shorthdr->vop_height = 144; + shorthdr->num_macroblocks_in_gob = 11; + shorthdr->num_gobs_in_vop = 9; + case 0x03: + shorthdr->vop_width = 352; + shorthdr->vop_height = 288; + shorthdr->num_macroblocks_in_gob = 22; + shorthdr->num_gobs_in_vop = 18; + case 0x04: + shorthdr->vop_width = 704; + shorthdr->vop_height = 576; + shorthdr->num_macroblocks_in_gob = 88; + shorthdr->num_gobs_in_vop = 18; + case 0x05: + shorthdr->vop_width = 1408; + shorthdr->vop_height = 1152; + shorthdr->num_macroblocks_in_gob = 352; + shorthdr->num_gobs_in_vop = 18; + default: + shorthdr->vop_width = 0; + shorthdr->vop_height = 0; + shorthdr->num_macroblocks_in_gob = 0; + shorthdr->num_gobs_in_vop = 0; + } + + shorthdr->picture_coding_type = + gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + zero_bits = gst_bit_reader_get_bits_uint8_unchecked (&br, 4); + + if (zero_bits != 0x00) + goto failed; + + shorthdr->vop_quant = gst_bit_reader_get_bits_uint8_unchecked (&br, 5); + zero_bits = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); + + if (zero_bits != 0x00) + goto failed; + + do { + READ_UINT8 (&br, shorthdr->pei, 1); + + if (shorthdr->pei == 1) + READ_UINT8 (&br, shorthdr->psupp, 8); + + } while (shorthdr->pei == 1); + + if (!gst_bit_reader_peek_bits_uint32 (&br, &gob_resync, 17)) + goto failed; + + /* gob_layer() */ + + /* Setting default values */ + shorthdr->gob_header_empty = 1; + shorthdr->gob_number = 0; + shorthdr->gob_frame_id = 0; + shorthdr->quant_scale = 0; + + if (gob_resync == 0x01) { + shorthdr->gob_header_empty = 0; + + gst_bit_reader_skip_unchecked (&br, 17); + READ_UINT8 (&br, shorthdr->gob_number, 5); + READ_UINT8 (&br, shorthdr->gob_frame_id, 2); + READ_UINT8 (&br, shorthdr->quant_scale, 5); + } + + shorthdr->size = gst_bit_reader_get_pos (&br); + + return GST_MPEG4_PARSER_OK; + +failed: + GST_WARNING ("Could not parse the Plane short header"); + + return GST_MPEG4_PARSER_ERROR; +} + +/** + * gst_mpeg4_next_resync: + * @packet: The #GstMpeg4Packet to fill + * @vop: The previously parsed #GstMpeg4VideoObjectPlane + * @offset: offset from which to start the parsing + * @data: The data to parse + * @size: The size of the @data to parse + * + * Parses @data and fills @packet with the information of the next resync packet + * found. + * + * Returns: a #GstMpeg4ParseResult + */ +GstMpeg4ParseResult +gst_mpeg4_next_resync (GstMpeg4Packet * packet, + const GstMpeg4VideoObjectPlane * vop, const guint8 * data, gsize size) +{ + guint markersize = 0, skip, remaining; + GstBitReader br; + + gst_bit_reader_init (&br, data, size); + + g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR); + g_return_val_if_fail (vop != NULL, GST_MPEG4_PARSER_ERROR); + + /* Skip to the end of the vop header */ + gst_bit_reader_skip (&br, vop->size); + + /* 5.2.3 Definition of nextbits_bytealigned() function */ + skip = vop->size % 8; + remaining = gst_bit_reader_get_remaining (&br); + if (!skip) { + if (remaining > 8 && br.data[br.byte + 1] == 0x7f) + skip = 8; + } + + /* Align to next byte */ + if (!gst_bit_reader_skip (&br, skip)) + goto failed; + + markersize = compute_resync_marker_size (vop); + + CHECK_REMAINING (&br, markersize); + + if (gst_bit_reader_peek_bits_uint32_unchecked (&br, markersize) != 0x01) + goto failed; + + GST_DEBUG ("Resync code found at %i", br.byte); + + packet->offset = br.byte; + packet->type = GST_MPEG4_RESYNC; + packet->size = 0; + packet->marker_size = markersize; + + return GST_MPEG4_PARSER_OK; + +failed: + GST_DEBUG ("No resync found in this buffer"); + + return GST_MPEG4_PARSER_NO_PACKET; +} + +/** + * gst_mpeg4_parse_video_packet_header: + * @videopackethdr: The #GstMpeg4VideoPacketHdr structure to fill + * @vol: The last parsed #GstMpeg4VideoObjectLayer, will be updated + * with the informations found during the parsing + * @vop: The last parsed #GstMpeg4VideoObjectPlane, will be updated + * with the informations found during the parsing + * @sprite_trajectory: A #GstMpeg4SpriteTrajectory to fill or %NULL + * with the informations found during the parsing + * @data: The data to parse, should be set after the resync marker. + * @size: The size of the data to parse + * + * Parsers @data containing the video packet header + * and fills the @videopackethdr structure + */ +GstMpeg4ParseResult +gst_mpeg4_parse_video_packet_header (GstMpeg4VideoPacketHdr * videopackethdr, + GstMpeg4VideoObjectLayer * vol, GstMpeg4VideoObjectPlane * vop, + GstMpeg4SpriteTrajectory * sprite_trajectory, const guint8 * data, + gsize size) +{ + guint8 markersize; + GstBitReader br = GST_BIT_READER_INIT (data, size); + + g_return_val_if_fail (videopackethdr != NULL, GST_MPEG4_PARSER_ERROR); + g_return_val_if_fail (vol != NULL, GST_MPEG4_PARSER_ERROR); + + markersize = compute_resync_marker_size (vop); + + CHECK_REMAINING (&br, markersize); + + if (gst_bit_reader_get_bits_uint32_unchecked (&br, markersize) != 0x01) + goto failed; + + if (vol->shape != GST_MPEG4_RECTANGULAR) { + READ_UINT8 (&br, videopackethdr->header_extension_code, 1); + if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC && + vop->coding_type == GST_MPEG4_I_VOP) { + + CHECK_REMAINING (&br, 56); + + U_READ_UINT16 (&br, vop->width, 13); + CHECK_MARKER (&br); + U_READ_UINT16 (&br, vop->height, 13); + CHECK_MARKER (&br); + U_READ_UINT16 (&br, vop->horizontal_mc_spatial_ref, 13); + CHECK_MARKER (&br); + U_READ_UINT16 (&br, vop->vertical_mc_spatial_ref, 13); + CHECK_MARKER (&br); + + /* Update macroblock infirmations */ + vop->mb_height = (vop->height + 15) / 16; + vop->mb_width = (vop->width + 15) / 16; + vop->mb_num = vop->mb_height * vop->mb_width; + } + } + + READ_UINT16 (&br, videopackethdr->macroblock_number, + g_bit_storage (vop->mb_num - 1)); + + if (vol->shape != GST_MPEG4_BINARY_ONLY) + READ_UINT16 (&br, videopackethdr->quant_scale, vol->quant_precision); + + if (vol->shape == GST_MPEG4_RECTANGULAR) + READ_UINT8 (&br, videopackethdr->header_extension_code, 1); + + if (videopackethdr->header_extension_code) { + guint timeincr = 0; + guint8 bit = 0, coding_type; + + do { + READ_UINT8 (&br, bit, 1); + timeincr++; + } while (bit); + + vol->vop_time_increment_bits = timeincr; + + CHECK_MARKER (&br); + READ_UINT16 (&br, vop->time_increment, timeincr); + CHECK_MARKER (&br); + READ_UINT8 (&br, coding_type, 2); + vop->coding_type = coding_type; + + if (vol->shape != GST_MPEG4_RECTANGULAR) { + READ_UINT8 (&br, vop->change_conv_ratio_disable, 1); + if (vop->coding_type != GST_MPEG4_I_VOP) + READ_UINT8 (&br, vop->shape_coding_type, 1); + } + + if (vol->shape != GST_MPEG4_BINARY_ONLY) { + READ_UINT8 (&br, vop->intra_dc_vlc_thr, 3); + + if (sprite_trajectory && vol->sprite_enable == GST_MPEG4_SPRITE_GMG && + vop->coding_type == GST_MPEG4_S_VOP && + vol->no_of_sprite_warping_points > 0) { + + parse_sprite_trajectory (&br, sprite_trajectory, + vol->no_of_sprite_warping_points); + } + + if (vol->reduced_resolution_vop_enable && + vol->shape == GST_MPEG4_RECTANGULAR && + (vop->coding_type == GST_MPEG4_P_VOP || + vop->coding_type == GST_MPEG4_I_VOP)) + READ_UINT8 (&br, vop->reduced_resolution, 1); + + if (vop->coding_type != GST_MPEG4_I_VOP) { + READ_UINT8 (&br, vop->fcode_forward, 3); + CHECK_ALLOWED (vop->fcode_forward, 1, 7); + } + + if (vop->coding_type == GST_MPEG4_B_VOP) { + READ_UINT8 (&br, vop->fcode_backward, 3); + CHECK_ALLOWED (vop->fcode_backward, 1, 7); + } + } + } + + if (vol->newpred_enable) { + guint16 nbbits = + vol->vop_time_increment_bits + 3 < 15 ? vop->time_increment + 3 : 15; + + READ_UINT16 (&br, vop->id, nbbits); + READ_UINT8 (&br, vop->id_for_prediction_indication, 1); + if (vop->id_for_prediction_indication) { + /* Would be nice if the standard actually told us... */ + READ_UINT16 (&br, vop->id, nbbits); + CHECK_MARKER (&br); + } + } + + videopackethdr->size = gst_bit_reader_get_pos (&br); + +failed: + GST_DEBUG ("Failed to parse video packet header"); + + return GST_MPEG4_PARSER_NO_PACKET; +} diff --git a/gst-libs/gst/codecparsers/gstmpeg4parser.h b/gst-libs/gst/codecparsers/gstmpeg4parser.h new file mode 100644 index 0000000000..c1fcb1c383 --- /dev/null +++ b/gst-libs/gst/codecparsers/gstmpeg4parser.h @@ -0,0 +1,583 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_MPEG4UTIL_H__ +#define __GST_MPEG4UTIL_H__ + +#include +#include + +typedef struct _GstMpeg4VisualObjectSequence GstMpeg4VisualObjectSequence; +typedef struct _GstMpeg4VisualObject GstMpeg4VisualObject; +typedef struct _GstMpeg4VideoObjectLayer GstMpeg4VideoObjectLayer; +typedef struct _GstMpeg4GroupOfVOP GstMpeg4GroupOfVOP; +typedef struct _GstMpeg4VideoObjectPlane GstMpeg4VideoObjectPlane; +typedef struct _GstMpeg4VideoSignalType GstMpeg4VideoSignalType; +typedef struct _GstMpeg4VideoPlaneShortHdr GstMpeg4VideoPlaneShortHdr; +typedef struct _GstMpeg4VideoPacketHdr GstMpeg4VideoPacketHdr; + +typedef struct _GstMpeg4SpriteTrajectory GstMpeg4SpriteTrajectory; + +typedef struct _GstMpeg4Packet GstMpeg4Packet; + +/** + * GstMpeg4StartCode: + * + * Defines the different startcodes present in the bitstream as + * defined in: Table 6-3 — Start code values + */ +typedef enum +{ + GST_MPEG4_VIDEO_OBJ_FIRST = 0x00, + GST_MPEG4_VIDEO_OBJ_LAST = 0x1f, + GST_MPEG4_VIDEO_LAYER_FIRST = 0x20, + GST_MPEG4_VIDEO_LAYER_LAST = 0x2f, + GST_MPEG4_VISUAL_OBJ_SEQ_START = 0xb0, + GST_MPEG4_VISUAL_OBJ_SEQ_END = 0xb1, + GST_MPEG4_USER_DATA = 0xb2, + GST_MPEG4_GROUP_OF_VOP = 0xb3, + GST_MPEG4_VIDEO_SESSION_ERR = 0xb4, + GST_MPEG4_VISUAL_OBJ = 0xb5, + GST_MPEG4_VIDEO_OBJ_PLANE = 0xb6, + GST_MPEG4_FBA = 0xba, + GST_MPEG4_FBA_PLAN = 0xbb, + GST_MPEG4_MESH = 0xbc, + GST_MPEG4_MESH_PLAN = 0xbd, + GST_MPEG4_STILL_TEXTURE_OBJ = 0xbe, + GST_MPEG4_TEXTURE_SPATIAL = 0xbf, + GST_MPEG4_TEXTURE_SNR_LAYER = 0xc0, + GST_MPEG4_TEXTURE_TILE = 0xc1, + GST_MPEG4_SHAPE_LAYER = 0xc2, + GST_MPEG4_STUFFING = 0xc3, + GST_MPEG4_SYSTEM_FIRST = 0xc6, + GST_MPEG4_SYSTEM_LAST = 0xff, + GST_MPEG4_RESYNC = 0xfff +} GstMpeg4StartCode; + +/** + * GstMpeg4VisualObjectType: + * + * Defines the different visual object types as + * defined in: Table 6-5 -- Meaning of visual object type + */ +typedef enum { + GST_MPEG4_VIDEO_ID = 0x01, + GST_MPEG4_STILL_TEXTURE_ID = 0x02, + GST_MPEG4_STILL_MESH_ID = 0x03, + GST_MPEG4_STILL_FBA_ID = 0x04, + GST_MPEG4_STILL_3D_MESH_ID = 0x05, + /*... reserved */ + +} GstMpeg4VisualObjectType; + +/** + * GstMpeg4AspectRatioInfo: + * @GST_MPEG4_SQUARE: 1:1 square + * @GST_MPEG4_625_TYPE_4_3: 12:11 (625-type for 4:3 picture) + * @GST_MPEG4_525_TYPE_4_3: 10:11 (525-type for 4:3 picture) + * @GST_MPEG4_625_TYPE_16_9: 16:11 (625-type stretched for 16:9 picture) + * @GST_MPEG4_525_TYPE_16_9: 40:33 (525-type stretched for 16:9 picture) + * @GST_MPEG4_EXTENDED_PAR: Extended par + * + * Defines the different pixel aspect ratios as + * defined in: Table 6-12 -- Meaning of pixel aspect ratio + */ +typedef enum { + GST_MPEG4_SQUARE = 0x01, + GST_MPEG4_625_TYPE_4_3 = 0x02, + GST_MPEG4_525_TYPE_4_3 = 0x03, + GST_MPEG4_625_TYPE_16_9 = 0x04, + GST_MPEG4_525_TYPE_16_9 = 0x05, + GST_MPEG4_EXTENDED_PAR = 0x0f, +} GstMpeg4AspectRatioInfo; + +/** + * GstMpeg4ParseResult: + * @GST_MPEG4_PARSER_OK: The parsing went well + * @GST_MPEG4_PARSER_BROKEN_DATA: The bitstream was broken + * @GST_MPEG4_PARSER_NO_PACKET: There was no packet in the buffer + * @GST_MPEG4_PARSER_NO_PACKET_END: There was no packet end in the buffer + * @GST_MPEG4_PARSER_NO_PACKET_ERROR: An error accured durint the parsing + * + * Result type of any parsing function. + */ +typedef enum { + GST_MPEG4_PARSER_OK, + GST_MPEG4_PARSER_BROKEN_DATA, + GST_MPEG4_PARSER_NO_PACKET, + GST_MPEG4_PARSER_NO_PACKET_END, + GST_MPEG4_PARSER_ERROR, +} GstMpeg4ParseResult; + +/** + * GstMpeg4VideoObjectCodingType: + * @GST_MPEG4_I_VOP: intra-coded (I) + * @GST_MPEG4_P_VOP: predictive-coded (P) + * @GST_MPEG4_B_VOP: bidirectionally-predictive-coded (B) + * @GST_MPEG4_S_VOP: sprite (S) + * + * The vop coding types as defined in: + * Table 6-20 -- Meaning of vop_coding_type + */ +typedef enum { + GST_MPEG4_I_VOP = 0x0, + GST_MPEG4_P_VOP = 0x1, + GST_MPEG4_B_VOP = 0x2, + GST_MPEG4_S_VOP = 0x3 +} GstMpeg4VideoObjectCodingType; + +/** + * GstMpeg4ChromaFormat + * + * The chroma format in use as + * defined in: Table 6-13 -- Meaning of chroma_format + */ +typedef enum { + /* Other value are reserved */ + GST_MPEG4_CHROMA_4_2_0 = 0x01 +} GstMpeg4ChromaFormat; + +/** + * GstMpeg4VideoObjectLayerShape: + * + * The different video object layer shapes as defined in: + * Table 6-16 — Video Object Layer shape type + */ +typedef enum { + GST_MPEG4_RECTANGULAR, + GST_MPEG4_BINARY, + GST_MPEG4_BINARY_ONLY, + GST_MPEG4_GRAYSCALE +} GstMpeg4VideoObjectLayerShape; + +/** + * GstMpeg4SpriteEnable: + * + * Indicates the usage of static sprite coding + * or global motion compensation (GMC) as defined in: + * Table V2 - 2 -- Meaning of sprite_enable codewords + */ +typedef enum { + GST_MPEG4_SPRITE_UNUSED, + GST_MPEG4_SPRITE_STATIC, + GST_MPEG4_SPRITE_GMG +} GstMpeg4SpriteEnable; + +/** + * GstMpeg4Profile: + * + * Different defined profiles as defined in: + * 9- Profiles and levels + * + * It is computed using: + * Table G.1 — FLC table for profile_and_level_indication + */ +typedef enum { + GST_MPEG4_PROFILE_CORE, + GST_MPEG4_PROFILE_MAIN, + GST_MPEG4_PROFILE_N_BIT, + GST_MPEG4_PROFILE_SIMPLE, + GST_MPEG4_PROFILE_HYBRYD, + GST_MPEG4_PROFILE_RESERVED, + GST_MPEG4_PROFILE_SIMPLE_FBA, + GST_MPEG4_PROFILE_CORE_STUDIO, + GST_MPEG4_PROFILE_SIMPLE_STUDIO, + GST_MPEG4_PROFILE_CORE_SCALABLE, + GST_MPEG4_PROFILE_ADVANCED_CORE, + GST_MPEG4_PROFILE_ADVANCED_SIMPLE, + GST_MPEG4_PROFILE_SIMPLE_SCALABLE, + GST_MPEG4_PROFILE_SCALABLE_TEXTURE, + GST_MPEG4_PROFILE_SIMPLE_FACE_ANIMATION, + GST_MPEG4_PROFILE_BASIC_ANIMATED_TEXTURE, + GST_MPEG4_PROFILE_ADVANCED_REALTIME_SIMPLE, + GST_MPEG4_PROFILE_ADVANCED_SCALABLE_TEXTURE, + GST_MPEG4_PROFILE_FINE_GRANULARITY_SCALABLE, + GST_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY +} GstMpeg4Profile; + +/** + * GstMpeg4Level: + * + * Different levels as defined in: + * 9- Profiles and levels + * + * It is computed using: + * Table G.1 — FLC table for profile_and_level_indication + */ +typedef enum { + GST_MPEG4_LEVEL0, + GST_MPEG4_LEVEL1, + GST_MPEG4_LEVEL2, + GST_MPEG4_LEVEL3, + GST_MPEG4_LEVEL3b, + GST_MPEG4_LEVEL4, + GST_MPEG4_LEVEL5, + GST_MPEG4_LEVEL_RESERVED +} GstMpeg4Level; + +/** + * GstMpeg4VisualObjectSequence: + * + * The visual object sequence structure as defined in: + * 6.2.2 Visual Object Sequence and Visual Object + */ +struct _GstMpeg4VisualObjectSequence { + guint8 profile_and_level_indication; + + /* Computed according to: + * Table G.1 — FLC table for profile_and_level_indication */ + GstMpeg4Level level; + GstMpeg4Profile profile; +}; + +/** + * The visual object structure as defined in: + * 6.2.2 Visual Object Sequence and Visual Object + */ +struct _GstMpeg4VisualObject { + guint8 is_identifier; + /* If is_identifier */ + guint8 verid; + guint8 priority; + + GstMpeg4VisualObjectType type; +}; + +/** + * GstMpeg4VideoSignalType: + * + * The video signal type structure as defined in: + * 6.2.2 Visual Object Sequence and Visual Object. + */ +struct _GstMpeg4VideoSignalType { + guint8 type; + + guint8 format; + guint8 range; + guint8 color_description; + guint8 color_primaries; + guint8 transfer_characteristics; + guint8 matrix_coefficients; +}; + +/** + * GstMpeg4VideoPlaneShortHdr: + * + * The video plane short header structure as defined in: + * 6.2.5.2 Video Plane with Short Header + */ +struct _GstMpeg4VideoPlaneShortHdr { + guint8 temporal_reference; + guint8 split_screen_indicator; + guint8 document_camera_indicator; + guint8 full_picture_freeze_release; + guint8 source_format; + guint8 picture_coding_type; + guint8 vop_quant; + guint8 pei; + guint8 psupp; + + /* Gob layer specific fields */ + guint8 gob_header_empty; + guint8 gob_number; + guint8 gob_frame_id; + guint8 quant_scale; + + /* Computed + * If all the values are set to 0, then it is reserved + * Table 6-25 -- Parameters Defined by source_format Field + */ + guint16 vop_width; + guint16 vop_height; + guint16 num_macroblocks_in_gob; + guint8 num_gobs_in_vop; + + /* The size in bits */ + guint size; +}; + +/** + * GstMpeg4VideoObjectLayer: + * + * The video object layer structure as defined in: + * 6.2.3 Video Object Layer + */ +struct _GstMpeg4VideoObjectLayer { + guint8 random_accessible_vol; + guint8 video_object_type_indication; + + guint8 is_object_layer_identifier; + /* if is_object_layer_identifier */ + guint8 verid; + guint8 priority; + + GstMpeg4AspectRatioInfo aspect_ratio_info; + guint8 par_width; + guint8 par_height; + + guint8 control_parameters; + /* if control_parameters */ + GstMpeg4ChromaFormat chroma_format; + guint8 low_delay; + guint8 vbv_parameters; + /* if vbv_parameters */ + guint16 first_half_bitrate; + guint16 latter_half_bitrate; + guint16 first_half_vbv_buffer_size; + guint16 latter_half_vbv_buffer_size; + guint16 first_half_vbv_occupancy; + guint16 latter_half_vbv_occupancy; + + /* Computed values */ + guint32 bit_rate; + guint32 vbv_buffer_size; + + GstMpeg4VideoObjectLayerShape shape; + /* if shape == GST_MPEG4_GRAYSCALE && verid =! 1 */ + guint8 shape_extension; + + guint16 vop_time_increment_resolution; + guint8 vop_time_increment_bits; + guint8 fixed_vop_rate; + /* if fixed_vop_rate */ + guint16 fixed_vop_time_increment; + + guint16 width; + guint16 height; + guint8 interlaced; + guint8 obmc_disable; + + GstMpeg4SpriteEnable sprite_enable; + /* if vol->sprite_enable == SPRITE_GMG or SPRITE_STATIC*/ + /* if vol->sprite_enable != GST_MPEG4_SPRITE_GMG */ + guint16 sprite_width; + guint16 sprite_height; + guint16 sprite_left_coordinate; + guint16 sprite_top_coordinate; + + guint8 no_of_sprite_warping_points; + guint8 sprite_warping_accuracy; + guint8 sprite_brightness_change; + /* if vol->sprite_enable != GST_MPEG4_SPRITE_GMG */ + guint8 low_latency_sprite_enable; + + /* if shape != GST_MPEG4_RECTANGULAR */ + guint8 sadct_disable; + + guint8 not_8_bit; + + /* if no_8_bit */ + guint8 quant_precision; + guint8 bits_per_pixel; + + /* if shape == GRAYSCALE */ + guint8 no_gray_quant_update; + guint8 composition_method; + guint8 linear_composition; + + guint8 quant_type; + /* if quant_type */ + guint8 load_intra_quant_mat; + guint8 intra_quant_mat[64]; + guint8 load_non_intra_quant_mat; + guint8 non_intra_quant_mat[64]; + + guint8 quarter_sample; + guint8 complexity_estimation_disable; + guint8 resync_marker_disable; + guint8 data_partitioned; + guint8 reversible_vlc; + guint8 newpred_enable; + guint8 reduced_resolution_vop_enable; + guint8 scalability; + guint8 enhancement_type; + + GstMpeg4VideoPlaneShortHdr short_hdr; +}; + +/** + * GstMpeg4SpriteTrajectory: + * + * The sprite trajectory structure as defined in: + * 7.8.4 Sprite reference point decoding and + * 6.2.5.4 Sprite coding + */ +struct _GstMpeg4SpriteTrajectory { + guint16 vop_ref_points[63]; /* Defined as "du" in 6.2.5.4 */ + guint16 sprite_ref_points[63]; /* Defined as "dv" in 6.2.5.4 */ +}; + +/** + * GstMpeg4GroupOfVOP: + * + * The group of video object plane structure as defined in: + * 6.2.4 Group of Video Object Plane + */ +struct _GstMpeg4GroupOfVOP { + guint8 hours; + guint8 minutes; + guint8 seconds; + + guint8 closed; + guint8 broken_link; +}; + +/** + * GstMpeg4VideoObjectPlane: + * + * The Video object plane structure as defined in: + * 6.2.5 Video Object Plane and Video Plane with Short Header + */ +struct _GstMpeg4VideoObjectPlane { + GstMpeg4VideoObjectCodingType coding_type; + + guint8 modulo_time_base; + guint16 time_increment; + + guint8 coded; + /* if newpred_enable */ + guint16 id; + guint8 id_for_prediction_indication; + guint16 id_for_prediction; + + guint16 width; + guint16 height; + guint16 horizontal_mc_spatial_ref; + guint16 vertical_mc_spatial_ref; + + guint8 rounding_type; + /*if vol->shape != GST_MPEG4_RECTANGULAR */ + guint8 background_composition; + guint8 change_conv_ratio_disable; + guint8 constant_alpha; + guint8 constant_alpha_value; + guint8 reduced_resolution; + + guint8 intra_dc_vlc_thr; + + + guint8 top_field_first; + guint8 alternate_vertical_scan_flag; + + guint16 quant; + + guint8 fcode_forward; + guint8 fcode_backward; + + guint8 shape_coding_type; + guint8 load_backward_shape; + guint8 ref_select_code; + + /* Computed macroblock informations */ + guint16 mb_height; + guint16 mb_width; + guint mb_num; + + /* The size of the header */ + guint size; +}; + +/** + * GstMpeg4VideoPacketHdr: + * @size: Size of the header in bit. + * + * The video packet header structure as defined in: + * 6.2.5.2 Video Plane with Short Header + */ +struct _GstMpeg4VideoPacketHdr { + guint8 header_extension_code; + guint16 macroblock_number; + guint16 quant_scale; + guint size; +}; + +/** + * GstMpeg4Packet: + * @type: the type of the packet that start at @offset + * @data: the data of the packet, statring at @offset + * @offset: offset of the start of the packet (without the 3 bytes startcode), but + * including the #GstMpeg4StartCode byte. + * @size: The size in bytes of the packet or %G_MAXUINT if the end wasn't found. + * Set to 0 if type == GST_MPEG4_RESYNC. + * @marker_size: The size in bit of the resync marker. + * + * A structure that contains the type of a packet, its offset and its size + */ +struct _GstMpeg4Packet +{ + const guint8 *data; + guint offset; + gsize size; + guint marker_size; + + GstMpeg4StartCode type; +}; + +GstMpeg4ParseResult gst_h263_parse (GstMpeg4Packet * packet, + const guint8 * data, guint offset, + gsize size); + + +GstMpeg4ParseResult gst_mpeg4_parse (GstMpeg4Packet * packet, + gboolean skip_user_data, + const guint8 * data, guint offset, + gsize size); + +GstMpeg4ParseResult +gst_mpeg4_parse_video_object_plane (GstMpeg4VideoObjectPlane *vop, + GstMpeg4SpriteTrajectory *sprite_trajectory, + GstMpeg4VideoObjectLayer *vol, + const guint8 * data, + gsize size); + +GstMpeg4ParseResult +gst_mpeg4_parse_group_of_vop (GstMpeg4GroupOfVOP *gov, + const guint8 * data, gsize size); + +GstMpeg4ParseResult +gst_mpeg4_parse_video_object_layer (GstMpeg4VideoObjectLayer *vol, + GstMpeg4VisualObject *vo, + const guint8 * data, gsize size); + +GstMpeg4ParseResult +gst_mpeg4_parse_visual_object (GstMpeg4VisualObject *vo, + GstMpeg4VideoSignalType *signal_type, + const guint8 * data, gsize size); + +GstMpeg4ParseResult +gst_mpeg4_parse_visual_object_sequence (GstMpeg4VisualObjectSequence *vos, + const guint8 * data, gsize size); +GstMpeg4ParseResult +gst_mpeg4_parse_video_plane_short_header (GstMpeg4VideoPlaneShortHdr * shorthdr, + const guint8 * data, gsize size); + +GstMpeg4ParseResult +gst_mpeg4_next_resync (GstMpeg4Packet * packet, + const GstMpeg4VideoObjectPlane * vop, + const guint8 *data, gsize size); + +GstMpeg4ParseResult +gst_mpeg4_parse_video_packet_header (GstMpeg4VideoPacketHdr * videopackethdr, + GstMpeg4VideoObjectLayer * vol, + GstMpeg4VideoObjectPlane * vop, + GstMpeg4SpriteTrajectory * sprite_trajectory, + const guint8 * data, gsize size); + +#endif /* __GST_MPEG4UTIL_H__ */