diff options
author | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2011-02-10 11:56:33 +0100 |
---|---|---|
committer | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2011-02-10 18:17:31 +0100 |
commit | b70f4b6ffad984f76efc6f5916f7d8db42c9e496 (patch) | |
tree | 8fb3610a00bcb68e2672ec013cd5b69fa1416075 | |
parent | 9de84b45bcbd43e2e96b0287355f5695bc911280 (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.c | 55 | ||||
-rw-r--r-- | gst/matroska/matroska-demux.h | 2 |
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; |