| |
| <!-- ############ chapter ############# --> |
| |
| <chapter id="chapter-building-pads"> |
| <title>Specifying the pads</title> |
| <para> |
| As explained before, pads are the port through which data goes in and out |
| of your element, and that makes them a very important item in the process |
| of element creation. In the boilerplate code, we have seen how static pad |
| templates take care of registering pad templates with the element class. |
| Here, we will see how to create actual elements, use an <function>_event |
| ()</function>-function to configure for a particular format and how to |
| register functions to let data flow through the element. |
| </para> |
| <para> |
| In the element <function>_init ()</function> function, you create the pad |
| from the pad template that has been registered with the element class in |
| the <function>_class_init ()</function> function. After creating the pad, |
| you have to set a <function>_chain ()</function> function pointer that will |
| receive and process the input data on the sinkpad. |
| You can optionally also set an <function>_event ()</function> function |
| pointer and a <function>_query ()</function> function pointer. |
| Alternatively, pads can also operate in looping mode, which means that they |
| can pull data themselves. More on this topic later. After that, you have |
| to register the pad with the element. This happens like this: |
| </para> |
| <programlisting><!-- example-begin init.func a --><!-- |
| #include "filter.h" |
| #include <string.h> |
| |
| static GstStateChangeReturn |
| gst_my_filter_change_state (GstElement * element, GstStateChange transition); |
| |
| G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT); |
| |
| static void |
| gst_my_filter_class_init (gpointer klass) |
| { |
| GstElementClass *element_class = GST_ELEMENT_CLASS (klass); |
| static GstStaticPadTemplate sink_template = |
| GST_STATIC_PAD_TEMPLATE ( |
| "sink", |
| GST_PAD_SINK, |
| GST_PAD_ALWAYS, |
| GST_STATIC_CAPS ("ANY") |
| ); |
| static GstStaticPadTemplate src_template = |
| GST_STATIC_PAD_TEMPLATE ( |
| "src", |
| GST_PAD_SRC, |
| GST_PAD_ALWAYS, |
| GST_STATIC_CAPS ("ANY") |
| ); |
| |
| gst_element_class_set_static_metadata (element_class, |
| "An example plugin", |
| "Example/FirstExample", |
| "Shows the basic structure of a plugin", |
| "your name <your.name@your.isp>"); |
| |
| gst_element_class_add_pad_template (element_class, |
| gst_static_pad_template_get (&src_template)); |
| gst_element_class_add_pad_template (element_class, |
| gst_static_pad_template_get (&sink_template)); |
| } |
| |
| static void |
| gst_my_filter_class_init (GstMyFilterClass * klass) |
| { |
| GST_ELEMENT_CLASS (klass)->change_state = gst_my_filter_change_state; |
| } |
| --><!-- example-end init.func a --> |
| <!-- example-begin init.func c --><!-- |
| static GstFlowReturn gst_my_filter_chain (GstPad *pad, |
| GstObject *parent, |
| GstBuffer *buf); |
| static gboolean gst_my_filter_sink_event (GstPad *pad, |
| GstObject *parent, |
| GstEvent *event); |
| static gboolean gst_my_filter_src_query (GstPad *pad, |
| GstObject *parent, |
| GstQuery *query); |
| static gboolean gst_my_filter_sink_query (GstPad *pad, |
| GstObject *parent, |
| GstQuery *query); |
| --><!-- example-end init.func c --> |
| <!-- example-begin init.func d --> |
| |
| static void |
| gst_my_filter_init (GstMyFilter *filter) |
| { |
| /* pad through which data comes in to the element */ |
| filter->sinkpad = gst_pad_new_from_static_template ( |
| &sink_template, "sink"); |
| /* pads are configured here with gst_pad_set_*_function () */ |
| <!-- example-end init.func d --> |
| <!-- example-begin init.func e --><!-- |
| gst_pad_set_chain_function (filter->sinkpad, gst_my_filter_chain); |
| gst_pad_set_event_function (filter->sinkpad, gst_my_filter_sink_event); |
| gst_pad_set_query_function (filter->sinkpad, gst_my_filter_sink_query); |
| --><!-- example-end init.func e --> |
| <!-- example-begin init.func f --> |
| gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); |
| |
| /* pad through which data goes out of the element */ |
| filter->srcpad = gst_pad_new_from_static_template ( |
| &src_template, "src"); |
| /* pads are configured here with gst_pad_set_*_function () */ |
| <!-- example-end init.func f --> |
| <!-- example-begin init.func g --><!-- |
| gst_pad_set_query_function (filter->srcpad, gst_my_filter_src_query); |
| --><!-- example-end init.func g --> |
| <!-- example-begin init.func h --> |
| gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); |
| |
| /* properties initial value */ |
| filter->silent = FALSE; |
| } |
| <!-- example-end init.func h --></programlisting> |
| |
| <!-- example-begin pads.c --><!-- |
| #include "init.func" |
| |
| static gboolean |
| gst_my_filter_event (GstPad * pad, GstObject * parent, GstEvent * event) |
| { |
| return gst_pad_event_default (pad, parent, event); |
| } |
| |
| static GstFlowReturn |
| gst_my_filter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) |
| { |
| return gst_pad_push (GST_MY_FILTER (parent)->srcpad, buf); |
| } |
| |
| static GstStateChangeReturn |
| gst_my_filter_change_state (GstElement * element, GstStateChange transition) |
| { |
| return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, |
| change_state, (element, transition), GST_STATE_CHANGE_SUCCESS); |
| } |
| |
| #include "register.func" |
| --><!-- example-end pads.c --> |
| </chapter> |
| |