[PATCH] queue2: Process SEEKING query

Jan Alexander Steffens (heftig) jan.steffens at gmail.com
Fri Jul 18 04:32:06 PDT 2014


In order to seek FLV streams, flvdemux creates a seek index;
however, this index is not created if upstream is not seekable.
gst_flv_demux_check_seekability was copied nearly verbatim from
GstBaseParse.

This commit adds QUERY_SEEKING handling to queue2, so RTMP live
streams become seekable when a queue2 in download or ringbuffer
mode is inserted:

rtmpsrc ! queue2 ! flvdemux

Alternatively, flvdemux could be altered to not require
seekability. I am unsure what is the best approach.
---
 plugins/elements/gstqueue2.c | 52 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/plugins/elements/gstqueue2.c b/plugins/elements/gstqueue2.c
index 144c684..fcc3cdc 100644
--- a/plugins/elements/gstqueue2.c
+++ b/plugins/elements/gstqueue2.c
@@ -3000,6 +3000,58 @@ gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
       gst_query_add_scheduling_mode (query, GST_PAD_MODE_PUSH);
       break;
     }
+    case GST_QUERY_SEEKING:
+    {
+      GstFormat format;
+      gboolean peer_success, upstream_seekable, queue_seekable;
+      gint64 segment_start, segment_end;
+
+      peer_success = gst_pad_peer_query (queue->sinkpad, query);
+
+      gst_query_parse_seeking (query,
+          &format, &upstream_seekable, &segment_start, &segment_end);
+
+      queue_seekable =
+          (format == GST_FORMAT_BYTES && !QUEUE_IS_USING_QUEUE (queue));
+
+      if (peer_success) {
+        if (upstream_seekable) {
+          GST_DEBUG_OBJECT (queue, "upstream seekable (%s)"
+              " from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT,
+              gst_format_get_name (format), segment_start, segment_end);
+          break;
+        }
+
+        if (!queue_seekable) {
+          GST_DEBUG_OBJECT (queue, "both upstream and queue unseekable");
+          break;
+        }
+      } else {
+        if (!queue_seekable) {
+          GST_DEBUG_OBJECT (queue,
+              "upstream query failed and queue unseekable");
+          goto peer_failed;
+        }
+
+        upstream_seekable = FALSE;
+        segment_start = 0;
+        segment_end = -1;
+
+        GST_DEBUG_OBJECT (queue, "doing duration query to discover seek end");
+        gst_pad_peer_query_duration (queue->sinkpad, format, &segment_end);
+
+        if (segment_end < 0) {
+          GST_DEBUG_OBJECT (queue, "fixing seekable segment to maximum");
+          segment_end = G_MAXINT64;
+        }
+      }
+
+      GST_DEBUG_OBJECT (queue, "queue seekable from %" G_GINT64_FORMAT
+          " to %" G_GINT64_FORMAT, segment_start, segment_end);
+
+      gst_query_set_seeking (query, format, TRUE, segment_start, segment_end);
+      break;
+    }
     default:
       /* peer handled other queries */
       if (!gst_pad_query_default (pad, parent, query))
-- 
2.0.1



More information about the gstreamer-devel mailing list