Remove GST_DEBUG_FUNCPTR where they're pointless
[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  * The adder allows to mix several streams into one by adding the data.
27  * Mixed data is clamped to the min/max values of the data format.
28  *
29  * The adder currently mixes all data received on the sinkpads as soon as
30  * possible without trying to synchronize the streams.
31  *
32  * <refsect2>
33  * <title>Example launch line</title>
34  * |[
35  * gst-launch audiotestsrc freq=100 ! adder name=mix ! audioconvert ! alsasink audiotestsrc freq=500 ! mix.
36  * ]| This pipeline produces two sine waves mixed together.
37  * </refsect2>
38  *
39  * Last reviewed on 2006-05-09 (0.10.7)
40  */
41 /* Element-Checklist-Version: 5 */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46 #include "gstadder.h"
47 #include <gst/audio/audio.h>
48 #include <string.h>             /* strcmp */
49 /*#include <liboil/liboil.h>*/
50
51 /* highest positive/lowest negative x-bit value we can use for clamping */
52 #define MAX_INT_32  ((gint32) (0x7fffffff))
53 #define MAX_INT_16  ((gint16) (0x7fff))
54 #define MAX_INT_8   ((gint8)  (0x7f))
55 #define MAX_UINT_32 ((guint32)(0xffffffff))
56 #define MAX_UINT_16 ((guint16)(0xffff))
57 #define MAX_UINT_8  ((guint8) (0xff))
58
59 #define MIN_INT_32  ((gint32) (0x80000000))
60 #define MIN_INT_16  ((gint16) (0x8000))
61 #define MIN_INT_8   ((gint8)  (0x80))
62 #define MIN_UINT_32 ((guint32)(0x00000000))
63 #define MIN_UINT_16 ((guint16)(0x0000))
64 #define MIN_UINT_8  ((guint8) (0x00))
65
66 enum
67 {
68   PROP_0,
69   PROP_FILTER_CAPS
70 };
71
72 #define GST_CAT_DEFAULT gst_adder_debug
73 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
74
75 /* elementfactory information */
76
77 #define CAPS \
78   "audio/x-raw-int, " \
79   "rate = (int) [ 1, MAX ], " \
80   "channels = (int) [ 1, MAX ], " \
81   "endianness = (int) BYTE_ORDER, " \
82   "width = (int) 32, " \
83   "depth = (int) 32, " \
84   "signed = (boolean) { true, false } ;" \
85   "audio/x-raw-int, " \
86   "rate = (int) [ 1, MAX ], " \
87   "channels = (int) [ 1, MAX ], " \
88   "endianness = (int) BYTE_ORDER, " \
89   "width = (int) 16, " \
90   "depth = (int) 16, " \
91   "signed = (boolean) { true, false } ;" \
92   "audio/x-raw-int, " \
93   "rate = (int) [ 1, MAX ], " \
94   "channels = (int) [ 1, MAX ], " \
95   "endianness = (int) BYTE_ORDER, " \
96   "width = (int) 8, " \
97   "depth = (int) 8, " \
98   "signed = (boolean) { true, false } ;" \
99   "audio/x-raw-float, " \
100   "rate = (int) [ 1, MAX ], " \
101   "channels = (int) [ 1, MAX ], " \
102   "endianness = (int) BYTE_ORDER, " \
103   "width = (int) { 32, 64 }"
104
105 static GstStaticPadTemplate gst_adder_src_template =
106 GST_STATIC_PAD_TEMPLATE ("src",
107     GST_PAD_SRC,
108     GST_PAD_ALWAYS,
109     GST_STATIC_CAPS (CAPS)
110     );
111
112 static GstStaticPadTemplate gst_adder_sink_template =
113 GST_STATIC_PAD_TEMPLATE ("sink%d",
114     GST_PAD_SINK,
115     GST_PAD_REQUEST,
116     GST_STATIC_CAPS (CAPS)
117     );
118
119 static void gst_adder_class_init (GstAdderClass * klass);
120 static void gst_adder_init (GstAdder * adder);
121 static void gst_adder_dispose (GObject * object);
122 static void gst_adder_set_property (GObject * object, guint prop_id,
123     const GValue * value, GParamSpec * pspec);
124 static void gst_adder_get_property (GObject * object, guint prop_id,
125     GValue * value, GParamSpec * pspec);
126
127 static gboolean gst_adder_setcaps (GstPad * pad, GstCaps * caps);
128 static gboolean gst_adder_query (GstPad * pad, GstQuery * query);
129 static gboolean gst_adder_src_event (GstPad * pad, GstEvent * event);
130 static gboolean gst_adder_sink_event (GstPad * pad, GstEvent * event);
131
132 static GstPad *gst_adder_request_new_pad (GstElement * element,
133     GstPadTemplate * temp, const gchar * unused);
134 static void gst_adder_release_pad (GstElement * element, GstPad * pad);
135
136 static GstStateChangeReturn gst_adder_change_state (GstElement * element,
137     GstStateChange transition);
138
139 static GstFlowReturn gst_adder_collected (GstCollectPads * pads,
140     gpointer user_data);
141
142 static GstElementClass *parent_class = NULL;
143
144 GType
145 gst_adder_get_type (void)
146 {
147   static GType adder_type = 0;
148
149   if (G_UNLIKELY (adder_type == 0)) {
150     static const GTypeInfo adder_info = {
151       sizeof (GstAdderClass), NULL, NULL,
152       (GClassInitFunc) gst_adder_class_init, NULL, NULL,
153       sizeof (GstAdder), 0,
154       (GInstanceInitFunc) gst_adder_init,
155     };
156
157     adder_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAdder",
158         &adder_info, 0);
159     GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "adder", 0,
160         "audio channel mixing element");
161   }
162   return adder_type;
163 }
164
165 /* clipping versions (for int)
166  * FIXME: what about: oil_add_s16 (out, out, in, bytes / sizeof (type))
167  */
168 #define MAKE_FUNC(name,type,ttype,min,max)                      \
169 static void name (type *out, type *in, gint bytes) {            \
170   gint i;                                                       \
171   ttype add;                                                    \
172   for (i = 0; i < bytes / sizeof (type); i++) {                 \
173     add = (ttype)out[i] + (ttype)in[i];                         \
174     out[i] = CLAMP (add, min, max);                             \
175   }                                                             \
176 }
177
178 /* unsigned versions (for int) */
179 #define MAKE_FUNC_US(name,type,ttype,max)                       \
180 static void name (type *out, type *in, gint bytes) {            \
181   gint i;                                                       \
182   ttype add;                                                    \
183   for (i = 0; i < bytes / sizeof (type); i++) {                 \
184     add = (ttype)out[i] + (ttype)in[i];                         \
185     out[i] = ((add <= max) ? add : max);                        \
186   }                                                             \
187 }
188
189 /* non-clipping versions (for float) */
190 #define MAKE_FUNC_NC(name,type)                                 \
191 static void name (type *out, type *in, gint bytes) {            \
192   gint i;                                                       \
193   for (i = 0; i < bytes / sizeof (type); i++)                   \
194     out[i] += in[i];                                            \
195 }
196
197 #if 0
198 /* right now, the liboil function don't seems to be faster on x86
199  * time gst-launch audiotestsrc num-buffers=50000 ! audio/x-raw-float ! adder name=m ! fakesink audiotestsrc num-buffers=50000 ! audio/x-raw-float ! m.
200  * time gst-launch audiotestsrc num-buffers=50000 ! audio/x-raw-float,width=32 ! adder name=m ! fakesink audiotestsrc num-buffers=50000 ! audio/x-raw-float,width=32 ! m.
201  */
202 static void
203 add_float32 (gfloat * out, gfloat * in, gint bytes)
204 {
205   oil_add_f32 (out, out, in, bytes / sizeof (gfloat));
206 }
207
208 static void
209 add_float64 (gdouble * out, gdouble * in, gint bytes)
210 {
211   oil_add_f64 (out, out, in, bytes / sizeof (gdouble));
212 }
213 #endif
214
215 /* *INDENT-OFF* */
216 MAKE_FUNC (add_int32, gint32, gint64, MIN_INT_32, MAX_INT_32)
217 MAKE_FUNC (add_int16, gint16, gint32, MIN_INT_16, MAX_INT_16)
218 MAKE_FUNC (add_int8, gint8, gint16, MIN_INT_8, MAX_INT_8)
219 MAKE_FUNC_US (add_uint32, guint32, guint64, MAX_UINT_32)
220 MAKE_FUNC_US (add_uint16, guint16, guint32, MAX_UINT_16)
221 MAKE_FUNC_US (add_uint8, guint8, guint16, MAX_UINT_8)
222 MAKE_FUNC_NC (add_float64, gdouble)
223 MAKE_FUNC_NC (add_float32, gfloat)
224 /* *INDENT-ON* */
225
226 /* we can only accept caps that we and downstream can handle.
227  * if we have filtercaps set, use those to constrain the target caps.
228  */
229 static GstCaps *
230 gst_adder_sink_getcaps (GstPad * pad)
231 {
232   GstAdder *adder;
233   GstCaps *result, *peercaps, *sinkcaps;
234
235   adder = GST_ADDER (GST_PAD_PARENT (pad));
236
237   GST_OBJECT_LOCK (adder);
238   /* get the downstream possible caps */
239   peercaps = gst_pad_peer_get_caps (adder->srcpad);
240
241   /* get the allowed caps on this sinkpad, we use the fixed caps function so
242    * that it does not call recursively in this function. */
243   sinkcaps = gst_pad_get_fixed_caps_func (pad);
244   if (peercaps) {
245     /* restrict with filter-caps if any */
246     if (adder->filter_caps) {
247       GST_DEBUG_OBJECT (adder, "filtering peer caps");
248       result = gst_caps_intersect (peercaps, adder->filter_caps);
249       gst_caps_unref (peercaps);
250       peercaps = result;
251     }
252     /* if the peer has caps, intersect */
253     GST_DEBUG_OBJECT (adder, "intersecting peer and template caps");
254     result = gst_caps_intersect (peercaps, sinkcaps);
255     gst_caps_unref (peercaps);
256     gst_caps_unref (sinkcaps);
257   } else {
258     /* the peer has no caps (or there is no peer), just use the allowed caps
259      * of this sinkpad. */
260     /* restrict with filter-caps if any */
261     if (adder->filter_caps) {
262       GST_DEBUG_OBJECT (adder, "no peer caps, using filtered sinkcaps");
263       result = gst_caps_intersect (sinkcaps, adder->filter_caps);
264       gst_caps_unref (sinkcaps);
265     } else {
266       GST_DEBUG_OBJECT (adder, "no peer caps, using sinkcaps");
267       result = sinkcaps;
268     }
269   }
270   GST_OBJECT_UNLOCK (adder);
271
272   GST_LOG_OBJECT (adder, "getting caps on pad %p,%s to %" GST_PTR_FORMAT, pad,
273       GST_PAD_NAME (pad), result);
274
275   return result;
276 }
277
278 /* the first caps we receive on any of the sinkpads will define the caps for all
279  * the other sinkpads because we can only mix streams with the same caps.
280  */
281 static gboolean
282 gst_adder_setcaps (GstPad * pad, GstCaps * caps)
283 {
284   GstAdder *adder;
285   GList *pads;
286   GstStructure *structure;
287   const char *media_type;
288
289   adder = GST_ADDER (GST_PAD_PARENT (pad));
290
291   GST_LOG_OBJECT (adder, "setting caps on pad %p,%s to %" GST_PTR_FORMAT, pad,
292       GST_PAD_NAME (pad), caps);
293
294   /* FIXME, see if the other pads can accept the format. Also lock the
295    * format on the other pads to this new format. */
296   GST_OBJECT_LOCK (adder);
297   pads = GST_ELEMENT (adder)->pads;
298   while (pads) {
299     GstPad *otherpad = GST_PAD (pads->data);
300
301     if (otherpad != pad) {
302       gst_caps_replace (&GST_PAD_CAPS (otherpad), caps);
303     }
304     pads = g_list_next (pads);
305   }
306   GST_OBJECT_UNLOCK (adder);
307
308   /* parse caps now */
309   structure = gst_caps_get_structure (caps, 0);
310   media_type = gst_structure_get_name (structure);
311   if (strcmp (media_type, "audio/x-raw-int") == 0) {
312     adder->format = GST_ADDER_FORMAT_INT;
313     gst_structure_get_int (structure, "width", &adder->width);
314     gst_structure_get_int (structure, "depth", &adder->depth);
315     gst_structure_get_int (structure, "endianness", &adder->endianness);
316     gst_structure_get_boolean (structure, "signed", &adder->is_signed);
317
318     GST_INFO_OBJECT (pad, "parse_caps sets adder to format int, %d bit",
319         adder->width);
320
321     if (adder->endianness != G_BYTE_ORDER)
322       goto not_supported;
323
324     switch (adder->width) {
325       case 8:
326         adder->func = (adder->is_signed ?
327             (GstAdderFunction) add_int8 : (GstAdderFunction) add_uint8);
328         break;
329       case 16:
330         adder->func = (adder->is_signed ?
331             (GstAdderFunction) add_int16 : (GstAdderFunction) add_uint16);
332         break;
333       case 32:
334         adder->func = (adder->is_signed ?
335             (GstAdderFunction) add_int32 : (GstAdderFunction) add_uint32);
336         break;
337       default:
338         goto not_supported;
339     }
340   } else if (strcmp (media_type, "audio/x-raw-float") == 0) {
341     adder->format = GST_ADDER_FORMAT_FLOAT;
342     gst_structure_get_int (structure, "width", &adder->width);
343     gst_structure_get_int (structure, "endianness", &adder->endianness);
344
345     GST_INFO_OBJECT (pad, "parse_caps sets adder to format float, %d bit",
346         adder->width);
347
348     if (adder->endianness != G_BYTE_ORDER)
349       goto not_supported;
350
351     switch (adder->width) {
352       case 32:
353         adder->func = (GstAdderFunction) add_float32;
354         break;
355       case 64:
356         adder->func = (GstAdderFunction) add_float64;
357         break;
358       default:
359         goto not_supported;
360     }
361   } else {
362     goto not_supported;
363   }
364
365   gst_structure_get_int (structure, "channels", &adder->channels);
366   gst_structure_get_int (structure, "rate", &adder->rate);
367   /* precalc bps */
368   adder->bps = (adder->width / 8) * adder->channels;
369
370   return TRUE;
371
372   /* ERRORS */
373 not_supported:
374   {
375     GST_DEBUG_OBJECT (adder, "unsupported format set as caps");
376     return FALSE;
377   }
378 }
379
380 /* FIXME, the duration query should reflect how long you will produce
381  * data, that is the amount of stream time until you will emit EOS.
382  *
383  * For synchronized mixing this is always the max of all the durations
384  * of upstream since we emit EOS when all of them finished.
385  *
386  * We don't do synchronized mixing so this really depends on where the
387  * streams where punched in and what their relative offsets are against
388  * eachother which we can get from the first timestamps we see.
389  *
390  * When we add a new stream (or remove a stream) the duration might
391  * also become invalid again and we need to post a new DURATION
392  * message to notify this fact to the parent.
393  * For now we take the max of all the upstream elements so the simple
394  * cases work at least somewhat.
395  */
396 static gboolean
397 gst_adder_query_duration (GstAdder * adder, GstQuery * query)
398 {
399   gint64 max;
400   gboolean res;
401   GstFormat format;
402   GstIterator *it;
403   gboolean done;
404
405   /* parse format */
406   gst_query_parse_duration (query, &format, NULL);
407
408   max = -1;
409   res = TRUE;
410   done = FALSE;
411
412   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
413   while (!done) {
414     GstIteratorResult ires;
415
416     gpointer item;
417
418     ires = gst_iterator_next (it, &item);
419     switch (ires) {
420       case GST_ITERATOR_DONE:
421         done = TRUE;
422         break;
423       case GST_ITERATOR_OK:
424       {
425         GstPad *pad = GST_PAD_CAST (item);
426
427         gint64 duration;
428
429         /* ask sink peer for duration */
430         res &= gst_pad_query_peer_duration (pad, &format, &duration);
431         /* take max from all valid return values */
432         if (res) {
433           /* valid unknown length, stop searching */
434           if (duration == -1) {
435             max = duration;
436             done = TRUE;
437           }
438           /* else see if bigger than current max */
439           else if (duration > max)
440             max = duration;
441         }
442         gst_object_unref (pad);
443         break;
444       }
445       case GST_ITERATOR_RESYNC:
446         max = -1;
447         res = TRUE;
448         gst_iterator_resync (it);
449         break;
450       default:
451         res = FALSE;
452         done = TRUE;
453         break;
454     }
455   }
456   gst_iterator_free (it);
457
458   if (res) {
459     /* and store the max */
460     GST_DEBUG_OBJECT (adder, "Total duration in format %s: %"
461         GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (max));
462     gst_query_set_duration (query, format, max);
463   }
464
465   return res;
466 }
467
468 static gboolean
469 gst_adder_query_latency (GstAdder * adder, GstQuery * query)
470 {
471   GstClockTime min, max;
472   gboolean live;
473   gboolean res;
474   GstIterator *it;
475   gboolean done;
476
477   res = TRUE;
478   done = FALSE;
479
480   live = FALSE;
481   min = 0;
482   max = GST_CLOCK_TIME_NONE;
483
484   /* Take maximum of all latency values */
485   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
486   while (!done) {
487     GstIteratorResult ires;
488
489     gpointer item;
490
491     ires = gst_iterator_next (it, &item);
492     switch (ires) {
493       case GST_ITERATOR_DONE:
494         done = TRUE;
495         break;
496       case GST_ITERATOR_OK:
497       {
498         GstPad *pad = GST_PAD_CAST (item);
499         GstQuery *peerquery;
500         GstClockTime min_cur, max_cur;
501         gboolean live_cur;
502
503         peerquery = gst_query_new_latency ();
504
505         /* Ask peer for latency */
506         res &= gst_pad_peer_query (pad, peerquery);
507
508         /* take max from all valid return values */
509         if (res) {
510           gst_query_parse_latency (peerquery, &live_cur, &min_cur, &max_cur);
511
512           if (min_cur > min)
513             min = min_cur;
514
515           if (max_cur != GST_CLOCK_TIME_NONE &&
516               ((max != GST_CLOCK_TIME_NONE && max_cur > max) ||
517                   (max == GST_CLOCK_TIME_NONE)))
518             max = max_cur;
519
520           live = live || live_cur;
521         }
522
523         gst_query_unref (peerquery);
524         gst_object_unref (pad);
525         break;
526       }
527       case GST_ITERATOR_RESYNC:
528         live = FALSE;
529         min = 0;
530         max = GST_CLOCK_TIME_NONE;
531         res = TRUE;
532         gst_iterator_resync (it);
533         break;
534       default:
535         res = FALSE;
536         done = TRUE;
537         break;
538     }
539   }
540   gst_iterator_free (it);
541
542   if (res) {
543     /* store the results */
544     GST_DEBUG_OBJECT (adder, "Calculated total latency: live %s, min %"
545         GST_TIME_FORMAT ", max %" GST_TIME_FORMAT,
546         (live ? "yes" : "no"), GST_TIME_ARGS (min), GST_TIME_ARGS (max));
547     gst_query_set_latency (query, live, min, max);
548   }
549
550   return res;
551 }
552
553 static gboolean
554 gst_adder_query (GstPad * pad, GstQuery * query)
555 {
556   GstAdder *adder = GST_ADDER (gst_pad_get_parent (pad));
557   gboolean res = FALSE;
558
559   switch (GST_QUERY_TYPE (query)) {
560     case GST_QUERY_POSITION:
561     {
562       GstFormat format;
563
564       gst_query_parse_position (query, &format, NULL);
565
566       switch (format) {
567         case GST_FORMAT_TIME:
568           /* FIXME, bring to stream time, might be tricky */
569           gst_query_set_position (query, format, adder->timestamp);
570           res = TRUE;
571           break;
572         case GST_FORMAT_DEFAULT:
573           gst_query_set_position (query, format, adder->offset);
574           res = TRUE;
575           break;
576         default:
577           break;
578       }
579       break;
580     }
581     case GST_QUERY_DURATION:
582       res = gst_adder_query_duration (adder, query);
583       break;
584     case GST_QUERY_LATENCY:
585       res = gst_adder_query_latency (adder, query);
586       break;
587     default:
588       /* FIXME, needs a custom query handler because we have multiple
589        * sinkpads */
590       res = gst_pad_query_default (pad, query);
591       break;
592   }
593
594   gst_object_unref (adder);
595   return res;
596 }
597
598 typedef struct
599 {
600   GstEvent *event;
601   gboolean flush;
602 } EventData;
603
604 static gboolean
605 forward_event_func (GstPad * pad, GValue * ret, EventData * data)
606 {
607   GstEvent *event = data->event;
608
609   gst_event_ref (event);
610   GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event));
611   if (!gst_pad_push_event (pad, event)) {
612     g_value_set_boolean (ret, FALSE);
613     GST_WARNING_OBJECT (pad, "Sending event  %p (%s) failed.",
614         event, GST_EVENT_TYPE_NAME (event));
615     /* quick hack to unflush the pads, ideally we need a way to just unflush
616      * this single collect pad */
617     if (data->flush)
618       gst_pad_send_event (pad, gst_event_new_flush_stop ());
619   } else {
620     GST_LOG_OBJECT (pad, "Sent event  %p (%s).",
621         event, GST_EVENT_TYPE_NAME (event));
622   }
623   gst_object_unref (pad);
624
625   /* continue on other pads, even if one failed */
626   return TRUE;
627 }
628
629 /* forwards the event to all sinkpads, takes ownership of the
630  * event
631  *
632  * Returns: TRUE if the event could be forwarded on all
633  * sinkpads.
634  */
635 static gboolean
636 forward_event (GstAdder * adder, GstEvent * event, gboolean flush)
637 {
638   gboolean ret;
639   GstIterator *it;
640   GstIteratorResult ires;
641   GValue vret = { 0 };
642   EventData data;
643
644   GST_LOG_OBJECT (adder, "Forwarding event %p (%s)", event,
645       GST_EVENT_TYPE_NAME (event));
646
647   data.event = event;
648   data.flush = flush;
649
650   g_value_init (&vret, G_TYPE_BOOLEAN);
651   g_value_set_boolean (&vret, TRUE);
652   it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder));
653   while (TRUE) {
654     ires = gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func,
655         &vret, &data);
656     switch (ires) {
657       case GST_ITERATOR_RESYNC:
658         GST_WARNING ("resync");
659         gst_iterator_resync (it);
660         g_value_set_boolean (&vret, TRUE);
661         break;
662       case GST_ITERATOR_OK:
663       case GST_ITERATOR_DONE:
664         ret = g_value_get_boolean (&vret);
665         goto done;
666       default:
667         ret = FALSE;
668         goto done;
669     }
670   }
671 done:
672   gst_iterator_free (it);
673   GST_LOG_OBJECT (adder, "Forwarded event %p (%s), ret=%d", event,
674       GST_EVENT_TYPE_NAME (event), ret);
675   gst_event_unref (event);
676
677   return ret;
678 }
679
680 static gboolean
681 gst_adder_src_event (GstPad * pad, GstEvent * event)
682 {
683   GstAdder *adder;
684   gboolean result;
685
686   adder = GST_ADDER (gst_pad_get_parent (pad));
687
688   switch (GST_EVENT_TYPE (event)) {
689     case GST_EVENT_SEEK:
690     {
691       GstSeekFlags flags;
692       GstSeekType curtype;
693       gint64 cur;
694       gboolean flush;
695
696       /* parse the seek parameters */
697       gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype,
698           &cur, NULL, NULL);
699
700       flush = (flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH;
701
702       /* check if we are flushing */
703       if (flush) {
704         /* make sure we accept nothing anymore and return WRONG_STATE */
705         gst_collect_pads_set_flushing (adder->collect, TRUE);
706
707         /* flushing seek, start flush downstream, the flush will be done
708          * when all pads received a FLUSH_STOP. */
709         gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ());
710       }
711       GST_DEBUG_OBJECT (adder, "handling seek event: %" GST_PTR_FORMAT, event);
712
713       /* now wait for the collected to be finished and mark a new
714        * segment. After we have the lock, no collect function is running and no
715        * new collect function will be called for as long as we're flushing. */
716       GST_OBJECT_LOCK (adder->collect);
717       if (curtype == GST_SEEK_TYPE_SET)
718         adder->segment_position = cur;
719       else
720         adder->segment_position = 0;
721       /* make sure we push a new segment, to inform about new basetime
722        * see FIXME in gst_adder_collected() */
723       adder->segment_pending = TRUE;
724       if (flush) {
725         /* Yes, we need to call _set_flushing again *WHEN* the streaming threads
726          * have stopped so that the cookie gets properly updated. */
727         gst_collect_pads_set_flushing (adder->collect, TRUE);
728       }
729       /* we might have a pending flush_stop event now. This event will either be
730        * sent by an upstream element when it completes the seek or we will push
731        * one in the collected callback ourself */
732       adder->flush_stop_pending = flush;
733       GST_OBJECT_UNLOCK (adder->collect);
734       GST_DEBUG_OBJECT (adder, "forwarding seek event: %" GST_PTR_FORMAT,
735           event);
736
737       result = forward_event (adder, event, flush);
738       if (!result) {
739         /* seek failed. maybe source is a live source. */
740         GST_DEBUG_OBJECT (adder, "seeking failed");
741       }
742       /* FIXME: ideally we would like to send a flush-stop event from here but
743        * collectpads does not have a method that allows us to do that. Instead
744        * we forward all flush-stop events we receive on the sinkpads. We might
745        * be sending too many flush-stop events. */
746       break;
747     }
748     case GST_EVENT_QOS:
749       /* QoS might be tricky */
750       result = FALSE;
751       break;
752     case GST_EVENT_NAVIGATION:
753       /* navigation is rather pointless. */
754       result = FALSE;
755       break;
756     default:
757       /* just forward the rest for now */
758       GST_DEBUG_OBJECT (adder, "forward unhandled event: %s",
759           GST_EVENT_TYPE_NAME (event));
760       result = forward_event (adder, event, FALSE);
761       break;
762   }
763   gst_object_unref (adder);
764
765   return result;
766 }
767
768 static gboolean
769 gst_adder_sink_event (GstPad * pad, GstEvent * event)
770 {
771   GstAdder *adder;
772   gboolean ret = TRUE;
773
774   adder = GST_ADDER (gst_pad_get_parent (pad));
775
776   GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event),
777       GST_DEBUG_PAD_NAME (pad));
778
779   switch (GST_EVENT_TYPE (event)) {
780     case GST_EVENT_FLUSH_STOP:
781       /* we received a flush-stop. The collect_event function will push the
782        * event past our element. We simply forward all flush-stop events, even
783        * when no flush-stop was pendingk, this is required because collectpads
784        * does not provide an API to handle-but-not-forward the flush-stop.
785        * We unset the pending flush-stop flag so that we don't send anymore
786        * flush-stop from the collect function later.
787        */
788       GST_OBJECT_LOCK (adder->collect);
789       adder->segment_pending = TRUE;
790       adder->flush_stop_pending = FALSE;
791       /* Clear pending tags */
792       if (adder->pending_events) {
793         g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL);
794         g_list_free (adder->pending_events);
795         adder->pending_events = NULL;
796       }
797       GST_OBJECT_UNLOCK (adder->collect);
798       break;
799     case GST_EVENT_TAG:
800       GST_OBJECT_LOCK (adder->collect);
801       /* collectpads is a pile of horse manure. */
802       adder->pending_events = g_list_append (adder->pending_events, event);
803       GST_OBJECT_UNLOCK (adder->collect);
804       goto beach;
805     default:
806       break;
807   }
808
809   /* now GstCollectPads can take care of the rest, e.g. EOS */
810   ret = adder->collect_event (pad, event);
811
812 beach:
813   gst_object_unref (adder);
814   return ret;
815 }
816
817 static void
818 gst_adder_class_init (GstAdderClass * klass)
819 {
820   GObjectClass *gobject_class = (GObjectClass *) klass;
821   GstElementClass *gstelement_class = (GstElementClass *) klass;
822
823   gobject_class->set_property = gst_adder_set_property;
824   gobject_class->get_property = gst_adder_get_property;
825   gobject_class->dispose = gst_adder_dispose;
826
827   gst_element_class_add_pad_template (gstelement_class,
828       gst_static_pad_template_get (&gst_adder_src_template));
829   gst_element_class_add_pad_template (gstelement_class,
830       gst_static_pad_template_get (&gst_adder_sink_template));
831   gst_element_class_set_details_simple (gstelement_class, "Adder",
832       "Generic/Audio",
833       "Add N audio channels together",
834       "Thomas Vander Stichele <thomas at apestaart dot org>");
835
836   parent_class = g_type_class_peek_parent (klass);
837
838   /**
839    * GstAdder:caps:
840    *
841    * Since: 0.10.24
842    */
843   g_object_class_install_property (gobject_class, PROP_FILTER_CAPS,
844       g_param_spec_boxed ("caps", "Target caps",
845           "Set target format for mixing (NULL means ANY). "
846           "Setting this property takes a reference to the supplied GstCaps "
847           "object.", GST_TYPE_CAPS,
848           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
849
850   gstelement_class->request_new_pad =
851       GST_DEBUG_FUNCPTR (gst_adder_request_new_pad);
852   gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_adder_release_pad);
853   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_adder_change_state);
854 }
855
856 static void
857 gst_adder_init (GstAdder * adder)
858 {
859   GstPadTemplate *template;
860
861   template = gst_static_pad_template_get (&gst_adder_src_template);
862   adder->srcpad = gst_pad_new_from_template (template, "src");
863   gst_object_unref (template);
864
865   gst_pad_set_getcaps_function (adder->srcpad,
866       GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
867   gst_pad_set_setcaps_function (adder->srcpad,
868       GST_DEBUG_FUNCPTR (gst_adder_setcaps));
869   gst_pad_set_query_function (adder->srcpad,
870       GST_DEBUG_FUNCPTR (gst_adder_query));
871   gst_pad_set_event_function (adder->srcpad,
872       GST_DEBUG_FUNCPTR (gst_adder_src_event));
873   gst_element_add_pad (GST_ELEMENT (adder), adder->srcpad);
874
875   adder->format = GST_ADDER_FORMAT_UNSET;
876   adder->padcount = 0;
877   adder->func = NULL;
878
879   adder->filter_caps = NULL;
880
881   /* keep track of the sinkpads requested */
882   adder->collect = gst_collect_pads_new ();
883   gst_collect_pads_set_function (adder->collect,
884       GST_DEBUG_FUNCPTR (gst_adder_collected), adder);
885 }
886
887 static void
888 gst_adder_dispose (GObject * object)
889 {
890   GstAdder *adder = GST_ADDER (object);
891
892   if (adder->collect) {
893     gst_object_unref (adder->collect);
894     adder->collect = NULL;
895   }
896   gst_caps_replace (&adder->filter_caps, NULL);
897   if (adder->pending_events) {
898     g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL);
899     g_list_free (adder->pending_events);
900     adder->pending_events = NULL;
901   }
902
903   G_OBJECT_CLASS (parent_class)->dispose (object);
904 }
905
906 static void
907 gst_adder_set_property (GObject * object, guint prop_id,
908     const GValue * value, GParamSpec * pspec)
909 {
910   GstAdder *adder = GST_ADDER (object);
911
912   switch (prop_id) {
913     case PROP_FILTER_CAPS:{
914       GstCaps *new_caps = NULL;
915       GstCaps *old_caps;
916       const GstCaps *new_caps_val = gst_value_get_caps (value);
917
918       if (new_caps_val != NULL) {
919         new_caps = (GstCaps *) new_caps_val;
920         gst_caps_ref (new_caps);
921       }
922
923       GST_OBJECT_LOCK (adder);
924       old_caps = adder->filter_caps;
925       adder->filter_caps = new_caps;
926       GST_OBJECT_UNLOCK (adder);
927
928       if (old_caps)
929         gst_caps_unref (old_caps);
930
931       GST_DEBUG_OBJECT (adder, "set new caps %" GST_PTR_FORMAT, new_caps);
932       break;
933     }
934     default:
935       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
936       break;
937   }
938 }
939
940 static void
941 gst_adder_get_property (GObject * object, guint prop_id, GValue * value,
942     GParamSpec * pspec)
943 {
944   GstAdder *adder = GST_ADDER (object);
945
946   switch (prop_id) {
947     case PROP_FILTER_CAPS:
948       GST_OBJECT_LOCK (adder);
949       gst_value_set_caps (value, adder->filter_caps);
950       GST_OBJECT_UNLOCK (adder);
951       break;
952     default:
953       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
954       break;
955   }
956 }
957
958
959 static GstPad *
960 gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ,
961     const gchar * unused)
962 {
963   gchar *name;
964   GstAdder *adder;
965   GstPad *newpad;
966   gint padcount;
967
968   if (templ->direction != GST_PAD_SINK)
969     goto not_sink;
970
971   adder = GST_ADDER (element);
972
973   /* increment pad counter */
974   padcount = g_atomic_int_exchange_and_add (&adder->padcount, 1);
975
976   name = g_strdup_printf ("sink%d", padcount);
977   newpad = gst_pad_new_from_template (templ, name);
978   GST_DEBUG_OBJECT (adder, "request new pad %s", name);
979   g_free (name);
980
981   gst_pad_set_getcaps_function (newpad,
982       GST_DEBUG_FUNCPTR (gst_adder_sink_getcaps));
983   gst_pad_set_setcaps_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_setcaps));
984   gst_collect_pads_add_pad (adder->collect, newpad, sizeof (GstCollectData));
985
986   /* FIXME: hacked way to override/extend the event function of
987    * GstCollectPads; because it sets its own event function giving the
988    * element no access to events */
989   adder->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
990   gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_sink_event));
991
992   /* takes ownership of the pad */
993   if (!gst_element_add_pad (GST_ELEMENT (adder), newpad))
994     goto could_not_add;
995
996   return newpad;
997
998   /* errors */
999 not_sink:
1000   {
1001     g_warning ("gstadder: request new pad that is not a SINK pad\n");
1002     return NULL;
1003   }
1004 could_not_add:
1005   {
1006     GST_DEBUG_OBJECT (adder, "could not add pad");
1007     gst_collect_pads_remove_pad (adder->collect, newpad);
1008     gst_object_unref (newpad);
1009     return NULL;
1010   }
1011 }
1012
1013 static void
1014 gst_adder_release_pad (GstElement * element, GstPad * pad)
1015 {
1016   GstAdder *adder;
1017
1018   adder = GST_ADDER (element);
1019
1020   GST_DEBUG_OBJECT (adder, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad));
1021
1022   gst_collect_pads_remove_pad (adder->collect, pad);
1023   gst_element_remove_pad (element, pad);
1024 }
1025
1026 static GstFlowReturn
1027 gst_adder_collected (GstCollectPads * pads, gpointer user_data)
1028 {
1029   /*
1030    * combine streams by adding data values
1031    * basic algorithm :
1032    * - this function is called when all pads have a buffer
1033    * - get available bytes on all pads.
1034    * - repeat for each input pad :
1035    *   - read available bytes, copy or add to target buffer
1036    *   - if there's an EOS event, remove the input channel
1037    * - push out the output buffer
1038    *
1039    * todo:
1040    * - would be nice to have a mixing mode, where instead of adding we mix
1041    *   - for float we could downscale after collect loop
1042    *   - for int we need to downscale each input to avoid clipping or
1043    *     mix into a temp (float) buffer and scale afterwards as well
1044    */
1045   GstAdder *adder;
1046   GSList *collected;
1047   GstFlowReturn ret;
1048   GstBuffer *outbuf = NULL;
1049   gpointer outdata = NULL;
1050   guint outsize;
1051   gboolean empty = TRUE;
1052
1053   adder = GST_ADDER (user_data);
1054
1055   /* this is fatal */
1056   if (G_UNLIKELY (adder->func == NULL))
1057     goto not_negotiated;
1058
1059   if (adder->flush_stop_pending) {
1060     gst_pad_push_event (adder->srcpad, gst_event_new_flush_stop ());
1061     adder->flush_stop_pending = FALSE;
1062   }
1063
1064   /* get available bytes for reading, this can be 0 which could mean empty
1065    * buffers or EOS, which we will catch when we loop over the pads. */
1066   outsize = gst_collect_pads_available (pads);
1067
1068   GST_LOG_OBJECT (adder,
1069       "starting to cycle through channels, %d bytes available (bps = %d)",
1070       outsize, adder->bps);
1071
1072   for (collected = pads->data; collected; collected = g_slist_next (collected)) {
1073     GstCollectData *collect_data;
1074     GstBuffer *inbuf;
1075     guint8 *indata;
1076     guint insize;
1077
1078     collect_data = (GstCollectData *) collected->data;
1079
1080     /* get a subbuffer of size bytes */
1081     inbuf = gst_collect_pads_take_buffer (pads, collect_data, outsize);
1082     /* NULL means EOS or an empty buffer so we still need to flush in
1083      * case of an empty buffer. */
1084     if (inbuf == NULL) {
1085       GST_LOG_OBJECT (adder, "channel %p: no bytes available", collect_data);
1086       continue;
1087     }
1088
1089     indata = GST_BUFFER_DATA (inbuf);
1090     insize = GST_BUFFER_SIZE (inbuf);
1091
1092     if (outbuf == NULL) {
1093       GST_LOG_OBJECT (adder, "channel %p: making output buffer of %d bytes",
1094           collect_data, outsize);
1095
1096       /* first buffer, alloc outsize.
1097        * FIXME: we can easily subbuffer and _make_writable.
1098        * FIXME: only create empty buffer for first non-gap buffer, so that we
1099        * only use adder function when really adding
1100        */
1101       outbuf = gst_buffer_new_and_alloc (outsize);
1102       outdata = GST_BUFFER_DATA (outbuf);
1103       gst_buffer_set_caps (outbuf, GST_PAD_CAPS (adder->srcpad));
1104
1105       if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
1106         GST_LOG_OBJECT (adder, "channel %p: copying %d bytes from data %p",
1107             collect_data, insize, indata);
1108         /* clear if we are only going to fill a partial buffer */
1109         if (G_UNLIKELY (outsize > insize))
1110           memset ((guint8 *) outdata + insize, 0, outsize - insize);
1111         /* and copy the data into it */
1112         memcpy (outdata, indata, insize);
1113         empty = FALSE;
1114       } else {
1115         /* clear whole buffer */
1116         GST_LOG_OBJECT (adder, "channel %p: zeroing %d bytes from data %p",
1117             collect_data, insize, indata);
1118         memset (outdata, 0, outsize);
1119       }
1120     } else {
1121       if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
1122         GST_LOG_OBJECT (adder, "channel %p: mixing %d bytes from data %p",
1123             collect_data, insize, indata);
1124         /* further buffers, need to add them */
1125         adder->func ((gpointer) outdata, (gpointer) indata, insize);
1126         empty = FALSE;
1127       } else {
1128         GST_LOG_OBJECT (adder, "channel %p: skipping %d bytes from data %p",
1129             collect_data, insize, indata);
1130       }
1131     }
1132     gst_buffer_unref (inbuf);
1133   }
1134
1135   /* can only happen when no pads to collect or all EOS */
1136   if (outbuf == NULL)
1137     goto eos;
1138
1139   /* our timestamping is very simple, just an ever incrementing
1140    * counter, the new segment time will take care of their respective
1141    * stream time. */
1142   if (adder->segment_pending) {
1143     GstEvent *event;
1144
1145     /* FIXME, use rate/applied_rate as set on all sinkpads.
1146      * - currently we just set rate as received from last seek-event
1147      * We could potentially figure out the duration as well using
1148      * the current segment positions and the stated stop positions.
1149      * Also we just start from stream time 0 which is rather
1150      * weird. For non-synchronized mixing, the time should be
1151      * the min of the stream times of all received segments,
1152      * rationale being that the duration is at least going to
1153      * be as long as the earliest stream we start mixing. This
1154      * would also be correct for synchronized mixing but then
1155      * the later streams would be delayed until the stream times
1156      * match.
1157      */
1158     event = gst_event_new_new_segment_full (FALSE, adder->segment_rate,
1159         1.0, GST_FORMAT_TIME, adder->timestamp, -1, adder->segment_position);
1160
1161     if (event) {
1162       if (!gst_pad_push_event (adder->srcpad, event)) {
1163         GST_WARNING_OBJECT (adder->srcpad, "Sending event  %p (%s) failed.",
1164             event, GST_EVENT_TYPE_NAME (event));
1165       }
1166       adder->segment_pending = FALSE;
1167       adder->segment_position = 0;
1168     } else {
1169       GST_WARNING_OBJECT (adder->srcpad, "Creating new segment event for "
1170           "start:%" G_GINT64_FORMAT "  pos:%" G_GINT64_FORMAT " failed",
1171           adder->timestamp, adder->segment_position);
1172     }
1173   }
1174
1175   if (G_UNLIKELY (adder->pending_events)) {
1176     GList *tmp = adder->pending_events;
1177
1178     while (tmp) {
1179       GstEvent *ev = (GstEvent *) tmp->data;
1180
1181       gst_pad_push_event (adder->srcpad, ev);
1182       tmp = g_list_next (tmp);
1183     }
1184     g_list_free (adder->pending_events);
1185     adder->pending_events = NULL;
1186   }
1187
1188   /* set timestamps on the output buffer */
1189   GST_BUFFER_TIMESTAMP (outbuf) = adder->timestamp;
1190   GST_BUFFER_OFFSET (outbuf) = adder->offset;
1191
1192   /* for the next timestamp, use the sample counter, which will
1193    * never accumulate rounding errors */
1194   adder->offset += outsize / adder->bps;
1195   adder->timestamp = gst_util_uint64_scale_int (adder->offset,
1196       GST_SECOND, adder->rate);
1197
1198   /* now we can set the duration of the buffer */
1199   GST_BUFFER_DURATION (outbuf) = adder->timestamp -
1200       GST_BUFFER_TIMESTAMP (outbuf);
1201
1202   /* if we only processed silence, mark output again as silence */
1203   if (empty)
1204     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
1205
1206   /* send it out */
1207   GST_LOG_OBJECT (adder, "pushing outbuf, timestamp %" GST_TIME_FORMAT,
1208       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
1209   ret = gst_pad_push (adder->srcpad, outbuf);
1210
1211   GST_LOG_OBJECT (adder, "pushed outbuf, result = %s", gst_flow_get_name (ret));
1212
1213   return ret;
1214
1215   /* ERRORS */
1216 not_negotiated:
1217   {
1218     GST_ELEMENT_ERROR (adder, STREAM, FORMAT, (NULL),
1219         ("Unknown data received, not negotiated"));
1220     return GST_FLOW_NOT_NEGOTIATED;
1221   }
1222 eos:
1223   {
1224     GST_DEBUG_OBJECT (adder, "no data available, must be EOS");
1225     gst_pad_push_event (adder->srcpad, gst_event_new_eos ());
1226     return GST_FLOW_UNEXPECTED;
1227   }
1228 }
1229
1230 static GstStateChangeReturn
1231 gst_adder_change_state (GstElement * element, GstStateChange transition)
1232 {
1233   GstAdder *adder;
1234   GstStateChangeReturn ret;
1235
1236   adder = GST_ADDER (element);
1237
1238   switch (transition) {
1239     case GST_STATE_CHANGE_NULL_TO_READY:
1240       break;
1241     case GST_STATE_CHANGE_READY_TO_PAUSED:
1242       adder->timestamp = 0;
1243       adder->offset = 0;
1244       adder->flush_stop_pending = FALSE;
1245       adder->segment_pending = TRUE;
1246       adder->segment_position = 0;
1247       adder->segment_rate = 1.0;
1248       gst_segment_init (&adder->segment, GST_FORMAT_UNDEFINED);
1249       gst_collect_pads_start (adder->collect);
1250       break;
1251     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1252       break;
1253     case GST_STATE_CHANGE_PAUSED_TO_READY:
1254       /* need to unblock the collectpads before calling the
1255        * parent change_state so that streaming can finish */
1256       gst_collect_pads_stop (adder->collect);
1257       break;
1258     default:
1259       break;
1260   }
1261
1262   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1263
1264   switch (transition) {
1265     default:
1266       break;
1267   }
1268
1269   return ret;
1270 }
1271
1272
1273 static gboolean
1274 plugin_init (GstPlugin * plugin)
1275 {
1276   /*oil_init (); */
1277
1278   if (!gst_element_register (plugin, "adder", GST_RANK_NONE, GST_TYPE_ADDER)) {
1279     return FALSE;
1280   }
1281
1282   return TRUE;
1283 }
1284
1285 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1286     GST_VERSION_MINOR,
1287     "adder",
1288     "Adds multiple streams",
1289     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)