diff options
-rw-r--r-- | ChangeLog | 12 | ||||
m--------- | common | 0 | ||||
-rw-r--r-- | gst/mpeg4videoparse/mpeg4videoparse.c | 82 |
3 files changed, 38 insertions, 56 deletions
@@ -1,3 +1,15 @@ +2008-05-22 Wim Taymans <wim.taymans@collabora.co.uk> + + Patch by: Sjoerd Simons <sjoerd at luon dot net> + + * gst/mpeg4videoparse/mpeg4videoparse.c: (gst_mpeg4vparse_push), + (gst_mpeg4vparse_drain), (gst_mpeg4vparse_chain), + (gst_mpeg4vparse_change_state): + Move some code around to integrate the startcode searching with the + other bits of parsing, avoid a whole bunch of peeks. + Get rid of invalid data that should not happen according to the specs. + Fixes #533559. + 2008-05-20 Sebastian Dröge <slomo@circular-chaos.org> Patch by: Bastien Nocera <hadess at hadess dot net> diff --git a/common b/common -Subproject e365978c480a8fffa4bdb61568fb2cd989d1b19 +Subproject 5e771924d59d9ac912237ea466d0c60ad95df5a diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index fc43f014..ce027ee7 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -121,32 +121,6 @@ gst_mpeg4vparse_set_new_caps (GstMpeg4VParse * parse, return res; } -static void -gst_mpeg4vparse_align (GstMpeg4VParse * parse) -{ - guint flushed = 0; - - /* Searching for a start code */ - while (gst_adapter_available (parse->adapter) >= 4) { - /* If we have enough data, ensure we're aligned to a start code */ - const guint8 *data = gst_adapter_peek (parse->adapter, 4); - - if (G_LIKELY (data[0] == 0 && data[1] == 0 && data[2] == 1)) { - GST_LOG_OBJECT (parse, "found start code with type %02X", data[3]); - parse->state = PARSE_START_FOUND; - break; - } else { - gst_adapter_flush (parse->adapter, 1); - flushed++; - parse->state = PARSE_NEED_START; - } - } - - if (G_UNLIKELY (flushed)) { - GST_LOG_OBJECT (parse, "flushed %u bytes while aligning", flushed); - } -} - #define VOS_STARTCODE 0xB0 #define VOS_ENDCODE 0xB1 #define USER_DATA_STARTCODE 0xB2 @@ -440,7 +414,7 @@ gst_mpeg4vparse_push (GstMpeg4VParse * parse, gsize size) /* Restart now that we flushed data */ parse->offset = 0; - parse->state = PARSE_START_FOUND; + parse->state = PARSE_NEED_START; parse->intra_frame = FALSE; } @@ -452,15 +426,39 @@ gst_mpeg4vparse_drain (GstMpeg4VParse * parse, GstBuffer * last_buffer) guint available = 0; available = gst_adapter_available (parse->adapter); + /* We do a quick check here to avoid the _peek() below. */ + if (G_UNLIKELY (available < 5)) { + GST_DEBUG_OBJECT (parse, "we need more data, %d < 5", available); + goto beach; + } data = gst_adapter_peek (parse->adapter, available); /* Need at least 5 more bytes, 4 for the startcode, 1 to optionally determine * the VOP frame type */ - while (parse->offset < available - 5) { + while (available >= 5 && parse->offset < available - 5) { if (data[parse->offset] == 0 && data[parse->offset + 1] == 0 && data[parse->offset + 2] == 1) { switch (parse->state) { + case PARSE_NEED_START: + switch (data[parse->offset + 3]) { + case VOP_STARTCODE: + case VOS_STARTCODE: + case GOP_STARTCODE: + /* valid starts of a frame */ + parse->state = PARSE_START_FOUND; + if (parse->offset > 0) { + GST_LOG_OBJECT (parse, "Flushing %u bytes", parse->offset); + gst_adapter_flush (parse->adapter, parse->offset); + parse->offset = 0; + available = gst_adapter_available (parse->adapter); + data = gst_adapter_peek (parse->adapter, available); + } + break; + default: + parse->offset += 4; + } + break; case PARSE_START_FOUND: switch (data[parse->offset + 3]) { case VOP_STARTCODE: @@ -498,15 +496,6 @@ gst_mpeg4vparse_drain (GstMpeg4VParse * parse, GstBuffer * last_buffer) break; case PARSE_VOP_FOUND: { /* We were in a VOP already, any start code marks the end of it */ - if (data[parse->offset + 3] == USER_DATA_STARTCODE) { - /* Userdata shouldn't come directly after a VOP, but some - * implementation do it anyways :( This prevents pushing - * USER_DATA as the initial bit of a buffer, which causes confusing - * with other elements */ - parse->offset += 4; - break; - } - GST_LOG_OBJECT (parse, "found VOP end marker at %u", parse->offset); gst_mpeg4vparse_push (parse, parse->offset); @@ -543,27 +532,9 @@ gst_mpeg4vparse_chain (GstPad * pad, GstBuffer * buffer) gst_adapter_push (parse->adapter, buffer); - /* We need to get aligned on a start code */ - if (G_UNLIKELY (parse->state == PARSE_NEED_START)) { - gst_mpeg4vparse_align (parse); - /* No start code found in that buffer */ - if (G_UNLIKELY (parse->state == PARSE_NEED_START)) { - GST_DEBUG_OBJECT (parse, "start code not found, need more data"); - goto beach; - } - } - - /* We need at least 8 bytes to find the next start code which marks the end - of the one we just found */ - if (G_UNLIKELY (gst_adapter_available (parse->adapter) < 8)) { - GST_DEBUG_OBJECT (parse, "start code found, need more data to find next"); - goto beach; - } - /* Drain the accumulated blocks frame per frame */ ret = gst_mpeg4vparse_drain (parse, buffer); -beach: gst_object_unref (parse); return ret; @@ -702,7 +673,6 @@ gst_mpeg4vparse_change_state (GstElement * element, GstStateChange transition) default: break; } - return ret; } |