Search code examples
video-streamingdelaygstreamer

Gstreamer: increase and decrease delay on-the-fly


I have a GStreamer pipeline to play live video from RTSP source. I want the user to be able to increase / decrease the delay. My approach to this is to have a queue element and manipulate its min-threshold-time parameter.

This seems to work at start. On for instance 10 seconds delay, The pipeline starts frozen, and continues after 10 seconds. But if I manipulate the time, nothing happens. I have tried other parameters as well, like max-size-time, without luck. leaky parameter causes the video to be jerky and bad quality.

Currently I am stopping and re-starting the pipeline, which looks terrible.

Pipeline I am using:

gst-launch-1.0 rtspsrc location=<...> ! rtph264depay ! h264parse ! capsfilter caps=video/x-h264 ! avdec_h264 ! videoconvert ! queue min-threshold-delay=<delay> ! autovideosink

Is there a command to force queue to flush the frames, some other element better suitable, or some other trick to accomplish this?


Solution

  • Got it working. Here's my solution:

    Pipeline:

    rtspsrc location=<...> ! rtph264depay ! queue max-size-buffers=0 max-size-bytes=0 max-size-time=$MAX_DELAY ! queue max-size-time=$SMALL_DELAY min-threshold-time=$DELAY ! decodebin ! autovideosink
    

    where:

    • $DELAY = video delay in gst time units
    • $MAX_DELAY = maximum video delay in gst time units
    • $SMALL_DELAY = a minimum delay, for instance like one millisecond, in gst time units

    The strategy is to have two queues, where the first one acts as a buffer, and the second acts as a balancer that ensures all messages are delayed exactly $DELAY amount of time. This can not be accomplished using one queue.

    Runtime:

    When the delay needs to be changed, the $DELAY value is changed on the second queue. After this, the pipeline needs to be sent a latency event using the new delay as latency. This causes the pipeline either freeze for a moment (if delay is increased), or to fast forward to catch up (if delay is decreased).

    Buffering status can be obtained by reading current-level-time property on the first queue and comparing it to delay that was set.