diff --git a/ChangeLog b/ChangeLog index 894187d6ce..c6f5b68b11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-01-29 Julien MOUTTE + + * docs/pwg/advanced-events.xml: Adding documentation on advanced event + handling (up and downstream). + * docs/pwg/advanced-interfaces.xml: Make it coherent with the + my_filter thing. + 2004-01-29 Ronald Bultje * docs/pwg/advanced-tagging.xml: diff --git a/docs/pwg/advanced-events.xml b/docs/pwg/advanced-events.xml index 884c5329b4..df7c77e7f4 100644 --- a/docs/pwg/advanced-events.xml +++ b/docs/pwg/advanced-events.xml @@ -1,6 +1,154 @@ Events: Seeking, Navigation and More - WRITEME + There are many different event types but only 2 ways they can travel accross + 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 + 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. + + 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 dowstream using + gst_pad_event_default. Here is an example for both + loop and chain based elements. + + 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; + } + ... +} + ]]> + + + 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 + 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 : + + + + + 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. + + + + + If you need to handle that event locally. For example a navigation + event that you will want to convert before sending it upstream. + + + + + The processing you will do in that event handler does not really matter + but there are important rules you have to absolutely respect because + one broken element event handler is breaking the whole pipeline event + handling. Here they are : + + + + + Always forward events you won't handle upstream using the default + gst_pad_event_default method. + + + + + If you are generating some new event based on the one you received + don't forget to gst_event_unref the event you received. + + + + + Event handler function are supposed to return TRUE or FALSE indicating + if the event has been handled or not. Never simply return TRUE/FALSE + in that handler except if you really know that you have handled that + event. + + + + + Here is an example of correct upstream event handling for a plugin + that wants to modify navigation events. + + + diff --git a/docs/pwg/advanced-interfaces.xml b/docs/pwg/advanced-interfaces.xml index c7a3788b5f..fdf9a4c123 100644 --- a/docs/pwg/advanced-interfaces.xml +++ b/docs/pwg/advanced-interfaces.xml @@ -490,31 +490,31 @@ gst_my_filter_probe_interface_init (GstPropertyProbeInterface *iface) window) - gst_myplugin_destroy_window (myplugin->window); + GstMyFilter *my_filter = GST_MY_FILTER (overlay); + + if (my_filter->window) + gst_my_filter_destroy_window (my_filter->window); - myplugin->window = xwindow_id; + my_filter->window = xwindow_id; } static void -gst_myplugin_get_desired_size (GstXOverlay *overlay, - guint *width, guint *height) +gst_my_filter_get_desired_size (GstXOverlay *overlay, + guint *width, guint *height) { - GstMyPlugin *my_plugin = GST_MYPLUGIN (overlay); + GstMyFilter *my_filter = GST_MY_FILTER (overlay); - *width = my_plugin->width; - *height = my_plugin->height; + *width = my_filter->width; + *height = my_filter->height; } static void -gst_myplugin_xoverlay_init (GstXOverlayClass *iface) +gst_my_filter_xoverlay_init (GstXOverlayClass *iface) { - iface->set_xwindow_id = gst_myplugin_set_xwindow_id; - iface->get_desired_size = gst_myplugin_get_desired_size; + iface->set_xwindow_id = gst_my_filter_set_xwindow_id; + iface->get_desired_size = gst_my_filter_get_desired_size; } ]]> @@ -523,18 +523,18 @@ gst_myplugin_xoverlay_init (GstXOverlayClass *iface) geometry and maybe create the window. win); + gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (my_filter), window->win); } static GstPadLinkReturn -gst_myplugin_sinkconnect (GstPad *pad, const GstCaps *caps) +gst_my_filter_sink_link (GstPad *pad, const GstCaps *caps) { - GstMyPlugin *my_plugin = GST_MYPLUGIN (overlay); + GstMyFilter *my_filter = GST_MY_FILTER (overlay); gint width, height; gboolean ret; ... @@ -542,10 +542,10 @@ gst_myplugin_sinkconnect (GstPad *pad, const GstCaps *caps) ret &= gst_structure_get_int (structure, "height", &height); if (!ret) return GST_PAD_LINK_REFUSED; - if (!my_plugin->window) - my_plugin->window = gst_myplugin_create_window (my_plugin, width, height); + if (!my_filter->window) + my_filter->window = gst_my_filter_create_window (my_filter, width, height); - gst_x_overlay_got_desired_size (GST_X_OVERLAY (my_plugin), + gst_x_overlay_got_desired_size (GST_X_OVERLAY (my_filter), width, height); ... }