summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <bilboed@bilboed.com>2011-06-12 12:55:40 +0200
committerEdward Hervey <bilboed@bilboed.com>2011-06-12 12:55:40 +0200
commitc27b16bfe3309e75117b3edb08e0da024ac0b534 (patch)
tree881b244c4e1c6fb2aef4ba32ad0e0870c3a00f44
parent7032cd12e72bf6c0802232b24147b5f47e91e4c5 (diff)
videoparsers: Speed up the start code search algorithm
Based on 96a7f9c8b1195129f0c2157cbbcbaa6cab45056e Makes it 3-4 times faster
-rw-r--r--gst/videoparsers/gstmpegvideoparse.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c
index 458f699db..7ebbdf36a 100644
--- a/gst/videoparsers/gstmpegvideoparse.c
+++ b/gst/videoparsers/gstmpegvideoparse.c
@@ -385,6 +385,53 @@ gst_mpegv_parse_process_sc (GstMpegvParse * mpvparse, GstBuffer * buf, gint off)
return ret;
}
+static inline guint
+scan_for_start_codes (const GstByteReader * reader, guint offset, guint size)
+{
+ const guint8 *data;
+ guint32 state;
+ guint i;
+
+ g_return_val_if_fail (size > 0, -1);
+ g_return_val_if_fail ((guint64) offset + size <= reader->size - reader->byte,
+ -1);
+
+ /* we can't find the pattern with less than 4 bytes */
+ if (G_UNLIKELY (size < 4))
+ return -1;
+
+ data = reader->data + reader->byte + offset;
+
+ /* set the state to something that does not match */
+ state = 0xffffffff;
+
+ /* now find data */
+ for (i = 0; i < size; i++) {
+ /* throw away one byte and move in the next byte */
+ state = ((state << 8) | data[i]);
+ if (G_UNLIKELY ((state & 0xffffff00) == 0x00000100)) {
+ /* we have a match but we need to have skipped at
+ * least 4 bytes to fill the state. */
+ if (G_LIKELY (i >= 3))
+ return offset + i - 3;
+ }
+
+ /* Accelerate search for start code */
+ if (data[i] > 1) {
+ while (i < (size - 4) && data[i] > 1) {
+ if (data[i + 3] > 1)
+ i += 4;
+ else
+ i += 1;
+ }
+ state = 0x00000100;
+ }
+ }
+
+ /* nothing found */
+ return -1;
+}
+
/* FIXME move into baseparse, or anything equivalent;
* see https://bugzilla.gnome.org/show_bug.cgi?id=650093 */
#define GST_BASE_PARSE_FRAME_FLAG_PARSING 0x10000
@@ -419,8 +466,7 @@ retry:
goto next;
}
- off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffff00, 0x00000100,
- off, GST_BUFFER_SIZE (buf) - off);
+ off = scan_for_start_codes (&reader, off, GST_BUFFER_SIZE (buf) - off);
GST_LOG_OBJECT (mpvparse, "possible sync at buffer offset %d", off);
@@ -453,8 +499,7 @@ next:
/* 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);
+ off = scan_for_start_codes (&reader, off, GST_BUFFER_SIZE (buf) - off);
GST_LOG_OBJECT (mpvparse, "next start code at %d", off);
if (off < 0) {