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 696675 - basesink: state change issue when adding alsasink dynamically
basesink: state change issue when adding alsasink dynamically
Status: RESOLVED DUPLICATE of bug 702282
Product: GStreamer
Classification: Platform
Component: gstreamer (core)
1.0.6
Other Linux
: Normal normal
: git master
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2013-03-27 08:41 UTC by Paul HENRYS
Modified: 2013-07-24 09:37 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Trace (6.30 KB, application/octet-stream)
2013-03-27 08:41 UTC, Paul HENRYS
  Details
Patch (1.40 KB, patch)
2013-03-27 08:41 UTC, Paul HENRYS
needs-work Details | Review

Description Paul HENRYS 2013-03-27 08:41:21 UTC
Created attachment 239930 [details]
Trace

While using alsasink element in a bin in a dynamic pipeline, I faced an issue when this bin selecting alsasink is already in PLAYING state. In such a case, alsasink might block in GST_BASE_SINK_PREROLL_WAIT() in gst_base_sink_wait_preroll().
Indeed, if the bin is already in PLAYING state and alsasink's state is synchronized on its parent, the pending state will be playing. Then, if gst_base_sink_do_preroll() is called before ASYNC set states have been performed, it will commit the state to PLAYING. Doing this, will prevent from calling gst_audio_base_sink_change_state() where important things are performed. Indeed, in the transition from pause to playing, gst_audio_ring_buffer_may_start() is called and set to true, and because it does not pass through this step in the conditions described above, it will block in preroll_wait.
Indeed, in gst_base_sink_chain_unlocked(), after committing to PLAYING state, render function of gstaudiobasesink is called and there it tries to render the buffer and write it in the ringbuffer which has not been started (gst_audio_base_sink_change_state() not called), the condition written==samples is not satisfied, gst_base_sink_wait_preroll() is called and it is stuck there.

In the patch in attachment, I added the call to gst_element_change_state() in gst_base_sink_commit_state() when committing to PLAYING state. It is not necessary to call it when committing to PAUSE state as the method is called before returning GST_STATE_CHANGE_ASYNC from the function setting the state.
I am not sure so far if this is a correct solution and comments would be greatly appreciated :)
Comment 1 Paul HENRYS 2013-03-27 08:41:55 UTC
Created attachment 239931 [details] [review]
Patch
Comment 2 Wim Taymans 2013-04-03 10:33:38 UTC
It does indeed not call the state_change function and it should do that.

I think your patch is however racy. It is possible that while you call the gst_element_change_state() a concurrent state change might happen. I think it somehow needs to take the STATE_LOCK as is a requirement for gst_element_change_state(). I will have a deeper look because this code should theoretically be similar to how the bin continues its state.
Comment 3 Wim Taymans 2013-04-03 16:25:01 UTC
Here is another racy attempt:

http://cgit.freedesktop.org/~wtay/gstreamer/log/?h=sink-states

I'm now thinking that we need to release the stream-lock before getting the state-lock..
Comment 4 Paul HENRYS 2013-04-04 06:07:47 UTC
Thx Wim for your feedback, I gonna try your fix.
Comment 5 Sebastian Dröge (slomo) 2013-07-24 09:27:32 UTC
Wim, any news on this?
Comment 6 Wim Taymans 2013-07-24 09:37:09 UTC
I think this is:

commit 124b8e38afa5a7e18b01d8f5969b7b20b9854030
Author: Wim Taymans <wim.taymans@collabora.co.uk>
Date:   Mon Jun 17 10:25:20 2013 +0200

    basesink: call state change in all cases
    
    When we asynchronously go from READY to PLAYING, also call the
    state change function so that subclasses can update their state for PLAYING.
    Because the PREROLL lock is not recursive, we can't make this without
    races and we must assume for now that the subclass can handle concurrent calls
    to PAUSED->PLAYING and PLAYING->PAUSED. We can make this assumption because not
    many elements actually do something in those state changes and the ones that
    did would be broken even more without this change.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=702282
Comment 7 Wim Taymans 2013-07-24 09:37:23 UTC

*** This bug has been marked as a duplicate of bug 702282 ***