[gst-devel] Question about async state changes..
Eric Zhang
nicolas.m.zhang at gmail.com
Tue Dec 2 03:26:20 CET 2008
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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20081202/18389176/attachment.htm>
More information about the gstreamer-devel
mailing list