streaming thread and gst_element_set_state in gstreamer

Wim Taymans wim.taymans at gmail.com
Thu Jul 10 05:33:56 PDT 2014


Some clarifications below,

On 10 July 2014 09:00, Edward Hervey <bilboed at bilboed.com> wrote:

> On Wed, 2014-07-09 at 02:11 -0600, Taeho Oh wrote:
> > Hello
> >
> >
> > I am a newbie in gstreamer and have several questions about gstreamer.
> > I am sorry if it is a silly question.
> >
> >
> > According
> > to
> http://lists.freedesktop.org/archives/gstreamer-devel/2006-July/012776.html
> ( gst_element_set_state hangs ? ), Mike said that
> > "You are not - ever - allowed to call gst_element_set_state() from one
> > of
> > these streaming threads."
>
>   So. That statement is not 100% true. If you have no clue what you're
> doing, you should indeed just respect that rule.
>
>   The first rule that *always* applies is:
>    An element (and the code within) is *never* allowed to change *its*
> state. Only the parent container(s) of an element can change its state.
> There are mechanisms to hint at the parent container that it should do
> that, but it's not common.
>    Furthermore, you are *not* allowed to change the state of
> upstream/downstream elements. That's the standard "black box"
> programming paradigm (as an element, you can only control your realm,
> i.e. what's in yourself).
>
>   Astute readers will have figured out the following though:
>    That being said, if your element is a GstBin/GstPipeline subclass, or
> if you are application code (which is the "container" of the top-level
> pipeline), you _can_ change, if/when needed, the state of the elements
> contained within yourself.
>    This is actually needed when you dynamically add/remove elements
> within yourself at runtime. _When_ you can do that is explained after.
>
>   Understanding why we have the initial statement (don't change states),
> and why it can cause havoc, can lead you to better understand what the
> issues can potentially be.
>
>
>   The common problem one wants to avoid is the following deadlock:
>   1) The "streaming" lock is taken on each pad (sourcepad and sinkpad,
> i.e. a link) whenever a buffer or serialized event/query is being pushed
> through them. The reason is ... to only allow one buffer (or serialized
> event/query) to go through that link.
>   2) If, from the thread that has gone through those links (and
> therefore holding those locks), you try to re-acquire that lock ... you
> will deadlock. That is the problem you want to avoid.
>

This is not a problem, the stream lock is recursive.


>
>   There are also a couple of other cases where those streaming locks
> will be taken:
>   1) The most other common one is when a pad is deactivated (which
> happens when the element it belongs to goes from PAUSED to READY, but
> also when pads are removed), it needs to ensure that no data flow is
> currently taking place.
>   # If you try to deactivate the pad, or by extension change the state
> of that element from PAUSED to READY, from the thread that was already
> flowing through it => deadlock.
>

This is only true for elements that created the GstTask for this streaming
thread and
not because of the streaming lock but because of the fact that it wants to
stop and join the thread you are currently in. We catch this case with a
big warning
on the console, we won't deadlock (for any GstTask).


>
>   2) An other one is for elements that initiate a streaming thread (such
> as push-based sources or pull-based demuxers which run what is commonly
> called a "loop" function) and that want to ensure that loop is no longer
> running.
>    For example, when a demuxer receives a seek (whether flushing or not)
> it wants to ensure that that loop is not running before it modifies the
> information/properties regarding where the loop should resume from (the
> requested position for example).
>   # If you try to seek on an element from that streaming thread =>
> deadlock.
>

Not true, you can seek fine from a streaming thread because the lock is
recursive, otherwise push based seeking would just never work.


>
>   Now, there are some cases where you can safely change an element
> state:
>   1) It's not connected downstream, you know the streaming thread that
> might flow out of that element will not block, you can change the state.



>   2) It is connected downstream, but it's in the NULL or READY state,
> you know no dataflow was happening, therefore it can't be
> pushing/blocking.
>   3) It is connected downstream, but you forced the streaming thread
> that might flow out of that element to never block, by issuing a
> GST_EVENT_FLUSH_START on the downstream pads (serialized-event/buffer
> pushes always return immediately on all pads that received that event).
>   4) Regardless of the above, you are bringing the state of an element
> "upwards" (i.e. from NULL=>READY, READY=>PAUSED, PAUSED=>PLAYING). In
> those cases, you either have no streaming happening (2), or it's already
> running and you are not attempting to stop it.
>

These cases are when  you want to change the state of an element to
READY/NULL individually without setting the state of the downstream
elements to READY first. You will do this when you want to dynamically
remove an element from a playing pipeline, for example.

Again, you can't do any of the above state changes from the streaming
thread that you would be trying to stop with a state change to READY/NULL.

So, in short, the only thing you can't do from a streaming thread is trying
to stop the element that created the streaming thread.

Wim

>
> >
> > Q1) In gstreamer user's point of view, where can I meet 'streaming
> > thread'? Should I assume that all callback functions(ex. typefind
> > have-type callback, pad-added callback, etc) run in 'streaming
> > thread'? Are there any other 'streaming thread' cases other than the
> > callback functions?
>

>   The short rule is :
>    * just assume signals and pad blocks will be emitted from a streaming
> thread. Never do state changes from that *unless* you understand
> everything I explained above.
>    * (asynchronous) messages from the bus are in your main thread,
> they're guaranteed not to be emitted from a streaming thread, you can do
> whatever you want.
>
>   => If you don't know for sure which thread it is, assume it's a
> streaming thread.
>
> >
> >
> > Q2) Are there any allowed scenarios where gst_element_set_state() can
> > be called in the streaming thread?
> > I am a little bit confused, because according to
> >
> http://debathena.mit.edu/trac/browser/trunk/third/gstreamer/docs/manual/helloworld2.xml?rev=21005,
> gst_element_set_state() is called in gst_play_have_type callback function.
>
>   Hopefully everything above made that clear.
>   1) It's code from outside the element/pipeline (it's application code)
>   2) it's bringing the state of that element (or rather pipeline)
> upwards (which doesn't acquire the streaming lock)
>
> >
> >
> > Q3) Are there any other gstreamer APIs not allowed to be called in the
> > 'streaming thread'?
>
>   Apart from changing state and seeking, it's down to sending serialized
> data (buffers, serialized events, serialized queries) downstream, which
> is perfectly fine since you're pushing data *downstream* and therefore
> not through the (upstream) streaming locks that might have been taken.
>


>
>   Hope this clarifies things a bit,
>
>    Edward
>
> >
> >
> > Best regards,
> >
> > Taeho
> > --
> > Taeho Oh ( ohhara at postech.edu )
> > http://ohhara.sarang.net
> > Postech ( Pohang University of Science and Technology )
> > http://www.postech.edu
> > Alticast Corp.
> > http://www.alticast.com
> > _______________________________________________
> > gstreamer-devel mailing list
> > gstreamer-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20140710/5dcf3e2b/attachment-0001.html>


More information about the gstreamer-devel mailing list