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 686459 - pulsesink: playbin uri=x.mp3 audio-sink='identity ! pulsesink' => not-negotiated flow error
pulsesink: playbin uri=x.mp3 audio-sink='identity ! pulsesink' => not-negotia...
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-good
git master
Other Linux
: Normal blocker
: 1.1.2
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2012-10-19 12:16 UTC by Tim-Philipp Müller
Modified: 2013-06-13 09:12 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
pulsesink: Take a lock on the ringbuffer in acceptcaps (1017 bytes, patch)
2013-05-27 05:48 UTC, Arun Raghavan
committed Details | Review
pulsesink: Get rid of acceptcaps side-effects (6.52 KB, patch)
2013-05-27 05:48 UTC, Arun Raghavan
committed Details | Review
pulsesink: Add a getcaps function (12.26 KB, patch)
2013-05-27 05:49 UTC, Arun Raghavan
needs-work Details | Review
pulsesink: Cache the getcaps/acceptcaps probe stream (6.79 KB, patch)
2013-05-27 05:49 UTC, Arun Raghavan
accepted-commit_now Details | Review
pulsesink: Add a getcaps function (12.84 KB, patch)
2013-06-06 13:36 UTC, Arun Raghavan
needs-work Details | Review
pulsesink: Add a getcaps function (13.68 KB, patch)
2013-06-10 07:31 UTC, Arun Raghavan
committed Details | Review
pulsesink: Cache the getcaps/acceptcaps probe stream (7.04 KB, patch)
2013-06-10 07:32 UTC, Arun Raghavan
committed Details | Review
Require libpulse >= 2.0 for pa_format_info_get_prop_* functions. (719 bytes, patch)
2013-06-12 23:15 UTC, Brendan Long
none Details | Review
pulsesink: Make 2.0 dependency optional (2.89 KB, patch)
2013-06-13 07:14 UTC, Arun Raghavan
committed Details | Review

Description Tim-Philipp Müller 2012-10-19 12:16:44 UTC
$ gst-launch-1.0 playbin uri=file:///foo.mp3 audio-sink='identity ! pulsesink'
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstMpegAudioParse:mpegaudioparse0: GStreamer encountered a general stream error.
Additional debug info:
gstbaseparse.c(3008): gst_base_parse_loop (): /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstMpegAudioParse:mpegaudioparse0:
streaming stopped, reason not-negotiated

pulsesink has mp3 in its template caps, but doesn't accept them via accept-caps. query_caps() on the sink pad seems to return caps containing mp3 as well, which seems wrong (the selected output in pulse is laptop speakers).
Comment 1 Wim Taymans 2012-10-24 09:35:34 UTC
The reason why it doesn't work with a basetransform in between is because basetransform doesn't forward the ACCEPT_CAPS query but it does a getcaps and _is_subset().
Comment 2 Tim-Philipp Müller 2012-10-24 10:11:24 UTC
Yes, I think get_caps is missing (or broken).
Comment 3 Arun Raghavan 2013-05-27 05:48:53 UTC
Created attachment 245366 [details] [review]
pulsesink: Take a lock on the ringbuffer in acceptcaps

This is neede as a concurrent state change could pull the context or
stream out from under our feet.
Comment 4 Arun Raghavan 2013-05-27 05:48:59 UTC
Created attachment 245367 [details] [review]
pulsesink: Get rid of acceptcaps side-effects

The sink info callback should not have side-effects on the GstPulseSink
object since we are sometimes using with a dummy stream in acceptcaps.
Comment 5 Arun Raghavan 2013-05-27 05:49:04 UTC
Created attachment 245368 [details] [review]
pulsesink: Add a getcaps function

this allows us to have more fine-tuned caps in READY or above. However,
this is _really_ inefficient since we create a new stream and query sink
for every getcaps in READY, which on a simple gst-launch line happens
about 35 times. The next step is to cache getcaps results.
Comment 6 Arun Raghavan 2013-05-27 05:49:09 UTC
Created attachment 245369 [details] [review]
pulsesink: Cache the getcaps/acceptcaps probe stream

getcaps is called frequently during stream setup, and creating a new
stream each time is very inefficient. There's some more room for
optimisation by caching the queried sink formats as well, but this needs
some more changes to listen for format changes on the sink as well (for
when supported formats change between probe stream creation and sink
querying).
Comment 7 Sebastian Dröge (slomo) 2013-05-27 09:34:36 UTC
Review of attachment 245366 [details] [review]:

Seems a bit risky to hold the object lock that long over that many function calls. Did you check that nothing called there can ever take the object lock itself, and that there's no lock order inversion anywhere (you introduce object_lock > mainloop lock here)
Comment 8 Sebastian Dröge (slomo) 2013-05-27 09:54:31 UTC
Review of attachment 245368 [details] [review]:

::: ext/pulse/pulsesink.c
@@ +2021,3 @@
+          /* raw formats PA supports == raw formats GST supports, so skip
+           * setting formats (FIXME?) */
+          ret = gst_caps_from_string ("audio/x-raw");

gst_caps_new_empty_simple()

Could you also use the GstAudioInfo caps creation function here? There are some fields missing here :)

@@ +2053,3 @@
+
+  if (pa_format_info_get_prop_int (format, PA_PROP_FORMAT_RATE, &rate) == 0)
+    gst_caps_set_simple (ret, "rate", G_TYPE_INT, rate, NULL);

Should always have rate and channels set, in the worst case the [1,MAX] range. Alternatively intersect with the template caps afterwards

@@ +2131,3 @@
+  }
+
+  if (!pbuf->stream) {

It should only create a stream and do all that when in >=READY state

@@ +2141,3 @@
+    pa_format_info_set_sample_format (format, PA_SAMPLE_S16LE);
+    pa_format_info_set_rate (format, GST_AUDIO_DEF_RATE);
+    pa_format_info_set_channels (format, GST_AUDIO_DEF_CHANNELS);

Can using this format ever fail although in general stuff would work?
Comment 9 Arun Raghavan 2013-05-30 13:08:32 UTC
(In reply to comment #7)
> Review of attachment 245366 [details] [review]:
> 
> Seems a bit risky to hold the object lock that long over that many function

I couldn't think of a better way to deal with the problem of making sure that only the real stream or probe stream can exist at any given time.

That said, there's potential to improve the lock granularity by dropping the object lock once the probe stream is set up. I'll try to hack this up shortly.

> calls. Did you check that nothing called there can ever take the object lock
> itself, and that there's no lock order inversion anywhere (you introduce
> object_lock > mainloop lock here)

The only callers of GST_OBJECT_LOCK within that file are the ones I've added. All other locks on the object are taken at the GstAudioRingBuffer class level so the object lock -> mainloop lock order should always hold.
Comment 10 Arun Raghavan 2013-06-06 10:51:32 UTC
(In reply to comment #8)
> Review of attachment 245368 [details] [review]:
> 
> ::: ext/pulse/pulsesink.c
> @@ +2021,3 @@
> +          /* raw formats PA supports == raw formats GST supports, so skip
> +           * setting formats (FIXME?) */
> +          ret = gst_caps_from_string ("audio/x-raw");
> 
> gst_caps_new_empty_simple()
> 
> Could you also use the GstAudioInfo caps creation function here? There are some
> fields missing here :)

I've fixed this and the next comment a little differently (and IMO less messily). Patch coming soon.

> @@ +2053,3 @@
> +
> +  if (pa_format_info_get_prop_int (format, PA_PROP_FORMAT_RATE, &rate) == 0)
> +    gst_caps_set_simple (ret, "rate", G_TYPE_INT, rate, NULL);
> 
> Should always have rate and channels set, in the worst case the [1,MAX] range.
> Alternatively intersect with the template caps afterwards

See previous note.

> @@ +2131,3 @@
> +  }
> +
> +  if (!pbuf->stream) {
> 
> It should only create a stream and do all that when in >=READY state

When we get to this point, we know we're in READY because there is a pbuf->context.

> @@ +2141,3 @@
> +    pa_format_info_set_sample_format (format, PA_SAMPLE_S16LE);
> +    pa_format_info_set_rate (format, GST_AUDIO_DEF_RATE);
> +    pa_format_info_set_channels (format, GST_AUDIO_DEF_CHANNELS);
> 
> Can using this format ever fail although in general stuff would work?

It really should not. Eventually, as the comment notes, I'd like to be able to connect with an "ANY" format. This needs some fixes with how the formats handling happens in PulseAudio, which I am doing independently.
Comment 11 Sebastian Dröge (slomo) 2013-06-06 12:47:14 UTC
(In reply to comment #9)

> > calls. Did you check that nothing called there can ever take the object lock
> > itself, and that there's no lock order inversion anywhere (you introduce
> > object_lock > mainloop lock here)
> 
> The only callers of GST_OBJECT_LOCK within that file are the ones I've added.
> All other locks on the object are taken at the GstAudioRingBuffer class level
> so the object lock -> mainloop lock order should always hold.

Note that various GStreamer functions can take the object lock too, like gst_object_get_parent() ;)

But if you checked all this I'm fine with the patch
Comment 12 Arun Raghavan 2013-06-06 13:36:34 UTC
Created attachment 246160 [details] [review]
pulsesink: Add a getcaps function

this allows us to have more fine-tuned caps in READY or above. However,
this is _really_ inefficient since we create a new stream and query sink
for every getcaps in READY, which on a simple gst-launch line happens
about 35 times. The next step is to cache getcaps results.
Comment 13 Sebastian Dröge (slomo) 2013-06-06 14:15:17 UTC
Review of attachment 246160 [details] [review]:

Looks good, can be pushed after fixing the second comment and if you think nothing else is missing

::: ext/pulse/pulsesink.c
@@ +2053,3 @@
+    gst_caps_set_simple (ret, "channels", G_TYPE_INT, channels, NULL);
+
+  /* FIXME: add channel map */

What's missing to implement that?

@@ +2222,3 @@
 
+  pad_caps = gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (psink));
+  ret = gst_caps_can_intersect (pad_caps, caps);

Should be gst_caps_is_subset(caps, pad_caps)

@@ +2300,3 @@
   } else {
     /* We're in READY, let's connect a stream to see if the format is
+     * accepted by whatever sink we're routed to */

Even fixed a typo ;)
Comment 14 Arun Raghavan 2013-06-10 07:31:41 UTC
Created attachment 246381 [details] [review]
pulsesink: Add a getcaps function

(updated to be able to read rate/channels as int array or range as well)
Comment 15 Arun Raghavan 2013-06-10 07:32:19 UTC
Created attachment 246382 [details] [review]
pulsesink: Cache the getcaps/acceptcaps probe stream

(updated to wait for probe destruction before creating the actual stream, else
compressed streams will fail to be created)
Comment 16 Arun Raghavan 2013-06-10 07:55:25 UTC
The following fixes have been pushed:
Comment 17 Brendan Long 2013-06-12 23:15:13 UTC
Created attachment 246676 [details] [review]
Require libpulse >= 2.0 for pa_format_info_get_prop_*
 functions.


The pa_format_info_get_prop_* functions were added in libpulse 2.0 (http://freedesktop.org/software/pulseaudio/doxygen/format_8h.html#aae6ab2ad009c17d0f999ce1011d99f08), so commit 14e784f9fc629af4c33b41dae159aa5060fb8f5f makes gst-plugins-good not build on Ubuntu 12.04:

  CC     libgstpulse_la-pulseutil.lo
pulsesink.c: In function 'gst_pulse_format_info_int_prop_to_value':
pulsesink.c:2028:3: error: implicit declaration of function 'pa_format_info_get_prop_int' [-Werror=implicit-function-declaration]
pulsesink.c:2028:3: error: nested extern declaration of 'pa_format_info_get_prop_int' [-Werror=nested-externs]
pulsesink.c:2032:3: error: implicit declaration of function 'pa_format_info_get_prop_int_array' [-Werror=implicit-function-declaration]
pulsesink.c:2032:3: error: nested extern declaration of 'pa_format_info_get_prop_int_array' [-Werror=nested-externs]
pulsesink.c:2043:3: error: implicit declaration of function 'pa_format_info_get_prop_int_range' [-Werror=implicit-function-declaration]
pulsesink.c:2043:3: error: nested extern declaration of 'pa_format_info_get_prop_int_range' [-Werror=nested-externs]
pulsesink.c: In function 'gst_pulse_format_info_to_caps':
pulsesink.c:2066:7: error: implicit declaration of function 'pa_format_info_to_sample_spec' [-Werror=implicit-function-declaration]
pulsesink.c:2066:7: error: nested extern declaration of 'pa_format_info_to_sample_spec' [-Werror=nested-externs]
pulsesink.c:2068:7: error: implicit declaration of function 'pa_format_info_get_prop_string' [-Werror=implicit-function-declaration]
pulsesink.c:2068:7: error: nested extern declaration of 'pa_format_info_get_prop_string' [-Werror=nested-externs]

This patch just requires libpulse >= 2.0, since that will fix the build. It may be nicer to keep building pulsesink and just use the old behavior if PA_MAJOR < 2.
Comment 18 Sebastian Dröge (slomo) 2013-06-13 06:43:18 UTC
Instead of this it looks possible to just conditionally disable the new stuff added by this patch if PA < 2.0 is used.
Comment 19 Arun Raghavan 2013-06-13 07:14:31 UTC
The following fix has been pushed:
0145702 pulsesink: Make 2.0 dependency optional

Thanks for the patch, Brendan. I've made the 2.0 optional instead for now,
since it's "only" a year old. :)


 functions.
 - none
Comment 20 Arun Raghavan 2013-06-13 07:14:39 UTC
Created attachment 246685 [details] [review]
pulsesink: Make 2.0 dependency optional

The getcaps function we added uses some pa_format_info_get_prop...
accessor functions that were only added in 2.0, so we only have our
getcaps implementation exist if we're compiling against libpulse 2.0 or
above.

Eventually, we could bump the minimum requirement to 2.0 or above.
Comment 21 Tim-Philipp Müller 2013-06-13 08:36:17 UTC
I don't think this is a good/complete fix like this.

If I understand it right, now this bug continues to exist if pulseaudio < 2.0 is used, and it's only fixed in newer pulseaudio? If that is true, then we should remove all passthrough support for older pulseaudio versions IMHO, so this breakage doesn't happen.
Comment 22 Arun Raghavan 2013-06-13 08:46:12 UTC
(In reply to comment #21)
> I don't think this is a good/complete fix like this.
> 
> If I understand it right, now this bug continues to exist if pulseaudio < 2.0
> is used, and it's only fixed in newer pulseaudio? If that is true, then we
> should remove all passthrough support for older pulseaudio versions IMHO, so
> this breakage doesn't happen.

That's fair, but then I think the resulting change would be larger than is worth supporting for the gain of supporting older versions. Maybe we /should/ then just bump the requirement to 2.0.
Comment 23 Arun Raghavan 2013-06-13 09:12:42 UTC
Reverted my patch and applied Brendan's with some modification for the commit message. We now depend on PulseAudio >= 2.0 unconditionally.