summaryrefslogtreecommitdiff
path: root/docs/pwg/building-pads.xml
blob: ddd2df2d8a8fa923a178989b51e7d42a8fcd7137 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

<!-- ############ 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 a <function>_setcaps
    ()</function>-functions 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>_base_init ()</function> function. After creating the pad,
    you have to set a <function>_setcaps ()</function> function pointer and
    optionally a <function>_getcaps ()</function> function pointer. Also, you
    have to set a <function>_chain ()</function> function pointer.
    Alternatively, pads can also operate in looping mode, which mans 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 &lt;string.h&gt;

static GstStateChangeReturn
gst_my_filter_change_state (GstElement * element, GstStateChange transition);

GST_BOILERPLATE (GstMyFilter, gst_my_filter, GstElement, GST_TYPE_ELEMENT);

static void
gst_my_filter_base_init (gpointer klass)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  static GstElementDetails my_filter_details = {
    "An example plugin",
    "Example/FirstExample",
    "Shows the basic structure of a plugin",
    "your name <your.name@your.isp>"
  };
  static GstStaticPadTemplate sink_factory =
  GST_STATIC_PAD_TEMPLATE (
    "sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
  );
  static GstStaticPadTemplate src_factory =
  GST_STATIC_PAD_TEMPLATE (
    "src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
  );

  gst_element_class_set_details (element_class, &my_filter_details);
  gst_element_class_add_pad_template (element_class,
        gst_static_pad_template_get (&src_factory));
  gst_element_class_add_pad_template (element_class,
        gst_static_pad_template_get (&sink_factory));
}

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 b -->
static gboolean		gst_my_filter_setcaps	(GstPad        *pad,
						 GstCaps       *caps);
static GstFlowReturn	gst_my_filter_chain	(GstPad        *pad,
						 GstBuffer     *buf);
<!-- example-end init.func b -->
<!-- example-begin init.func c --><!--
static GstCaps *	gst_my_filter_getcaps	(GstPad        *pad);
static gboolean		gst_my_filter_event	(GstPad        *pad,
						 GstEvent      *event);
--><!-- example-end init.func c -->
<!-- example-begin init.func d -->

static void
gst_my_filter_init (GstMyFilter *filter)
{
  GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);

  /* pad through which data comes in to the element */
  filter-&gt;sinkpad = gst_pad_new_from_template (
	gst_element_class_get_pad_template (klass, "sink"), "sink");
  gst_pad_set_setcaps_function (filter-&gt;sinkpad, gst_my_filter_setcaps);
  gst_pad_set_chain_function (filter-&gt;sinkpad, gst_my_filter_chain);
<!-- example-end init.func d -->
<!-- example-begin init.func e --><!--
  gst_pad_set_getcaps_function (filter-&gt;sinkpad, gst_my_filter_getcaps);
  gst_pad_set_event_function (filter-&gt;sinkpad, gst_my_filter_event);
--><!-- example-end init.func e -->
<!-- example-begin init.func f -->
  gst_element_add_pad (GST_ELEMENT (filter), filter-&gt;sinkpad);

  /* pad through which data goes out of the element */
  filter-&gt;srcpad = gst_pad_new_from_template (
	gst_element_class_get_pad_template (klass, "src"), "src");
<!-- example-end init.func f -->
<!-- example-begin init.func g --><!--
  gst_pad_set_getcaps_function (filter-&gt;srcpad, gst_my_filter_getcaps);
--><!-- example-end init.func g -->
<!-- example-begin init.func h -->
  gst_element_add_pad (GST_ELEMENT (filter), filter-&gt;srcpad);

  /* properties initial value */
  filter->silent = FALSE;
}
  <!-- example-end init.func h --></programlisting>

  <sect1 id="section-pads-linkfn" xreflabel="The link function">
  <title>The setcaps-function</title>
  <para>
    The <function>_setcaps ()</function>-function is called during caps
    negotiation, which is discussed in great detail in <xref
    linkend="chapter-negotiation"/>. This is the process where the linked
    pads decide on the streamtype that will transfer between them. A full
    list of type-definitions can be found in <xref
    linkend="chapter-building-types"/>. A <function>_link ()</function>
    receives a pointer to a <ulink type="http"
    url="../../gstreamer/html/gstreamer-GstCaps.html"><classname>GstCaps</classname></ulink>
    struct that defines the proposed streamtype, and can respond with
    either <quote>yes</quote> (<symbol>TRUE</symbol>) or <quote>no</quote>
    (<symbol>FALSE</symbol>). If the element responds positively towards
    the streamtype, that type will be used on the pad. An example:
  </para>
  <programlisting><!-- example-begin caps.func a -->
static gboolean
gst_my_filter_setcaps (GstPad  *pad,
		       GstCaps *caps)
{
  GstStructure *structure = gst_caps_get_structure (caps, 0);
  GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
  const gchar *mime;

  /* Since we're an audio filter, we want to handle raw audio
   * and from that audio type, we need to get the samplerate and
   * number of channels. */
  mime = gst_structure_get_name (structure);
  if (strcmp (mime, "audio/x-raw-int") != 0) {
    GST_WARNING ("Wrong mimetype %s provided, we only support %s",
		 mime, "audio/x-raw-int");
    return FALSE;
  }

  /* we're a filter and don't touch the properties of the data.
   * That means we can set the given caps unmodified on the next
   * element, and use that negotiation return value as ours. */
  if (!gst_pad_set_caps (filter-&gt;srcpad, caps))
    return FALSE;

  /* Capsnego succeeded, get the stream properties for internal
   * usage and return success. */
  gst_structure_get_int (structure, "rate", &amp;filter-&gt;samplerate);
  gst_structure_get_int (structure, "channels", &amp;filter-&gt;channels);

  g_print ("Caps negotiation succeeded with %d Hz @ %d channels\n",
	   filter-&gt;samplerate, filter-&gt;channels);

  return TRUE;
}
<!-- example-end caps.func a -->
<!-- example-begin caps.func b --><!--
static GstCaps *
gst_my_filter_getcaps (GstPad * pad)
{
  GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
  GstPad *otherpad = (pad == filter-&gt;srcpad) ? filter-&gt;sinkpad :
						  filter-&gt;srcpad;
  GstCaps *othercaps = gst_pad_get_allowed_caps (otherpad);

  return othercaps;
}
  --><!-- example-end caps.func b --></programlisting>
  <para>
    In here, we check the mimetype of the provided caps. Normally, you don't
    need to do that in your own plugin/element, because the core does that
    for you. We simply use it to show how to retrieve the mimetype from a
    provided set of caps. Types are stored in <ulink type="http"
    url="../../gstreamer/html/gstreamer-GstStructure.html"><classname>GstStructure
    </classname></ulink> internally. A <ulink
    type="http" url="../../gstreamer/html/gstreamer-GstCaps.html"><classname>GstCaps
    </classname></ulink> is nothing more than a small
    wrapper for 0 or more structures/types. From the structure, you can also
    retrieve properties, as is shown above with the function
    <function>gst_structure_get_int ()</function>.
  </para>
  <para>
    If your <function>_link ()</function> function does not need to perform
    any specific operation (i.e. it will only forward caps), you can set it
    to <function>gst_pad_proxy_link ()</function>. This is a link forwarding
    function implementation provided by the core. It is useful for elements
    such as <classname>identity</classname>.
  </para>
  </sect1>
<!-- example-begin pads.c --><!--
#include "init.func"
#include "caps.func"

static gboolean
gst_my_filter_event (GstPad * pad, GstEvent * event)
{
  return gst_pad_event_default (pad, event);
}

static GstFlowReturn
gst_my_filter_chain (GstPad * pad, GstBuffer * buf)
{
  return gst_pad_push (GST_MY_FILTER (GST_OBJECT_PARENT (pad))->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>