From 477870c5444a314781f25c82e1c666b8e5988715 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 17 Aug 2006 18:11:11 +0000 Subject: [PATCH] docs/pwg/: Update for 0.10 API (#340627). Add myself to authors list. Original commit message from CVS: * docs/pwg/advanced-events.xml: * docs/pwg/titlepage.xml: Update for 0.10 API (#340627). Add myself to authors list. --- ChangeLog | 7 + docs/pwg/advanced-events.xml | 466 +++++++++++++++++++++---------------------- docs/pwg/titlepage.xml | 10 + 3 files changed, 244 insertions(+), 239 deletions(-) diff --git a/ChangeLog b/ChangeLog index dbf0fa1..2b37747 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2006-08-17 Tim-Philipp Müller + * docs/pwg/advanced-events.xml: + * docs/pwg/titlepage.xml: + Update for 0.10 API (#340627). Add myself + to authors list. + +2006-08-17 Tim-Philipp Müller + * docs/libs/gstreamer-libs-docs.sgml: * docs/libs/gstreamer-libs-sections.txt: * libs/gst/check/gstbufferstraw.c: diff --git a/docs/pwg/advanced-events.xml b/docs/pwg/advanced-events.xml index 1eeb9a6..e90a9b9 100644 --- a/docs/pwg/advanced-events.xml +++ b/docs/pwg/advanced-events.xml @@ -1,9 +1,9 @@ Events: Seeking, Navigation and More - There are many different event types but only 2 ways they can travel across + There are many different event types but only two ways they can travel in the pipeline: downstream or upstream. It is very important to understand - how both of those methods work because if one element in the pipeline is not + how both of these methods work because if one element in the pipeline is not handling them correctly the whole event system of the pipeline is broken. We will try to explain here how these methods work and how elements are supposed to implement them. @@ -11,76 +11,96 @@ Downstream events - Downstream events are received through the sink pad's dataflow. Depending - if your element is loop or chain based you will receive events in your - loop/chain function as a GstData with gst_pad_pull - or directly in the function call arguments. So when receiving dataflow - from the sink pad you have to check first if this data chunk is an event. - If that's the case you check what kind of event it is to react on relevant - ones and then forward others downstream using - gst_pad_event_default. Here is an example for both - loop and chain based elements. + Downstream events are received through the sink pad's event handler, + as set using gst_pad_set_event_function () when + the pad was created. + + + Downstream events can travel in two ways: they can be in-band (serialised + with the buffer flow) or out-of-band (travelling through the pipeline + instantly, possibly not in the same thread as the streaming thread that + is processing the buffers, skipping ahead of buffers being processed + or queued in the pipeline). The most common downstream events + (NEWSEGMENT, EOS, TAG) are all serialised with the buffer flow. + + + Here is a typical event function: -/* Chain based element */ -static void -gst_my_filter_chain (GstPad *pad, - GstData *data) +static gboolean +gst_my_filter_sink_event (GstPad *pad, GstEvent * event) { - GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad)); - ... - if (GST_IS_EVENT (data)) { - GstEvent *event = GST_EVENT (data); + GstMyFilter *filter; + gboolean ret; - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - /* end-of-stream, we should close down all stream leftovers here */ - gst_my_filter_stop_processing (filter); - /* fall-through to default event handling */ - default: - gst_pad_event_default (pad, event); - break; - } - return; - } + filter = GST_MY_FILTER (gst_pad_get_parent (pad)); ... -} -/* Loop based element */ -static void -gst_my_filter_loop (GstElement *element) -{ - GstMyFilter *filter = GST_MY_FILTER (element); - GstData *data = NULL; - - data = gst_pad_pull (filter->sinkpad); - - if (GST_IS_EVENT (data)) { - GstEvent *event = GST_EVENT (data); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - /* end-of-stream, we should close down all stream leftovers here */ - gst_my_filter_stop_processing (filter); - /* fall-through to default event handling */ - default: - gst_pad_event_default (filter->sinkpad, event); - break; - } - return; + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + /* maybe save and/or update the current segment (e.g. for output + * clipping) or convert the event into one in a different format + * (e.g. BYTES to TIME) or drop it and set a flag to send a newsegment + * event in a different format later */ + ret = gst_pad_push_event (filter->src_pad, event); + break; + case GST_EVENT_EOS: + /* end-of-stream, we should close down all stream leftovers here */ + gst_my_filter_stop_processing (filter); + ret = gst_pad_push_event (filter->src_pad, event); + break; + case GST_EVENT_FLUSH_STOP: + gst_my_filter_clear_temporary_buffers (filter); + ret = gst_pad_push_event (filter->src_pad, event); + break; + default: + ret = gst_pad_event_default (pad, event); + break; } + ... + gst_object_unref (filter); + return ret; } + + If your element is chain-based, you will almost always have to implement + a sink event function, since that is how you are notified about + new segments and the end of the stream. + + + If your element is exclusively loop-based, you may or may not want a + sink event function (since the element is driving the pipeline it will + know the length of the stream in advance or be notified by the flow + return value of gst_pad_pull_range(). In some cases + even loop-based element may receive events from upstream though (for + example audio decoders with an id3demux or apedemux element in front of + them, or demuxers that are being fed input from sources that send + additional information about the stream in custom events, as DVD sources + do). + Upstream events - Upstream events are generated by an element somewhere in the pipeline and - sent using the gst_pad_send_event function. This - function simply realizes the pad and call the default event handler of that - pad. The default event handler of pads is gst_pad_event_default - , it basically sends the event to the peer pad. So upstream events always + Upstream events are generated by an element somewhere downstream in + the pipeline (example: a video sink may generate navigation + events that informs upstream elements about the current position of + the mouse pointer). This may also happen indirectly on request of the + application, for example when the application executes a seek on a + pipeline this seek request will be passed on to a sink element which + will then in turn generate an upstream seek event. + + + The most common upstream events are seek events and Quality-of-Service + (QoS) events. + + + An upstream event can be sent using the + gst_pad_send_event function. This + function simply call the default event handler of that pad. The default + event handler of pads is gst_pad_event_default, and + it basically sends the event to the peer pad. So upstream events always arrive on the src pad of your element and are handled by the default event handler except if you override that handler to handle it yourself. There are some specific cases where you have to do that : @@ -89,13 +109,15 @@ gst_my_filter_loop (GstElement *element) If you have multiple sink pads in your element. In that case you will - have to decide which one of the sink pads you will send the event to. + have to decide which one of the sink pads you will send the event to + (if not all of them). If you need to handle that event locally. For example a navigation - event that you will want to convert before sending it upstream. + event that you will want to convert before sending it upstream, or + a QoS event that you want to handle. @@ -126,94 +148,84 @@ gst_my_filter_loop (GstElement *element) event. + + + Remember that the event handler might be called from a different + thread than the streaming thread, so make sure you use + appropriate locking everywhere and at the beginning of the function + obtain a reference to your element via the + gst_pad_get_parent() (and release it again at + the end of the function with gst_object_unref (). + + - - Here is an example of correct upstream event handling for a plugin - that wants to modify navigation events. - - -static gboolean -gst_my_filter_handle_src_event (GstPad *pad, - GstEvent *event) -{ - GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NAVIGATION: - GstEvent *new_event = gst_event_new (GST_EVENT_NAVIGATION);; - /* Create a new event based on received one and then send it */ - ... - gst_event_unref (event); - return gst_pad_event_default (pad, new_event); - default: - /* Falling back to default event handling for that pad */ - return gst_pad_event_default (pad, event); - } -} - All Events Together In this chapter follows a list of all defined events that are currently - being used, plus how they should be used/interpreted. Events are stored - in a GstEvent - structure, which is simply a big C union with the - types for each event in it. For the next development cycle, we intend to - switch events over to GstStructure - , - but you don't need to worry about that too much for now. + being used, plus how they should be used/interpreted. You can check the + what type a certain event is using the GST_EVENT_TYPE macro (or if you + need a string for debugging purposes you can use GST_EVENT_TYPE_NAME). In this chapter, we will discuss the following events: - - + + + - - + + For more comprehensive information about events and how they should be + used correctly in various circumstances please consult the GStreamer + design documentation. This section only gives a general overview. + End of Stream (EOS) End-of-stream events are sent if the stream that an element sends out is finished. An element receiving this event (from upstream, so it - receives it on its sinkpad) will generally forward the event further - downstream and set itself to EOS (gst_element_set_eos ()). - gst_pad_event_default () takes care of all this, - so most elements do not need to support this event. Exceptions are + receives it on its sinkpad) will generally just process any buffered + data (if there is any) and then forward the event further downstream. + The gst_pad_event_default () takes care of all + this, so most elements do not need to support this event. Exceptions are elements that explicitly need to close a resource down on EOS, and N-to-1 elements. Note that the stream itself is not a resource that should be closed down on EOS! Applications might seek - back to a point before EOS and set the pipeline to PLAYING again. + back to a point before EOS and continue playing again. - The EOS event (GST_EVENT_EOS) has no properties, - and that makes it one of the simplest events in &GStreamer;. It is - created using gst_event_new (GST_EVENT_EOS);. + The EOS event has no properties, which makes it one of the simplest + events in &GStreamer;. It is created using the + gst_event_new_eos() function. - Some elements support the EOS event upstream, too. This signals the - element to go into EOS as soon as possible and signal the EOS event - forward downstream. This is useful for elements that have no concept - of end-of-stream themselves. Examples are TV card sources, audio card - sources, etc. This is not (yet) part of the official specifications of - this event, though. + It is important to note that only elements driving the + pipeline should ever send an EOS event. If your element + is chain-based, it is not driving the pipeline. Chain-based elements + should just return GST_FLOW_UNEXPECTED from their chain function at + the end of the stream (or the configured segment), the upstream + element that is driving the pipeline will then take care of + sending the EOS event (or alternatively post a SEGMENT_DONE message + on the bus depending on the mode of operation). If you are implementing + your own source element, you also do not need to ever manually send + an EOS event, you should also just return GST_FLOW_UNEXPECTED in + your create function (assuming your element derives from GstBaseSrc + or GstPushSrc). - - Flush + + Flush Start - The flush event is being sent downstream if all buffers and caches + The flush start event is sent downstream if all buffers and caches in the pipeline should be emptied. Queue elements will empty their internal list of buffers when they receive this event, for example. File sink elements (e.g. filesink) will flush @@ -226,21 +238,64 @@ gst_my_filter_handle_src_event (GstPad *pad, event handler. - The flush event is created with gst_event_new (GST_EVENT_FLUSH);. - Like the EOS event, it has no properties. + As a side-effect of flushing all data from the pipeline, this event + unblocks the streaming thread by making all pads reject data until + they receive a signal + (elements trying to push data will get a WRONG_STATE flow return + and stop processing data). + + + The flush-start event is created with the + gst_event_new_flush_start (). + Like the EOS event, it has no properties. This event is usually + only created by elements driving the pipeline, like source elements + operating in push-mode or pull-range based demuxers/decoders. - - Stream Discontinuity + + Flush Stop + + The flush-stop event is sent by an element driving the pipeline + after a flush-start and tells pads and elements downstream that + they should accept events and buffers again (there will be at + least a NEWSEGMENT event before any buffers first though). + + + If your element keeps temporary caches of stream data, it should + clear them when it receives a FLUSH-STOP event (and also whenever + its chain function receives a buffer with the DISCONT flag set). + + + The flush-stop event is created with + gst_event_new_flush_stop (). Like the EOS event, + it has no properties. + + + + + New Segment + + A new segment event is sent downstream to either announce a new + segment of data in the data stream or to update the current segment + with new values. A new segment event must always be sent before the + first buffer of data and after a flush (see above). + + + The first new segment event is created by the element driving the + pipeline, like a source operating in push-mode or a demuxer/decoder + operating pull-based. This new segment event then travels down the + pipeline and may be transformed on the way (a decoder, for example, + might receive a new-segment event in BYTES format and might transform + this into a new-segment event in TIMES format based on the average + bitrate). + - A discontinuity event is sent downstream to indicate a discontinuity in - the data stream. This can happen because the application used the seek - event to seek to a different position in the stream, but it can also be - because a real-time network source temporarily lost the connection. - After the connection is restored, the data stream will continue, but - not at the same point where it got lost. Therefore, a discontinuity - event is being sent downstream, too. + New segment events may also be used to indicate 'gaps' in the stream, + like in a subtitle stream for example where there may not be any + data at all for a considerable amount of (stream) time. This is done + by updating the segment start of the current segment (see the design + documentation for more details). Depending on the element type, the event can simply be forwarded using @@ -249,43 +304,22 @@ gst_my_filter_handle_src_event (GstPad *pad, which generally have a byte-to-time conversion concept. Their input is usually byte-based, so the incoming event will have an offset in byte units (GST_FORMAT_BYTES), too. Elements - downstream, however, expect discontinuity events in time units, so that + downstream, however, expect new segment events in time units, so that it can be used to update the pipeline clock. Therefore, demuxers and similar elements should not forward the event, but parse it, free it - and send a new discontinuity event (in time units, + and send a new newsegment event (in time units, GST_FORMAT_TIME) further downstream. - The discontinuity event is created using the function - gst_event_new_discontinuous (). It should set a - boolean value which indicates if the discontinuity event is sent - because of a new media type (this can happen if - during iteration - - a new location was set on a network source or on a file source). - then, it should give a list of formats and offsets in that format. The - list should be terminated by 0 as format. + The newsegment event is created using the function + gst_event_new_new_segment (). See the API + reference and design document for details about its parameters. - -static void -my_filter_some_function (GstMyFilter *filter) -{ - GstEvent *event; -[..] - event = gst_event_new_discontinuous (FALSE, - GST_FORMAT_BYTES, 0, - GST_FORMAT_TIME, 0, - 0); - gst_pad_push (filter->srcpad, GST_DATA (event)); -[..] -} - - Elements parsing this event can use macros and functions to access the - various properties. GST_EVENT_DISCONT_NEW_MEDIA (event) - checks the new-media boolean value. - gst_event_discont_get_value (event, format, &value) - gets the offset of the new stream position in the specified format. If - that format was not specified when creating the event, the function - returns FALSE. + Elements parsing this event can use gst_event_parse_new_segment_full() + to extract the event details. Elements may find the GstSegment + API useful to keep track of the current segment (if they want to use + it for output clipping, for example). @@ -294,100 +328,50 @@ my_filter_some_function (GstMyFilter *filter) Seek events are meant to request a new stream position to elements. This new position can be set in several formats (time, bytes or - units [a term indicating frames for video, samples for - audio, etc.]). Seeking can be done with respect to the end-of-file, - start-of-file or current position, and can happen in both upstream and - downstream direction. Elements receiving seek events should, depending - on the element type, either forward it (filters, decoders), change the - format in which the event is given and forward it (demuxers), handle - the event by changing the file pointer in their internal stream - resource (file sources) or something else. - - - Seek events are, like discontinuity events, built up using positions in - specified formats (time, bytes, units). They are created using the - function gst_event_new_seek (), where the first - argument is the seek type (indicating with respect to which position - [current, end, start] the seek should be applied, and the format in - which the new position is given (time, bytes, units), and an offset - which is the requested position in the specified format. + default units [a term indicating frames for video, + channel-independent samples for audio, etc.]). Seeking can be done with + respect to the end-of-file, start-of-file or current position, and + usually happens in upstream direction (downstream seeking is done by + sending a NEWSEGMENT event with the appropriate offsets for elements + that support that, like filesink). - -static void -my_filter_some_function (GstMyFilter *filter) -{ - GstEvent *event; -[..] - /* seek to the start of a resource */ - event = gst_event_new_seek (GST_SEEK_SET | GST_FORMAT_BYTES, 0); - gst_pad_push (filter->srcpad, GST_DATA (event)); -[..] -} - - Elements parsing this event can use macros and functions to access the - properties. The seek type can be retrieved using - GST_EVENT_SEEK_TYPE (event). This seek type - contains both the indicator of with respect to what position the seek - should be applied, and the format in which the seek event is given. - To get either one of these properties separately, use - GST_EVENT_SEEK_FORMAT (event) or - GST_EVENT_SEEK_METHOD (event). The requested - position is available through GST_EVENT_SEEK_OFFSET (event), - and is given in the specified format. + Elements receiving seek events should, depending on the element type, + either just forward it upstream (filters, decoders), change the + format in which the event is given and then forward it (demuxers), + or handle the event by changing the file pointer in their internal + stream resource (file sources, demuxers/decoders driving the pipeline + in pull-mode) or something else. - - - - Stream Filler - The filler event is, as the name says, a filler of the - stream which has no special meaning associated with itself. It is used - to provide data to downstream elements and should be interpreted as a - way of assuring that the normal data flow will continue further - downstream. The event is especially intended for real-time MIDI source - elements, which only generate data when something changes. - MIDI decoders will therefore stall if nothing changes for several - seconds, and therefore playback will stop. The filler event is sent - downstream to assure the MIDI decoder that nothing changed, so that the - normal decoding process will continue and playback will, too. Unless - you intend to work with MIDI or other control-language-based data - types, you don't need this event. You can mostly simply forward it - with gst_pad_event_default (). + Seek events are built up using positions in specified formats (time, + bytes, units). They are created using the function + gst_event_new_seek (). Note that many plugins do + not support seeking from the end of the stream or from the current + position. An element not driving the pipeline and forwarding a seek + request should not assume that the seek succeeded or actually happened, + it should operate based on the NEWSEGMENT events it receives. - The stream filler is created using gst_event_new (GST_EVENT_FILLER);. - It has no properties. + Elements parsing this event can do this using + gst_event_parse_seek(). - - Interruption - - The interrupt event is generated by queue elements and sent downstream - if a timeout occurs on the stream. The scheduler will use this event to - get back in its own main loop and schedule other elements. This - prevents deadlocks or a stream stall if no data is generated over a - part of the pipeline for a considerable amount of time. The scheduler - will process this event internally, so any normal elements do not need - to generate or handle this event at all. - + + Navigation - The difference between the filler event and the interrupt event is that - the filler event is a real part of a pipeline, so it will reach fellow - elements, which can use it to "do nothing else than what I used to do". - The interrupt event never reaches fellow elements. + Navigation events are sent upstream by video sinks to inform upstream + elements of where the mouse pointer is, if and where mouse pointer + clicks have happened, or if keys have been pressed or released. - The interrupt event (gst_event_new (GST_EVENT_INTERRUPT);) - has no properties. + All this information is contained in the event structure which can + be obtained with gst_event_get_structure (). - - - - Navigation - WRITEME + Check out the navigationtest element in gst-plugins-good for an idea + how to extract navigation information from this event. @@ -403,13 +387,17 @@ my_filter_some_function (GstMyFilter *filter) The tag event is created using the function - gst_event_new_tag (). It requires a filled - taglist as argument. + gst_event_new_tag (), but more often elements will + use either the gst_element_found_tags () function + or the gst_element_found_tags_for_pad (), which + will do both: post a tag message on the bus and send a tag event + downstream. All of these functions require a filled-in taglist as + argument, which they will take ownership of. Elements parsing this event can use the function - gst_event_tag_get_list (event) to acquire the - taglist that was parsed. + gst_event_parse_tag () to acquire the + taglist that the event contains. diff --git a/docs/pwg/titlepage.xml b/docs/pwg/titlepage.xml index dabdf54..de135ff 100644 --- a/docs/pwg/titlepage.xml +++ b/docs/pwg/titlepage.xml @@ -62,6 +62,16 @@ + + + Tim-Philipp + Müller + + + tim centricular . net + + + -- 2.7.4