From: Wim Taymans Date: Mon, 1 Oct 2012 09:24:52 +0000 (+0200) Subject: pwg: fix events and base classes X-Git-Tag: 1.0.1~33 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=94b801aaa9b985c7a70a6afe6fcfcabdd7312fd9;p=platform%2Fupstream%2Fgstreamer.git pwg: fix events and base classes --- diff --git a/docs/pwg/advanced-events.xml b/docs/pwg/advanced-events.xml index b755452..5d10d55 100644 --- a/docs/pwg/advanced-events.xml +++ b/docs/pwg/advanced-events.xml @@ -21,26 +21,26 @@ 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. + (SEGMENT, CAPS, TAG, EOS) are all serialised with the buffer flow. Here is a typical event function: static gboolean -gst_my_filter_sink_event (GstPad *pad, GstEvent * event) +gst_my_filter_sink_event (GstPad *pad, GstObject * parent, GstEvent * event) { GstMyFilter *filter; gboolean ret; - filter = GST_MY_FILTER (gst_pad_get_parent (pad)); + filter = GST_MY_FILTER (parent); ... switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: /* 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 + * (e.g. BYTES to TIME) or drop it and set a flag to send a segment * event in a different format later */ ret = gst_pad_push_event (filter->src_pad, event); break; @@ -54,19 +54,18 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) ret = gst_pad_push_event (filter->src_pad, event); break; default: - ret = gst_pad_event_default (pad, event); + ret = gst_pad_event_default (pad, parent, 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. + segments, caps and the end of the stream. If your element is exclusively loop-based, you may or may not want a @@ -92,18 +91,19 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) will then in turn generate an upstream seek event. - The most common upstream events are seek events and Quality-of-Service - (QoS) events. + The most common upstream events are seek events, Quality-of-Service + (QoS) and reconfigure 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 : + it basically sends the event to the peer of the internally linked 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 : @@ -130,8 +130,9 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) - Always forward events you won't handle upstream using the default - gst_pad_event_default method. + Always handle events you won't handle using the default + gst_pad_event_default method. This method will + depending on the event, forward the event or drop it. @@ -152,10 +153,7 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * 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 (). + appropriate locking everywhere. @@ -173,13 +171,18 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) In this chapter, we will discuss the following events: + + + + + + - + - For more comprehensive information about events and how they should be @@ -187,6 +190,88 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) design documentation. This section only gives a general overview. + + Stream Start + + WRITEME + + + + + Caps + + WRITEME + + + + + Segment + + A segment event is sent downstream to announce the range of valid + timestamps in the stream and how they should be transformed into + running-time and stream-time. A segment event must always be sent + before the first buffer of data and after a flush (see above). + + + The first 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 segment event then travels down the + pipeline and may be transformed on the way (a decoder, for example, + might receive a segment event in BYTES format and might transform + this into a segment event in TIMES format based on the average + bitrate). + + + Depending on the element type, the event can simply be forwarded using + gst_pad_event_default (), or it should be parsed + and a modified event should be sent on. The last is true for demuxers, + 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 segment events in time units, so that + it can be used to synchronize against the pipeline clock. Therefore, + demuxers and similar elements should not forward the event, but parse + it, free it and send a segment event (in time units, + GST_FORMAT_TIME) further downstream. + + + The segment event is created using the function + gst_event_new_segment (). See the API + reference and design document for details about its parameters. + + + Elements parsing this event can use gst_event_parse_segment() + 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). + + + + + Tag (metadata) + + Tagging events are being sent downstream to indicate the tags as parsed + from the stream data. This is currently used to preserve tags during + stream transcoding from one format to the other. Tags are discussed + extensively in . Most + elements will simply forward the event by calling + gst_pad_event_default (). + + + The tag event is created using the function + gst_event_new_tag (), but more often elements will + send a tag event downstream that will be converted into a message + on the bus by sink elements. + 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_parse_tag () to acquire the + taglist that the event contains. + + + End of Stream (EOS) @@ -217,16 +302,31 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) 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_EOS in - your create function (assuming your element derives from GstBaseSrc - or GstPushSrc). + your create or fill function (assuming your element derives from + GstBaseSrc or GstPushSrc). + + + + + Table Of Contents + + WRITEME + + + + + Gap + + WRITEME Flush Start - The flush start event is sent downstream if all buffers and caches - in the pipeline should be emptied. Queue elements will + The flush start event is sent downstream (in push mode) or upstream + (in pull mode) 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 the kernel-to-disk cache (fdatasync () or @@ -259,7 +359,7 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) 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). + least a SEGMENT event before any buffers first though). If your element keeps temporary caches of stream data, it should @@ -268,58 +368,17 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) The flush-stop event is created with - gst_event_new_flush_stop (). Like the EOS event, - it has no properties. + gst_event_new_flush_stop (). It has one + parameter that controls if the running-time of the pipeline should + be reset to 0 or not. Normally aftera flushing seek, the + running_time is set back to 0. - - 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). - + + Quality Of Service (QOS) - 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 - gst_pad_event_default (), or it should be parsed - and a modified event should be sent on. The last is true for demuxers, - 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 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 newsegment event (in time units, - GST_FORMAT_TIME) further downstream. - - - 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. - - - 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). + WRITEME @@ -330,9 +389,9 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) This new position can be set in several formats (time, bytes or 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 + respect to the end-of-file or start-of-file, and usually happens in upstream direction (downstream seeking is done by - sending a NEWSEGMENT event with the appropriate offsets for elements + sending a SEGMENT event with the appropriate offsets for elements that support that, like filesink). @@ -347,10 +406,10 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) 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 + not support seeking from the end of the stream. + 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. + it should operate based on the SEGMENT events it receives. Elements parsing this event can do this using @@ -375,30 +434,5 @@ gst_my_filter_sink_event (GstPad *pad, GstEvent * event) - - Tag (metadata) - - Tagging events are being sent downstream to indicate the tags as parsed - from the stream data. This is currently used to preserve tags during - stream transcoding from one format to the other. Tags are discussed - extensively in . Most - elements will simply forward the event by calling - gst_pad_event_default (). - - - The tag event is created using the function - 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_parse_tag () to acquire the - taglist that the event contains. - - diff --git a/docs/pwg/other-base.xml b/docs/pwg/other-base.xml index e8ac480..484f436 100644 --- a/docs/pwg/other-base.xml +++ b/docs/pwg/other-base.xml @@ -35,6 +35,10 @@ automatically. + The base class implement much of the synchronization logic that a + sink has to perform. + + The GstBaseSink base-class specifies some limitations on elements, though: @@ -42,26 +46,8 @@ It requires that the sink only has one sinkpad. Sink elements that - need more than one sinkpad, cannot use this base-class. - - - - - The base-class owns the pad, and specifies caps negotiation, data - handling, pad allocation and such functions. If you need more than - the ones provided as virtual functions, then you cannot use this - base-class. - - - - - By implementing the pad_allocate () function, - it is possible for upstream elements to use special memory, such - as memory on the X server side that only the sink can allocate, or - even hardware memory mmap ()'ed from the kernel. - Note that in almost all cases, you will want to subclass the - GstBuffer object, so that your own set of - functions will be called when the buffer loses its last reference. + need more than one sinkpad, must make a manager element with + multiple GstBaseSink elements inside. @@ -109,13 +95,19 @@ gst_my_sink_class_init (GstMySinkClass * klass) Writing an audio sink Essentially, audio sink implementations are just a special case of a - general sink. There are two audio base classes that you can choose to + general sink. An audio sink has the added complexity that it needs to + schedule playback of samples. It must match the clock selected in the + pipeline against the clock of the audio device and calculate and + compensate for drift and jitter. + + + There are two audio base classes that you can choose to derive from, depending on your needs: - GstBaseAudiosink and - GstAudioSink. The baseaudiosink provides full + GstAudioBasesink and + GstAudioSink. The audiobasesink provides full control over how synchronization and scheduling is handled, by using a ringbuffer that the derived class controls and provides. The - audiosink base-class is a derived class of the baseaudiosink, + audiosink base-class is a derived class of the audiobasesink, implementing a standard ringbuffer implementing default synchronization and providing a standard audio-sample clock. Derived classes of this base class merely need to provide a _open @@ -123,7 +115,7 @@ gst_my_sink_class_init (GstMySinkClass * klass) () function implementation, and some optional functions. This should suffice for many sound-server output elements and even most interfaces. More demanding audio systems, such as Jack, would - want to implement the GstBaseAudioSink + want to implement the GstAudioBaseSink base-class. @@ -243,15 +235,9 @@ gst_my_sink_class_init (GstMySinkClass * klass) There is one and only one sourcepad. Source elements requiring - multiple sourcepads cannot use this base-class. - - - - - Since the base-class owns the pad and derived classes can only - control it as far as the virtual functions allow, you are limited - to the functionality provided by the virtual functions. If you need - more, you cannot use this base-class. + multiple sourcepads must implement a manager bin and use multiple + source elements internally or make a manager element that uses + a source element and a demuxer inside. @@ -259,9 +245,6 @@ gst_my_sink_class_init (GstMySinkClass * klass) It is possible to use special memory, such as X server memory pointers or mmap ()'ed memory areas, as data pointers in buffers returned from the create() virtual function. - In almost all cases, you will want to subclass - GstBuffer so that your own set of functions can - be called when the buffer is destroyed. @@ -275,7 +258,7 @@ gst_my_sink_class_init (GstMySinkClass * klass) linkend="section-base-audiosink"/>; one is ringbuffer-based, and requires the derived class to take care of its own scheduling, synchronization and such. The other is based on this - GstBaseAudioSrc and is called + GstAudioBaseSrc and is called GstAudioSrc, and provides a simple open (), close () and read () interface, which is rather simple to