From 93ddea2a70991f24f2b4de81d2d9beb0136c9a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 18 Jan 2017 10:27:38 +0000 Subject: [PATCH] matroskademux: extract cluster prevsize if available This is useful for reverse playback/trickmodes without an index, and will also be useful in the seek handler if we need to scan back to find a cluster that starts with a keyframe. https://bugzilla.gnome.org/show_bug.cgi?id=790696 --- gst/matroska/matroska-demux.c | 18 +++++++++++++++++- gst/matroska/matroska-demux.h | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index fb7832990e..824110477c 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -306,6 +306,8 @@ gst_matroska_demux_reset (GstElement * element) demux->to_time = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; + demux->cluster_prevsize = 0; + demux->seen_cluster_prevsize = FALSE; demux->next_cluster_offset = 0; demux->stream_last_time = GST_CLOCK_TIME_NONE; demux->last_cluster_offset = 0; @@ -4659,6 +4661,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, break; case GST_MATROSKA_READ_STATE_SCANNING: if (id != GST_MATROSKA_ID_CLUSTER && + id != GST_MATROSKA_ID_PREVSIZE && id != GST_MATROSKA_ID_CLUSTERTIMECODE) { if (demux->common.start_resync_offset != -1) { /* we need to skip byte per byte if we are scanning for a new cluster @@ -4742,6 +4745,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, } demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = demux->common.offset; + demux->cluster_prevsize = 0; if (G_UNLIKELY (!demux->seek_first && demux->seek_block)) { GST_DEBUG_OBJECT (demux, "seek target block %" G_GUINT64_FORMAT " not found in Cluster, trying next Cluster's first block instead", @@ -4873,8 +4877,18 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, GST_OBJECT_UNLOCK (demux); } break; + case GST_MATROSKA_ID_PREVSIZE:{ + guint64 num; + + GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml)); + if ((ret = gst_ebml_read_uint (&ebml, &id, &num)) != GST_FLOW_OK) + goto parse_failed; + GST_LOG_OBJECT (demux, "ClusterPrevSize: %" G_GUINT64_FORMAT, num); + demux->cluster_prevsize = num; + demux->seen_cluster_prevsize = TRUE; + break; + } case GST_MATROSKA_ID_POSITION: - case GST_MATROSKA_ID_PREVSIZE: case GST_MATROSKA_ID_ENCRYPTEDBLOCK: case GST_MATROSKA_ID_SILENTTRACKS: GST_DEBUG_OBJECT (demux, @@ -5245,6 +5259,7 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstObject * parent, demux->common.segment.position = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; + demux->cluster_prevsize = 0; demux->need_segment = TRUE; demux->segment_seqnum = gst_event_get_seqnum (event); /* but keep some of the upstream segment */ @@ -5297,6 +5312,7 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstObject * parent, demux->common.segment.duration = dur; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; + demux->cluster_prevsize = 0; GST_OBJECT_UNLOCK (demux); /* fall-through */ } diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index 2fe248b455..1e0826f2b8 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -84,6 +84,7 @@ typedef struct _GstMatroskaDemux { /* some state saving */ GstClockTime cluster_time; guint64 cluster_offset; + guint64 cluster_prevsize; /* 0 if unknown */ guint64 first_cluster_offset; guint64 next_cluster_offset; GstClockTime requested_seek_time; @@ -105,6 +106,15 @@ typedef struct _GstMatroskaDemux { GArray *seek_index; gint seek_entry; + gboolean seen_cluster_prevsize; /* We track this because the + * first cluster won't have + * this set, so we can't just + * check cluster_prevsize to + * determine if it's there + * or not. We assume if one + * cluster has it, all but + * the first will have it. */ + /* gap handling */ guint64 max_gap_time;