building-pads.xml 8.32 KB
Newer Older
1
2
3
4
5
6

<!-- ############ chapter ############# -->

<chapter id="cha-building-pads">
  <title>Specifying the pads</title>
  <para>
7
8
9
10
11
12
13
14
    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 <function>_link ()</function>
    and <function>_getcaps ()</function> functions to let other elements know
    their capabilities and how to register functions to let data flow through
    the element.
15
  </para>
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
  <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>_link ()</function> function pointer and a
    <function>_getcaps ()</function> function pointer. Optionally, you can
    set a <function>_chain ()</function> function pointer (on sink pads in
    filter and sink elements) through which data will come in to the element,
    or (on source pads in source elements) a <function>_get ()</function>
    function pointer through which data will be pulled from the element. After
    that, you have to register the pad with the element. This happens like
    this:
  </para>
  <programlisting>
static GstPadLinkReturn	gst_my_filter_link	(GstPad        *pad,
						 const GstCaps *caps);
static GstCaps *	gst_my_filter_getcaps	(GstPad        *pad);
static void		gst_my_filter_chain	(GstPad        *pad,
						 GstData       *data);

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->sinkpad = gst_pad_new_from_template (
	gst_element_class_get_pad_template (klass, "sink"), "sink");
  gst_pad_set_link_function (filter->sinkpad, gst_my_filter_link);
  gst_pad_set_getcaps_function (filter->sinkpad, gst_my_filter_getcaps);
  gst_pad_set_chain_function (filter->sinkpad, gst_my_filter_chain);
  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);

  /* pad through which data goes out of the element */
  filter->srcpad = gst_pad_new_from_template (
	gst_element_class_get_pad_template (klass, "src"), "src");
  gst_pad_set_link_function (filter->srcpad, gst_my_filter_link);
  gst_pad_set_getcaps_function (filter->srcpad, gst_my_filter_getcaps);
  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
[..]
}
  </programlisting>
  <para>
    The <function>_link ()</function> is called during caps 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="cha-building-types"/>. A <function>_link ()</function>
    receives a pointer to a <classname>GstCaps</classname> struct that
    defines the proposed streamtype, and can respond with either
    <quote>yes</quote> (<classname>GST_PAD_LINK_OK</classname>),
    <quote>no</quote> (<classname>GST_PAD_LINK_REFUSED</classname>) or
    <quote>don't know yet</quote> (<classname>GST_PAD_LINK_DELAYED</classname>).
    If the element responds positively towards the streamtype, that type
    will be used on the pad. An example:
  </para>
  <programlisting>
static GstPadLinkReturn
gst_my_filter_link (GstPad        *pad,
		    const GstCaps *caps)
{
  GstStructure *structure = gst_caps_get_structure (caps, 0);
  GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
  GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
					       filter->srcpad;
  GstPadLinkReturn ret;
  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 GST_PAD_LINK_REFUSED;
  }

  /* 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. */
  ret = gst_pad_try_set_caps (otherpad, gst_caps_copy (caps));
  if (GST_PAD_LINK_FAILED (ret))
    return ret;

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

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

  return ret;
}
  </programlisting>
  <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>
  <para>
    The <function>_getcaps ()</function> funtion is used to request the list
    of supported formats and properties from the element. In some cases, this
    will be equal to the formats provided by the pad template, in which case
    this function can be omitted. In some cases, too, it will not depend on
    anything inside this element, but it will rather depend on the input from
    another element linked to this element's sink or source pads. In that case,
    you can use <function>gst_pad_proxy_getcaps</function> as implementation,
    it provides getcaps forwarding in the core. However, in many cases, the
    format supported by this element cannot be defined externally, but is
    more specific than those provided by the pad template. In this case, you
    should use a <function>_getcaps ()</function> function. In the case as
    specified below, we assume that our filter is able to resample sound, so
    it would be able to provide any samplerate (indifferent from the samplerate
    specified on the other pad) on both pads. It explains how a
    <function>_getcaps ()</function> can be used to do this.
  </para>
  <programlisting>
static GstCaps *
gst_my_filter_getcaps (GstPad *pad)
{
  GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
  GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
					       filter->srcpad;
  GstCaps *othercaps = gst_pad_get_allowed_caps (otherpad), *caps;
  gint n;

  if (gst_caps_is_empty (othercaps))
    return othercaps;

  /* We support *any* samplerate, indifferent from the samplerate
   * supported by the linked elements on both sides. */
  for (i = 0; i < gst_caps_get_size (othercaps); i++) {
    GstStructure *structure = gst_caps_get_structure (othercaps, i);

    gst_structure_remove_field (structure, "rate");
  }
  caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad));
  gst_caps_free (othercaps);

  return caps;
}
  </programlisting>
  <para>
    Obviously, many elements will not need this complex mechanism, because they
    are much simpler than that. They only support one format, or their format
    is fixed but the contents of the format depend on the stream or something
    else. In those cases, <emphasis>explicit caps</emphasis> are an easy way
    of handling caps. Explicit caps are an easy way of specifying one, fixed,
    supported format on a pad. Pads using explicit caps do not implement their
    own <function>_getcaps ()</function> or <function>_link ()</function>
    functions. When the exact format is known, an elements uses
    <function>gst_pad_set_explicit_caps ()</function> to specify the exact
    format. This is very useful for demuxers, for example.
  </para>
  <programlisting>
static void
gst_my_filter_init (GstMyFilter *filter)
{
  GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);
[..]
  filter->srcpad = gst_pad_new_from_template (
	gst_element_class_get_pad_template (klass, "src"), "src");
  gst_pad_use_explicit_caps (filter->srcpad);
[..]
}

static void
gst_my_filter_somefunction (GstMyFilter *filter)
{
  GstCaps *caps = ..;
[..]
  gst_pad_set_explicit_caps (filter->srcpad, caps);
[..]
}
  </programlisting>
194
195
</chapter>