2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
4 * 2005 Wim Taymans <wim@fluendo.com>
5 * 2007 Andy Wingo <wingo at pobox.com>
7 * deinterleave.c: deinterleave samples, based on interleave.c
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
33 #define GST_TYPE_DEINTERLEAVE (gst_deinterleave_get_type())
34 #define GST_DEINTERLEAVE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DEINTERLEAVE,GstDeinterleave))
35 #define GST_DEINTERLEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DEINTERLEAVE,GstDeinterleaveClass))
36 #define GST_DEINTERLEAVE_GET_CLASS(obj) \
37 (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_DEINTERLEAVE,GstDeinterleaveClass))
38 #define GST_IS_DEINTERLEAVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DEINTERLEAVE))
39 #define GST_IS_DEINTERLEAVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEINTERLEAVE))
41 typedef struct _GstDeinterleave GstDeinterleave;
42 typedef struct _GstDeinterleaveClass GstDeinterleaveClass;
45 struct _GstDeinterleave
55 struct _GstDeinterleaveClass
57 GstElementClass parent_class;
61 GST_DEBUG_CATEGORY_STATIC (gst_deinterleave_debug);
62 #define GST_CAT_DEFAULT gst_deinterleave_debug
65 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src%d",
68 GST_STATIC_CAPS ("audio/x-raw-float, "
69 "rate = (int) [ 1, MAX ], "
70 "channels = (int) 1, "
71 "endianness = (int) BYTE_ORDER, " "width = (int) 32")
73 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
76 GST_STATIC_CAPS ("audio/x-raw-float, "
77 "rate = (int) [ 1, MAX ], "
78 "channels = (int) [ 1, MAX ], "
79 "endianness = (int) BYTE_ORDER, " "width = (int) 32")
83 GST_BOILERPLATE (GstDeinterleave, gst_deinterleave, GstElement,
87 static GstFlowReturn gst_deinterleave_chain (GstPad * pad, GstBuffer * buffer);
88 static gboolean gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps);
89 static gboolean gst_deinterleave_sink_activate_push (GstPad * pad,
93 static const GstElementDetails details =
94 GST_ELEMENT_DETAILS ("Audio deinterleaver",
95 "Filter/Converter/Audio",
96 "Splits one interleaved multichannel audio stream into many mono audio streams",
97 "Andy Wingo <wingo at pobox.com>, " "Iain <iain@prettypeople.org>");
100 gst_deinterleave_base_init (gpointer g_class)
102 GST_DEBUG_CATEGORY_INIT (gst_deinterleave_debug, "interleave", 0,
103 "interleave element");
105 gst_element_class_set_details (g_class, &details);
107 gst_element_class_add_pad_template (g_class,
108 gst_static_pad_template_get (&sink_template));
109 gst_element_class_add_pad_template (g_class,
110 gst_static_pad_template_get (&src_template));
114 gst_deinterleave_class_init (GstDeinterleaveClass * klass)
120 gst_deinterleave_init (GstDeinterleave * self, GstDeinterleaveClass * klass)
122 self->sink = gst_pad_new_from_static_template (&sink_template, "sink");
124 gst_pad_set_chain_function (self->sink,
125 GST_DEBUG_FUNCPTR (gst_deinterleave_chain));
126 gst_pad_set_setcaps_function (self->sink,
127 GST_DEBUG_FUNCPTR (gst_deinterleave_sink_setcaps));
128 gst_pad_set_activatepush_function (self->sink,
129 GST_DEBUG_FUNCPTR (gst_deinterleave_sink_activate_push));
131 gst_element_add_pad (GST_ELEMENT (self), self->sink);
135 gst_deinterleave_add_new_pads (GstDeinterleave * self, GstCaps * caps)
140 for (i = 0; i < self->channels; i++) {
141 gchar *name = g_strdup_printf ("src%d", i);
143 pad = gst_pad_new_from_static_template (&src_template, name);
145 gst_pad_set_caps (pad, caps);
146 gst_pad_use_fixed_caps (pad);
147 GST_PAD_UNSET_FLUSHING (pad);
148 gst_element_add_pad (GST_ELEMENT (self), pad);
151 gst_element_no_more_pads (GST_ELEMENT (self));
155 gst_deinterleave_remove_pads (GstDeinterleave * self)
160 elem = GST_ELEMENT (self);
162 GST_INFO_OBJECT (self, "remove_pads()");
164 srcs = g_list_copy (elem->srcpads);
166 for (l = srcs; l; l = l->next)
167 gst_element_remove_pad (elem, GST_PAD (l->data));
169 gst_pad_set_caps (self->sink, NULL);
170 gst_caps_replace (&self->sinkcaps, NULL);
176 gst_deinterleave_sink_setcaps (GstPad * pad, GstCaps * caps)
178 GstDeinterleave *self;
180 self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));
182 if (self->sinkcaps && !gst_caps_is_equal (caps, self->sinkcaps)) {
183 goto cannot_change_caps_dog;
185 GST_DEBUG_OBJECT (self, "got caps: %" GST_PTR_FORMAT, caps);
186 gst_caps_replace (&self->sinkcaps, caps);
193 srccaps = gst_caps_copy (caps);
194 s = gst_caps_get_structure (srccaps, 0);
195 if (!gst_structure_get_int (s, "channels", &self->channels))
197 gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
198 gst_deinterleave_add_new_pads (self, srccaps);
199 gst_caps_unref (srccaps);
202 gst_object_unref (self);
206 cannot_change_caps_dog:
208 gst_object_unref (self);
213 g_warning ("yarr, shiver me timbers");
214 gst_object_unref (self);
220 gst_deinterleave_process (GstDeinterleave * self, GstBuffer * buf)
225 guint bufsize, i, j, channels, pads_pushed, nframes;
226 GstBuffer **buffers_out;
229 elem = GST_ELEMENT (self);
231 channels = self->channels;
232 buffers_out = g_alloca (sizeof (GstBuffer *) * channels);
233 nframes = GST_BUFFER_SIZE (buf) / channels / sizeof (gfloat);
234 bufsize = nframes * sizeof (gfloat);
237 for (i = 0; i < channels; i++)
238 buffers_out[i] = NULL;
240 for (srcs = elem->srcpads, i = 0; srcs; srcs = srcs->next, i++) {
241 GstPad *pad = (GstPad *) srcs->data;
243 buffers_out[i] = NULL;
244 ret = gst_pad_alloc_buffer (pad, -1, bufsize, GST_PAD_CAPS (pad),
247 if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
248 goto alloc_buffer_failed;
249 if (buffers_out[i] && GST_BUFFER_SIZE (buffers_out[i]) != bufsize)
250 goto alloc_buffer_bad_size;
252 if (buffers_out[i]) {
253 GST_BUFFER_TIMESTAMP (buffers_out[i]) = GST_BUFFER_TIMESTAMP (buf);
254 GST_BUFFER_OFFSET (buffers_out[i]) = GST_BUFFER_OFFSET (buf);
255 GST_BUFFER_DURATION (buffers_out[i]) = GST_BUFFER_DURATION (buf);
260 for (srcs = elem->srcpads, i = 0; srcs; srcs = srcs->next, i++) {
261 GstPad *pad = (GstPad *) srcs->data;
263 in = (gfloat *) GST_BUFFER_DATA (buf);
264 in += i; /* gfloat * arith */
265 if (buffers_out[i]) {
266 out = (gfloat *) GST_BUFFER_DATA (buffers_out[i]);
267 for (j = 0; j < nframes; j++)
268 out[j] = in[j * channels];
270 ret = gst_pad_push (pad, buffers_out[i]);
271 buffers_out[i] = NULL;
272 if (ret == GST_FLOW_OK)
274 else if (ret == GST_FLOW_NOT_LINKED)
282 ret = GST_FLOW_NOT_LINKED;
288 GST_WARNING ("gst_pad_alloc_buffer() returned %d", ret);
292 alloc_buffer_bad_size:
294 GST_WARNING ("called alloc_buffer(), but didn't get requested bytes");
295 ret = GST_FLOW_NOT_NEGOTIATED;
300 GST_DEBUG ("push() failed");
305 for (i = 0; i < channels; i++)
307 gst_buffer_unref (buffers_out[i]);
313 gst_deinterleave_chain (GstPad * pad, GstBuffer * buffer)
315 GstDeinterleave *self;
318 self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));
320 ret = gst_deinterleave_process (self, buffer);
322 if (ret != GST_FLOW_OK)
323 GST_WARNING_OBJECT (self, "process failed");
325 gst_object_unref (self);
331 gst_deinterleave_sink_activate_push (GstPad * pad, gboolean active)
333 GstDeinterleave *self;
335 self = GST_DEINTERLEAVE (gst_pad_get_parent (pad));
338 gst_deinterleave_remove_pads (self);
340 gst_object_unref (self);