Tizen 2.0 Release
[framework/multimedia/gst-plugins-good0.10.git] / gst / interleave / interleave.c
1 /* GStreamer
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>
6  *                    2008 Sebastian Dröge <slomo@circular-chaos.rg>
7  *
8  * interleave.c: interleave samples, mostly based on adder.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 /* TODO:
27  *       - handle caps changes
28  *       - handle more queries/events
29  */
30
31 /**
32  * SECTION:element-interleave
33  * @see_also: deinterleave
34  *
35  * Merges separate mono inputs into one interleaved stream.
36  * 
37  * This element handles all raw floating point sample formats and all signed integer sample formats. The first
38  * caps on one of the sinkpads will set the caps of the output so usually an audioconvert element should be
39  * placed before every sinkpad of interleave.
40  * 
41  * It's possible to change the number of channels while the pipeline is running by adding or removing
42  * some of the request pads but this will change the caps of the output buffers. Changing the input
43  * caps is _not_ supported yet.
44  * 
45  * The channel number of every sinkpad in the out can be retrieved from the "channel" property of the pad.
46  * 
47  * <refsect2>
48  * <title>Example launch line</title>
49  * |[
50  * gst-launch filesrc location=file.mp3 ! decodebin ! audioconvert ! "audio/x-raw-int,channels=2" ! deinterleave name=d  interleave name=i ! audioconvert ! wavenc ! filesink location=test.wav    d.src0 ! queue ! audioconvert ! i.sink1    d.src1 ! queue ! audioconvert ! i.sink0
51  * ]| Decodes and deinterleaves a Stereo MP3 file into separate channels and
52  * then interleaves the channels again to a WAV file with the channel with the
53  * channels exchanged.
54  * |[
55  * gst-launch interleave name=i ! audioconvert ! wavenc ! filesink location=file.wav  filesrc location=file1.wav ! decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.sink0   filesrc location=file2.wav ! decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.sink1
56  * ]| Interleaves two Mono WAV files to a single Stereo WAV file.
57  * </refsect2>
58  */
59
60 #ifdef HAVE_CONFIG_H
61 #  include "config.h"
62 #endif
63
64 #include <gst/gst.h>
65 #include <string.h>
66 #include "interleave.h"
67
68 #include <gst/audio/multichannel.h>
69
70 GST_DEBUG_CATEGORY_STATIC (gst_interleave_debug);
71 #define GST_CAT_DEFAULT gst_interleave_debug
72
73 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink%d",
74     GST_PAD_SINK,
75     GST_PAD_REQUEST,
76     GST_STATIC_CAPS ("audio/x-raw-int, "
77         "rate = (int) [ 1, MAX ], "
78         "channels = (int) 1, "
79         "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
80         "width = (int) { 8, 16, 24, 32 }, "
81         "depth = (int) [ 1, 32 ], "
82         "signed = (boolean) true; "
83         "audio/x-raw-float, "
84         "rate = (int) [ 1, MAX ], "
85         "channels = (int) 1, "
86         "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, "
87         "width = (int) { 32, 64 }")
88     );
89
90 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
91     GST_PAD_SRC,
92     GST_PAD_ALWAYS,
93     GST_STATIC_CAPS ("audio/x-raw-int, "
94         "rate = (int) [ 1, MAX ], "
95         "channels = (int) [ 1, MAX ], "
96         "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
97         "width = (int) { 8, 16, 24, 32 }, "
98         "depth = (int) [ 1, 32 ], "
99         "signed = (boolean) true; "
100         "audio/x-raw-float, "
101         "rate = (int) [ 1, MAX ], "
102         "channels = (int) [ 1, MAX ], "
103         "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, "
104         "width = (int) { 32, 64 }")
105     );
106
107 #define MAKE_FUNC(type) \
108 static void interleave_##type (guint##type *out, guint##type *in, \
109     guint stride, guint nframes) \
110 { \
111   gint i; \
112   \
113   for (i = 0; i < nframes; i++) { \
114     *out = in[i]; \
115     out += stride; \
116   } \
117 }
118
119 MAKE_FUNC (8);
120 MAKE_FUNC (16);
121 MAKE_FUNC (32);
122 MAKE_FUNC (64);
123
124 static void
125 interleave_24 (guint8 * out, guint8 * in, guint stride, guint nframes)
126 {
127   gint i;
128
129   for (i = 0; i < nframes; i++) {
130     memcpy (out, in, 3);
131     out += stride * 3;
132     in += 3;
133   }
134 }
135
136 typedef struct
137 {
138   GstPad parent;
139   guint channel;
140 } GstInterleavePad;
141
142 enum
143 {
144   PROP_PAD_0,
145   PROP_PAD_CHANNEL
146 };
147
148 static void gst_interleave_pad_class_init (GstPadClass * klass);
149
150 #define GST_TYPE_INTERLEAVE_PAD (gst_interleave_pad_get_type())
151 #define GST_INTERLEAVE_PAD(pad) (G_TYPE_CHECK_INSTANCE_CAST((pad),GST_TYPE_INTERLEAVE_PAD,GstInterleavePad))
152 #define GST_INTERLEAVE_PAD_CAST(pad) ((GstInterleavePad *) pad)
153 #define GST_IS_INTERLEAVE_PAD(pad) (G_TYPE_CHECK_INSTANCE_TYPE((pad),GST_TYPE_INTERLEAVE_PAD))
154 static GType
155 gst_interleave_pad_get_type (void)
156 {
157   static GType type = 0;
158
159   if (G_UNLIKELY (type == 0)) {
160     type = g_type_register_static_simple (GST_TYPE_PAD,
161         g_intern_static_string ("GstInterleavePad"), sizeof (GstPadClass),
162         (GClassInitFunc) gst_interleave_pad_class_init,
163         sizeof (GstInterleavePad), NULL, 0);
164   }
165   return type;
166 }
167
168 static void
169 gst_interleave_pad_get_property (GObject * object,
170     guint prop_id, GValue * value, GParamSpec * pspec)
171 {
172   GstInterleavePad *self = GST_INTERLEAVE_PAD (object);
173
174   switch (prop_id) {
175     case PROP_PAD_CHANNEL:
176       g_value_set_uint (value, self->channel);
177       break;
178     default:
179       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
180       break;
181   }
182 }
183
184 static void
185 gst_interleave_pad_class_init (GstPadClass * klass)
186 {
187   GObjectClass *gobject_class = (GObjectClass *) klass;
188
189   gobject_class->get_property = gst_interleave_pad_get_property;
190
191   g_object_class_install_property (gobject_class,
192       PROP_PAD_CHANNEL,
193       g_param_spec_uint ("channel",
194           "Channel number",
195           "Number of the channel of this pad in the output", 0, G_MAXUINT, 0,
196           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
197 }
198
199 GST_BOILERPLATE (GstInterleave, gst_interleave, GstElement, GST_TYPE_ELEMENT);
200
201 enum
202 {
203   PROP_0,
204   PROP_CHANNEL_POSITIONS,
205   PROP_CHANNEL_POSITIONS_FROM_INPUT
206 };
207
208 static void gst_interleave_set_property (GObject * object,
209     guint prop_id, const GValue * value, GParamSpec * pspec);
210 static void gst_interleave_get_property (GObject * object,
211     guint prop_id, GValue * value, GParamSpec * pspec);
212
213 static GstPad *gst_interleave_request_new_pad (GstElement * element,
214     GstPadTemplate * templ, const gchar * name);
215 static void gst_interleave_release_pad (GstElement * element, GstPad * pad);
216
217 static GstStateChangeReturn gst_interleave_change_state (GstElement * element,
218     GstStateChange transition);
219
220 static gboolean gst_interleave_src_query (GstPad * pad, GstQuery * query);
221
222 static gboolean gst_interleave_src_event (GstPad * pad, GstEvent * event);
223
224 static gboolean gst_interleave_sink_event (GstPad * pad, GstEvent * event);
225
226 static gboolean gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps);
227
228 static GstCaps *gst_interleave_sink_getcaps (GstPad * pad);
229
230 static GstFlowReturn gst_interleave_collected (GstCollectPads * pads,
231     GstInterleave * self);
232
233 static void
234 gst_interleave_finalize (GObject * object)
235 {
236   GstInterleave *self = GST_INTERLEAVE (object);
237
238   if (self->collect) {
239     gst_object_unref (self->collect);
240     self->collect = NULL;
241   }
242
243   if (self->channel_positions
244       && self->channel_positions != self->input_channel_positions) {
245     g_value_array_free (self->channel_positions);
246     self->channel_positions = NULL;
247   }
248
249   if (self->input_channel_positions) {
250     g_value_array_free (self->input_channel_positions);
251     self->input_channel_positions = NULL;
252   }
253
254   gst_caps_replace (&self->sinkcaps, NULL);
255
256   G_OBJECT_CLASS (parent_class)->finalize (object);
257 }
258
259 static gboolean
260 gst_interleave_check_channel_positions (GValueArray * positions)
261 {
262   gint i;
263   guint channels;
264   GstAudioChannelPosition *pos;
265   gboolean ret;
266
267   channels = positions->n_values;
268   pos = g_new (GstAudioChannelPosition, positions->n_values);
269
270   for (i = 0; i < channels; i++) {
271     GValue *v = g_value_array_get_nth (positions, i);
272
273     pos[i] = g_value_get_enum (v);
274   }
275
276   ret = gst_audio_check_channel_positions (pos, channels);
277   g_free (pos);
278
279   return ret;
280 }
281
282 static void
283 gst_interleave_set_channel_positions (GstInterleave * self, GstStructure * s)
284 {
285   GValue pos_array = { 0, };
286   gint i;
287
288   g_value_init (&pos_array, GST_TYPE_ARRAY);
289
290   if (self->channel_positions
291       && self->channels == self->channel_positions->n_values
292       && gst_interleave_check_channel_positions (self->channel_positions)) {
293     GST_DEBUG_OBJECT (self, "Using provided channel positions");
294     for (i = 0; i < self->channels; i++)
295       gst_value_array_append_value (&pos_array,
296           g_value_array_get_nth (self->channel_positions, i));
297   } else {
298     GValue pos_none = { 0, };
299
300     GST_WARNING_OBJECT (self, "Using NONE channel positions");
301
302     g_value_init (&pos_none, GST_TYPE_AUDIO_CHANNEL_POSITION);
303     g_value_set_enum (&pos_none, GST_AUDIO_CHANNEL_POSITION_NONE);
304
305     for (i = 0; i < self->channels; i++)
306       gst_value_array_append_value (&pos_array, &pos_none);
307
308     g_value_unset (&pos_none);
309   }
310   gst_structure_set_value (s, "channel-positions", &pos_array);
311   g_value_unset (&pos_array);
312 }
313
314 static void
315 gst_interleave_base_init (gpointer g_class)
316 {
317   gst_element_class_set_details_simple (g_class, "Audio interleaver",
318       "Filter/Converter/Audio",
319       "Folds many mono channels into one interleaved audio stream",
320       "Andy Wingo <wingo at pobox.com>, "
321       "Sebastian Dröge <slomo@circular-chaos.org>");
322
323   gst_element_class_add_static_pad_template (g_class, &sink_template);
324   gst_element_class_add_static_pad_template (g_class, &src_template);
325 }
326
327 static void
328 gst_interleave_class_init (GstInterleaveClass * klass)
329 {
330   GstElementClass *gstelement_class;
331   GObjectClass *gobject_class;
332
333   gobject_class = G_OBJECT_CLASS (klass);
334   gstelement_class = GST_ELEMENT_CLASS (klass);
335
336   GST_DEBUG_CATEGORY_INIT (gst_interleave_debug, "interleave", 0,
337       "interleave element");
338
339   /* Reference GstInterleavePad class to have the type registered from
340    * a threadsafe context
341    */
342   g_type_class_ref (GST_TYPE_INTERLEAVE_PAD);
343
344   gobject_class->finalize = gst_interleave_finalize;
345   gobject_class->set_property = gst_interleave_set_property;
346   gobject_class->get_property = gst_interleave_get_property;
347
348   /**
349    * GstInterleave:channel-positions
350    * 
351    * Channel positions: This property controls the channel positions
352    * that are used on the src caps. The number of elements should be
353    * the same as the number of sink pads and the array should contain
354    * a valid list of channel positions. The n-th element of the array
355    * is the position of the n-th sink pad.
356    *
357    * These channel positions will only be used if they're valid and the
358    * number of elements is the same as the number of channels. If this
359    * is not given a NONE layout will be used.
360    *
361    */
362   g_object_class_install_property (gobject_class, PROP_CHANNEL_POSITIONS,
363       g_param_spec_value_array ("channel-positions", "Channel positions",
364           "Channel positions used on the output",
365           g_param_spec_enum ("channel-position", "Channel position",
366               "Channel position of the n-th input",
367               GST_TYPE_AUDIO_CHANNEL_POSITION,
368               GST_AUDIO_CHANNEL_POSITION_NONE,
369               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
370           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
371
372   /**
373    * GstInterleave:channel-positions-from-input
374    * 
375    * Channel positions from input: If this property is set to %TRUE the channel
376    * positions will be taken from the input caps if valid channel positions for
377    * the output can be constructed from them. If this is set to %TRUE setting the
378    * channel-positions property overwrites this property again.
379    *
380    */
381   g_object_class_install_property (gobject_class,
382       PROP_CHANNEL_POSITIONS_FROM_INPUT,
383       g_param_spec_boolean ("channel-positions-from-input",
384           "Channel positions from input",
385           "Take channel positions from the input", TRUE,
386           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
387
388   gstelement_class->request_new_pad =
389       GST_DEBUG_FUNCPTR (gst_interleave_request_new_pad);
390   gstelement_class->release_pad =
391       GST_DEBUG_FUNCPTR (gst_interleave_release_pad);
392   gstelement_class->change_state =
393       GST_DEBUG_FUNCPTR (gst_interleave_change_state);
394 }
395
396 static void
397 gst_interleave_init (GstInterleave * self, GstInterleaveClass * klass)
398 {
399   self->src = gst_pad_new_from_static_template (&src_template, "src");
400
401   gst_pad_set_query_function (self->src,
402       GST_DEBUG_FUNCPTR (gst_interleave_src_query));
403   gst_pad_set_event_function (self->src,
404       GST_DEBUG_FUNCPTR (gst_interleave_src_event));
405
406   gst_element_add_pad (GST_ELEMENT (self), self->src);
407
408   self->collect = gst_collect_pads_new ();
409   gst_collect_pads_set_function (self->collect,
410       (GstCollectPadsFunction) gst_interleave_collected, self);
411
412   self->input_channel_positions = g_value_array_new (0);
413   self->channel_positions_from_input = TRUE;
414   self->channel_positions = self->input_channel_positions;
415 }
416
417 static void
418 gst_interleave_set_property (GObject * object, guint prop_id,
419     const GValue * value, GParamSpec * pspec)
420 {
421   GstInterleave *self = GST_INTERLEAVE (object);
422
423   switch (prop_id) {
424     case PROP_CHANNEL_POSITIONS:
425       if (self->channel_positions &&
426           self->channel_positions != self->input_channel_positions)
427         g_value_array_free (self->channel_positions);
428
429       self->channel_positions = g_value_dup_boxed (value);
430       self->channel_positions_from_input = FALSE;
431       break;
432     case PROP_CHANNEL_POSITIONS_FROM_INPUT:
433       self->channel_positions_from_input = g_value_get_boolean (value);
434
435       if (self->channel_positions_from_input) {
436         if (self->channel_positions &&
437             self->channel_positions != self->input_channel_positions)
438           g_value_array_free (self->channel_positions);
439         self->channel_positions = self->input_channel_positions;
440       }
441       break;
442     default:
443       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
444       break;
445   }
446 }
447
448 static void
449 gst_interleave_get_property (GObject * object, guint prop_id,
450     GValue * value, GParamSpec * pspec)
451 {
452   GstInterleave *self = GST_INTERLEAVE (object);
453
454   switch (prop_id) {
455     case PROP_CHANNEL_POSITIONS:
456       g_value_set_boxed (value, self->channel_positions);
457       break;
458     case PROP_CHANNEL_POSITIONS_FROM_INPUT:
459       g_value_set_boolean (value, self->channel_positions_from_input);
460       break;
461     default:
462       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
463       break;
464   }
465 }
466
467 static GstPad *
468 gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ,
469     const gchar * req_name)
470 {
471   GstInterleave *self = GST_INTERLEAVE (element);
472   GstPad *new_pad;
473   gchar *pad_name;
474   gint channels, padnumber;
475   GValue val = { 0, };
476
477   if (templ->direction != GST_PAD_SINK)
478     goto not_sink_pad;
479
480 #if GLIB_CHECK_VERSION(2,29,5)
481   channels = g_atomic_int_add (&self->channels, 1);
482   padnumber = g_atomic_int_add (&self->padcounter, 1);
483 #else
484   channels = g_atomic_int_exchange_and_add (&self->channels, 1);
485   padnumber = g_atomic_int_exchange_and_add (&self->padcounter, 1);
486 #endif
487
488   pad_name = g_strdup_printf ("sink%d", padnumber);
489   new_pad = GST_PAD_CAST (g_object_new (GST_TYPE_INTERLEAVE_PAD,
490           "name", pad_name, "direction", templ->direction,
491           "template", templ, NULL));
492   GST_INTERLEAVE_PAD_CAST (new_pad)->channel = channels;
493   GST_DEBUG_OBJECT (self, "requested new pad %s", pad_name);
494   g_free (pad_name);
495
496   gst_pad_set_setcaps_function (new_pad,
497       GST_DEBUG_FUNCPTR (gst_interleave_sink_setcaps));
498   gst_pad_set_getcaps_function (new_pad,
499       GST_DEBUG_FUNCPTR (gst_interleave_sink_getcaps));
500
501   gst_collect_pads_add_pad (self->collect, new_pad, sizeof (GstCollectData));
502
503   /* FIXME: hacked way to override/extend the event function of
504    * GstCollectPads; because it sets its own event function giving the
505    * element no access to events */
506   self->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (new_pad);
507   gst_pad_set_event_function (new_pad,
508       GST_DEBUG_FUNCPTR (gst_interleave_sink_event));
509
510   if (!gst_element_add_pad (element, new_pad))
511     goto could_not_add;
512
513   g_value_init (&val, GST_TYPE_AUDIO_CHANNEL_POSITION);
514   g_value_set_enum (&val, GST_AUDIO_CHANNEL_POSITION_NONE);
515   self->input_channel_positions =
516       g_value_array_append (self->input_channel_positions, &val);
517   g_value_unset (&val);
518
519   /* Update the src caps if we already have them */
520   if (self->sinkcaps) {
521     GstCaps *srccaps;
522     GstStructure *s;
523
524     /* Take lock to make sure processing finishes first */
525     GST_OBJECT_LOCK (self->collect);
526
527     srccaps = gst_caps_copy (self->sinkcaps);
528     s = gst_caps_get_structure (srccaps, 0);
529
530     gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL);
531     gst_interleave_set_channel_positions (self, s);
532
533     gst_pad_set_caps (self->src, srccaps);
534     gst_caps_unref (srccaps);
535
536     GST_OBJECT_UNLOCK (self->collect);
537   }
538
539   return new_pad;
540
541   /* errors */
542 not_sink_pad:
543   {
544     g_warning ("interleave: requested new pad that is not a SINK pad\n");
545     return NULL;
546   }
547 could_not_add:
548   {
549     GST_DEBUG_OBJECT (self, "could not add pad %s", GST_PAD_NAME (new_pad));
550     gst_collect_pads_remove_pad (self->collect, new_pad);
551     gst_object_unref (new_pad);
552     return NULL;
553   }
554 }
555
556 static void
557 gst_interleave_release_pad (GstElement * element, GstPad * pad)
558 {
559   GstInterleave *self = GST_INTERLEAVE (element);
560   GList *l;
561
562   g_return_if_fail (GST_IS_INTERLEAVE_PAD (pad));
563
564   /* Take lock to make sure we're not changing this when processing buffers */
565   GST_OBJECT_LOCK (self->collect);
566
567   g_atomic_int_add (&self->channels, -1);
568
569   g_value_array_remove (self->input_channel_positions,
570       GST_INTERLEAVE_PAD_CAST (pad)->channel);
571
572   /* Update channel numbers */
573   GST_OBJECT_LOCK (self);
574   for (l = GST_ELEMENT_CAST (self)->sinkpads; l != NULL; l = l->next) {
575     GstInterleavePad *ipad = GST_INTERLEAVE_PAD (l->data);
576
577     if (GST_INTERLEAVE_PAD_CAST (pad)->channel < ipad->channel)
578       ipad->channel--;
579   }
580   GST_OBJECT_UNLOCK (self);
581
582   /* Update the src caps if we already have them */
583   if (self->sinkcaps) {
584     if (self->channels > 0) {
585       GstCaps *srccaps;
586       GstStructure *s;
587
588       srccaps = gst_caps_copy (self->sinkcaps);
589       s = gst_caps_get_structure (srccaps, 0);
590
591       gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL);
592       gst_interleave_set_channel_positions (self, s);
593
594       gst_pad_set_caps (self->src, srccaps);
595       gst_caps_unref (srccaps);
596     } else {
597       gst_caps_replace (&self->sinkcaps, NULL);
598       gst_pad_set_caps (self->src, NULL);
599     }
600   }
601
602   GST_OBJECT_UNLOCK (self->collect);
603
604   gst_collect_pads_remove_pad (self->collect, pad);
605   gst_element_remove_pad (element, pad);
606 }
607
608 static GstStateChangeReturn
609 gst_interleave_change_state (GstElement * element, GstStateChange transition)
610 {
611   GstInterleave *self;
612   GstStateChangeReturn ret;
613
614   self = GST_INTERLEAVE (element);
615
616   switch (transition) {
617     case GST_STATE_CHANGE_NULL_TO_READY:
618       break;
619     case GST_STATE_CHANGE_READY_TO_PAUSED:
620       self->timestamp = 0;
621       self->offset = 0;
622       self->segment_pending = TRUE;
623       self->segment_position = 0;
624       self->segment_rate = 1.0;
625       gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
626       gst_collect_pads_start (self->collect);
627       break;
628     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
629       break;
630     default:
631       break;
632   }
633
634   /* Stop before calling the parent's state change function as
635    * GstCollectPads might take locks and we would deadlock in that
636    * case
637    */
638   if (transition == GST_STATE_CHANGE_PAUSED_TO_READY)
639     gst_collect_pads_stop (self->collect);
640
641   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
642
643   switch (transition) {
644     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
645       break;
646     case GST_STATE_CHANGE_PAUSED_TO_READY:
647       gst_pad_set_caps (self->src, NULL);
648       gst_caps_replace (&self->sinkcaps, NULL);
649       break;
650     case GST_STATE_CHANGE_READY_TO_NULL:
651       break;
652     default:
653       break;
654   }
655
656   return ret;
657 }
658
659 static void
660 __remove_channels (GstCaps * caps)
661 {
662   GstStructure *s;
663   gint i, size;
664
665   size = gst_caps_get_size (caps);
666   for (i = 0; i < size; i++) {
667     s = gst_caps_get_structure (caps, i);
668     gst_structure_remove_field (s, "channel-positions");
669     gst_structure_remove_field (s, "channels");
670   }
671 }
672
673 static void
674 __set_channels (GstCaps * caps, gint channels)
675 {
676   GstStructure *s;
677   gint i, size;
678
679   size = gst_caps_get_size (caps);
680   for (i = 0; i < size; i++) {
681     s = gst_caps_get_structure (caps, i);
682     if (channels > 0)
683       gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL);
684     else
685       gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
686   }
687 }
688
689 /* we can only accept caps that we and downstream can handle. */
690 static GstCaps *
691 gst_interleave_sink_getcaps (GstPad * pad)
692 {
693   GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
694   GstCaps *result, *peercaps, *sinkcaps;
695
696   GST_OBJECT_LOCK (self);
697
698   /* If we already have caps on one of the sink pads return them */
699   if (self->sinkcaps) {
700     result = gst_caps_copy (self->sinkcaps);
701   } else {
702     /* get the downstream possible caps */
703     peercaps = gst_pad_peer_get_caps (self->src);
704     /* get the allowed caps on this sinkpad */
705     sinkcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
706     __remove_channels (sinkcaps);
707     if (peercaps) {
708       __remove_channels (peercaps);
709       /* if the peer has caps, intersect */
710       GST_DEBUG_OBJECT (pad, "intersecting peer and template caps");
711       result = gst_caps_intersect (peercaps, sinkcaps);
712       gst_caps_unref (peercaps);
713       gst_caps_unref (sinkcaps);
714     } else {
715       /* the peer has no caps (or there is no peer), just use the allowed caps
716        * of this sinkpad. */
717       GST_DEBUG_OBJECT (pad, "no peer caps, using sinkcaps");
718       result = sinkcaps;
719     }
720     __set_channels (result, 1);
721   }
722
723   GST_OBJECT_UNLOCK (self);
724
725   gst_object_unref (self);
726
727   GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, result);
728
729   return result;
730 }
731
732 static void
733 gst_interleave_set_process_function (GstInterleave * self)
734 {
735   switch (self->width) {
736     case 8:
737       self->func = (GstInterleaveFunc) interleave_8;
738       break;
739     case 16:
740       self->func = (GstInterleaveFunc) interleave_16;
741       break;
742     case 24:
743       self->func = (GstInterleaveFunc) interleave_24;
744       break;
745     case 32:
746       self->func = (GstInterleaveFunc) interleave_32;
747       break;
748     case 64:
749       self->func = (GstInterleaveFunc) interleave_64;
750       break;
751     default:
752       g_assert_not_reached ();
753       break;
754   }
755 }
756
757 static gboolean
758 gst_interleave_sink_setcaps (GstPad * pad, GstCaps * caps)
759 {
760   GstInterleave *self;
761
762   g_return_val_if_fail (GST_IS_INTERLEAVE_PAD (pad), FALSE);
763
764   self = GST_INTERLEAVE (gst_pad_get_parent (pad));
765
766   /* First caps that are set on a sink pad are used as output caps */
767   /* TODO: handle caps changes */
768   if (self->sinkcaps && !gst_caps_is_subset (caps, self->sinkcaps)) {
769     goto cannot_change_caps;
770   } else {
771     GstCaps *srccaps;
772     GstStructure *s;
773     gboolean res;
774
775     s = gst_caps_get_structure (caps, 0);
776
777     if (!gst_structure_get_int (s, "width", &self->width))
778       goto no_width;
779
780     if (!gst_structure_get_int (s, "rate", &self->rate))
781       goto no_rate;
782
783     gst_interleave_set_process_function (self);
784
785     if (gst_structure_has_field (s, "channel-positions")) {
786       const GValue *pos_array;
787
788       pos_array = gst_structure_get_value (s, "channel-positions");
789       if (GST_VALUE_HOLDS_ARRAY (pos_array)
790           && gst_value_array_get_size (pos_array) == 1) {
791         const GValue *pos = gst_value_array_get_value (pos_array, 0);
792
793         GValue *apos = g_value_array_get_nth (self->input_channel_positions,
794             GST_INTERLEAVE_PAD_CAST (pad)->channel);
795
796         g_value_set_enum (apos, g_value_get_enum (pos));
797       }
798     }
799
800     srccaps = gst_caps_copy (caps);
801     s = gst_caps_get_structure (srccaps, 0);
802
803     gst_structure_set (s, "channels", G_TYPE_INT, self->channels, NULL);
804     gst_interleave_set_channel_positions (self, s);
805
806     res = gst_pad_set_caps (self->src, srccaps);
807     gst_caps_unref (srccaps);
808
809     if (!res)
810       goto src_did_not_accept;
811   }
812
813   if (!self->sinkcaps) {
814     GstCaps *sinkcaps = gst_caps_copy (caps);
815     GstStructure *s = gst_caps_get_structure (sinkcaps, 0);
816
817     gst_structure_remove_field (s, "channel-positions");
818
819     gst_caps_replace (&self->sinkcaps, sinkcaps);
820
821     gst_caps_unref (sinkcaps);
822   }
823
824   gst_object_unref (self);
825
826   return TRUE;
827
828 cannot_change_caps:
829   {
830     GST_WARNING_OBJECT (self, "caps of %" GST_PTR_FORMAT " already set, can't "
831         "change", self->sinkcaps);
832     gst_object_unref (self);
833     return FALSE;
834   }
835 src_did_not_accept:
836   {
837     GST_WARNING_OBJECT (self, "src did not accept setcaps()");
838     gst_object_unref (self);
839     return FALSE;
840   }
841 no_width:
842   {
843     GST_WARNING_OBJECT (self, "caps did not have width: %" GST_PTR_FORMAT,
844         caps);
845     gst_object_unref (self);
846     return FALSE;
847   }
848 no_rate:
849   {
850     GST_WARNING_OBJECT (self, "caps did not have rate: %" GST_PTR_FORMAT, caps);
851     gst_object_unref (self);
852     return FALSE;
853   }
854 }
855
856 static gboolean
857 gst_interleave_sink_event (GstPad * pad, GstEvent * event)
858 {
859   GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
860   gboolean ret;
861
862   GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
863       GST_DEBUG_PAD_NAME (pad));
864
865   switch (GST_EVENT_TYPE (event)) {
866     case GST_EVENT_FLUSH_STOP:
867       /* mark a pending new segment. This event is synchronized
868        * with the streaming thread so we can safely update the
869        * variable without races. It's somewhat weird because we
870        * assume the collectpads forwarded the FLUSH_STOP past us
871        * and downstream (using our source pad, the bastard!).
872        */
873       self->segment_pending = TRUE;
874       break;
875     default:
876       break;
877   }
878
879   /* now GstCollectPads can take care of the rest, e.g. EOS */
880   ret = self->collect_event (pad, event);
881
882   gst_object_unref (self);
883   return ret;
884 }
885
886 static gboolean
887 gst_interleave_src_query_duration (GstInterleave * self, GstQuery * query)
888 {
889   gint64 max;
890   gboolean res;
891   GstFormat format;
892   GstIterator *it;
893   gboolean done;
894
895   /* parse format */
896   gst_query_parse_duration (query, &format, NULL);
897
898   max = -1;
899   res = TRUE;
900   done = FALSE;
901
902   /* Take maximum of all durations */
903   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self));
904   while (!done) {
905     GstIteratorResult ires;
906
907     gpointer item;
908
909     ires = gst_iterator_next (it, &item);
910     switch (ires) {
911       case GST_ITERATOR_DONE:
912         done = TRUE;
913         break;
914       case GST_ITERATOR_OK:
915       {
916         GstPad *pad = GST_PAD_CAST (item);
917
918         gint64 duration;
919
920         /* ask sink peer for duration */
921         res &= gst_pad_query_peer_duration (pad, &format, &duration);
922         /* take max from all valid return values */
923         if (res) {
924           /* valid unknown length, stop searching */
925           if (duration == -1) {
926             max = duration;
927             done = TRUE;
928           }
929           /* else see if bigger than current max */
930           else if (duration > max)
931             max = duration;
932         }
933         gst_object_unref (pad);
934         break;
935       }
936       case GST_ITERATOR_RESYNC:
937         max = -1;
938         res = TRUE;
939         gst_iterator_resync (it);
940         break;
941       default:
942         res = FALSE;
943         done = TRUE;
944         break;
945     }
946   }
947   gst_iterator_free (it);
948
949   if (res) {
950     /* If in bytes format we have to multiply with the number of channels
951      * to get the correct results. All other formats should be fine */
952     if (format == GST_FORMAT_BYTES && max != -1)
953       max *= self->channels;
954
955     /* and store the max */
956     GST_DEBUG_OBJECT (self, "Total duration in format %s: %"
957         GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (max));
958     gst_query_set_duration (query, format, max);
959   }
960
961   return res;
962 }
963
964 static gboolean
965 gst_interleave_src_query_latency (GstInterleave * self, GstQuery * query)
966 {
967   GstClockTime min, max;
968   gboolean live;
969   gboolean res;
970   GstIterator *it;
971   gboolean done;
972
973   res = TRUE;
974   done = FALSE;
975
976   live = FALSE;
977   min = 0;
978   max = GST_CLOCK_TIME_NONE;
979
980   /* Take maximum of all latency values */
981   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self));
982   while (!done) {
983     GstIteratorResult ires;
984     gpointer item;
985
986     ires = gst_iterator_next (it, &item);
987     switch (ires) {
988       case GST_ITERATOR_DONE:
989         done = TRUE;
990         break;
991       case GST_ITERATOR_OK:
992       {
993         GstPad *pad = GST_PAD_CAST (item);
994         GstQuery *peerquery;
995         GstClockTime min_cur, max_cur;
996         gboolean live_cur;
997
998         peerquery = gst_query_new_latency ();
999
1000         /* Ask peer for latency */
1001         res &= gst_pad_peer_query (pad, peerquery);
1002
1003         /* take max from all valid return values */
1004         if (res) {
1005           gst_query_parse_latency (peerquery, &live_cur, &min_cur, &max_cur);
1006
1007           if (min_cur > min)
1008             min = min_cur;
1009
1010           if (max_cur != GST_CLOCK_TIME_NONE &&
1011               ((max != GST_CLOCK_TIME_NONE && max_cur > max) ||
1012                   (max == GST_CLOCK_TIME_NONE)))
1013             max = max_cur;
1014
1015           live = live || live_cur;
1016         }
1017
1018         gst_query_unref (peerquery);
1019         gst_object_unref (pad);
1020         break;
1021       }
1022       case GST_ITERATOR_RESYNC:
1023         live = FALSE;
1024         min = 0;
1025         max = GST_CLOCK_TIME_NONE;
1026         res = TRUE;
1027         gst_iterator_resync (it);
1028         break;
1029       default:
1030         res = FALSE;
1031         done = TRUE;
1032         break;
1033     }
1034   }
1035   gst_iterator_free (it);
1036
1037   if (res) {
1038     /* store the results */
1039     GST_DEBUG_OBJECT (self, "Calculated total latency: live %s, min %"
1040         GST_TIME_FORMAT ", max %" GST_TIME_FORMAT,
1041         (live ? "yes" : "no"), GST_TIME_ARGS (min), GST_TIME_ARGS (max));
1042     gst_query_set_latency (query, live, min, max);
1043   }
1044
1045   return res;
1046 }
1047
1048 static gboolean
1049 gst_interleave_src_query (GstPad * pad, GstQuery * query)
1050 {
1051   GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
1052   gboolean res = FALSE;
1053
1054   switch (GST_QUERY_TYPE (query)) {
1055     case GST_QUERY_POSITION:
1056     {
1057       GstFormat format;
1058
1059       gst_query_parse_position (query, &format, NULL);
1060
1061       switch (format) {
1062         case GST_FORMAT_TIME:
1063           /* FIXME, bring to stream time, might be tricky */
1064           gst_query_set_position (query, format, self->timestamp);
1065           res = TRUE;
1066           break;
1067         case GST_FORMAT_BYTES:
1068           gst_query_set_position (query, format,
1069               self->offset * self->channels * self->width);
1070           res = TRUE;
1071           break;
1072         case GST_FORMAT_DEFAULT:
1073           gst_query_set_position (query, format, self->offset);
1074           res = TRUE;
1075           break;
1076         default:
1077           break;
1078       }
1079       break;
1080     }
1081     case GST_QUERY_DURATION:
1082       res = gst_interleave_src_query_duration (self, query);
1083       break;
1084     case GST_QUERY_LATENCY:
1085       res = gst_interleave_src_query_latency (self, query);
1086       break;
1087     default:
1088       /* FIXME, needs a custom query handler because we have multiple
1089        * sinkpads */
1090       res = gst_pad_query_default (pad, query);
1091       break;
1092   }
1093
1094   gst_object_unref (self);
1095   return res;
1096 }
1097
1098 static gboolean
1099 forward_event_func (GstPad * pad, GValue * ret, GstEvent * event)
1100 {
1101   gst_event_ref (event);
1102   GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event));
1103   if (!gst_pad_push_event (pad, event)) {
1104     g_value_set_boolean (ret, FALSE);
1105     GST_WARNING_OBJECT (pad, "Sending event  %p (%s) failed.",
1106         event, GST_EVENT_TYPE_NAME (event));
1107   } else {
1108     GST_LOG_OBJECT (pad, "Sent event  %p (%s).",
1109         event, GST_EVENT_TYPE_NAME (event));
1110   }
1111   gst_object_unref (pad);
1112   return TRUE;
1113 }
1114
1115 static gboolean
1116 forward_event (GstInterleave * self, GstEvent * event)
1117 {
1118   GstIterator *it;
1119   GValue vret = { 0 };
1120
1121   GST_LOG_OBJECT (self, "Forwarding event %p (%s)", event,
1122       GST_EVENT_TYPE_NAME (event));
1123
1124   g_value_init (&vret, G_TYPE_BOOLEAN);
1125   g_value_set_boolean (&vret, TRUE);
1126   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (self));
1127   gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, &vret,
1128       event);
1129   gst_iterator_free (it);
1130   gst_event_unref (event);
1131
1132   return g_value_get_boolean (&vret);
1133 }
1134
1135
1136 static gboolean
1137 gst_interleave_src_event (GstPad * pad, GstEvent * event)
1138 {
1139   GstInterleave *self = GST_INTERLEAVE (gst_pad_get_parent (pad));
1140   gboolean result;
1141
1142   switch (GST_EVENT_TYPE (event)) {
1143     case GST_EVENT_QOS:
1144       /* QoS might be tricky */
1145       result = FALSE;
1146       break;
1147     case GST_EVENT_SEEK:
1148     {
1149       GstSeekFlags flags;
1150       GstSeekType curtype;
1151       gint64 cur;
1152
1153       /* parse the seek parameters */
1154       gst_event_parse_seek (event, &self->segment_rate, NULL, &flags, &curtype,
1155           &cur, NULL, NULL);
1156
1157       /* check if we are flushing */
1158       if (flags & GST_SEEK_FLAG_FLUSH) {
1159         /* make sure we accept nothing anymore and return WRONG_STATE */
1160         gst_collect_pads_set_flushing (self->collect, TRUE);
1161
1162         /* flushing seek, start flush downstream, the flush will be done
1163          * when all pads received a FLUSH_STOP. */
1164         gst_pad_push_event (self->src, gst_event_new_flush_start ());
1165       }
1166
1167       /* now wait for the collected to be finished and mark a new
1168        * segment */
1169       GST_OBJECT_LOCK (self->collect);
1170       if (curtype == GST_SEEK_TYPE_SET)
1171         self->segment_position = cur;
1172       else
1173         self->segment_position = 0;
1174       self->segment_pending = TRUE;
1175       GST_OBJECT_UNLOCK (self->collect);
1176
1177       result = forward_event (self, event);
1178       break;
1179     }
1180     case GST_EVENT_NAVIGATION:
1181       /* navigation is rather pointless. */
1182       result = FALSE;
1183       break;
1184     default:
1185       /* just forward the rest for now */
1186       result = forward_event (self, event);
1187       break;
1188   }
1189   gst_object_unref (self);
1190
1191   return result;
1192 }
1193
1194 static GstFlowReturn
1195 gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
1196 {
1197   guint size;
1198   GstBuffer *outbuf;
1199   GstFlowReturn ret = GST_FLOW_OK;
1200   GSList *collected;
1201   guint nsamples;
1202   guint ncollected = 0;
1203   gboolean empty = TRUE;
1204   gint width = self->width / 8;
1205
1206   g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED);
1207   g_return_val_if_fail (self->width > 0, GST_FLOW_NOT_NEGOTIATED);
1208   g_return_val_if_fail (self->channels > 0, GST_FLOW_NOT_NEGOTIATED);
1209   g_return_val_if_fail (self->rate > 0, GST_FLOW_NOT_NEGOTIATED);
1210
1211   size = gst_collect_pads_available (pads);
1212
1213   g_return_val_if_fail (size % width == 0, GST_FLOW_ERROR);
1214
1215   GST_DEBUG_OBJECT (self, "Starting to collect %u bytes from %d channels", size,
1216       self->channels);
1217
1218   nsamples = size / width;
1219
1220   ret =
1221       gst_pad_alloc_buffer (self->src, GST_BUFFER_OFFSET_NONE,
1222       size * self->channels, GST_PAD_CAPS (self->src), &outbuf);
1223
1224   if (ret != GST_FLOW_OK) {
1225     return ret;
1226   } else if (outbuf == NULL || GST_BUFFER_SIZE (outbuf) < size * self->channels) {
1227     gst_buffer_unref (outbuf);
1228     return GST_FLOW_NOT_NEGOTIATED;
1229   } else if (!gst_caps_is_equal (GST_BUFFER_CAPS (outbuf),
1230           GST_PAD_CAPS (self->src))) {
1231     gst_buffer_unref (outbuf);
1232     return GST_FLOW_NOT_NEGOTIATED;
1233   }
1234
1235   memset (GST_BUFFER_DATA (outbuf), 0, size * self->channels);
1236
1237   for (collected = pads->data; collected != NULL; collected = collected->next) {
1238     GstCollectData *cdata;
1239     GstBuffer *inbuf;
1240     guint8 *outdata;
1241
1242     cdata = (GstCollectData *) collected->data;
1243
1244     inbuf = gst_collect_pads_take_buffer (pads, cdata, size);
1245     if (inbuf == NULL) {
1246       GST_DEBUG_OBJECT (cdata->pad, "No buffer available");
1247       goto next;
1248     }
1249     ncollected++;
1250
1251     if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP))
1252       goto next;
1253
1254     empty = FALSE;
1255     outdata =
1256         GST_BUFFER_DATA (outbuf) +
1257         width * GST_INTERLEAVE_PAD_CAST (cdata->pad)->channel;
1258
1259     self->func (outdata, GST_BUFFER_DATA (inbuf), self->channels, nsamples);
1260
1261   next:
1262     if (inbuf)
1263       gst_buffer_unref (inbuf);
1264   }
1265
1266   if (ncollected == 0)
1267     goto eos;
1268
1269   if (self->segment_pending) {
1270     GstEvent *event;
1271
1272     event = gst_event_new_new_segment_full (FALSE, self->segment_rate,
1273         1.0, GST_FORMAT_TIME, self->timestamp, -1, self->segment_position);
1274
1275     gst_pad_push_event (self->src, event);
1276     self->segment_pending = FALSE;
1277     self->segment_position = 0;
1278   }
1279
1280   GST_BUFFER_TIMESTAMP (outbuf) = self->timestamp;
1281   GST_BUFFER_OFFSET (outbuf) = self->offset;
1282
1283   self->offset += nsamples;
1284   self->timestamp = gst_util_uint64_scale_int (self->offset,
1285       GST_SECOND, self->rate);
1286
1287   GST_BUFFER_DURATION (outbuf) = self->timestamp -
1288       GST_BUFFER_TIMESTAMP (outbuf);
1289
1290   if (empty)
1291     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
1292
1293   GST_LOG_OBJECT (self, "pushing outbuf, timestamp %" GST_TIME_FORMAT,
1294       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
1295   ret = gst_pad_push (self->src, outbuf);
1296
1297   return ret;
1298
1299 eos:
1300   {
1301     GST_DEBUG_OBJECT (self, "no data available, must be EOS");
1302     gst_buffer_unref (outbuf);
1303     gst_pad_push_event (self->src, gst_event_new_eos ());
1304     return GST_FLOW_UNEXPECTED;
1305   }
1306 }