[gst-devel] Question about async state changes..

Eric Zhang nicolas.m.zhang at gmail.com
Tue Dec 2 08:17:07 CET 2008


Hi, gstreamer-devel:

    These docs may be a good start:

    <gstreamer root directory>/docs/design/part-element-sink.txt
    <gstreamer root directory>/docs/design/part-preroll.txt
    <gstreamer root directory>/docs/design/part-states.txt
    <gstreamer root directory>/docs/design/part-element-source.txt

    Unfortunately, these docs are not step by step tutorials. Actually, they
are some keypoints in gstreamer design. So, I think you will have more
questions after reading these, at that time, read the source codes directly.

Eric Zhang
2008/12/2 John Grossman <johngro at google.com>

> ok - do you know a good place to read up on GStreamer's design patterns
> when it comes to asynchronous state changing?  The application and plugin
> development handbooks don't seem to cover the topic in much detail.
>
> peace
> -john
>
>
> On Mon, Dec 1, 2008 at 6:26 PM, Eric Zhang <nicolas.m.zhang at gmail.com>wrote:
>
>> Hi, gstreamer-devel:
>>
>>     Basically, in gstreamer, ASYNC state changing is used by sink elements
>> to perform preroll. So let source element performs a ASYNC state change is
>> not a good idea.
>>
>>     And the ASYNC state changing typically happens during READY->PAUSED
>> while not NULL->READY.
>>
>>     So my opinion is you'd better think your design again to try to follow
>> the gstreamer's design patterns. If your source element want to fetch
>> something in network -- just do it, there is no need to return ASYNC. For
>> example, I am working on rtsp/rtp stuffs now and the rtspsrc will do a lot
>> of works during NULL->READY and READY->PAUSED to communicate with RTSP
>> server.
>>
>> Eric Zhang
>>
>> 2008/12/2 John Grossman <johngro at google.com>
>>
>>>  bump...
>>>
>>> Still looking for some help with this issue; does anyone have an idea of
>>> what might be going on?  Alternatively, does anyone know of a good example
>>> of how to properly implement an element which performs async state changes
>>> which I could use to set myself straight?
>>>
>>> TIA
>>>
>>> peace
>>> -john
>>>
>>>
>>> On Tue, Nov 25, 2008 at 7:28 PM, John Grossman <johngro at google.com>wrote:
>>>
>>>>
>>>> Hello, my name is John and I am a developer currently working on writing
>>>> a gstreamer plugin to act as a source element.  I'm having some trouble with
>>>> async state changes and I was hoping that someone on this list could provide
>>>> some insight.  Basically, my element needs to make the transition from NULL
>>>> to READY asynchronously.  After my element has transitioned to READY,
>>>> downstream elements expect me to answer questions like, "how long is the
>>>> source in bytes".  I am actually fetching the source over a network, but I
>>>> want to provide a pull interface to make file oriented demux elements
>>>> happy.  It will take me some time to get this information from the network
>>>> so it is important for me to make the transition asynchronously.
>>>>
>>>> I have overridden the change_state, get_state and set_state methods of
>>>> my element so that I can have some control over the process.  My change
>>>> state just calls to the base element's change_state for any transition
>>>> except for NULL_TO_READY.  When I see the NULL_TO_READY change, I kick off
>>>> my network fetch and return GST_STATE_CHANGE_ASYNC.
>>>>
>>>> My set state method always calls the base element's set_state; I pretty
>>>> much just have it hooked so that I can see what the base element is
>>>> returning to the rest of the framework.
>>>>
>>>> My get_state implementation will return the base element's get_state,
>>>> unless I am in an asynchronous transition from NULL to READY.  In this case,
>>>> it waits for the signal from the rest of my code that has managed to fetch
>>>> the required info from the network.  If the get times out, it will return
>>>> ASYNC again.  If something goes wrong fetching the file over the net, it
>>>> will return FAILURE, and if everything went well it will return SUCCESS (and
>>>> my element should officially be in the READY state).
>>>>
>>>> Unfortunately, things do not seem to be working as I expected.  Even
>>>> though I return ASYNC at the appropriate time in my implementation of
>>>> change_state, the base implementation of set_state is simply returning
>>>> SUCCESS.  I am working with the 0.10.21 version of GStreamer, and I think I
>>>> have tracked the issue down to the implementation of
>>>> gst_element_change_state in gstelement.c at line 2412.  This function calls
>>>> my implementation of change_state and then switches on the return value I
>>>> give back.  The handler for GST_STATE_CHANGE_ASYNC looks like the
>>>> following...
>>>>
>>>> case GST_STATE_CHANGE_ASYNC:
>>>> {
>>>>   GstState target;
>>>>
>>>>   GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
>>>>       "element will change state ASYNC");
>>>>
>>>>   target = GST_STATE_TARGET (element);
>>>>
>>>>   if (target > GST_STATE_READY)
>>>>     goto async;
>>>>
>>>>   /* else we just continue the state change downwards */
>>>>   GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
>>>>       "forcing commit state %s <= %s",
>>>>       gst_element_state_get_name (target),
>>>>       gst_element_state_get_name (GST_STATE_READY));
>>>>
>>>>   ret = gst_element_continue_state (element, GST_STATE_CHANGE_SUCCESS);
>>>>   break;
>>>> }
>>>>
>>>> Essentially, what seems to be killing me is the "if (target >
>>>> GST_STATE_READY) statement".  The system is attempting to go from NULL to
>>>> READY, and this line seems to be saying that asynchronous transitions can
>>>> only be made if the target state is either PAUSED or PLAYING.  (BTW - I am
>>>> seeing both the "element will change state ASYNC" and the "forcing commit
>>>> state" messages in my debug logs).  I couldn't make sense of the comment
>>>> following the if statement so I did some research in the CVS archives to see
>>>> if I could track down where this if statement came from.  You can check out
>>>> the diffs here
>>>>
>>>> http://webcvs.freedesktop.org/gstreamer/gstreamer/gst/gstelement.c?r1=1.448&r2=1.449
>>>> but to save you some time, here is what the code used to look like
>>>> (about 20 months ago)
>>>>
>>>> case GST_STATE_CHANGE_ASYNC:
>>>>    GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
>>>>        "element will change state ASYNC");
>>>>
>>>>    /* if we go upwards, we give the app a change to wait for
>>>>     * completion */
>>>>    if (current < next)
>>>>      goto async;
>>>>
>>>>    /* else we just continue the state change downwards */
>>>>    GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
>>>>        "forcing commit state %s < %s",
>>>>        gst_element_state_get_name (current),
>>>>        gst_element_state_get_name (next));
>>>>
>>>>    ret = gst_element_continue_state (element, GST_STATE_CHANGE_SUCCESS);
>>>>    break;
>>>>
>>>> Essentially, it looked like the code used to allow async state changes
>>>> while moving up in the state sequence, but not while moving down.  I suspect
>>>> this was to prevent element from blocking shutdown by never completing their
>>>> state changes.  With the code change present in 1.449, it looks like
>>>> elements are allowed to make an async state change to either PLAYING or
>>>> PAUSED, but not if their target is NULL or READY.
>>>>
>>>> This is where I get confused...  If I had set the target state of my
>>>> pipeline directly to PLAYING instead of just READY, it looks like this code
>>>> would have allowed me to make the async change from NULL to READY.  So if
>>>> the purpose of this code is to force the change from NULL to READY to be
>>>> synchronous, it seems like there are ways of wiggling around it.
>>>>
>>>> If the behavior of this code was supposed to be the same as before
>>>> (allowing async in the up direction instead of down), then it seems like "if
>>>> (current < target)" is the appropriate change, instead of "if (target >
>>>> READY)".
>>>>
>>>> It has also occurred to me that the intention might have been to allow
>>>> async changes in both directions instead of just up, but not if the target
>>>> state is set to NULL (in which case the pipeline is tearing down and should
>>>> do so with all haste).  If that is the case, then the if statement present
>>>> here might just have a typo ("if (target > GST_STATE_READY)" instead of "if
>>>> (target >= GST_STATE_READY)")
>>>>
>>>> Does anyone know what the intention was here?  If the intent was to
>>>> actually prevent elements from transitioning from NULL to READY
>>>> asynchronously, then does anyone know how I should be approaching my problem
>>>> instead?  I suppose I could build my graph by adding just my source element,
>>>> setting it to ready, and then waiting for a bus message from the async part
>>>> of my element indicating that it has fetched the initial data.  That really
>>>> didn't seem to be in the spirit of things, however, since it would mean that
>>>> my application needed to be aware of my source's particular requirements.
>>>>
>>>> Thanks in advance for any help anyone out there can provide.
>>>>
>>>> -john
>>>>
>>>
>>>
>>> -------------------------------------------------------------------------
>>> This SF.Net email is sponsored by the Moblin Your Move Developer's
>>> challenge
>>> Build the coolest Linux based applications with Moblin SDK & win great
>>> prizes
>>> Grand prize is a trip for two to an Open Source event anywhere in the
>>> world
>>> http://moblin-contest.org/redirect.php?banner_id=100&url=/
>>> _______________________________________________
>>> gstreamer-devel mailing list
>>> gstreamer-devel at lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
>>>
>>>
>>
>> -------------------------------------------------------------------------
>> This SF.Net email is sponsored by the Moblin Your Move Developer's
>> challenge
>> Build the coolest Linux based applications with Moblin SDK & win great
>> prizes
>> Grand prize is a trip for two to an Open Source event anywhere in the
>> world
>> http://moblin-contest.org/redirect.php?banner_id=100&url=/
>> _______________________________________________
>> gstreamer-devel mailing list
>> gstreamer-devel at lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
>>
>>
>
> -------------------------------------------------------------------------
> This SF.Net email is sponsored by the Moblin Your Move Developer's
> challenge
> Build the coolest Linux based applications with Moblin SDK & win great
> prizes
> Grand prize is a trip for two to an Open Source event anywhere in the world
> http://moblin-contest.org/redirect.php?banner_id=100&url=/
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20081202/4a08024d/attachment.htm>


More information about the gstreamer-devel mailing list