streaming thread and gst_element_set_state in gstreamer
Edward Hervey
bilboed at bilboed.com
Thu Jul 10 00:00:38 PDT 2014
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.
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.
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.
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.
>
> 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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20140710/79e54934/attachment.sig>
More information about the gstreamer-devel
mailing list