matroskademux: store cluster positions provided by SeekHead

... and use those, if available, to locate a cluster rather than scanning.
This commit is contained in:
Mark Nauwelaerts 2011-02-10 11:56:33 +01:00
parent 9de84b45bc
commit b70f4b6ffa
2 changed files with 57 additions and 0 deletions

View file

@ -399,6 +399,11 @@ gst_matroska_demux_reset (GstElement * element)
demux->index = NULL; demux->index = NULL;
} }
if (demux->clusters) {
g_array_free (demux->clusters, TRUE);
demux->clusters = NULL;
}
/* reset timers */ /* reset timers */
demux->clock = NULL; demux->clock = NULL;
demux->time_scale = 1000000; demux->time_scale = 1000000;
@ -2326,6 +2331,17 @@ gst_matroska_demux_move_to_entry (GstMatroskaDemux * demux,
return TRUE; 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, /* searches for a cluster start from @pos,
* return GST_FLOW_OK and cluster position in @pos if found */ * return GST_FLOW_OK and cluster position in @pos if found */
static GstFlowReturn static GstFlowReturn
@ -2342,6 +2358,30 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
orig_offset = demux->offset; 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 */ /* read in at newpos and scan for ebml cluster id */
while (1) { while (1) {
GstByteReader reader; GstByteReader reader;
@ -2410,6 +2450,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos)
buf = NULL; buf = NULL;
} }
exit:
demux->offset = orig_offset; demux->offset = orig_offset;
*pos = newpos; *pos = newpos;
return ret; return ret;
@ -5383,6 +5424,17 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux,
break; 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: default:
GST_DEBUG_OBJECT (demux, "Ignoring Seek entry for ID=0x%x", seek_id); GST_DEBUG_OBJECT (demux, "Ignoring Seek entry for ID=0x%x", seek_id);
break; break;
@ -5429,6 +5481,9 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux, GstEbmlRead * ebml)
DEBUG_ELEMENT_STOP (demux, ebml, "SeekHead", ret); 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; return ret;
} }

View file

@ -92,6 +92,8 @@ typedef struct _GstMatroskaDemux {
/* a cue (index) table */ /* a cue (index) table */
GArray *index; GArray *index;
/* cluster positions (optional) */
GArray *clusters;
/* timescale in the file */ /* timescale in the file */
guint64 time_scale; guint64 time_scale;