Segment seeking on various sources - Streaming mode/random-access

Hello everyone!

I have a looping element which does segment seeking on a parsebin, taking in an an arbitrary source. Works well when using filesrc, but I have also tried using source’s like urisourcebin and videotestsrc non-live with a set amount of buffers.

Both sources have a duration and are seekable when querying.
But I have issues:

  1. urisourcebin get <matroskademux0>e[00m Segment seek not supported in streaming mode
  2. videotestsrc gets stuck in an infinite seek, segment-done loop.

Lets look at the urisourcebin issue. It seems to be because we operate in push (streaming mode)

      if (!demux->streaming)
        res = gst_matroska_demux_handle_seek_event (demux, pad, event);
      else
        res = gst_matroska_demux_handle_seek_push (demux, pad, event);

the __seek_push branch does not allow for non-flushing seeks.

How pipe looks when using the element exemple:
gst-launch-1.0 urisourcebin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.mkv ! parsebinloop ! decodebin ! queue ! videoconvert ! autovideosink

If the issue is that the urisourcebin operates in push-mode and filesrc in pull-mode is it possible to change behaviour of source to operate as in pull–mode?
I’m thinking maybe a “non-consuming” queue inbetween with a max amount of buffers that the demuxer can pull from and perform easy seeking, but have not gotten something like that to work.

tldr; conditions to make segment seeking work for other sources?

Any guidance is super appreciate! Thanks!

There’s a mode where it plugs a queue2 element or downloadbuffer element which can “translate” from push to pull mode in front of a demuxer.

You can try setting urisourcebin ring-buffer-max-size=... (to something generous, like MBs). Not sure if you need the download property as well.

Will only work if server announces a content-size though and supports seeking (range requests).

Get error when running with the property, without using custom element.
ex. gst-launch pipe

gst-launch-1.0 urisourcebin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.mkv ring-buffer-max-size=2000000 download=true ! decodebin ! queue ! videoconvert ! autovideosink
(gst-launch-1.0:1822): GStreamer-CRITICAL **: 12:34:52.127: pushing on pad typefind:src but it was not activated in push mode

(gst-launch-1.0:1822): GStreamer-WARNING **: 12:34:52.127: 
Trying to join task 0x7f78718f0800 from its thread would deadlock.
You cannot change the state of an element from its streaming
thread. Use g_idle_add() or post a GstMessage on the bus to
schedule the state change from the main thread.

But even if, this is exactly what I want but I think it would be nicer if driven by the parsebinloop element.

inkpads can be the driving force behind a pipeline by operating in pull-mode, while the sourcepads of the element still operate in push-mode
from the pad activation stage

You think that might work for this setup? Haven’t found an element that uses that technique yet, nice for some inspiration

Just to double check: What’s your GStreamer version?

I can reproduce your critical with 1.24.7 and decodebin, but it goes away with decodebin3 it seems:

This works well for me:

gst-launch-1.0 urisourcebin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.mkv ring-buffer-max-size=2000000 download=true ! decodebin3 ! queue ! videoconvert ! navseek ! autovideosink

(navseek will catch right-arrow/left-arrow for seeking if the video sink picked is one that supports navigation events like ximagesink/xvimagesink)

1 Like

You could push the problem to the users of the element by stating that it requires a source that can handle segment seeks or non-flushing seeks? And allowing for passing properties to the source?

Thanks for the help both of you!

After some meditation I have some follow-ups. The ring-buffer critical error happens for parsebin as well which I depend on. My element is inbetween the decodebin.
But the implementation for the ring-buffer is still interesting! So attempting to do same within my element.
ex.

gst-launch-1.0 urisourcebin uri=*url* ! parsebinloop ! \
decodebin3 ! queue ! videoconvert ! navseek ! autovideosink

where parsebinloop is basically:

downloadbuffer ! parsebin

(attempted with queue2 as well)

It just gets stuck and I get no buffers to the parsebin.

In the demux_sink_activate() it will seek query upstream. If succesfull it will go into pull mode else push/stream-mode.
In pull-mode I expect we should be able to do seeking and get buffers from downloadbuffer element.

At glance, can you see something missing from this setup?

downloadbuffer notes:

The downloadbuffer provides push and pull based scheduling on its source pad and will efficiently seek in the upstream element when needed.

I assume here if we seek within bounds of downloadbuffer it will perform the seeking