static guint gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length) { GstAlsaSink *alsa; gint err; gint cptr; gint16 *ptr = data; alsa = GST_ALSA_SINK (asink); if (alsa->iec958 && alsa->need_swap) { guint i; GST_DEBUG_OBJECT (asink, "swapping bytes"); for (i = 0; i < length / 2; i++) { ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]); } } GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length); cptr = length / alsa->bytes_per_sample; GST_ALSA_SINK_LOCK (asink); while (cptr > 0) { /* start by doing a blocking wait for free space. Set the timeout * to 4 times the period time */ err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000)); if (err < 0) { GST_DEBUG_OBJECT (asink, "wait error, %d", err); } else { GST_DELAY_SINK_LOCK (asink); err = snd_pcm_writei (alsa->handle, ptr, cptr); GST_DELAY_SINK_UNLOCK (asink); } GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr); if (err < 0) { GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err)); if (err == -EAGAIN) { continue; } else if (xrun_recovery (alsa, alsa->handle, err) < 0) { goto write_error; } continue; } ptr += snd_pcm_frames_to_bytes (alsa->handle, err); cptr -= err; } GST_ALSA_SINK_UNLOCK (asink); return length - (cptr * alsa->bytes_per_sample); write_error: { GST_ALSA_SINK_UNLOCK (asink); return length; /* skip one period */ } }
static guint gst_alsasink_delay (GstAudioSink * asink) { GstAlsaSink *alsa; snd_pcm_sframes_t delay; int res; alsa = GST_ALSA_SINK (asink); GST_DELAY_SINK_LOCK (asink); res = snd_pcm_delay (alsa->handle, &delay); GST_DELAY_SINK_UNLOCK (asink); if (G_UNLIKELY (res < 0)) { /* on errors, report 0 delay */ GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res); delay = 0; } if (G_UNLIKELY (delay < 0)) { /* make sure we never return a negative delay */ GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay"); delay = 0; } return delay; }
static gint gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length) { GstAlsaSink *alsa; gint err; gint cptr; guint8 *ptr = data; alsa = GST_ALSA_SINK (asink); if (alsa->iec958 && alsa->need_swap) { guint i; guint16 *ptr_tmp = (guint16 *) ptr; GST_DEBUG_OBJECT (asink, "swapping bytes"); for (i = 0; i < length / 2; i++) { ptr_tmp[i] = GUINT16_SWAP_LE_BE (ptr_tmp[i]); } } GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length); cptr = length / alsa->bpf; GST_ALSA_SINK_LOCK (asink); while (cptr > 0) { /* start by doing a blocking wait for free space. Set the timeout * to 4 times the period time */ err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000)); if (err < 0) { GST_DEBUG_OBJECT (asink, "wait error, %d", err); } else { GST_DELAY_SINK_LOCK (asink); err = snd_pcm_writei (alsa->handle, ptr, cptr); GST_DELAY_SINK_UNLOCK (asink); } GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr); if (err < 0) { GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err)); if (err == -EAGAIN) { continue; } else if (err == -ENODEV) { goto device_disappeared; } else if (xrun_recovery (alsa, alsa->handle, err) < 0) { goto write_error; } continue; } ptr += snd_pcm_frames_to_bytes (alsa->handle, err); cptr -= err; } GST_ALSA_SINK_UNLOCK (asink); return length - (cptr * alsa->bpf); write_error: { GST_ALSA_SINK_UNLOCK (asink); return length; /* skip one period */ } device_disappeared: { GST_ELEMENT_ERROR (asink, RESOURCE, WRITE, (_("Error outputting to audio device. " "The device has been disconnected.")), (NULL)); goto write_error; } }