From 9d6621a30dad77b69afd24e6b25792a2dcf78da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 15 Aug 2018 12:53:34 +0100 Subject: [PATCH] matroskademux: implement keyframe search also without cluster prev size If we have cluster prev size (GStreamer muxer will write it by default), we can go back to the previous cluster efficiently, but if we don't then just search backwards until we find a cluster ebml identifier, like we do when searching for clusters in the bisection loop. --- gst/matroska/matroska-demux.c | 37 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 5f94c6038e..b7e13bb801 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -2250,11 +2250,6 @@ gst_matroska_demux_scan_back_for_keyframe_cluster (GstMatroskaDemux * demux, GST_DEBUG_OBJECT (demux, "Cluster starts with delta frame, backtracking"); - if (cluster.prev_size == 0 || cluster.prev_size > off) { - GST_LOG_OBJECT (demux, "Cluster has no or invalid prev size, stopping"); - break; - } - /* Don't scan back more than this much in time from the cluster we * originally landed on. This is mostly a sanity check in case a file * always has keyframes in the middle of clusters and never at the @@ -2271,7 +2266,24 @@ gst_matroska_demux_scan_back_for_keyframe_cluster (GstMatroskaDemux * demux, } } - off -= cluster.prev_size; + /* If we have cluster prev_size we can skip back efficiently. If not, + * we'll just do a brute force search for a cluster identifier */ + if (cluster.prev_size > 0 && off >= cluster.prev_size) { + off -= cluster.prev_size; + } else { + GstFlowReturn flow; + + GST_LOG_OBJECT (demux, "Cluster has no or invalid prev size, searching " + "for previous cluster instead then"); + + flow = gst_matroska_demux_search_cluster (demux, &off, FALSE); + if (flow != GST_FLOW_OK) { + GST_DEBUG_OBJECT (demux, "cluster search yielded flow %s, stopping", + gst_flow_get_name (flow)); + break; + } + } + if (off <= first_cluster_offset) { GST_LOG_OBJECT (demux, "Reached first cluster, stopping"); *cluster_offset = first_cluster_offset; @@ -2507,15 +2519,10 @@ retry: * that starts with a keyframe - and if not backtrack until we find one that * does. */ if (demux->have_nonintraonly_v_streams && demux->max_backtrack_distance > 0) { - if (demux->seen_cluster_prevsize) { - if (gst_matroska_demux_scan_back_for_keyframe_cluster (demux, - &cluster_offset, &cluster_time)) { - GST_INFO_OBJECT (demux, "Adjusted cluster to %" GST_TIME_FORMAT " @ " - "%" G_GUINT64_FORMAT, GST_TIME_ARGS (cluster_time), cluster_offset); - } - } else { - GST_FIXME_OBJECT (demux, "implement scanning back to prev cluster " - "without cluster prev size field"); + if (gst_matroska_demux_scan_back_for_keyframe_cluster (demux, + &cluster_offset, &cluster_time)) { + GST_INFO_OBJECT (demux, "Adjusted cluster to %" GST_TIME_FORMAT " @ " + "%" G_GUINT64_FORMAT, GST_TIME_ARGS (cluster_time), cluster_offset); } }