After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 746808 - Queue with min-threshold stalls dynamic pipeline
Queue with min-threshold stalls dynamic pipeline
Status: RESOLVED WONTFIX
Product: GStreamer
Classification: Platform
Component: gstreamer (core)
git master
Other Linux
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2015-03-26 11:40 UTC by Jesper Larsen
Modified: 2015-04-06 21:50 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test application that stalls the pipeline (2.37 KB, text/x-csrc)
2015-03-26 11:40 UTC, Jesper Larsen
  Details
deprecate min-threshold-* (3.49 KB, patch)
2015-04-06 16:24 UTC, Vincent Penquerc'h
none Details | Review

Description Jesper Larsen 2015-03-26 11:40:50 UTC
Created attachment 300348 [details]
Test application that stalls the pipeline

I'm not 100% sure whether this is a bug or a mistake on my part. I have attached the test application I'm using.

I have a pipeline that looks like this

audiotestsrc is-live=true ! queue min-threshold-time=3s ! fakesink

Running that pipeline works as I expect. The pipeline position stays at 0 while the level in the buffer is filling to 3s, and then the pipeline position starts to increase.

Now, I want to change the sink at some point, keeping the cached data in the queue. 8 seconds after starting the pipeline, I add a blocking probe to the srcpad of the queue.

In the probe callback I do the following:
1. Set the state of the sink to NULL
2. Remove the sink from the pipeline
3. Add a second fakesink element to the pipeline
4. Link the queue and the second fakesink
5. Sync the state of the second fakesink to the pipeline

I would expect the pipeline to continue running with the new sink in place.

What I'm actually seeing is that the sink is prerolled with a single buffer, and then nothing more happens. The queue is not getting any buffers even though all elements in the pipeline reports as PLAYING, if I save a dot graph.

If I don't set min-threshold on the queue, data is flowing after I have changed the sink.
Comment 1 Vincent Penquerc'h 2015-04-02 16:47:06 UTC
It seems to be working here at first glance:

Buit with:
gcc `pkg-config --cflags gstreamer-1.0 glib-2.0 gobject-2.0`  -o minimal minimal.c `pkg-config --libs gstreamer-1.0 glib-2.0 gobject-2.0`

Run with:
./minimal

Typical output:
$ ./minimal 
Pipeline position: 0:00:01.626144737, Queue level: 0:00:00.000000000
Pipeline position: 0:00:02.624602787, Queue level: 0:00:00.000000000
Pipeline position: 0:00:03.623060837, Queue level: 0:00:00.000000000
Pipeline position: 0:00:04.621518887, Queue level: 0:00:00.000000000
Pipeline position: 0:00:05.619976936, Queue level: 0:00:00.000000000
Pipeline position: 0:00:06.618434986, Queue level: 0:00:00.000000000
Pipeline position: 0:00:07.616893036, Queue level: 0:00:00.000000000
Pipeline position: 0:00:00.000000000, Queue level: 0:00:00.000000000
Pipeline position: 0:00:09.613809136, Queue level: 0:00:00.000000000
Pipeline position: 0:00:10.612267186, Queue level: 0:00:00.000000000
Pipeline position: 0:00:11.610725236, Queue level: 0:00:00.000000000
Pipeline position: 0:00:12.609183286, Queue level: 0:00:00.023219955
^C

If I run with GST_DEBUG=*SCHED*:9, I see buffers flowing to the sink well after the 8 second mark.

Is this not what you're seeing, or am I misunderstanding what you're describing ?
Comment 2 Jesper Larsen 2015-04-02 20:09:25 UTC
I accidentally uploaded the file where I have set min-threshold-time to 0. Sorry about that.

For a min-threshold-time of 0 I can confirm your findings above.

The problem appears when min-threshold-time is set to a non-zero value.
Try changing line 21 to

g_object_set (queue, "min-threshold-time", 3 * GST_SECOND,

I get this output

Pipeline position: 0:00:00.000000000, Queue level: 0:00:00.836485486
Pipeline position: 0:00:00.000000000, Queue level: 0:00:01.834943536
Pipeline position: 0:00:00.000000000, Queue level: 0:00:02.833401586
Pipeline position: 0:00:00.813265531, Queue level: 0:00:02.995374150
Pipeline position: 0:00:01.834943536, Queue level: 0:00:02.995374150
Pipeline position: 0:00:02.833401586, Queue level: 0:00:02.995374150
Pipeline position: 0:00:03.831859636, Queue level: 0:00:02.995374150
Pipeline position: 0:00:00.038213632, Queue level: 0:00:02.995374150
Pipeline position: 0:00:04.853537640, Queue level: 0:00:02.995374149
Pipeline position: 0:00:04.853537640, Queue level: 0:00:02.995374149
Pipeline position: 0:00:04.853537640, Queue level: 0:00:02.995374149
Pipeline position: 0:00:04.853537640, Queue level: 0:00:02.995374149
Pipeline position: 0:00:04.853537640, Queue level: 0:00:02.995374149

Notice have neither the queue level nor the position is increasing.
Comment 3 Vincent Penquerc'h 2015-04-03 08:54:43 UTC
I get the same stalling behavior as you now.
Comment 4 Vincent Penquerc'h 2015-04-03 13:58:34 UTC
What seems to be happening is that an allocation query is sent from the source after the second sink is plugged, and is pushed onto the queue's, er, queue.

Normally, the queue's thread will push whatever's in the queue's queue if possible. If the first item is not a buffer or buffer list (for instance, if it is an allocation query), it will be sent. However, in this case, the allocation query is at the end of the queue's queue, which happens not to be its head too as there's close to 3 seconds' worth of buffers waiting there. One more buffer incoming would cause the queue to push again, but it's now waiting for the allocation query to be answered from upstream, which it won't since the push thread isn't pushing.

I can't clear the queue, as it would drop those three seconds. Maybe I could slip the allocation query in front of the queue, which would work I think, but I'm not sure how best to select which set of events/queries to prepend instead of append. In general, we want to keep ordering between buffers and events. Worse, gst/gstquery.h shows the allocation query to be serialized.

Another possibility would be to temporarily disregard the min-threshold when an allocation query (and maybe a set of other events/queries) is received, until this query (or other event/query) has been pushed by the queue's thread. This would seem to be like a good compromise, but (1) might upset whatever caused min-threshold to be used (unfluid playback ?), and (2) would also need to choose which set of events/queries would cause this temporary override.

Any gst maintainer with an opinion on this ?
Comment 5 Tim-Philipp Müller 2015-04-03 15:31:52 UTC
It looks like expected behaviour to me.

Jesper, what are you trying to achieve here exactly?
Comment 6 Jesper Larsen 2015-04-03 15:45:57 UTC
I'm trying to do a "delayed" recording of a live source. Meaning that I want to keep x seconds of buffer such that I can start saving buffers to file where the first buffer saved would be from x seconds ago.

What seems odd is that the queue is not getting fed with buffers from the live source. When the pipeline is first started, the queue is not forwarding buffers until it reaches the min-threshold. However, the queue is receiving buffers. If the sink is changed the queue no longer receives buffers, which means it never pushes buffers to the new sink.

I currently workaround this by setting the min-threshold to 0 when the sink is changed, and then resetting the min-threshold to x seconds when the new sink reaches PLAYING. I guess this is basically the same Vincent suggests by temporarily disregarding the min-threshold.
Comment 7 Tim-Philipp Müller 2015-04-03 16:01:38 UTC
It sounds like what you want is basically a 'backbuffer'. When you start recording, you want to include data from a few seconds before the record button was hit.

http://people.freedesktop.org/~tpm/code/test-backlog-recording-h264.c

Implements that using a different approach: it uses a leaky queue with a pad block. While the pad is blocked, old buffers are getting dropped. The same should happen to any allocation query in that case.
Comment 8 Jesper Larsen 2015-04-03 16:19:00 UTC
Thanks for the link. It seems to be a better approach than my current workaround.

The current min-threshold behaviour still seems odd to me though, but at least I can work around it.
Comment 9 Vincent Penquerc'h 2015-04-06 08:58:33 UTC
It still seems wrong to be that the queue hangs, as the reconfigure query is an implementation detail from the point of view of the min-threshold high level behavior.
Comment 10 Tim-Philipp Müller 2015-04-06 10:16:26 UTC
The allocation query is serialised. That causes some problems, but also solves some other problems. In any case, that's how it is. I don't see what we can do here. (I also think we should deprecate that min-threshold property)
Comment 11 Vincent Penquerc'h 2015-04-06 16:24:17 UTC
Created attachment 301030 [details] [review]
deprecate min-threshold-*

Here's a patch that deprecates those properties as you suggested.
And then this can be closed as invalid.
Comment 12 Tim-Philipp Müller 2015-04-06 21:50:54 UTC
More like WONTFIX than INVALID :)

But I'd like to hear from more people before deprecating that property.