gst/mpeg4videoparse/mpeg4videoparse.c: Move some code around to integrate the startcode searching with the other bits...

Original commit message from CVS:
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.
This commit is contained in:
Sjoerd Simons 2008-05-22 14:03:05 +00:00 committed by Wim Taymans
parent fb7879098c
commit b3bc29bc64
3 changed files with 39 additions and 57 deletions

View file

@ -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>

2
common

@ -1 +1 @@
Subproject commit e365978c480a8fffa4bdb61568fb2cd989d1b197
Subproject commit 5e771924d59d9ac912237ea466d0c60ad95df5ab

View file

@ -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;
}