<div dir="ltr">Thank you guys for the thorough explanation!<br><div class="gmail_extra"><br></div><div class="gmail_extra">Best regards,</div><div class="gmail_extra">Taeho<br><br><div class="gmail_quote">On Thu, Jul 10, 2014 at 6:33 AM, Wim Taymans <span dir="ltr"><<a href="mailto:wim.taymans@gmail.com" target="_blank">wim.taymans@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">Some clarifications below,</div><div class="gmail_extra"><br><div class="gmail_quote">
On 10 July 2014 09:00, Edward Hervey <span dir="ltr"><<a href="mailto:bilboed@bilboed.com" target="_blank">bilboed@bilboed.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>On Wed, 2014-07-09 at 02:11 -0600, Taeho Oh wrote:<br>
> Hello<br>
><br>
><br>
> I am a newbie in gstreamer and have several questions about gstreamer.<br>
> I am sorry if it is a silly question.<br>
><br>
><br>
> According<br>
> to <a href="http://lists.freedesktop.org/archives/gstreamer-devel/2006-July/012776.html" target="_blank">http://lists.freedesktop.org/archives/gstreamer-devel/2006-July/012776.html</a> ( gst_element_set_state hangs ? ), Mike said that<br>


> "You are not - ever - allowed to call gst_element_set_state() from one<br>
> of<br>
> these streaming threads."<br>
<br>
</div>  So. That statement is not 100% true. If you have no clue what you're<br>
doing, you should indeed just respect that rule.<br>
<br>
  The first rule that *always* applies is:<br>
   An element (and the code within) is *never* allowed to change *its*<br>
state. Only the parent container(s) of an element can change its state.<br>
There are mechanisms to hint at the parent container that it should do<br>
that, but it's not common.<br>
   Furthermore, you are *not* allowed to change the state of<br>
upstream/downstream elements. That's the standard "black box"<br>
programming paradigm (as an element, you can only control your realm,<br>
i.e. what's in yourself).<br>
<br>
  Astute readers will have figured out the following though:<br>
   That being said, if your element is a GstBin/GstPipeline subclass, or<br>
if you are application code (which is the "container" of the top-level<br>
pipeline), you _can_ change, if/when needed, the state of the elements<br>
contained within yourself.<br>
   This is actually needed when you dynamically add/remove elements<br>
within yourself at runtime. _When_ you can do that is explained after.<br>
<br>
  Understanding why we have the initial statement (don't change states),<br>
and why it can cause havoc, can lead you to better understand what the<br>
issues can potentially be.<br>
<br>
<br>
  The common problem one wants to avoid is the following deadlock:<br>
  1) The "streaming" lock is taken on each pad (sourcepad and sinkpad,<br>
i.e. a link) whenever a buffer or serialized event/query is being pushed<br>
through them. The reason is ... to only allow one buffer (or serialized<br>
event/query) to go through that link.<br>
  2) If, from the thread that has gone through those links (and<br>
therefore holding those locks), you try to re-acquire that lock ... you<br>
will deadlock. That is the problem you want to avoid.<br></blockquote><div><br></div><div>This is not a problem, the stream lock is recursive.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<br>
  There are also a couple of other cases where those streaming locks<br>
will be taken:<br>
  1) The most other common one is when a pad is deactivated (which<br>
happens when the element it belongs to goes from PAUSED to READY, but<br>
also when pads are removed), it needs to ensure that no data flow is<br>
currently taking place.<br>
  # If you try to deactivate the pad, or by extension change the state<br>
of that element from PAUSED to READY, from the thread that was already<br>
flowing through it => deadlock.<br></blockquote><div><br></div><div>This is only true for elements that created the GstTask for this streaming thread and</div><div>not because of the streaming lock but because of the fact that it wants to</div>

<div>stop and join the thread you are currently in. We catch this case with a big warning</div><div>on the console, we won't deadlock (for any GstTask).</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<br>
  2) An other one is for elements that initiate a streaming thread (such<br>
as push-based sources or pull-based demuxers which run what is commonly<br>
called a "loop" function) and that want to ensure that loop is no longer<br>
running.<br>
   For example, when a demuxer receives a seek (whether flushing or not)<br>
it wants to ensure that that loop is not running before it modifies the<br>
information/properties regarding where the loop should resume from (the<br>
requested position for example).<br>
  # If you try to seek on an element from that streaming thread =><br>
deadlock.<br></blockquote><div><br></div><div>Not true, you can seek fine from a streaming thread because the lock is recursive, otherwise push based seeking would just never work.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<br>
  Now, there are some cases where you can safely change an element<br>
state:<br>
  1) It's not connected downstream, you know the streaming thread that<br>
might flow out of that element will not block, you can change the state.</blockquote><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  2) It is connected downstream, but it's in the NULL or READY state,<br>
you know no dataflow was happening, therefore it can't be<br>
pushing/blocking.<br>
  3) It is connected downstream, but you forced the streaming thread<br>
that might flow out of that element to never block, by issuing a<br>
GST_EVENT_FLUSH_START on the downstream pads (serialized-event/buffer<br>
pushes always return immediately on all pads that received that event).<br>
  4) Regardless of the above, you are bringing the state of an element<br>
"upwards" (i.e. from NULL=>READY, READY=>PAUSED, PAUSED=>PLAYING). In<br>
those cases, you either have no streaming happening (2), or it's already<br>
running and you are not attempting to stop it.<br></blockquote><div><br></div><div>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.</div>

<div><br></div><div>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.</div><div><br></div><div>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.</div>

<div> </div><div>Wim</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><br>
><br>
> Q1) In gstreamer user's point of view, where can I meet 'streaming<br>
> thread'? Should I assume that all callback functions(ex. typefind<br>
> have-type callback, pad-added callback, etc) run in 'streaming<br>
> thread'? Are there any other 'streaming thread' cases other than the<br>
> callback functions? </div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>
<br>
</div>  The short rule is :<br>
   * just assume signals and pad blocks will be emitted from a streaming<br>
thread. Never do state changes from that *unless* you understand<br>
everything I explained above.<br>
   * (asynchronous) messages from the bus are in your main thread,<br>
they're guaranteed not to be emitted from a streaming thread, you can do<br>
whatever you want.<br>
<br>
  => If you don't know for sure which thread it is, assume it's a<br>
streaming thread.<br>
<div><br>
><br>
><br>
> Q2) Are there any allowed scenarios where gst_element_set_state() can<br>
> be called in the streaming thread?<br>
> I am a little bit confused, because according to<br>
> <a href="http://debathena.mit.edu/trac/browser/trunk/third/gstreamer/docs/manual/helloworld2.xml?rev=21005" target="_blank">http://debathena.mit.edu/trac/browser/trunk/third/gstreamer/docs/manual/helloworld2.xml?rev=21005</a>, gst_element_set_state() is called in gst_play_have_type callback function.<br>


<br>
</div>  Hopefully everything above made that clear.<br>
  1) It's code from outside the element/pipeline (it's application code)<br>
  2) it's bringing the state of that element (or rather pipeline)<br>
upwards (which doesn't acquire the streaming lock)<br>
<div><br>
><br>
><br>
> Q3) Are there any other gstreamer APIs not allowed to be called in the<br>
> 'streaming thread'?<br>
<br>
</div>  Apart from changing state and seeking, it's down to sending serialized<br>
data (buffers, serialized events, serialized queries) downstream, which<br>
is perfectly fine since you're pushing data *downstream* and therefore<br>
not through the (upstream) streaming locks that might have been taken.<br></blockquote><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
  Hope this clarifies things a bit,<br>
<br>
   Edward<br>
<div><br>
><br>
><br>
> Best regards,<br>
><br>
> Taeho<br>
> --<br>
> Taeho Oh ( <a href="mailto:ohhara@postech.edu" target="_blank">ohhara@postech.edu</a> )<br>
> <a href="http://ohhara.sarang.net" target="_blank">http://ohhara.sarang.net</a><br>
> Postech ( Pohang University of Science and Technology )<br>
> <a href="http://www.postech.edu" target="_blank">http://www.postech.edu</a><br>
> Alticast Corp.<br>
> <a href="http://www.alticast.com" target="_blank">http://www.alticast.com</a><br>
</div><div><div>> _______________________________________________<br>
> gstreamer-devel mailing list<br>
> <a href="mailto:gstreamer-devel@lists.freedesktop.org" target="_blank">gstreamer-devel@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel</a><br>
<br>
</div></div><br>_______________________________________________<br>
gstreamer-devel mailing list<br>
<a href="mailto:gstreamer-devel@lists.freedesktop.org" target="_blank">gstreamer-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel</a><br>
<br></blockquote></div><br></div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Taeho Oh ( <a href="mailto:ohhara@postech.edu" target="_blank">ohhara@postech.edu</a> )                       <a href="http://ohhara.sarang.net" target="_blank">http://ohhara.sarang.net</a><br>
Postech ( Pohang University of Science and Technology ) <a href="http://www.postech.edu" target="_blank">http://www.postech.edu</a><br>Alticast Corp.                                         <a href="http://www.alticast.com" target="_blank">http://www.alticast.com</a>
</div></div>