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