diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index e2d3976f0c..bc1c279c90 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -4,7 +4,7 @@ libgstvideoparsersbad_la_SOURCES = plugin.c \ h263parse.c gsth263parse.c \ gstdiracparse.c dirac_parse.c \ gsth264parse.c gstmpegvideoparse.c \ - gstmpeg4videoparse.c mpeg4parse.c + gstmpeg4videoparse.c libgstvideoparsersbad_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ @@ -19,7 +19,7 @@ libgstvideoparsersbad_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gsth263parse.h h263parse.h \ gstdiracparse.h dirac_parse.h \ gsth264parse.h gstmpegvideoparse.h \ - gstmpeg4videoparse.h mpeg4parse.h + gstmpeg4videoparse.h Android.mk: Makefile.am $(BUILT_SOURCES) androgenizer \ diff --git a/gst/videoparsers/gstmpeg4videoparse.c b/gst/videoparsers/gstmpeg4videoparse.c index 1612626851..6170ae1664 100644 --- a/gst/videoparsers/gstmpeg4videoparse.c +++ b/gst/videoparsers/gstmpeg4videoparse.c @@ -3,8 +3,10 @@ * @author Sjoerd Simons * Copyright (C) <2007> Julien Moutte * Copyright (C) <2011> Mark Nauwelaerts - * Copyright (C) <2011> Collabora Multimedia * Copyright (C) <2011> Nokia Corporation + * 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 @@ -49,7 +51,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, ); /* Properties */ -#define DEFAULT_PROP_DROP TRUE +#define DEFAULT_PROP_DROP TRUE #define DEFAULT_CONFIG_INTERVAL (0) enum @@ -183,8 +185,8 @@ gst_mpeg4vparse_reset_frame (GstMpeg4VParse * mp4vparse) /* done parsing; reset state */ mp4vparse->last_sc = -1; mp4vparse->vop_offset = -1; - mp4vparse->vos_offset = -1; - mp4vparse->vo_offset = -1; + mp4vparse->vo_found = FALSE; + mp4vparse->vol_offset = -1; } static void @@ -195,7 +197,7 @@ gst_mpeg4vparse_reset (GstMpeg4VParse * mp4vparse) mp4vparse->update_caps = TRUE; gst_buffer_replace (&mp4vparse->config, NULL); - memset (&mp4vparse->params, 0, sizeof (mp4vparse->params)); + memset (&mp4vparse->vol, 0, sizeof (mp4vparse->vol)); } static gboolean @@ -225,30 +227,46 @@ gst_mpeg4vparse_stop (GstBaseParse * parse) } static gboolean -gst_mpeg4vparse_process_config (GstMpeg4VParse * mp4vparse, const guint8 * data, - gsize size) +gst_mpeg4vparse_process_config (GstMpeg4VParse * mp4vparse, + const guint8 * data, guint offset, gsize size) { /* only do stuff if something new */ if (mp4vparse->config && size == GST_BUFFER_SIZE (mp4vparse->config) && memcmp (GST_BUFFER_DATA (mp4vparse->config), data, size) == 0) return TRUE; - if (!gst_mpeg4_params_parse_config (&mp4vparse->params, data, size)) { - GST_DEBUG_OBJECT (mp4vparse, "failed to parse config data (size %" - G_GSSIZE_FORMAT ")", size); + if (mp4vparse->vol_offset < 0) { + GST_WARNING ("No video object Layer parsed in this frame, cannot accept " + "config"); return FALSE; } + /* If the parsing fail, we accept the config only if we don't have + * any config yet. */ + if (gst_mpeg4_parse_video_object_layer (&mp4vparse->vol, + NULL, data + mp4vparse->vol_offset, + size - mp4vparse->vol_offset) != GST_MPEG4_PARSER_OK && + mp4vparse->config) + return FALSE; + + GST_LOG_OBJECT (mp4vparse, "Width/Height: %u/%u, " + "time increment resolution: %u fixed time increment: %u", + mp4vparse->vol.height, mp4vparse->vol.width, + mp4vparse->vol.vop_time_increment_resolution, + mp4vparse->vol.fixed_vop_time_increment); + + GST_LOG_OBJECT (mp4vparse, "accepting parsed config size %" G_GSSIZE_FORMAT, size); - /* parsing ok, so accept it as new config */ if (mp4vparse->config != NULL) gst_buffer_unref (mp4vparse->config); mp4vparse->config = gst_buffer_new_and_alloc (size); + memcpy (GST_BUFFER_DATA (mp4vparse->config), data, size); + /* trigger src caps update */ mp4vparse->update_caps = TRUE; @@ -257,68 +275,73 @@ gst_mpeg4vparse_process_config (GstMpeg4VParse * mp4vparse, const guint8 * data, /* caller guarantees at least start code in @buf at @off */ static gboolean -gst_mpeg4vparse_process_sc (GstMpeg4VParse * mp4vparse, GstBuffer * buf, - gint off) +gst_mpeg4vparse_process_sc (GstMpeg4VParse * mp4vparse, GstMpeg4Packet * packet, + gsize size) { - guint8 *data; - guint code; - g_return_val_if_fail (buf && GST_BUFFER_SIZE (buf) >= off + 4, FALSE); - - data = GST_BUFFER_DATA (buf); - code = data[off + 3]; - - GST_LOG_OBJECT (mp4vparse, "process startcode %x", code); + GST_LOG_OBJECT (mp4vparse, "process startcode %x", packet->type); /* if we found a VOP, next start code ends it, * except for final VOS end sequence code included in last VOP-frame */ - if (mp4vparse->vop_offset >= 0 && code != MPEG4_VOS_ENDCODE) { - if (G_LIKELY (GST_BUFFER_SIZE (buf) > mp4vparse->vop_offset + 4)) { + if (mp4vparse->vop_offset >= 0 && + packet->type != GST_MPEG4_VISUAL_OBJ_SEQ_END) { + if (G_LIKELY (size > mp4vparse->vop_offset + 1)) { mp4vparse->intra_frame = - ((data[mp4vparse->vop_offset + 4] >> 6 & 0x3) == 0); + ((packet->data[mp4vparse->vop_offset + 1] >> 6 & 0x3) == 0); } else { GST_WARNING_OBJECT (mp4vparse, "no data following VOP startcode"); mp4vparse->intra_frame = FALSE; } - GST_LOG_OBJECT (mp4vparse, "ending frame of size %d, is intra %d", off, - mp4vparse->intra_frame); + GST_LOG_OBJECT (mp4vparse, "ending frame of size %d, is intra %d", + packet->offset - 3, mp4vparse->intra_frame); return TRUE; } - switch (code) { - case MPEG4_VOP_STARTCODE: - case MPEG4_GOP_STARTCODE: + switch (packet->type) { + case GST_MPEG4_VIDEO_OBJ_PLANE: + case GST_MPEG4_GROUP_OF_VOP: { - gint offset; - if (code == MPEG4_VOP_STARTCODE) { + if (packet->type == GST_MPEG4_VIDEO_OBJ_PLANE) { GST_LOG_OBJECT (mp4vparse, "startcode is VOP"); - mp4vparse->vop_offset = off; + mp4vparse->vop_offset = packet->offset; } else { GST_LOG_OBJECT (mp4vparse, "startcode is GOP"); } /* parse config data ending here if proper startcodes found earlier; * preferably start at VOS (visual object sequence), * otherwise at VO (video object) */ - offset = mp4vparse->vos_offset >= 0 ? - mp4vparse->vos_offset : mp4vparse->vo_offset; - if (offset >= 0) { - gst_mpeg4vparse_process_config (mp4vparse, GST_BUFFER_DATA (buf), off); + if (mp4vparse->vo_found) { + + /*Do not take care startcode into account */ + gst_mpeg4vparse_process_config (mp4vparse, + packet->data, packet->offset, packet->offset - 3); + /* avoid accepting again for a VOP sc following a GOP sc */ - mp4vparse->vos_offset = -1; - mp4vparse->vo_offset = -1; + mp4vparse->vo_found = FALSE; } break; } - case MPEG4_VOS_STARTCODE: - GST_LOG_OBJECT (mp4vparse, "startcode is VOS"); - mp4vparse->vos_offset = off; + case GST_MPEG4_VISUAL_OBJ_SEQ_START: + GST_LOG_OBJECT (mp4vparse, "Visual Sequence Start"); + mp4vparse->vo_found = TRUE; break; + case GST_MPEG4_VISUAL_OBJ: + GST_LOG_OBJECT (mp4vparse, "Visual Object"); default: - /* VO (video object) cases */ - if (code <= 0x1f) { - GST_LOG_OBJECT (mp4vparse, "startcode is VO"); - mp4vparse->vo_offset = off; + if (packet->type >= GST_MPEG4_VIDEO_LAYER_FIRST && + packet->type <= GST_MPEG4_VIDEO_LAYER_LAST) { + + GST_LOG_OBJECT (mp4vparse, "Video Object Layer"); + + /* wee keep track of the offset to parse later on */ + if (mp4vparse->vol_offset < 0) + mp4vparse->vol_offset = packet->offset; + + /* VO (video object) cases */ + } else if (packet->type <= GST_MPEG4_VIDEO_OBJ_LAST) { + GST_LOG_OBJECT (mp4vparse, "Video object"); + mp4vparse->vo_found = TRUE; } break; } @@ -336,15 +359,15 @@ gst_mpeg4vparse_check_valid_frame (GstBaseParse * parse, GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { GstMpeg4VParse *mp4vparse = GST_MPEG4VIDEO_PARSE (parse); - GstBuffer *buf = frame->buffer; - GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); + GstMpeg4Packet packet; + guint8 *data = GST_BUFFER_DATA (frame->buffer); + guint size = GST_BUFFER_SIZE (frame->buffer); gint off = 0; gboolean ret; - guint code; retry: /* at least start code and subsequent byte */ - if (G_UNLIKELY (GST_BUFFER_SIZE (buf) - off < 5)) + if (G_UNLIKELY (size - off < 5)) return FALSE; /* avoid stale cached parsing state */ @@ -362,36 +385,33 @@ retry: goto next; } - off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffff00, 0x00000100, - off, GST_BUFFER_SIZE (buf) - off); - - GST_LOG_OBJECT (mp4vparse, "possible sync at buffer offset %d", off); - /* didn't find anything that looks like a sync word, skip */ - if (G_UNLIKELY (off < 0)) { - *skipsize = GST_BUFFER_SIZE (buf) - 3; - return FALSE; + switch (gst_mpeg4_parse (&packet, TRUE, data, off, size)) { + case (GST_MPEG4_PARSER_NO_PACKET): + case (GST_MPEG4_PARSER_ERROR): + *skipsize = size - 3; + return FALSE; + default: + break; } + off = packet.offset; /* possible frame header, but not at offset 0? skip bytes before sync */ - if (G_UNLIKELY (off > 0)) { + if (G_UNLIKELY (off > 4)) { *skipsize = off; return FALSE; } - /* ensure start code looks like a real starting start code */ - code = GST_BUFFER_DATA (buf)[3]; - switch (code) { - case MPEG4_VOP_STARTCODE: - case MPEG4_VOS_STARTCODE: - case MPEG4_GOP_STARTCODE: + switch (packet.type) { + case GST_MPEG4_GROUP_OF_VOP: + case GST_MPEG4_VISUAL_OBJ_SEQ_START: + case GST_MPEG4_VIDEO_OBJ_PLANE: break; default: - if (code <= 0x1f) + if (packet.type <= GST_MPEG4_VIDEO_OBJ_LAST) break; /* undesirable sc */ GST_LOG_OBJECT (mp4vparse, "start code is no VOS, VO, VOP or GOP"); - off++; goto retry; } @@ -399,37 +419,45 @@ retry: mp4vparse->last_sc = 0; /* examine start code, which should not end frame at present */ - gst_mpeg4vparse_process_sc (mp4vparse, buf, 0); + gst_mpeg4vparse_process_sc (mp4vparse, &packet, size); next: + GST_LOG_OBJECT (mp4vparse, "Looking for frame end"); + /* start is fine as of now */ *skipsize = 0; /* position a bit further than last sc */ off++; - /* so now we have start code at start of data; locate next start code */ - off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffff00, 0x00000100, - off, GST_BUFFER_SIZE (buf) - off); - GST_LOG_OBJECT (mp4vparse, "next start code at %d", off); - if (off < 0) { - /* if draining, take all */ - if (GST_BASE_PARSE_DRAINING (parse)) { - off = GST_BUFFER_SIZE (buf); - ret = TRUE; - } else { - /* resume scan where we left it */ - mp4vparse->last_sc = GST_BUFFER_SIZE (buf) - 4; - /* request best next available */ - *framesize = G_MAXUINT; - return FALSE; - } - } else { - /* decide whether this startcode ends a frame */ - ret = gst_mpeg4vparse_process_sc (mp4vparse, buf, off); + /* so now we have start code at start of data; locate next packet */ + switch (gst_mpeg4_parse (&packet, TRUE, data, off, size)) { + case (GST_MPEG4_PARSER_NO_PACKET_END): + ret = gst_mpeg4vparse_process_sc (mp4vparse, &packet, size); + if (ret) + break; + case (GST_MPEG4_PARSER_NO_PACKET): + case (GST_MPEG4_PARSER_ERROR): + /* if draining, take all */ + if (GST_BASE_PARSE_DRAINING (parse)) { + *framesize = size; + return TRUE; + } else { + /* resume scan where we left it */ + mp4vparse->last_sc = size - 3; + /* request best next available */ + *framesize = G_MAXUINT; + return FALSE; + } + default: + /* decide whether this startcode ends a frame */ + ret = gst_mpeg4vparse_process_sc (mp4vparse, &packet, size); + break; } + off = packet.offset; + if (ret) { - *framesize = off; + *framesize = off - 3; } else { goto next; } @@ -442,6 +470,8 @@ gst_mpeg4vparse_update_src_caps (GstMpeg4VParse * mp4vparse) { GstCaps *caps = NULL; + GST_LOG_OBJECT (mp4vparse, "Updating caps"); + /* only update if no src caps yet or explicitly triggered */ if (G_LIKELY (GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (mp4vparse)) && !mp4vparse->update_caps)) @@ -474,15 +504,15 @@ gst_mpeg4vparse_update_src_caps (GstMpeg4VParse * mp4vparse) GST_TYPE_BUFFER, mp4vparse->config, NULL); } - if (mp4vparse->params.width > 0 && mp4vparse->params.height > 0) { - gst_caps_set_simple (caps, "width", G_TYPE_INT, mp4vparse->params.width, - "height", G_TYPE_INT, mp4vparse->params.height, NULL); + if (mp4vparse->vol.width > 0 && mp4vparse->vol.height > 0) { + gst_caps_set_simple (caps, "width", G_TYPE_INT, mp4vparse->vol.width, + "height", G_TYPE_INT, mp4vparse->vol.height, NULL); } /* perhaps we have a framerate */ - if (mp4vparse->params.fixed_time_increment != 0) { - gint fps_num = mp4vparse->params.time_increment_resolution; - gint fps_den = mp4vparse->params.fixed_time_increment; + if (mp4vparse->vol.fixed_vop_time_increment != 0) { + gint fps_num = mp4vparse->vol.vop_time_increment_resolution; + gint fps_den = mp4vparse->vol.fixed_vop_time_increment; GstClockTime latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num); gst_caps_set_simple (caps, "framerate", @@ -493,11 +523,10 @@ gst_mpeg4vparse_update_src_caps (GstMpeg4VParse * mp4vparse) } /* or pixel-aspect-ratio */ - if (mp4vparse->params.aspect_ratio_width > 0 && - mp4vparse->params.aspect_ratio_height > 0) { + if (mp4vparse->vol.par_width > 0 && mp4vparse->vol.par_height > 0) { gst_caps_set_simple (caps, "pixel-aspect-ratio", - GST_TYPE_FRACTION, mp4vparse->params.aspect_ratio_width, - mp4vparse->params.aspect_ratio_height, NULL); + GST_TYPE_FRACTION, mp4vparse->vol.par_width, + mp4vparse->vol.par_height, NULL); } gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (mp4vparse), caps); @@ -518,7 +547,7 @@ gst_mpeg4vparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); if (G_UNLIKELY (mp4vparse->drop && !mp4vparse->config)) { - GST_DEBUG_OBJECT (mp4vparse, "dropping frame as no config yet"); + GST_LOG_OBJECT (mp4vparse, "dropping frame as no config yet"); return GST_BASE_PARSE_FLOW_DROPPED; } else return GST_FLOW_OK; @@ -530,7 +559,7 @@ gst_mpeg4vparse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) GstMpeg4VParse *mp4vparse = GST_MPEG4VIDEO_PARSE (parse); GstBuffer *buffer = frame->buffer; - /* periodic SPS/PPS sending */ + /* periodic config sending */ if (mp4vparse->interval > 0) { GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); guint64 diff; @@ -590,6 +619,11 @@ gst_mpeg4vparse_set_caps (GstBaseParse * parse, GstCaps * caps) GstStructure *s; const GValue *value; GstBuffer *buf; + guint8 *data; + gsize size; + + GstMpeg4Packet packet; + GstMpeg4ParseResult res; GST_DEBUG_OBJECT (parse, "setcaps called with %" GST_PTR_FORMAT, caps); @@ -600,8 +634,22 @@ gst_mpeg4vparse_set_caps (GstBaseParse * parse, GstCaps * caps) /* best possible parse attempt, * src caps are based on sink caps so it will end up in there * whether sucessful or not */ + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + res = gst_mpeg4_parse (&packet, TRUE, data, 0, size); + + while (res == GST_MPEG4_PARSER_OK || res == GST_MPEG4_PARSER_NO_PACKET_END) { + + if (packet.type >= GST_MPEG4_VIDEO_LAYER_FIRST && + packet.type <= GST_MPEG4_VIDEO_LAYER_LAST) + mp4vparse->vol_offset = packet.offset; + + res = gst_mpeg4_parse (&packet, TRUE, data, packet.offset, size); + } + + /* And take it as config */ gst_mpeg4vparse_process_config (mp4vparse, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf)); + 3, GST_BUFFER_SIZE (buf)); } /* let's not interfere and accept regardless of config parsing success */ diff --git a/gst/videoparsers/gstmpeg4videoparse.h b/gst/videoparsers/gstmpeg4videoparse.h index 317118288a..d76435f410 100644 --- a/gst/videoparsers/gstmpeg4videoparse.h +++ b/gst/videoparsers/gstmpeg4videoparse.h @@ -23,7 +23,7 @@ #include #include -#include "mpeg4parse.h" +#include G_BEGIN_DECLS @@ -50,14 +50,14 @@ struct _GstMpeg4VParse { /* parse state */ gint last_sc; gint vop_offset; - gint vos_offset; - gint vo_offset; + gboolean vo_found; gboolean intra_frame; gboolean update_caps; GstBuffer *config; guint8 profile; - MPEG4Params params; + GstMpeg4VideoObjectLayer vol; + gboolean vol_offset; /* properties */ gboolean drop; diff --git a/gst/videoparsers/mpeg4parse.c b/gst/videoparsers/mpeg4parse.c deleted file mode 100644 index 5c8ce9574c..0000000000 --- a/gst/videoparsers/mpeg4parse.c +++ /dev/null @@ -1,294 +0,0 @@ -/* GStreamer MPEG4-2 video Parser - * Copyright (C) <2008> Mindfruit B.V. - * @author Sjoerd Simons - * Copyright (C) <2007> Julien Moutte - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "mpeg4parse.h" - -#include - -GST_DEBUG_CATEGORY_EXTERN (mpeg4v_parse_debug); -#define GST_CAT_DEFAULT mpeg4v_parse_debug - - -#define GET_BITS(b, num, bits) G_STMT_START { \ - if (!gst_bit_reader_get_bits_uint32(b, bits, num)) \ - goto failed; \ - GST_TRACE ("parsed %d bits: %d", num, *(bits)); \ -} G_STMT_END - -#define MARKER_BIT(b) G_STMT_START { \ - guint32 i; \ - GET_BITS(b, 1, &i); \ - if (i != 0x1) \ - goto failed; \ -} G_STMT_END - -static inline gboolean -next_start_code (GstBitReader * b) -{ - guint32 bits = 0; - - GET_BITS (b, 1, &bits); - if (bits != 0) - goto failed; - - while (b->bit != 0) { - GET_BITS (b, 1, &bits); - if (bits != 0x1) - goto failed; - } - - return TRUE; - -failed: - return FALSE; -} - -static inline gboolean -skip_user_data (GstBitReader * bs, guint32 * bits) -{ - while (*bits == MPEG4_USER_DATA_STARTCODE_MARKER) { - guint32 b = 0; - - do { - GET_BITS (bs, 8, &b); - *bits = (*bits << 8) | b; - } while ((*bits >> 8) != MPEG4_START_MARKER); - } - - return TRUE; - -failed: - return FALSE; -} - - -static gint aspect_ratio_table[6][2] = { - {-1, -1}, {1, 1}, {12, 11}, {10, 11}, {16, 11}, {40, 33} -}; - -static gboolean -gst_mpeg4_params_parse_vo (MPEG4Params * params, GstBitReader * br) -{ - guint32 bits; - guint16 time_increment_resolution = 0; - guint16 fixed_time_increment = 0; - gint aspect_ratio_width = -1, aspect_ratio_height = -1; - gint height = -1, width = -1; - - /* expecting a video object startcode */ - GET_BITS (br, 32, &bits); - if (bits > 0x11F) - goto failed; - - /* expecting a video object layer startcode */ - GET_BITS (br, 32, &bits); - if (bits < 0x120 || bits > 0x12F) - goto failed; - - /* ignore random accessible vol and video object type indication */ - GET_BITS (br, 9, &bits); - - GET_BITS (br, 1, &bits); - if (bits) { - /* skip video object layer verid and priority */ - GET_BITS (br, 7, &bits); - } - - /* aspect ratio info */ - GET_BITS (br, 4, &bits); - if (bits == 0) - goto failed; - - /* check if aspect ratio info is extended par */ - if (bits == 0xf) { - GET_BITS (br, 8, &bits); - aspect_ratio_width = bits; - GET_BITS (br, 8, &bits); - aspect_ratio_height = bits; - } else if (bits < 0x6) { - aspect_ratio_width = aspect_ratio_table[bits][0]; - aspect_ratio_height = aspect_ratio_table[bits][1]; - } - GST_DEBUG ("aspect ratio %d/%d", aspect_ratio_width, aspect_ratio_height); - - GET_BITS (br, 1, &bits); - if (bits) { - /* vol control parameters, skip chroma and low delay */ - GET_BITS (br, 3, &bits); - GET_BITS (br, 1, &bits); - if (bits) { - /* skip vbv_parameters */ - if (!gst_bit_reader_skip (br, 79)) - goto failed; - } - } - - /* layer shape */ - GET_BITS (br, 2, &bits); - /* only support rectangular */ - if (bits != 0) - goto failed; - - MARKER_BIT (br); - GET_BITS (br, 16, &bits); - time_increment_resolution = bits; - MARKER_BIT (br); - - GST_DEBUG ("time increment resolution %d", time_increment_resolution); - - GET_BITS (br, 1, &bits); - if (bits) { - /* fixed time increment */ - int n; - - /* Length of the time increment is the minimal number of bits needed to - * represent time_increment_resolution-1 */ - for (n = 0; ((time_increment_resolution - 1) >> n) != 0; n++); - GET_BITS (br, n, &bits); - - fixed_time_increment = bits; - } else { - /* When fixed_vop_rate is not set we can't guess any framerate */ - fixed_time_increment = 0; - } - GST_DEBUG ("fixed time increment %d", fixed_time_increment); - - /* assuming rectangular shape */ - MARKER_BIT (br); - GET_BITS (br, 13, &bits); - width = bits; - MARKER_BIT (br); - GET_BITS (br, 13, &bits); - height = bits; - MARKER_BIT (br); - GST_DEBUG ("width x height: %d x %d", width, height); - - /* so we got it all, report back */ - params->width = width; - params->height = height; - params->time_increment_resolution = time_increment_resolution; - params->fixed_time_increment = fixed_time_increment; - params->aspect_ratio_width = aspect_ratio_width; - params->aspect_ratio_height = aspect_ratio_height; - - return TRUE; - - /* ERRORS */ -failed: - { - GST_WARNING ("Failed to parse config data"); - return FALSE; - } -} - -static gboolean -gst_mpeg4_params_parse_vos (MPEG4Params * params, GstBitReader * br) -{ - guint32 bits = 0; - - GET_BITS (br, 32, &bits); - if (bits != MPEG4_VOS_STARTCODE_MARKER) - goto failed; - - GET_BITS (br, 8, &bits); - params->profile = bits; - - /* invalid profile, warn but carry on */ - if (params->profile == 0) { - GST_WARNING ("Invalid profile in VOS"); - } - - /* Expect Visual Object startcode */ - GET_BITS (br, 32, &bits); - - /* but skip optional user data */ - if (!skip_user_data (br, &bits)) - goto failed; - - if (bits != MPEG4_VISUAL_OBJECT_STARTCODE_MARKER) - goto failed; - - GET_BITS (br, 1, &bits); - if (bits == 0x1) { - /* Skip visual_object_verid and priority */ - GET_BITS (br, 7, &bits); - } - - GET_BITS (br, 4, &bits); - /* Only support video ID */ - if (bits != 0x1) - goto failed; - - /* video signal type */ - GET_BITS (br, 1, &bits); - - if (bits == 0x1) { - /* video signal type, ignore format and range */ - GET_BITS (br, 4, &bits); - - GET_BITS (br, 1, &bits); - if (bits == 0x1) { - /* ignore color description */ - GET_BITS (br, 24, &bits); - } - } - - if (!next_start_code (br)) - goto failed; - - /* skip optional user data */ - GET_BITS (br, 32, &bits); - if (!skip_user_data (br, &bits)) - goto failed; - - /* rewind to start code */ - gst_bit_reader_set_pos (br, gst_bit_reader_get_pos (br) - 32); - - return gst_mpeg4_params_parse_vo (params, br); - - /* ERRORS */ -failed: - { - GST_WARNING ("Failed to parse config data"); - return FALSE; - } -} - -gboolean -gst_mpeg4_params_parse_config (MPEG4Params * params, const guint8 * data, - guint size) -{ - GstBitReader br; - - if (size < 4) - return FALSE; - - gst_bit_reader_init (&br, data, size); - - if (data[3] == MPEG4_VOS_STARTCODE) - return gst_mpeg4_params_parse_vos (params, &br); - else - return gst_mpeg4_params_parse_vo (params, &br); -} diff --git a/gst/videoparsers/mpeg4parse.h b/gst/videoparsers/mpeg4parse.h deleted file mode 100644 index cf79e88722..0000000000 --- a/gst/videoparsers/mpeg4parse.h +++ /dev/null @@ -1,63 +0,0 @@ -/* GStreamer MPEG4-2 video Parser - * Copyright (C) <2008> Mindfruit B.V. - * @author Sjoerd Simons - * Copyright (C) <2007> Julien Moutte - * - * 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_MPEG4_PARAMS_H__ -#define __GST_MPEG4_PARAMS_H__ - -#include - -G_BEGIN_DECLS - -#define MPEG4_VIDEO_OBJECT_STARTCODE_MIN 0x00 -#define MPEG4_VIDEO_OBJECT_STARTCODE_MAX 0x1F -#define MPEG4_VOS_STARTCODE 0xB0 -#define MPEG4_VOS_ENDCODE 0xB1 -#define MPEG4_USER_DATA_STARTCODE 0xB2 -#define MPEG4_GOP_STARTCODE 0xB3 -#define MPEG4_VISUAL_OBJECT_STARTCODE 0xB5 -#define MPEG4_VOP_STARTCODE 0xB6 - -#define MPEG4_START_MARKER 0x000001 -#define MPEG4_VISUAL_OBJECT_STARTCODE_MARKER \ - ((MPEG4_START_MARKER << 8) + MPEG4_VISUAL_OBJECT_STARTCODE) -#define MPEG4_VOS_STARTCODE_MARKER \ - ((MPEG4_START_MARKER << 8) + MPEG4_VOS_STARTCODE) -#define MPEG4_USER_DATA_STARTCODE_MARKER \ - ((MPEG4_START_MARKER << 8) + MPEG4_USER_DATA_STARTCODE) - - -typedef struct _MPEG4Params MPEG4Params; - -struct _MPEG4Params -{ - gint profile; - - gint width, height; - gint aspect_ratio_width, aspect_ratio_height; - gint time_increment_resolution; - gint fixed_time_increment; -}; - -GstFlowReturn gst_mpeg4_params_parse_config (MPEG4Params * params, - const guint8 * data, guint size); - -G_END_DECLS -#endif