configure.ac: Require CVS of core for new API in collectpads.
[platform/upstream/gstreamer.git] / gst / adder / gstadder.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2001 Thomas <thomas@apestaart.org>
4  *               2005,2006 Wim Taymans <wim@fluendo.com>
5  *
6  * adder.c: Adder element, N in, one out, samples are added
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 /**
24  * SECTION:element-adder
25  *
26  * <refsect2>
27  * <para>
28  * The Adder allows to mix several streams into one by adding the data.
29  * Mixed data is clamped to the min/max values of the data format.
30  * </para>
31  * <title>Example launch line</title>
32  * <para>
33  * <programlisting>
34  * gst-launch audiotestsrc freq=100 ! adder name=mix ! audioconvert ! alsasink audiotestsrc freq=500 ! mix.
35  * </programlisting>
36  * This pipeline produces two sine waves mixed together.
37  * </para>
38  * <para>
39  * The Adder currently mixes all data received on the sinkpads as soon as possible
40  * without trying to synchronize the streams.
41  * </para>
42  * </refsect2>
43  *
44  * Last reviewed on 2006-05-09 (0.10.7)
45  */
46 /* Element-Checklist-Version: 5 */
47
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
51 #include "gstadder.h"
52 #include <gst/audio/audio.h>
53 #include <string.h>             /* strcmp */
54
55 /* highest positive/lowest negative x-bit value we can use for clamping */
56 #define MAX_INT_32  ((gint32) (0x7fffffff))
57 #define MAX_INT_16  ((gint16) (0x7fff))
58 #define MAX_INT_8   ((gint8)  (0x7f))
59 #define MAX_UINT_32 ((guint32)(0xffffffff))
60 #define MAX_UINT_16 ((guint16)(0xffff))
61 #define MAX_UINT_8  ((guint8) (0xff))
62
63 #define MIN_INT_32  ((gint32) (0x80000000))
64 #define MIN_INT_16  ((gint16) (0x8000))
65 #define MIN_INT_8   ((gint8)  (0x80))
66 #define MIN_UINT_32 ((guint32)(0x00000000))
67 #define MIN_UINT_16 ((guint16)(0x0000))
68 #define MIN_UINT_8  ((guint8) (0x00))
69
70 #define GST_CAT_DEFAULT gst_adder_debug
71 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
72
73 /* elementfactory information */
74 static const GstElementDetails adder_details = GST_ELEMENT_DETAILS ("Adder",
75     "Generic/Audio",
76     "Add N audio channels together",
77     "Thomas <thomas@apestaart.org>");
78
79 static GstStaticPadTemplate gst_adder_src_template =
80     GST_STATIC_PAD_TEMPLATE ("src",
81     GST_PAD_SRC,
82     GST_PAD_ALWAYS,
83     GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; "
84         GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS)
85     );
86
87 static GstStaticPadTemplate gst_adder_sink_template =
88     GST_STATIC_PAD_TEMPLATE ("sink%d",
89     GST_PAD_SINK,
90     GST_PAD_REQUEST,
91     GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS "; "
92         GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS)
93     );
94
95 static void gst_adder_class_init (GstAdderClass * klass);
96 static void gst_adder_init (GstAdder * adder);
97 static void gst_adder_finalize (GObject * object);
98
99 static gboolean gst_adder_setcaps (GstPad * pad, GstCaps * caps);
100 static gboolean gst_adder_query (GstPad * pad, GstQuery * query);
101 static gboolean gst_adder_src_event (GstPad * pad, GstEvent * event);
102 static gboolean gst_adder_sink_event (GstPad * pad, GstEvent * event);
103
104 static GstPad *gst_adder_request_new_pad (GstElement * element,
105     GstPadTemplate * temp, const gchar * unused);
106 static void gst_adder_release_pad (GstElement * element, GstPad * pad);
107
108 static GstStateChangeReturn gst_adder_change_state (GstElement * element,
109     GstStateChange transition);
110
111 static GstFlowReturn gst_adder_collected (GstCollectPads * pads,
112     gpointer user_data);
113
114 static GstElementClass *parent_class = NULL;
115
116 GType
117 gst_adder_get_type (void)
118 {
119   static GType adder_type = 0;
120
121   if (G_UNLIKELY (adder_type == 0)) {
122     static const GTypeInfo adder_info = {
123       sizeof (GstAdderClass), NULL, NULL,
124       (GClassInitFunc) gst_adder_class_init, NULL, NULL,
125       sizeof (GstAdder), 0,
126       (GInstanceInitFunc) gst_adder_init,
127     };
128
129     adder_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAdder",
130         &adder_info, 0);
131     GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "adder", 0,
132         "audio channel mixing element");
133   }
134   return adder_type;
135 }
136
137 /* clipping versions */
138 #define MAKE_FUNC(name,type,ttype,min,max)                      \
139 static void name (type *out, type *in, gint bytes) {            \
140   gint i;                                                       \
141   for (i = 0; i < bytes / sizeof (type); i++)                   \
142     out[i] = CLAMP ((ttype)out[i] + (ttype)in[i], min, max);    \
143 }
144
145 /* non-clipping versions (for float) */
146 #define MAKE_FUNC_NC(name,type,ttype)                           \
147 static void name (type *out, type *in, gint bytes) {            \
148   gint i;                                                       \
149   for (i = 0; i < bytes / sizeof (type); i++)                   \
150     out[i] = (ttype)out[i] + (ttype)in[i];                      \
151 }
152
153 /* *INDENT-OFF* */
154 MAKE_FUNC (add_int32, gint32, gint64, MIN_INT_32, MAX_INT_32)
155 MAKE_FUNC (add_int16, gint16, gint32, MIN_INT_16, MAX_INT_16)
156 MAKE_FUNC (add_int8, gint8, gint16, MIN_INT_8, MAX_INT_8)
157 MAKE_FUNC (add_uint32, guint32, guint64, MIN_UINT_32, MAX_UINT_32)
158 MAKE_FUNC (add_uint16, guint16, guint32, MIN_UINT_16, MAX_UINT_16)
159 MAKE_FUNC (add_uint8, guint8, guint16, MIN_UINT_8, MAX_UINT_8)
160 MAKE_FUNC_NC (add_float64, gdouble, gdouble)
161 MAKE_FUNC_NC (add_float32, gfloat, gfloat)
162 /* *INDENT-ON* */
163
164 /* we can only accept caps that we and downstream can handle. */
165 static GstCaps *
166 gst_adder_sink_getcaps (GstPad * pad)
167 {
168   GstAdder *adder;
169   GstCaps *result, *peercaps, *sinkcaps;
170
171   adder = GST_ADDER (GST_PAD_PARENT (pad));
172
173   GST_OBJECT_LOCK (adder);
174   /* get the downstream possible caps */
175   peercaps = gst_pad_peer_get_caps (adder->srcpad);
176   /* get the allowed caps on this sinkpad, we use the fixed caps function so
177    * that it does not call recursively in this function. */
178   sinkcaps = gst_pad_get_fixed_caps_func (pad);
179   if (peercaps) {
180     /* if the peer has caps, intersect */
181     GST_DEBUG_OBJECT (adder, "intersecting peer and template caps");
182     result = gst_caps_intersect (peercaps, sinkcaps);
183     gst_caps_unref (peercaps);
184     gst_caps_unref (sinkcaps);
185   } else {
186     /* the peer has no caps (or there is no peer), just use the allowed caps
187      * of this sinkpad. */
188     GST_DEBUG_OBJECT (adder, "no peer caps, using sinkcaps");
189     result = sinkcaps;
190   }
191   GST_OBJECT_UNLOCK (adder);
192
193   return result;
194 }
195
196 /* the first caps we receive on any of the sinkpads will define the caps for all
197  * the other sinkpads because we can only mix streams with the same caps.
198  * */
199 static gboolean
200 gst_adder_setcaps (GstPad * pad, GstCaps * caps)
201 {
202   GstAdder *adder;
203   GList *pads;
204   GstStructure *structure;
205   const char *media_type;
206
207   adder = GST_ADDER (GST_PAD_PARENT (pad));
208
209   GST_LOG_OBJECT (adder, "setting caps on pad %p,%s to %" GST_PTR_FORMAT, pad,
210       GST_PAD_NAME (pad), caps);
211
212   /* FIXME, see if the other pads can accept the format. Also lock the
213    * format on the other pads to this new format. */
214   GST_OBJECT_LOCK (adder);
215   pads = GST_ELEMENT (adder)->pads;
216   while (pads) {
217     GstPad *otherpad = GST_PAD (pads->data);
218
219     if (otherpad != pad) {
220       gst_caps_replace (&GST_PAD_CAPS (otherpad), caps);
221     }
222     pads = g_list_next (pads);
223   }
224   GST_OBJECT_UNLOCK (adder);
225
226   /* parse caps now */
227   structure = gst_caps_get_structure (caps, 0);
228   media_type = gst_structure_get_name (structure);
229   if (strcmp (media_type, "audio/x-raw-int") == 0) {
230     GST_DEBUG_OBJECT (adder, "parse_caps sets adder to format int");
231     adder->format = GST_ADDER_FORMAT_INT;
232     gst_structure_get_int (structure, "width", &adder->width);
233     gst_structure_get_int (structure, "depth", &adder->depth);
234     gst_structure_get_int (structure, "endianness", &adder->endianness);
235     gst_structure_get_boolean (structure, "signed", &adder->is_signed);
236
237     if (adder->endianness != G_BYTE_ORDER)
238       goto not_supported;
239
240     switch (adder->width) {
241       case 8:
242         adder->func = (adder->is_signed ?
243             (GstAdderFunction) add_int8 : (GstAdderFunction) add_uint8);
244         break;
245       case 16:
246         adder->func = (adder->is_signed ?
247             (GstAdderFunction) add_int16 : (GstAdderFunction) add_uint16);
248         break;
249       case 32:
250         adder->func = (adder->is_signed ?
251             (GstAdderFunction) add_int32 : (GstAdderFunction) add_uint32);
252         break;
253       default:
254         goto not_supported;
255     }
256   } else if (strcmp (media_type, "audio/x-raw-float") == 0) {
257     GST_DEBUG_OBJECT (adder, "parse_caps sets adder to format float");
258     adder->format = GST_ADDER_FORMAT_FLOAT;
259     gst_structure_get_int (structure, "width", &adder->width);
260
261     switch (adder->width) {
262       case 32:
263         adder->func = (GstAdderFunction) add_float32;
264         break;
265       case 64:
266         adder->func = (GstAdderFunction) add_float64;
267         break;
268       default:
269         goto not_supported;
270     }
271   } else {
272     goto not_supported;
273   }
274
275   gst_structure_get_int (structure, "channels", &adder->channels);
276   gst_structure_get_int (structure, "rate", &adder->rate);
277   /* precalc bps */
278   adder->bps = (adder->width / 8) * adder->channels;
279
280   return TRUE;
281
282   /* ERRORS */
283 not_supported:
284   {
285     GST_DEBUG_OBJECT (adder, "unsupported format set as caps");
286     return FALSE;
287   }
288 }
289
290 /* FIXME, the duration query should reflect how long you will produce
291  * data, that is the amount of stream time until you will emit EOS.
292  *
293  * For synchronized mixing this is always the max of all the durations
294  * of upstream since we emit EOS when all of them finished.
295  *
296  * We don't do synchronized mixing so this really depends on where the
297  * streams where punched in and what their relative offsets are against
298  * eachother which we can get from the first timestamps we see.
299  *
300  * When we add a new stream (or remove a stream) the duration might
301  * also become invalid again and we need to post a new DURATION
302  * message to notify this fact to the parent.
303  * For now we take the max of all the upstream elements so the simple
304  * cases work at least somewhat.
305  */
306 static gboolean
307 gst_adder_query_duration (GstAdder * adder, GstQuery * query)
308 {
309   gint64 max;
310   gboolean res;
311   GstFormat format;
312   GstIterator *it;
313   gboolean done;
314
315   /* parse format */
316   gst_query_parse_duration (query, &format, NULL);
317
318   max = -1;
319   res = TRUE;
320   done = FALSE;
321
322   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
323   while (!done) {
324     GstIteratorResult ires;
325     gpointer item;
326
327     ires = gst_iterator_next (it, &item);
328     switch (ires) {
329       case GST_ITERATOR_DONE:
330         done = TRUE;
331         break;
332       case GST_ITERATOR_OK:
333       {
334         GstPad *pad = GST_PAD_CAST (item);
335         gint64 duration;
336
337         /* ask sink peer for duration */
338         res &= gst_pad_query_peer_duration (pad, &format, &duration);
339         /* take max from all valid return values */
340         if (res) {
341           /* valid unknown length, stop searching */
342           if (duration == -1) {
343             max = duration;
344             done = TRUE;
345           }
346           /* else see if bigger than current max */
347           else if (duration > max)
348             max = duration;
349         }
350         break;
351       }
352       case GST_ITERATOR_RESYNC:
353         max = -1;
354         res = TRUE;
355         break;
356       default:
357         res = FALSE;
358         done = TRUE;
359         break;
360     }
361   }
362   gst_iterator_free (it);
363
364   if (res) {
365     /* and store the max */
366     gst_query_set_duration (query, format, max);
367   }
368
369   return res;
370 }
371
372 static gboolean
373 gst_adder_query (GstPad * pad, GstQuery * query)
374 {
375   GstAdder *adder = GST_ADDER (gst_pad_get_parent (pad));
376   gboolean res = FALSE;
377
378   switch (GST_QUERY_TYPE (query)) {
379     case GST_QUERY_POSITION:
380     {
381       GstFormat format;
382
383       gst_query_parse_position (query, &format, NULL);
384
385       switch (format) {
386         case GST_FORMAT_TIME:
387           /* FIXME, bring to stream time, might be tricky */
388           gst_query_set_position (query, format, adder->timestamp);
389           res = TRUE;
390           break;
391         case GST_FORMAT_DEFAULT:
392           gst_query_set_position (query, format, adder->offset);
393           res = TRUE;
394           break;
395         default:
396           break;
397       }
398       break;
399     }
400     case GST_QUERY_DURATION:
401       res = gst_adder_query_duration (adder, query);
402       break;
403     default:
404       /* FIXME, needs a custom query handler because we have multiple
405        * sinkpads */
406       res = gst_pad_query_default (pad, query);
407       break;
408   }
409
410   gst_object_unref (adder);
411   return res;
412 }
413
414 static gboolean
415 forward_event_func (GstPad * pad, GValue * ret, GstEvent * event)
416 {
417   gst_event_ref (event);
418   GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event));
419   if (!gst_pad_push_event (pad, event)) {
420     g_value_set_boolean (ret, FALSE);
421     GST_WARNING_OBJECT (pad, "Sending event  %p (%s) failed.",
422         event, GST_EVENT_TYPE_NAME (event));
423   } else {
424     GST_LOG_OBJECT (pad, "Sent event  %p (%s).",
425         event, GST_EVENT_TYPE_NAME (event));
426   }
427   gst_object_unref (pad);
428   return TRUE;
429 }
430
431 /* forwards the event to all sinkpads, takes ownership of the
432  * event
433  *
434  * Returns: TRUE if the event could be forwarded on all
435  * sinkpads.
436  */
437 static gboolean
438 forward_event (GstAdder * adder, GstEvent * event)
439 {
440   gboolean ret;
441   GstIterator *it;
442   GValue vret = { 0 };
443
444   GST_LOG_OBJECT (adder, "Forwarding event %p (%s)", event,
445       GST_EVENT_TYPE_NAME (event));
446
447   ret = TRUE;
448
449   g_value_init (&vret, G_TYPE_BOOLEAN);
450   g_value_set_boolean (&vret, TRUE);
451   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
452   gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, &vret,
453       event);
454   gst_iterator_free (it);
455   gst_event_unref (event);
456
457   ret = g_value_get_boolean (&vret);
458
459   return ret;
460 }
461
462 static gboolean
463 gst_adder_src_event (GstPad * pad, GstEvent * event)
464 {
465   GstAdder *adder;
466   gboolean result;
467
468   adder = GST_ADDER (gst_pad_get_parent (pad));
469
470   switch (GST_EVENT_TYPE (event)) {
471     case GST_EVENT_QOS:
472       /* QoS might be tricky */
473       result = FALSE;
474       break;
475     case GST_EVENT_SEEK:
476     {
477       GstSeekFlags flags;
478       GstSeekType curtype;
479       gint64 cur;
480
481       /* parse the seek parameters */
482       gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype,
483           &cur, NULL, NULL);
484
485       /* check if we are flushing */
486       if (flags & GST_SEEK_FLAG_FLUSH) {
487         /* make sure we accept nothing anymore and return WRONG_STATE */
488         gst_collect_pads_set_flushing (adder->collect, TRUE);
489
490         /* flushing seek, start flush downstream, the flush will be done
491          * when all pads received a FLUSH_STOP. */
492         gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ());
493       }
494
495       /* now wait for the collected to be finished and mark a new
496        * segment */
497       GST_OBJECT_LOCK (adder->collect);
498       if (curtype == GST_SEEK_TYPE_SET)
499         adder->segment_position = cur;
500       else
501         adder->segment_position = 0;
502       adder->segment_pending = TRUE;
503       GST_OBJECT_UNLOCK (adder->collect);
504
505       result = forward_event (adder, event);
506       break;
507     }
508     case GST_EVENT_NAVIGATION:
509       /* navigation is rather pointless. */
510       result = FALSE;
511       break;
512     default:
513       /* just forward the rest for now */
514       result = forward_event (adder, event);
515       break;
516   }
517   gst_object_unref (adder);
518
519   return result;
520 }
521
522 static gboolean
523 gst_adder_sink_event (GstPad * pad, GstEvent * event)
524 {
525   GstAdder *adder;
526   gboolean ret;
527
528   adder = GST_ADDER (gst_pad_get_parent (pad));
529
530   GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
531       GST_DEBUG_PAD_NAME (pad));
532
533   switch (GST_EVENT_TYPE (event)) {
534     case GST_EVENT_FLUSH_STOP:
535       /* mark a pending new segment. This event is synchronized
536        * with the streaming thread so we can safely update the
537        * variable without races. It's somewhat weird because we
538        * assume the collectpads forwarded the FLUSH_STOP past us
539        * and downstream (using our source pad, the bastard!).
540        */
541       adder->segment_pending = TRUE;
542       break;
543     default:
544       break;
545   }
546
547   /* now GstCollectPads can take care of the rest, e.g. EOS */
548   ret = adder->collect_event (pad, event);
549
550   gst_object_unref (adder);
551   return ret;
552 }
553
554 static void
555 gst_adder_class_init (GstAdderClass * klass)
556 {
557   GObjectClass *gobject_class;
558   GstElementClass *gstelement_class;
559
560   gobject_class = (GObjectClass *) klass;
561
562   gobject_class->finalize = gst_adder_finalize;
563
564   gstelement_class = (GstElementClass *) klass;
565
566   gst_element_class_add_pad_template (gstelement_class,
567       gst_static_pad_template_get (&gst_adder_src_template));
568   gst_element_class_add_pad_template (gstelement_class,
569       gst_static_pad_template_get (&gst_adder_sink_template));
570   gst_element_class_set_details (gstelement_class, &adder_details);
571
572   parent_class = g_type_class_peek_parent (klass);
573
574   gstelement_class->request_new_pad = gst_adder_request_new_pad;
575   gstelement_class->release_pad = gst_adder_release_pad;
576   gstelement_class->change_state = gst_adder_change_state;
577 }
578
579 static void
580 gst_adder_init (GstAdder * adder)
581 {
582   GstPadTemplate *template;
583
584   template = gst_static_pad_template_get (&gst_adder_src_template);
585   adder->srcpad = gst_pad_new_from_template (template, "src");
586   gst_object_unref (template);
587   gst_pad_set_getcaps_function (adder->srcpad,
588       GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
589   gst_pad_set_setcaps_function (adder->srcpad,
590       GST_DEBUG_FUNCPTR (gst_adder_setcaps));
591   gst_pad_set_query_function (adder->srcpad,
592       GST_DEBUG_FUNCPTR (gst_adder_query));
593   gst_pad_set_event_function (adder->srcpad,
594       GST_DEBUG_FUNCPTR (gst_adder_src_event));
595   gst_element_add_pad (GST_ELEMENT (adder), adder->srcpad);
596
597   adder->format = GST_ADDER_FORMAT_UNSET;
598   adder->padcount = 0;
599   adder->func = NULL;
600
601   /* keep track of the sinkpads requested */
602   adder->collect = gst_collect_pads_new ();
603   gst_collect_pads_set_function (adder->collect,
604       GST_DEBUG_FUNCPTR (gst_adder_collected), adder);
605 }
606
607 static void
608 gst_adder_finalize (GObject * object)
609 {
610   GstAdder *adder = GST_ADDER (object);
611
612   gst_object_unref (adder->collect);
613   adder->collect = NULL;
614
615   G_OBJECT_CLASS (parent_class)->finalize (object);
616 }
617
618 static GstPad *
619 gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ,
620     const gchar * unused)
621 {
622   gchar *name;
623   GstAdder *adder;
624   GstPad *newpad;
625   gint padcount;
626
627   if (templ->direction != GST_PAD_SINK)
628     goto not_sink;
629
630   adder = GST_ADDER (element);
631
632   /* increment pad counter */
633   padcount = g_atomic_int_exchange_and_add (&adder->padcount, 1);
634
635   name = g_strdup_printf ("sink%d", padcount);
636   newpad = gst_pad_new_from_template (templ, name);
637   GST_DEBUG_OBJECT (adder, "request new pad %s", name);
638   g_free (name);
639
640   gst_pad_set_getcaps_function (newpad,
641       GST_DEBUG_FUNCPTR (gst_adder_sink_getcaps));
642   gst_pad_set_setcaps_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_setcaps));
643   gst_collect_pads_add_pad (adder->collect, newpad, sizeof (GstCollectData));
644
645   /* FIXME: hacked way to override/extend the event function of
646    * GstCollectPads; because it sets its own event function giving the
647    * element no access to events */
648   adder->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
649   gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_sink_event));
650
651   /* takes ownership of the pad */
652   if (!gst_element_add_pad (GST_ELEMENT (adder), newpad))
653     goto could_not_add;
654
655   return newpad;
656
657   /* errors */
658 not_sink:
659   {
660     g_warning ("gstadder: request new pad that is not a SINK pad\n");
661     return NULL;
662   }
663 could_not_add:
664   {
665     GST_DEBUG_OBJECT (adder, "could not add pad");
666     gst_collect_pads_remove_pad (adder->collect, newpad);
667     gst_object_unref (newpad);
668     return NULL;
669   }
670 }
671
672 static void
673 gst_adder_release_pad (GstElement * element, GstPad * pad)
674 {
675   GstAdder *adder;
676
677   adder = GST_ADDER (element);
678
679   GST_DEBUG_OBJECT (adder, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad));
680
681   gst_collect_pads_remove_pad (adder->collect, pad);
682   gst_element_remove_pad (element, pad);
683 }
684
685 static GstFlowReturn
686 gst_adder_collected (GstCollectPads * pads, gpointer user_data)
687 {
688   /*
689    * combine channels by adding sample values
690    * basic algorithm :
691    * - this function is called when all pads have a buffer
692    * - get available bytes on all pads.
693    * - repeat for each input pad :
694    *   - read available bytes, copy or add to target buffer
695    *   - if there's an EOS event, remove the input channel
696    * - push out the output buffer
697    */
698   GstAdder *adder;
699   guint size;
700   GSList *collected;
701   GstBuffer *outbuf;
702   GstFlowReturn ret;
703   gpointer outbytes;
704   gboolean empty = TRUE;
705
706   adder = GST_ADDER (user_data);
707
708   /* this is fatal */
709   if (G_UNLIKELY (adder->func == NULL))
710     goto not_negotiated;
711
712   /* get available bytes for reading, this can be 0 which could mean
713    * empty buffers or EOS, which we will catch when we loop over the
714    * pads. */
715   size = gst_collect_pads_available (pads);
716
717   GST_LOG_OBJECT (adder,
718       "starting to cycle through channels, %d bytes available (bps = %d)", size,
719       adder->bps);
720
721   outbuf = NULL;
722   outbytes = NULL;
723
724   for (collected = pads->data; collected; collected = g_slist_next (collected)) {
725     GstCollectData *data;
726     guint8 *bytes;
727     guint len;
728     GstBuffer *inbuf;
729
730     data = (GstCollectData *) collected->data;
731
732     /* get a subbuffer of size bytes */
733     inbuf = gst_collect_pads_take_buffer (pads, data, size);
734     /* NULL means EOS or an empty buffer so we still need to flush in
735      * case of an empty buffer. */
736     if (inbuf == NULL) {
737       GST_LOG_OBJECT (adder, "channel %p: no bytes available", data);
738       goto next;
739     }
740
741     bytes = GST_BUFFER_DATA (inbuf);
742     len = GST_BUFFER_SIZE (inbuf);
743
744     if (outbuf == NULL) {
745       GST_LOG_OBJECT (adder, "channel %p: making output buffer of %d bytes",
746           data, size);
747
748       /* first buffer, alloc size bytes. FIXME, we can easily subbuffer
749        * and _make_writable. */
750       outbuf = gst_buffer_new_and_alloc (size);
751       outbytes = GST_BUFFER_DATA (outbuf);
752       gst_buffer_set_caps (outbuf, GST_PAD_CAPS (adder->srcpad));
753
754       if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
755         /* clear if we are only going to fill a partial buffer */
756         if (G_UNLIKELY (size > len))
757           memset (outbytes, 0, size);
758
759         GST_LOG_OBJECT (adder, "channel %p: copying %d bytes from data %p",
760             data, len, bytes);
761
762         /* and copy the data into it */
763         memcpy (outbytes, bytes, len);
764         empty = FALSE;
765       } else {
766         GST_LOG_OBJECT (adder, "channel %p: zeroing %d bytes from data %p",
767             data, len, bytes);
768         memset (outbytes, 0, size);
769       }
770     } else {
771       if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
772         GST_LOG_OBJECT (adder, "channel %p: mixing %d bytes from data %p",
773             data, len, bytes);
774         /* other buffers, need to add them */
775         adder->func ((gpointer) outbytes, (gpointer) bytes, len);
776         empty = FALSE;
777       } else {
778         GST_LOG_OBJECT (adder, "channel %p: skipping %d bytes from data %p",
779             data, len, bytes);
780       }
781     }
782   next:
783     if (inbuf)
784       gst_buffer_unref (inbuf);
785   }
786
787   /* can only happen when no pads to collect or all EOS */
788   if (outbuf == NULL)
789     goto eos;
790
791   /* our timestamping is very simple, just an ever incrementing
792    * counter, the new segment time will take care of their respective
793    * stream time. */
794   if (adder->segment_pending) {
795     GstEvent *event;
796
797     /* FIXME, use rate/applied_rate as set on all sinkpads.
798      * - currently we just set rate as received from last seek-event
799      * We could potentially figure out the duration as well using
800      * the current segment positions and the stated stop positions.
801      * Also we just start from stream time 0 which is rather
802      * weird. For non-synchronized mixing, the time should be
803      * the min of the stream times of all received segments,
804      * rationale being that the duration is at least going to
805      * be as long as the earliest stream we start mixing. This
806      * would also be correct for synchronized mixing but then
807      * the later streams would be delayed until the stream times
808      * match.
809      */
810     event = gst_event_new_new_segment_full (FALSE, adder->segment_rate,
811         1.0, GST_FORMAT_TIME, adder->timestamp, -1, adder->segment_position);
812
813     gst_pad_push_event (adder->srcpad, event);
814     adder->segment_pending = FALSE;
815     adder->segment_position = 0;
816   }
817
818   /* set timestamps on the output buffer */
819   GST_BUFFER_TIMESTAMP (outbuf) = adder->timestamp;
820   GST_BUFFER_OFFSET (outbuf) = adder->offset;
821
822   /* for the next timestamp, use the sample counter, which will
823    * never accumulate rounding errors */
824   adder->offset += size / adder->bps;
825   adder->timestamp = gst_util_uint64_scale_int (adder->offset,
826       GST_SECOND, adder->rate);
827
828   /* now we can set the duration of the buffer */
829   GST_BUFFER_DURATION (outbuf) = adder->timestamp -
830       GST_BUFFER_TIMESTAMP (outbuf);
831
832   /* if we only processed silence, mark output again as silence */
833   if (empty)
834     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
835
836   /* send it out */
837   GST_LOG_OBJECT (adder, "pushing outbuf, timestamp %" GST_TIME_FORMAT,
838       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
839   ret = gst_pad_push (adder->srcpad, outbuf);
840
841   return ret;
842
843   /* ERRORS */
844 not_negotiated:
845   {
846     GST_ELEMENT_ERROR (adder, STREAM, FORMAT, (NULL),
847         ("Unknown data received, not negotiated"));
848     return GST_FLOW_NOT_NEGOTIATED;
849   }
850 eos:
851   {
852     GST_DEBUG_OBJECT (adder, "no data available, must be EOS");
853     gst_pad_push_event (adder->srcpad, gst_event_new_eos ());
854     return GST_FLOW_UNEXPECTED;
855   }
856 }
857
858 static GstStateChangeReturn
859 gst_adder_change_state (GstElement * element, GstStateChange transition)
860 {
861   GstAdder *adder;
862   GstStateChangeReturn ret;
863
864   adder = GST_ADDER (element);
865
866   switch (transition) {
867     case GST_STATE_CHANGE_NULL_TO_READY:
868       break;
869     case GST_STATE_CHANGE_READY_TO_PAUSED:
870       adder->timestamp = 0;
871       adder->offset = 0;
872       adder->segment_pending = TRUE;
873       adder->segment_position = 0;
874       adder->segment_rate = 1.0;
875       gst_segment_init (&adder->segment, GST_FORMAT_UNDEFINED);
876       gst_collect_pads_start (adder->collect);
877       break;
878     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
879       break;
880     case GST_STATE_CHANGE_PAUSED_TO_READY:
881       /* need to unblock the collectpads before calling the
882        * parent change_state so that streaming can finish */
883       gst_collect_pads_stop (adder->collect);
884       break;
885     default:
886       break;
887   }
888
889   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
890
891   switch (transition) {
892     default:
893       break;
894   }
895
896   return ret;
897 }
898
899
900 static gboolean
901 plugin_init (GstPlugin * plugin)
902 {
903   if (!gst_element_register (plugin, "adder", GST_RANK_NONE, GST_TYPE_ADDER)) {
904     return FALSE;
905   }
906
907   return TRUE;
908 }
909
910 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
911     GST_VERSION_MINOR,
912     "adder",
913     "Adds multiple streams",
914     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)