summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2011-02-10 11:56:33 +0100
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2011-02-10 18:17:31 +0100
commitb70f4b6ffad984f76efc6f5916f7d8db42c9e496 (patch)
tree8fb3610a00bcb68e2672ec013cd5b69fa1416075
parent9de84b45bcbd43e2e96b0287355f5695bc911280 (diff)
matroskademux: store cluster positions provided by SeekHead
... and use those, if available, to locate a cluster rather than scanning.
-rw-r--r--gst/matroska/matroska-demux.c55
-rw-r--r--gst/matroska/matroska-demux.h2
2 files changed, 57 insertions, 0 deletions
diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index f1b2b783f..76431193c 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -396,12 +396,17 @@ gst_matroska_demux_reset (GstElement * element)
/* reset indexes */
if (demux->index) {
g_array_free (demux->index, TRUE);
demux->index = NULL;
}
+ if (demux->clusters) {
+ g_array_free (demux->clusters, TRUE);
+ demux->clusters = NULL;
+ }
+
/* reset timers */
demux->clock = NULL;
demux->time_scale = 1000000;
demux->created = G_MININT64;
demux->index_parsed = FALSE;
@@ -2323,12 +2328,23 @@ gst_matroska_demux_move_to_entry (GstMatroskaDemux * demux,
GST_OBJECT_UNLOCK (demux);
return TRUE;
}
+static gint
+gst_matroska_cluster_compare (gint64 * i1, gint64 * i2)
+{
+ if (*i1 < *i2)
+ return -1;
+ else if (*i1 > *i2)
+ return 1;
+ else
+ return 0;
+}
+
/* searches for a cluster start from @pos,
* return GST_FLOW_OK and cluster position in @pos if found */
static GstFlowReturn
gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
{
gint64 newpos = *pos;
@@ -2339,12 +2355,36 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
guint64 length;
guint32 id;
guint needed;
orig_offset = demux->offset;
+ GST_LOG_OBJECT (demux, "searching cluster following offset %" G_GINT64_FORMAT,
+ *pos);
+
+ if (demux->clusters) {
+ gint64 *cpos;
+
+ cpos = gst_util_array_binary_search (demux->clusters->data,
+ demux->clusters->len, sizeof (gint64),
+ (GCompareDataFunc) gst_matroska_cluster_compare,
+ GST_SEARCH_MODE_AFTER, pos, NULL);
+ /* sanity check */
+ if (cpos) {
+ GST_DEBUG_OBJECT (demux,
+ "cluster reported at offset %" G_GINT64_FORMAT, *cpos);
+ demux->offset = *cpos;
+ ret =
+ gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed);
+ if (ret == GST_FLOW_OK && id == GST_MATROSKA_ID_CLUSTER) {
+ newpos = *cpos;
+ goto exit;
+ }
+ }
+ }
+
/* read in at newpos and scan for ebml cluster id */
while (1) {
GstByteReader reader;
gint cluster_pos;
ret = gst_pad_pull_range (demux->sinkpad, newpos, chunk, &buf);
@@ -2407,12 +2447,13 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
if (buf) {
gst_buffer_unref (buf);
buf = NULL;
}
+exit:
demux->offset = orig_offset;
*pos = newpos;
return ret;
}
/* bisect and scan through file for cluster starting before @time,
@@ -5380,12 +5421,23 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
finish:
/* seek back */
demux->offset = before_pos;
break;
}
+ case GST_MATROSKA_ID_CLUSTER:
+ {
+ guint64 pos = seek_pos + demux->ebml_segment_start;
+
+ GST_LOG_OBJECT (demux, "Cluster position");
+ if (G_UNLIKELY (!demux->clusters))
+ demux->clusters = g_array_sized_new (TRUE, TRUE, sizeof (guint64), 100);
+ g_array_append_val (demux->clusters, pos);
+ break;
+ }
+
default:
GST_DEBUG_OBJECT (demux, "Ignoring Seek entry for ID=0x%x", seek_id);
break;
}
DEBUG_ELEMENT_STOP (demux, ebml, "Seek", ret);
@@ -5426,12 +5478,15 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux, GstEbmlRead * ebml)
break;
}
}
DEBUG_ELEMENT_STOP (demux, ebml, "SeekHead", ret);
+ /* Sort clusters by position for easier searching */
+ g_array_sort (demux->clusters, (GCompareFunc) gst_matroska_cluster_compare);
+
return ret;
}
#define GST_FLOW_OVERFLOW GST_FLOW_CUSTOM_ERROR
#define MAX_BLOCK_SIZE (15 * 1024 * 1024)
diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h
index b31f79cb6..a35a5935a 100644
--- a/gst/matroska/matroska-demux.h
+++ b/gst/matroska/matroska-demux.h
@@ -89,12 +89,14 @@ typedef struct _GstMatroskaDemux {
/* start-of-segment */
guint64 ebml_segment_start;
/* a cue (index) table */
GArray *index;
+ /* cluster positions (optional) */
+ GArray *clusters;
/* timescale in the file */
guint64 time_scale;
/* keeping track of playback position */
GstSegment segment;