expand tabs
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstbaseaudiosink.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstbaseaudiosink.c: 
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <string.h>
24
25 #include "gstbaseaudiosink.h"
26
27 GST_DEBUG_CATEGORY_STATIC (gst_base_audio_sink_debug);
28 #define GST_CAT_DEFAULT gst_base_audio_sink_debug
29
30 /* BaseAudioSink signals and args */
31 enum
32 {
33   /* FILL ME */
34   LAST_SIGNAL
35 };
36
37 /* we tollerate a 10th of a second diff before we start resyncing. This
38  * should be enough to compensate for various rounding errors in the timestamp
39  * and sample offset position. */
40 #define DIFF_TOLERANCE  10
41
42 #define DEFAULT_BUFFER_TIME     500 * GST_USECOND
43 #define DEFAULT_LATENCY_TIME    10 * GST_USECOND
44 #define DEFAULT_PROVIDE_CLOCK   TRUE
45
46 enum
47 {
48   PROP_0,
49   PROP_BUFFER_TIME,
50   PROP_LATENCY_TIME,
51   PROP_PROVIDE_CLOCK,
52 };
53
54 #define _do_init(bla) \
55     GST_DEBUG_CATEGORY_INIT (gst_base_audio_sink_debug, "baseaudiosink", 0, "baseaudiosink element");
56
57 GST_BOILERPLATE_FULL (GstBaseAudioSink, gst_base_audio_sink, GstBaseSink,
58     GST_TYPE_BASE_SINK, _do_init);
59
60 static void gst_base_audio_sink_dispose (GObject * object);
61
62 static void gst_base_audio_sink_set_property (GObject * object, guint prop_id,
63     const GValue * value, GParamSpec * pspec);
64 static void gst_base_audio_sink_get_property (GObject * object, guint prop_id,
65     GValue * value, GParamSpec * pspec);
66
67 static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement *
68     element, GstStateChange transition);
69
70 static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem);
71 static GstClockTime gst_base_audio_sink_get_time (GstClock * clock,
72     GstBaseAudioSink * sink);
73 static void gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data,
74     guint len, gpointer user_data);
75
76 static GstFlowReturn gst_base_audio_sink_preroll (GstBaseSink * bsink,
77     GstBuffer * buffer);
78 static GstFlowReturn gst_base_audio_sink_render (GstBaseSink * bsink,
79     GstBuffer * buffer);
80 static gboolean gst_base_audio_sink_event (GstBaseSink * bsink,
81     GstEvent * event);
82 static void gst_base_audio_sink_get_times (GstBaseSink * bsink,
83     GstBuffer * buffer, GstClockTime * start, GstClockTime * end);
84 static gboolean gst_base_audio_sink_setcaps (GstBaseSink * bsink,
85     GstCaps * caps);
86
87 //static guint gst_base_audio_sink_signals[LAST_SIGNAL] = { 0 };
88
89 static void
90 gst_base_audio_sink_base_init (gpointer g_class)
91 {
92 }
93
94 static void
95 gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass)
96 {
97   GObjectClass *gobject_class;
98   GstElementClass *gstelement_class;
99   GstBaseSinkClass *gstbasesink_class;
100
101   gobject_class = (GObjectClass *) klass;
102   gstelement_class = (GstElementClass *) klass;
103   gstbasesink_class = (GstBaseSinkClass *) klass;
104
105   gobject_class->set_property =
106       GST_DEBUG_FUNCPTR (gst_base_audio_sink_set_property);
107   gobject_class->get_property =
108       GST_DEBUG_FUNCPTR (gst_base_audio_sink_get_property);
109   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_base_audio_sink_dispose);
110
111   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_TIME,
112       g_param_spec_int64 ("buffer-time", "Buffer Time",
113           "Size of audio buffer in milliseconds (-1 = default)",
114           -1, G_MAXINT64, DEFAULT_BUFFER_TIME, G_PARAM_READWRITE));
115   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LATENCY_TIME,
116       g_param_spec_int64 ("latency-time", "Latency Time",
117           "Audio latency in milliseconds (-1 = default)",
118           -1, G_MAXINT64, DEFAULT_LATENCY_TIME, G_PARAM_READWRITE));
119   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PROVIDE_CLOCK,
120       g_param_spec_boolean ("provide-clock", "Provide Clock",
121           "Provide a clock to be used as the global pipeline clock",
122           DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE));
123
124   gstelement_class->change_state =
125       GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state);
126   gstelement_class->provide_clock =
127       GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock);
128
129   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event);
130   gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll);
131   gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_base_audio_sink_render);
132   gstbasesink_class->get_times =
133       GST_DEBUG_FUNCPTR (gst_base_audio_sink_get_times);
134   gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_sink_setcaps);
135 }
136
137 static void
138 gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink,
139     GstBaseAudioSinkClass * g_class)
140 {
141   baseaudiosink->buffer_time = DEFAULT_BUFFER_TIME;
142   baseaudiosink->latency_time = DEFAULT_LATENCY_TIME;
143   baseaudiosink->provide_clock = DEFAULT_PROVIDE_CLOCK;
144
145   baseaudiosink->provided_clock = gst_audio_clock_new ("clock",
146       (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink);
147 }
148
149 static void
150 gst_base_audio_sink_dispose (GObject * object)
151 {
152   GstBaseAudioSink *sink;
153
154   sink = GST_BASE_AUDIO_SINK (object);
155
156   if (sink->provided_clock)
157     gst_object_unref (sink->provided_clock);
158   sink->provided_clock = NULL;
159
160   if (sink->ringbuffer)
161     gst_object_unref (sink->ringbuffer);
162   sink->ringbuffer = NULL;
163
164   G_OBJECT_CLASS (parent_class)->dispose (object);
165 }
166
167 static GstClock *
168 gst_base_audio_sink_provide_clock (GstElement * elem)
169 {
170   GstBaseAudioSink *sink;
171   GstClock *clock;
172
173   sink = GST_BASE_AUDIO_SINK (elem);
174
175   if (sink->provide_clock)
176     clock = GST_CLOCK_CAST (gst_object_ref (sink->provided_clock));
177   else
178     clock = NULL;
179
180   return clock;
181 }
182
183 static GstClockTime
184 gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink)
185 {
186   guint64 samples;
187   GstClockTime result;
188
189   if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0)
190     return GST_CLOCK_TIME_NONE;
191
192   /* our processed samples are always increasing */
193   samples = gst_ring_buffer_samples_done (sink->ringbuffer);
194
195   result = samples * GST_SECOND / sink->ringbuffer->spec.rate;
196
197   return result;
198 }
199
200 static void
201 gst_base_audio_sink_set_property (GObject * object, guint prop_id,
202     const GValue * value, GParamSpec * pspec)
203 {
204   GstBaseAudioSink *sink;
205
206   sink = GST_BASE_AUDIO_SINK (object);
207
208   switch (prop_id) {
209     case PROP_BUFFER_TIME:
210       sink->buffer_time = g_value_get_int64 (value);
211       break;
212     case PROP_LATENCY_TIME:
213       sink->latency_time = g_value_get_int64 (value);
214       break;
215     case PROP_PROVIDE_CLOCK:
216       sink->provide_clock = g_value_get_boolean (value);
217       break;
218     default:
219       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
220       break;
221   }
222 }
223
224 static void
225 gst_base_audio_sink_get_property (GObject * object, guint prop_id,
226     GValue * value, GParamSpec * pspec)
227 {
228   GstBaseAudioSink *sink;
229
230   sink = GST_BASE_AUDIO_SINK (object);
231
232   switch (prop_id) {
233     case PROP_BUFFER_TIME:
234       g_value_set_int64 (value, sink->buffer_time);
235       break;
236     case PROP_LATENCY_TIME:
237       g_value_set_int64 (value, sink->latency_time);
238       break;
239     case PROP_PROVIDE_CLOCK:
240       g_value_set_boolean (value, sink->provide_clock);
241       break;
242     default:
243       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
244       break;
245   }
246 }
247
248 static gboolean
249 gst_base_audio_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
250 {
251   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
252   GstRingBufferSpec *spec;
253
254   spec = &sink->ringbuffer->spec;
255
256   GST_DEBUG ("release old ringbuffer");
257
258   /* release old ringbuffer */
259   gst_ring_buffer_release (sink->ringbuffer);
260
261   GST_DEBUG ("parse caps");
262
263   spec->buffer_time = sink->buffer_time;
264   spec->latency_time = sink->latency_time;
265
266   /* parse new caps */
267   if (!gst_ring_buffer_parse_caps (spec, caps))
268     goto parse_error;
269
270   gst_ring_buffer_debug_spec_buff (spec);
271
272   GST_DEBUG ("acquire new ringbuffer");
273
274   if (!gst_ring_buffer_acquire (sink->ringbuffer, spec))
275     goto acquire_error;
276
277   /* calculate actual latency and buffer times */
278   spec->latency_time =
279       spec->segsize * GST_MSECOND / (spec->rate * spec->bytes_per_sample);
280   spec->buffer_time =
281       spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate *
282       spec->bytes_per_sample);
283
284   gst_ring_buffer_debug_spec_buff (spec);
285
286   return TRUE;
287
288   /* ERRORS */
289 parse_error:
290   {
291     GST_DEBUG ("could not parse caps");
292     return FALSE;
293   }
294 acquire_error:
295   {
296     GST_DEBUG ("could not acquire ringbuffer");
297     return FALSE;
298   }
299 }
300
301 static void
302 gst_base_audio_sink_get_times (GstBaseSink * bsink, GstBuffer * buffer,
303     GstClockTime * start, GstClockTime * end)
304 {
305   /* our clock sync is a bit too much for the base class to handle so
306    * we implement it ourselves. */
307   *start = GST_CLOCK_TIME_NONE;
308   *end = GST_CLOCK_TIME_NONE;
309 }
310
311 static gboolean
312 gst_base_audio_sink_event (GstBaseSink * bsink, GstEvent * event)
313 {
314   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
315
316   switch (GST_EVENT_TYPE (event)) {
317     case GST_EVENT_FLUSH_START:
318       gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
319       break;
320     case GST_EVENT_FLUSH_STOP:
321       /* always resync on sample after a flush */
322       sink->next_sample = -1;
323       gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
324       break;
325     case GST_EVENT_EOS:
326       gst_ring_buffer_start (sink->ringbuffer);
327       break;
328     default:
329       break;
330   }
331   return TRUE;
332 }
333
334 static GstFlowReturn
335 gst_base_audio_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
336 {
337   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink);
338
339   if (!gst_ring_buffer_is_acquired (sink->ringbuffer))
340     goto wrong_state;
341
342   /* we don't really do anything when prerolling. We could make a
343    * property to play this buffer to have some sort of scrubbing
344    * support. */
345   return GST_FLOW_OK;
346
347 wrong_state:
348   {
349     GST_DEBUG ("ringbuffer in wrong state");
350     GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
351         ("sink not negotiated."), ("sink not negotiated."));
352     return GST_FLOW_NOT_NEGOTIATED;
353   }
354 }
355
356 static guint64
357 gst_base_audio_sink_get_offset (GstBaseAudioSink * sink)
358 {
359   guint64 sample;
360   gint writeseg, segdone, sps;
361   gint diff;
362
363   /* assume we can append to the previous sample */
364   sample = sink->next_sample;
365
366   sps = sink->ringbuffer->samples_per_seg;
367
368   /* figure out the segment and the offset inside the segment where
369    * the sample should be written. */
370   writeseg = sample / sps;
371
372   /* get the currently processed segment */
373   segdone = g_atomic_int_get (&sink->ringbuffer->segdone)
374       - sink->ringbuffer->segbase;
375
376   /* see how far away it is from the write segment */
377   diff = writeseg - segdone;
378   if (diff < 0) {
379     /* sample would be dropped, position to next playable position */
380     sample = (segdone + 1) * sps;
381   }
382
383   return sample;
384 }
385
386 static GstFlowReturn
387 gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
388 {
389   guint64 render_offset, in_offset;
390   GstClockTime time, render_time, duration;
391   GstClockTimeDiff render_diff;
392   GstBaseAudioSink *sink;
393   GstRingBuffer *ringbuf;
394   gint64 diff;
395   guint8 *data;
396   guint size;
397   guint samples;
398   gint bps;
399   gdouble crate;
400   GstClockTime crate_num;
401   GstClockTime crate_denom;
402   GstClockTime cinternal, cexternal;
403
404   sink = GST_BASE_AUDIO_SINK (bsink);
405
406   ringbuf = sink->ringbuffer;
407
408   /* can't do anything when we don't have the device */
409   if (!gst_ring_buffer_is_acquired (ringbuf))
410     goto wrong_state;
411
412   bps = ringbuf->spec.bytes_per_sample;
413
414   size = GST_BUFFER_SIZE (buf);
415   if (size % bps != 0)
416     goto wrong_size;
417
418   samples = size / bps;
419
420   in_offset = GST_BUFFER_OFFSET (buf);
421   time = GST_BUFFER_TIMESTAMP (buf);
422   duration = GST_BUFFER_DURATION (buf);
423   data = GST_BUFFER_DATA (buf);
424
425   GST_DEBUG ("time %" GST_TIME_FORMAT ", offset %llu, start %" GST_TIME_FORMAT,
426       GST_TIME_ARGS (time), in_offset, GST_TIME_ARGS (bsink->segment.start));
427
428   /* if not valid timestamp or we don't need to sync, try to play
429    * sample ASAP */
430   if (!GST_CLOCK_TIME_IS_VALID (time) || !bsink->sync) {
431     render_offset = gst_base_audio_sink_get_offset (sink);
432     goto no_sync;
433   }
434
435   render_diff = time - bsink->segment.start;
436
437   /* samples should be rendered based on their timestamp. All samples
438    * arriving before the segment.start are to be thrown away */
439   /* FIXME, for now we drop the sample completely, we should
440    * in fact clip the sample. Same for the segment.stop, actually. */
441   if (render_diff < 0)
442     goto out_of_segment;
443
444   gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal,
445       &crate_num, &crate_denom);
446
447   /* bring buffer timestamp to stream time */
448   render_time = render_diff;
449   /* adjust for rate */
450   render_time /= ABS (bsink->segment.rate);
451   /* adjust for accumulated segments */
452   render_time += bsink->segment.accum;
453   /* add base time to get absolute clock time */
454   render_time +=
455       (gst_element_get_base_time (GST_ELEMENT_CAST (bsink)) - cexternal) +
456       cinternal;
457   /* and bring the time to the offset in the buffer */
458   render_offset = render_time * ringbuf->spec.rate / GST_SECOND;
459
460   /* roundoff errors in timestamp conversion */
461   if (sink->next_sample != -1)
462     diff = ABS ((gint64) render_offset - (gint64) sink->next_sample);
463   else
464     diff = ringbuf->spec.rate;
465
466   GST_DEBUG ("render time %" GST_TIME_FORMAT
467       ", render offset %llu, diff %lld, samples %lu",
468       GST_TIME_ARGS (render_time), render_offset, diff, samples);
469
470   /* we tollerate a 10th of a second diff before we start resyncing. This
471    * should be enough to compensate for various rounding errors in the timestamp
472    * and sample offset position. */
473   if (diff < ringbuf->spec.rate / DIFF_TOLERANCE) {
474     GST_DEBUG ("align with prev sample, %" G_GINT64_FORMAT " < %lu", diff,
475         ringbuf->spec.rate / DIFF_TOLERANCE);
476     /* just align with previous sample then */
477     render_offset = sink->next_sample;
478   } else {
479     GST_DEBUG ("resync");
480   }
481
482 no_sync:
483   crate = ((gdouble) crate_num) / crate_denom;
484   GST_DEBUG_OBJECT (sink,
485       "internal %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ", rate %g",
486       cinternal, cexternal, crate);
487
488   /* clip length based on rate */
489   samples = MIN (samples, samples / (crate * ABS (bsink->segment.rate)));
490
491   /* the next sample should be current sample and its length */
492   sink->next_sample = render_offset + samples;
493
494   gst_ring_buffer_commit (ringbuf, render_offset, data, samples);
495
496   if (GST_CLOCK_TIME_IS_VALID (time) && time + duration >= bsink->segment.stop) {
497     GST_DEBUG ("start playback because we are at the end of segment");
498     gst_ring_buffer_start (ringbuf);
499   }
500
501   return GST_FLOW_OK;
502
503 out_of_segment:
504   {
505     GST_DEBUG ("dropping sample out of segment time %" GST_TIME_FORMAT
506         ", start %" GST_TIME_FORMAT,
507         GST_TIME_ARGS (time), GST_TIME_ARGS (bsink->segment.start));
508     return GST_FLOW_OK;
509   }
510 wrong_state:
511   {
512     GST_DEBUG ("ringbuffer not negotiated");
513     GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
514         ("sink not negotiated."), ("sink not negotiated."));
515     return GST_FLOW_NOT_NEGOTIATED;
516   }
517 wrong_size:
518   {
519     GST_DEBUG ("wrong size");
520     GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND,
521         ("sink received buffer of wrong size."),
522         ("sink received buffer of wrong size."));
523     return GST_FLOW_ERROR;
524   }
525 }
526
527 GstRingBuffer *
528 gst_base_audio_sink_create_ringbuffer (GstBaseAudioSink * sink)
529 {
530   GstBaseAudioSinkClass *bclass;
531   GstRingBuffer *buffer = NULL;
532
533   bclass = GST_BASE_AUDIO_SINK_GET_CLASS (sink);
534   if (bclass->create_ringbuffer)
535     buffer = bclass->create_ringbuffer (sink);
536
537   if (buffer)
538     gst_object_set_parent (GST_OBJECT (buffer), GST_OBJECT (sink));
539
540   return buffer;
541 }
542
543 static void
544 gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len,
545     gpointer user_data)
546 {
547   //GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (data);
548 }
549
550 static GstStateChangeReturn
551 gst_base_audio_sink_change_state (GstElement * element,
552     GstStateChange transition)
553 {
554   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
555   GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (element);
556
557   switch (transition) {
558     case GST_STATE_CHANGE_NULL_TO_READY:
559       if (sink->ringbuffer == NULL) {
560         sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink);
561         gst_ring_buffer_set_callback (sink->ringbuffer,
562             gst_base_audio_sink_callback, sink);
563       }
564       if (!gst_ring_buffer_open_device (sink->ringbuffer))
565         return GST_STATE_CHANGE_FAILURE;
566       sink->next_sample = 0;
567       break;
568     case GST_STATE_CHANGE_READY_TO_PAUSED:
569       gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE);
570       break;
571     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
572     {
573       GstClock *clock;
574
575       GST_OBJECT_LOCK (sink);
576       clock = GST_ELEMENT_CLOCK (sink);
577       /* if we are slaved to a clock, we need to set the initial
578        * calibration */
579       if (clock != sink->provided_clock) {
580         GstClockTime time;
581         GstClockTime rate_num, rate_denom;
582
583         time = gst_clock_get_internal_time (sink->provided_clock);
584
585         GST_DEBUG_OBJECT (sink, "time: %" GST_TIME_FORMAT,
586             GST_TIME_ARGS (time));
587
588         gst_clock_set_master (sink->provided_clock, clock);
589         /* FIXME, this is not yet accurate enough for smooth playback */
590         gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num,
591             &rate_denom);
592         /* Does not work yet. */
593         gst_clock_set_calibration (sink->provided_clock,
594             time, element->base_time, rate_num, rate_denom);
595       }
596       GST_OBJECT_UNLOCK (sink);
597       break;
598     }
599     case GST_STATE_CHANGE_PAUSED_TO_READY:
600       gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE);
601       break;
602     default:
603       break;
604   }
605
606   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
607
608   switch (transition) {
609     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
610       gst_ring_buffer_pause (sink->ringbuffer);
611       /* slop slaving ourselves to the master, if any */
612       gst_clock_set_master (sink->provided_clock, NULL);
613       break;
614     case GST_STATE_CHANGE_PAUSED_TO_READY:
615       gst_ring_buffer_release (sink->ringbuffer);
616       gst_pad_set_caps (GST_BASE_SINK_PAD (sink), NULL);
617       break;
618     case GST_STATE_CHANGE_READY_TO_NULL:
619       gst_ring_buffer_close_device (sink->ringbuffer);
620       break;
621     default:
622       break;
623   }
624
625   return ret;
626 }