2 * Copyright (C) 2001 CodeFactory AB
3 * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
4 * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
5 * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
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.
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.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "gstalsasink.h"
27 #include "gstalsaclock.h"
29 /* elementfactory information */
30 static GstElementDetails gst_alsa_sink_details = GST_ELEMENT_DETAILS (
33 "Output to a sound card via ALSA",
34 "Thomas Nyberg <thomas@codefactory.se>, "
35 "Andy Wingo <apwingo@eos.ncsu.edu>, "
36 "Benjamin Otte <in7y118@public.uni-hamburg.de>"
39 static GstPadTemplate * gst_alsa_sink_pad_factory (void);
40 static GstPadTemplate * gst_alsa_sink_request_pad_factory(void);
41 static void gst_alsa_sink_base_init (gpointer g_class);
42 static void gst_alsa_sink_class_init (gpointer g_klass,
44 static void gst_alsa_sink_init (GstAlsaSink * this);
45 static inline void gst_alsa_sink_flush_one_pad (GstAlsaSink * sink,
47 static void gst_alsa_sink_flush_pads (GstAlsaSink * sink);
48 static int gst_alsa_sink_mmap (GstAlsa * this,
49 snd_pcm_sframes_t * avail);
50 static int gst_alsa_sink_write (GstAlsa * this,
51 snd_pcm_sframes_t * avail);
52 static void gst_alsa_sink_loop (GstElement * element);
53 static gboolean gst_alsa_sink_check_event (GstAlsaSink * sink,
55 static GstElementStateReturn gst_alsa_sink_change_state (GstElement * element);
57 static GstClockTime gst_alsa_sink_get_time (GstAlsa * this);
59 static GstAlsa *sink_parent_class = NULL;
61 static GstPadTemplate *
62 gst_alsa_sink_pad_factory (void)
64 static GstPadTemplate *template = NULL;
67 template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
68 gst_alsa_caps (SND_PCM_FORMAT_UNKNOWN, -1, -1));
72 static GstPadTemplate *
73 gst_alsa_sink_request_pad_factory (void)
75 static GstPadTemplate *template = NULL;
79 gst_pad_template_new ("sink%d", GST_PAD_SINK, GST_PAD_REQUEST,
80 gst_alsa_caps (SND_PCM_FORMAT_UNKNOWN, -1, 1));
85 gst_alsa_sink_get_type (void)
87 static GType alsa_sink_type = 0;
89 if (!alsa_sink_type) {
90 static const GTypeInfo alsa_sink_info = {
91 sizeof (GstAlsaSinkClass),
92 gst_alsa_sink_base_init,
94 gst_alsa_sink_class_init,
99 (GInstanceInitFunc) gst_alsa_sink_init,
102 alsa_sink_type = g_type_register_static (GST_TYPE_ALSA, "GstAlsaSink", &alsa_sink_info, 0);
104 return alsa_sink_type;
108 gst_alsa_sink_base_init (gpointer g_class)
110 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
112 gst_element_class_add_pad_template (element_class, gst_alsa_sink_pad_factory ());
113 gst_element_class_add_pad_template (element_class, gst_alsa_sink_request_pad_factory ());
115 gst_element_class_set_details (element_class, &gst_alsa_sink_details);
119 gst_alsa_sink_class_init (gpointer g_class, gpointer class_data)
121 GObjectClass *object_class;
122 GstElementClass *element_class;
123 GstAlsaClass *alsa_class;
124 GstAlsaSinkClass *klass;
126 klass = (GstAlsaSinkClass *) g_class;
127 object_class = (GObjectClass *) klass;
128 element_class = (GstElementClass *) klass;
129 alsa_class = (GstAlsaClass *) klass;
131 if (sink_parent_class == NULL)
132 sink_parent_class = g_type_class_ref (GST_TYPE_ALSA);
134 alsa_class->stream = SND_PCM_STREAM_PLAYBACK;
135 alsa_class->transmit_mmap = gst_alsa_sink_mmap;
136 alsa_class->transmit_rw = gst_alsa_sink_write;
138 element_class->change_state = gst_alsa_sink_change_state;
141 gst_alsa_sink_init (GstAlsaSink *sink)
143 GstAlsa *this = GST_ALSA (sink);
145 this->pad[0] = gst_pad_new_from_template (gst_alsa_sink_pad_factory (), "sink");
146 gst_pad_set_link_function (this->pad[0], gst_alsa_link);
147 gst_pad_set_getcaps_function (this->pad[0], gst_alsa_get_caps);
148 gst_element_add_pad (GST_ELEMENT (this), this->pad[0]);
150 this->clock = gst_alsa_clock_new ("alsasinkclock", gst_alsa_sink_get_time, this);
151 /* we hold a ref to our clock until we're disposed */
152 gst_object_ref (GST_OBJECT (this->clock));
153 gst_object_sink (GST_OBJECT (this->clock));
155 gst_element_set_loop_function (GST_ELEMENT (this), gst_alsa_sink_loop);
159 gst_alsa_sink_flush_one_pad (GstAlsaSink *sink, gint i)
161 switch (sink->behaviour[i]) {
164 gst_data_unref (GST_DATA (sink->buf[i]));
166 sink->data[i] = NULL;
167 sink->behaviour[i] = 0;
171 g_free (sink->data[i]);
172 sink->data[i] = NULL;
173 sink->behaviour[i] = 0;
177 g_assert_not_reached ();
181 gst_alsa_sink_flush_pads (GstAlsaSink *sink)
185 for (i = 0; i < GST_ELEMENT (sink)->numpads; i++) {
186 /* flush twice to unref buffer when behaviour == 1 */
187 gst_alsa_sink_flush_one_pad (sink, i);
188 gst_alsa_sink_flush_one_pad (sink, i);
191 /* TRUE, if everything should continue */
193 gst_alsa_sink_check_event (GstAlsaSink *sink, gint pad_nr)
195 gboolean cont = TRUE;
196 GstEvent *event = GST_EVENT (sink->buf[pad_nr]);
197 GstAlsa *this = GST_ALSA (sink);
200 switch (GST_EVENT_TYPE (event)) {
202 gst_alsa_set_eos (this);
205 case GST_EVENT_INTERRUPT:
208 case GST_EVENT_DISCONTINUOUS:
212 /* only the first pad my seek */
216 if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &value)) {
217 gst_element_set_time (GST_ELEMENT (this), value);
218 } else if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT, &value)) {
219 value = gst_alsa_samples_to_timestamp (this, value);
220 gst_element_set_time (GST_ELEMENT (this), value);
221 } else if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &value)) {
222 value = gst_alsa_bytes_to_timestamp (this, value);
223 gst_element_set_time (GST_ELEMENT (this), value);
225 GST_ERROR_OBJECT (this, "couldn't extract time from discont event. Bad things might happen!");
232 GST_INFO_OBJECT (this, "got an unknown event (Type: %d)", GST_EVENT_TYPE (event));
235 gst_event_unref (event);
236 sink->buf[pad_nr] = NULL;
238 /* the element at the top of the chain did not emit an event. */
239 g_assert_not_reached ();
244 gst_alsa_sink_mmap (GstAlsa *this, snd_pcm_sframes_t *avail)
246 snd_pcm_uframes_t offset;
247 const snd_pcm_channel_area_t *dst;
248 snd_pcm_channel_area_t *src;
249 GstAlsaSink *sink = GST_ALSA_SINK (this);
250 int i, err, width = snd_pcm_format_physical_width (this->format->format);
252 /* areas points to the memory areas that belong to gstreamer. */
253 src = g_malloc0 (this->format->channels * sizeof(snd_pcm_channel_area_t));
255 if (((GstElement *) this)->numpads == 1) {
257 for (i = 0; i < this->format->channels; i++) {
258 src[i].addr = sink->data[0];
259 src[i].first = i * width;
260 src[i].step = this->format->channels * width;
264 for (i = 0; i < this->format->channels; i++) {
265 src[i].addr = sink->data[i];
271 if ((err = snd_pcm_mmap_begin (this->handle, &dst, &offset, avail)) < 0) {
272 GST_ERROR_OBJECT (this, "mmap failed: %s", snd_strerror (err));
276 if ((err = snd_pcm_areas_copy (dst, offset, src, 0, this->format->channels, *avail, this->format->format)) < 0) {
277 snd_pcm_mmap_commit (this->handle, offset, 0);
278 GST_ERROR_OBJECT (this, "data copy failed: %s", snd_strerror (err));
281 if ((err = snd_pcm_mmap_commit (this->handle, offset, *avail)) < 0) {
282 GST_ERROR_OBJECT (this, "mmap commit failed: %s", snd_strerror (err));
289 gst_alsa_sink_write (GstAlsa *this, snd_pcm_sframes_t *avail)
291 GstAlsaSink *sink = GST_ALSA_SINK (this);
292 void *channels[this->format->channels];
295 if (((GstElement *) this)->numpads == 1) {
297 err = snd_pcm_writei (this->handle, sink->data[0], *avail);
300 for (i = 0; i < this->format->channels; i++) {
301 channels[i] = sink->data[i];
303 err = snd_pcm_writen (this->handle, channels, *avail);
308 gst_alsa_xrun_recovery (this);
311 GST_ERROR_OBJECT (this, "error on data access: %s", snd_strerror (err));
316 gst_alsa_sink_loop (GstElement *element)
318 snd_pcm_sframes_t avail, avail2, copied, sample_diff, max_discont;
319 snd_pcm_uframes_t samplestamp, time_sample;
321 guint bytes; /* per channel */
322 GstAlsa *this = GST_ALSA (element);
323 GstAlsaSink *sink = GST_ALSA_SINK (element);
325 g_return_if_fail (sink != NULL);
329 avail = gst_alsa_update_avail (this);
330 if (avail == -EPIPE) goto sink_restart;
331 if (avail < 0) return;
334 /* Not enough space. We grab data nonetheless and sleep afterwards */
335 if (avail < this->period_size) {
336 avail = this->period_size;
339 /* check how many bytes we still have in all our bytestreams */
340 /* initialize this value to a somewhat sane state, we might alloc this much data below (which would be a bug, but who knows)... */
341 bytes = this->period_size * this->period_count * element->numpads * 8; /* must be > max sample size in bytes */
342 for (i = 0; i < element->numpads; i++) {
343 g_assert (this->pad[i] != NULL);
344 while (sink->size[i] == 0) {
346 sink->buf[i] = GST_BUFFER (gst_pad_pull (this->pad[i]));
347 if (GST_IS_EVENT (sink->buf[i])) {
348 if (gst_alsa_sink_check_event (sink, i))
352 /* caps nego failed somewhere */
353 if (this->format == NULL) {
354 GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL),
355 ("ALSA format not negotiated"));
357 samplestamp = gst_alsa_timestamp_to_samples (this, GST_BUFFER_TIMESTAMP (sink->buf[i]));
358 max_discont = gst_alsa_timestamp_to_samples (this, this->max_discont);
359 time_sample = gst_alsa_timestamp_to_samples (this, gst_element_get_time (GST_ELEMENT (this)));
360 snd_pcm_delay (this->handle, &sample_diff);
361 /* actual diff = buffer samplestamp - played - to_play */
362 sample_diff = samplestamp - time_sample - sample_diff;
364 if ((!GST_BUFFER_TIMESTAMP_IS_VALID (sink->buf[i])) ||
365 (-max_discont <= sample_diff && sample_diff <= max_discont)) {
367 /* difference between expected and current is < GST_ALSA_DEVIATION */
369 sink->size[i] = sink->buf[i]->size;
370 sink->data[i] = sink->buf[i]->data;
371 sink->behaviour[i] = 0;
372 } else if (sample_diff > 0) {
373 /* there are empty samples in front of us, fill them with silence */
374 int samples = MIN (bytes, sample_diff) *
375 (element->numpads == 1 ? this->format->channels : 1);
376 int size = samples * snd_pcm_format_physical_width (this->format->format) / 8;
377 GST_INFO_OBJECT (this, "Allocating %d bytes (%ld samples) now to resync: sample %ld expected, but got %ld",
378 size, MIN (bytes, sample_diff), time_sample, samplestamp);
379 sink->data[i] = g_try_malloc (size);
380 if (!sink->data[i]) {
381 GST_WARNING_OBJECT (this, "error allocating %d bytes, buffers unsynced now.", size);
384 sink->size[i] = size;
385 if (0 != snd_pcm_format_set_silence (this->format->format, sink->data[i], samples)) {
386 GST_WARNING_OBJECT (this, "error silencing buffer, enjoy the noise.");
388 sink->behaviour[i] = 1;
389 } else if (gst_alsa_samples_to_bytes (this, -sample_diff) >= sink->buf[i]->size) {
390 GST_INFO_OBJECT (this, "Skipping %lu samples to resync (complete buffer): sample %ld expected, but got %ld",
391 gst_alsa_bytes_to_samples (this, sink->buf[i]->size), time_sample, samplestamp);
392 /* this buffer is way behind */
393 gst_buffer_unref (sink->buf[i]);
396 } else if (sample_diff < 0) {
397 gint difference = gst_alsa_samples_to_bytes (this, -samplestamp);
398 GST_INFO_OBJECT (this, "Skipping %lu samples to resync: sample %ld expected, but got %ld",
399 (gulong) -sample_diff, time_sample, samplestamp);
400 /* this buffer is only a bit behind */
401 sink->size[i] = sink->buf[i]->size - difference;
402 sink->data[i] = sink->buf[i]->data + difference;
403 sink->behaviour[i] = 0;
405 g_assert_not_reached ();
408 bytes = MIN (bytes, sink->size[i]);
411 avail = MIN (avail, gst_alsa_bytes_to_samples (this, bytes));
413 /* wait until the hw buffer has enough space */
414 while (gst_element_get_state (element) == GST_STATE_PLAYING && (avail2 = gst_alsa_update_avail (this)) < avail) {
415 if (avail2 <= -EPIPE) goto sink_restart;
416 if (avail2 < 0) return;
417 if (avail2 < avail && snd_pcm_state(this->handle) != SND_PCM_STATE_RUNNING)
418 if (!gst_alsa_start (this)) return;
419 if (gst_alsa_pcm_wait (this) == FALSE)
423 /* FIXME: lotsa stuff can have happened while fetching data. Do we need to check something? */
425 /* put this data into alsa */
426 if ((copied = this->transmit (this, &avail)) < 0)
428 /* update our clock */
429 this->transmitted += copied;
431 bytes = gst_alsa_samples_to_bytes (this, copied);
432 for (i = 0; i < element->numpads; i++) {
433 if ((sink->size[i] -= bytes) == 0) {
434 gst_alsa_sink_flush_one_pad (sink, i);
437 g_assert (sink->size[i] > 0);
438 if (sink->behaviour[i] != 1)
439 sink->data[i] += bytes;
443 if (snd_pcm_state(this->handle) != SND_PCM_STATE_RUNNING && snd_pcm_avail_update (this->handle) == 0) {
444 gst_alsa_start (this);
449 static GstElementStateReturn
450 gst_alsa_sink_change_state (GstElement *element)
454 g_return_val_if_fail (element != NULL, FALSE);
455 sink = GST_ALSA_SINK (element);
457 switch (GST_STATE_TRANSITION (element)) {
458 case GST_STATE_NULL_TO_READY:
459 case GST_STATE_READY_TO_PAUSED:
460 case GST_STATE_PAUSED_TO_PLAYING:
461 case GST_STATE_PLAYING_TO_PAUSED:
463 case GST_STATE_PAUSED_TO_READY:
464 gst_alsa_sink_flush_pads (sink);
466 case GST_STATE_READY_TO_NULL:
469 g_assert_not_reached();
472 if (GST_ELEMENT_CLASS (sink_parent_class)->change_state)
473 return GST_ELEMENT_CLASS (sink_parent_class)->change_state (element);
475 return GST_STATE_SUCCESS;
479 gst_alsa_sink_get_time (GstAlsa *this)
481 snd_pcm_sframes_t delay;
483 if (snd_pcm_delay (this->handle, &delay) == 0 && this->format) {
484 return GST_SECOND * (GstClockTime) (this->transmitted > delay ? this->transmitted - delay : 0) / this->format->rate;