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; }
int audioStreamer_ALSA::Read(char *buf, int len) // returns 0 if blocked, < 0 if error, > 0 if data { int ret; if (m_sleep >= 0) { struct pollfd pfds[32]; int cnt=snd_pcm_poll_descriptors(pcm_handle,pfds,32); if (cnt>0) poll(pfds,cnt,m_sleep); } ret=snd_pcm_readi(pcm_handle, buf, len/(m_nch*(m_bps/8))); if (ret < 0) { if (ret != -EAGAIN) { snd_pcm_prepare(pcm_handle); } return 0; } #if 0 snd_pcm_sframes_t del=0; if (!snd_pcm_delay(pcm_handle,&del) && del > m_bufsize/2 /* JF>used to be /1 */) { audiostream_onover(); for (;;) if (snd_pcm_readi(pcm_handle, buf, len/(m_nch*(m_bps/8)))<0) break; // we have too many samples, eat some } #endif return ret*m_nch*(m_bps/8); }
int audioStreamer_ALSA::Write(char *buf, int len) // returns 0 on success { snd_pcm_sframes_t del=0; if (!len) return 0; int cnt=1; if (!m_started || !snd_pcm_delay(pcm_handle,&del) && del<1) { if (m_started) audiostream_onunder(); else m_started=1; cnt=m_nfrags; memset(buf,0,len); // reduce noise } while (cnt-->0) { int ret=snd_pcm_writei(pcm_handle, buf, len/(m_nch*(m_bps/8))); if (ret < 0) { if (ret == -EPIPE) snd_pcm_prepare(pcm_handle); return 0; } } return 0; }
static uint64_t laudio_alsa_get_pos(void) { snd_pcm_sframes_t delay; int ret; if (pcm_pos == 0) return 0; if (pcm_last_error != 0) return pcm_pos; if (snd_pcm_state(hdl) != SND_PCM_STATE_RUNNING) return pcm_pos; ret = snd_pcm_delay(hdl, &delay); if (ret < 0) { DPRINTF(E_WARN, L_LAUDIO, "Could not obtain PCM delay: %s\n", snd_strerror(ret)); return pcm_pos; } return pcm_pos - delay; }
static int alsa_stream_get_position(cubeb_stream * stm, uint64_t * position) { snd_pcm_sframes_t delay; assert(stm && position); pthread_mutex_lock(&stm->mutex); delay = -1; if (snd_pcm_state(stm->pcm) != SND_PCM_STATE_RUNNING || snd_pcm_delay(stm->pcm, &delay) != 0) { *position = stm->last_position; pthread_mutex_unlock(&stm->mutex); return CUBEB_OK; } assert(delay >= 0); *position = 0; if (stm->write_position >= (snd_pcm_uframes_t) delay) { *position = stm->write_position - delay; } stm->last_position = *position; pthread_mutex_unlock(&stm->mutex); return CUBEB_OK; }
size_t audio_offset() { snd_pcm_delay(playback_handle, &delay); return written - delay; }
static void CheckXRUN(IDsDriverBufferImpl* This) { snd_pcm_state_t state = snd_pcm_state(This->pcm); snd_pcm_sframes_t delay; int err; snd_pcm_hwsync(This->pcm); snd_pcm_delay(This->pcm, &delay); if ( state == SND_PCM_STATE_XRUN ) { err = snd_pcm_prepare(This->pcm); CommitAll(This); snd_pcm_start(This->pcm); WARN("xrun occurred\n"); if ( err < 0 ) ERR("recovery from xrun failed, prepare failed: %s\n", snd_strerror(err)); } else if ( state == SND_PCM_STATE_SUSPENDED ) { int err = snd_pcm_resume(This->pcm); TRACE("recovery from suspension occurred\n"); if (err < 0 && err != -EAGAIN){ err = snd_pcm_prepare(This->pcm); if (err < 0) ERR("recovery from suspend failed, prepare failed: %s\n", snd_strerror(err)); } } else if ( state != SND_PCM_STATE_RUNNING ) { FIXME("Unhandled state: %d\n", state); } }
void alsa_pause(struct codec *c, int p) { struct alsa_state *state = (struct alsa_state *) c->data; if (snd_pcm_state(state->dev) != SND_PCM_STATE_PAUSED) snd_pcm_delay(state->dev, &state->delay); snd_pcm_pause(state->dev, p); }
static void alsa_close () { snd_pcm_sframes_t delay; assert (handle != NULL); /* play what remained in the buffer */ if (alsa_buf_fill) { assert (alsa_buf_fill < chunk_size); snd_pcm_format_set_silence (params.format, alsa_buf + alsa_buf_fill, (chunk_size - alsa_buf_fill) / bytes_per_frame * params.channels); alsa_buf_fill = chunk_size; play_buf_chunks (); } /* Wait for ALSA buffers to empty. * Do not be tempted to use snd_pcm_nonblock() and snd_pcm_drain() * here; there are two bugs in ALSA which make it a bad idea (see * the SVN commit log for r2550). Instead we sleep for the duration * of the still unplayed samples. */ if (snd_pcm_delay (handle, &delay) == 0) usleep ((uint64_t) delay * 1000000 / params.rate); snd_pcm_close (handle); logit ("ALSA device closed"); params.format = 0; params.rate = 0; params.channels = 0; handle = NULL; }
ssize_t alsa_delay(struct codec *c) { struct alsa_state *state = (struct alsa_state *) c->data; if (snd_pcm_state(state->dev) == SND_PCM_STATE_PAUSED) return state->delay; snd_pcm_delay(state->dev, &state->delay); return state->delay; }
static void audio_get_output_timestamp(AVFormatContext *s1, int stream, int64_t *dts, int64_t *wall) { AlsaData *s = s1->priv_data; snd_pcm_sframes_t delay = 0; *wall = av_gettime(); snd_pcm_delay(s->h, &delay); *dts = s1->streams[0]->cur_dts - delay; }
float delay() { if (!runnable) return 0.0; snd_pcm_sframes_t delay; snd_pcm_delay(pcm, &delay); return (float)delay / fps; }
qint64 QAudioInputPrivate::bytesAvailable() const { if ( !handle ) return 0; snd_pcm_sframes_t frames; if ( snd_pcm_delay( handle, &frames ) < 0 ) return 0; return snd_pcm_frames_to_bytes( handle, frames ); }
static int alsa_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch) { decoder_t *d = (decoder_t *)ad; media_pipe_t *mp = ad->ad_mp; int c; retry: c = snd_pcm_wait(d->h, 100); if(c >= 0) { c = snd_pcm_avail_update(d->h); } if(c == -EPIPE) { snd_pcm_prepare(d->h); usleep(100000); TRACE(TRACE_DEBUG, "ALSA", "Audio underrun"); d->samples = 0; goto retry; } c = MIN(d->max_frames_per_write, c); uint8_t *planes[8] = {0}; planes[0] = d->tmp; c = avresample_read(ad->ad_avr, planes, c); snd_pcm_status_t *status; int err; snd_pcm_status_alloca(&status); if ((err = snd_pcm_status(d->h, status)) >= 0) { if(pts != AV_NOPTS_VALUE) { snd_htimestamp_t hts; snd_pcm_status_get_trigger_htstamp(status, &hts); int64_t ts = hts.tv_sec * 1000000LL + hts.tv_nsec / 1000; ts += d->samples * 1000000LL / ad->ad_out_sample_rate; hts_mutex_lock(&mp->mp_clock_mutex); mp->mp_audio_clock_avtime = ts; mp->mp_audio_clock = pts; mp->mp_audio_clock_epoch = epoch; hts_mutex_unlock(&mp->mp_clock_mutex); } } snd_pcm_sframes_t fr; if(!snd_pcm_delay(d->h, &fr)) ad->ad_delay = 1000000L * fr / ad->ad_out_sample_rate; c = snd_pcm_writei(d->h, d->tmp, c); d->samples += c; return 0; }
static snd_pcm_sframes_t alsaspdifsink_delay (AlsaSPDIFSink * sink) { snd_pcm_sframes_t delay; int err; err = snd_pcm_delay (sink->pcm, &delay); if (err < 0 || delay < 0) { return 0; } return delay; }
static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice *audio) { UINT64 latency = 0; snd_pcm_sframes_t frames = 0; TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio; if(alsa->out_handle && alsa->actual_rate > 0 && snd_pcm_delay(alsa->out_handle, &frames) == 0 && frames > 0) { latency = ((UINT64)frames) * 10000000LL / (UINT64) alsa->actual_rate; } return latency; }
APULSE_EXPORT const pa_timing_info * pa_stream_get_timing_info(pa_stream *s) { trace_info_f("F %s s=%p\n", __func__, s); snd_pcm_sframes_t delay; if (snd_pcm_delay(s->ph, &delay) != 0) delay = 0; s->timing_info.read_index = s->timing_info.write_index - delay * pa_frame_size(&s->ss); return &s->timing_info; }
static long long get_delay(void) { snd_pcm_sframes_t frames = 0; snd_pcm_delay(alsa_handle, &frames); if (frames < 0) { #if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */ snd_pcm_forward(alsa_handle, -frames); #endif frames = 0; } return (long long)(frames * 1000000L / device_sample_rate); }
static int alsa_bufferspace(void) { int err; snd_pcm_sframes_t delay; if ((err = snd_pcm_delay(handle, &delay)) < 0) { if ((err = xrun_recovery(handle, err)) < 0) { log_message(LOG_DEFAULT, "Delay error: %s", snd_strerror(err)); } return alsa_bufsize; } return alsa_bufsize - delay; }
/** * \brief Obtain delay for a running PCM handle * \param pcm ordinary PCM handle * \param delayp Returned delay in frames * \return 0 on success otherwise a negative error code * * Delay is distance between current application frame position and * sound frame position. * It's positive and less than buffer size in normal situation, * negative on playback underrun and greater than buffer size on * capture overrun. */ int sndo_pcm_delay(sndo_pcm_t *pcm, snd_pcm_sframes_t *delayp) { int err; snd_pcm_sframes_t pdelay, cdelay; assert(pcm); assert(delayp); err = sndo_pcm_check_setup(pcm); if (err < 0) return err; if (pcm->playback) err = snd_pcm_avail_update(pcm->playback); if (err >= 0 && pcm->capture) err = snd_pcm_avail_update(pcm->capture); if (err >= 0 && pcm->playback) err = snd_pcm_delay(pcm->playback, &pdelay); if (err >= 0 && pcm->capture) err = snd_pcm_delay(pcm->capture, &cdelay); if (pdelay > cdelay) pdelay = cdelay; *delayp = pdelay; return err; }
/* close the audio device */ int ao_plugin_close(ao_device *device) { ao_alsa_internal *internal; if (device) { if ((internal = (ao_alsa_internal *) device->internal)) { if (internal->pcm_handle) { /* this is a PulseAudio ALSA emulation bug workaround; snd_pcm_drain always takes about 2 seconds, even if there's nothing to drain. Rather than wait for no reason, determine the current playback depth, wait that long, then kill the stream. Remove this code once Pulse gets fixed. */ snd_pcm_sframes_t sframes; if(snd_pcm_delay (internal->pcm_handle, &sframes)){ snd_pcm_drain(internal->pcm_handle); }else{ double s = (double)(sframes - internal->static_delay)/internal->sample_rate; if(s>1){ /* something went wrong; fall back */ snd_pcm_drain(internal->pcm_handle); }else{ if(s>0){ struct timespec sleep,wake; sleep.tv_sec = (int)s; sleep.tv_nsec = (s-sleep.tv_sec)*1000000000; while(nanosleep(&sleep,&wake)<0){ if(errno==EINTR) sleep=wake; else break; } } } } snd_pcm_close(internal->pcm_handle); if(internal->local_config) snd_config_delete(internal->local_config); internal->local_config=NULL; internal->pcm_handle=NULL; } } else awarn("ao_plugin_close called with uninitialized ao_device->internal\n"); } else awarn("ao_plugin_close called with uninitialized ao_device\n"); return 1; }
int alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency) { snd_pcm_sframes_t delay; /* This function returns the delay in frames until a frame written using snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */ if (snd_pcm_delay(stm->pcm, &delay)) { return CUBEB_ERROR; } *latency = delay; return CUBEB_OK; }
/*---------------------------------------------------------------------- | AlsaOutput_GetStatus +---------------------------------------------------------------------*/ BLT_METHOD AlsaOutput_GetStatus(BLT_OutputNode* _self, BLT_OutputNodeStatus* status) { AlsaOutput* self = ATX_SELF(AlsaOutput, BLT_OutputNode); snd_pcm_status_t* pcm_status; snd_pcm_sframes_t delay = 0; int io_result; /* default values */ status->media_time.seconds = 0; status->media_time.nanoseconds = 0; status->flags = 0; /* get the driver status */ snd_pcm_status_alloca_no_assert(&pcm_status); io_result = snd_pcm_status(self->device_handle, pcm_status); if (io_result != 0) { return BLT_FAILURE; } delay = snd_pcm_status_get_delay(pcm_status); if (delay == 0) { /* workaround buggy alsa drivers */ io_result = snd_pcm_delay(self->device_handle, &delay); if (io_result != 0) { return BLT_FAILURE; } } if (delay > 0 && self->media_type.sample_rate) { ATX_UInt64 media_time_samples = (self->next_media_time * (ATX_UInt64)self->media_type.sample_rate)/ (ATX_UInt64)1000000000; ATX_UInt64 media_time_ns; if (delay <= (snd_pcm_sframes_t)media_time_samples) { media_time_samples -= delay; } else { media_time_samples = 0; } media_time_ns = (media_time_samples*(ATX_UInt64)1000000000)/self->media_type.sample_rate; status->media_time = BLT_TimeStamp_FromNanos(media_time_ns); } else { status->media_time = BLT_TimeStamp_FromNanos(self->next_media_time); } /* return the computed media time */ ATX_LOG_FINEST_3("delay = %lld samples, input port time = %lld, media time = %lld", (ATX_UInt64)delay, self->next_media_time, BLT_TimeStamp_ToNanos(status->media_time)); return BLT_SUCCESS; }
static void *peeper(void *data) { int thread_no = (long)data; snd_pcm_sframes_t val; snd_pcm_status_t *stat; snd_htimestamp_t tstamp; int mode = running_mode, err; snd_pcm_status_alloca(&stat); while (running) { if (running_mode == MODE_RANDOM) mode = rand() % MODE_RANDOM; switch (mode) { case MODE_AVAIL_UPDATE: val = snd_pcm_avail_update(pcm); err = 0; break; case MODE_STATUS: err = snd_pcm_status(pcm, stat); val = snd_pcm_status_get_avail(stat); break; case MODE_HWSYNC: err = snd_pcm_hwsync(pcm); break; case MODE_TIMESTAMP: err = snd_pcm_htimestamp(pcm, (snd_pcm_uframes_t *)&val, &tstamp); break; default: err = snd_pcm_delay(pcm, &val); break; } if (quiet) continue; if (running_mode == MODE_RANDOM) { fprintf(stderr, "%d%c%s", thread_no, mode_suffix[mode], err ? "!" : ""); } else { if (show_value && mode != MODE_HWSYNC) fprintf(stderr, "\r%d ", (int)val); else fprintf(stderr, "%d%s", thread_no, err ? "!" : ""); } } return NULL; }
int snd_pcm_avail_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *availp, snd_pcm_sframes_t *delayp) { int err; snd_pcm_sframes_t val; err = snd_pcm_delay(pcm, delayp); if (err < 0) return err; val = snd_pcm_avail_update(pcm); if (val < 0) return (int)val; *availp = val; return 0; }
/* static MJR */ int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, s32 __user *src) { snd_pcm_sframes_t delay; /*mm_segment_t*/ unsigned long fs; // MJR int err; fs = snd_enter_user(); err = snd_pcm_delay(substream, &delay); snd_leave_user(fs); if (err < 0) return err; if (put_user(delay, src)) return -EFAULT; return err; }
static int alsa_get_buff_fill () { if (handle) { int err; snd_pcm_sframes_t delay; if ((err = snd_pcm_delay(handle, &delay)) < 0) { logit ("snd_pcm_delay() failed: %s", snd_strerror(err)); return 0; } /* delay can be negative when underrun occur */ return delay >= 0 ? delay * bytes_per_frame : 0; } return 0; }
bool SoundOutput_alsa::is_full() { int rc; snd_pcm_sframes_t delay; if (handle == nullptr) return false; rc = snd_pcm_delay(handle, &delay); if (rc < 0) { log_event("debug", "ClanSound: snd_pcm_delay() failed!?"); return false; } /* See if there is more then one period free in the buffer */ return delay > (snd_pcm_sframes_t)(frames_in_buffer - frames_in_period); }
static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, s32 __user *src) { snd_pcm_sframes_t delay; mm_segment_t fs; int err; fs = snd_enter_user(); err = snd_pcm_delay(substream, &delay); snd_leave_user(fs); if (err < 0) return err; if (put_user(delay, src)) return -EFAULT; return err; }
int AudioALSA::write_buffer(char *buffer, int size) { // Don't give up and drop the buffer on the first error. int attempts = 0; int done = 0; int samples = size / (device->out_bits / 8) / device->get_ochannels(); if(!get_output()) return 0; while(attempts < 2 && !done && !interrupted) { // Buffers written must be equal to period_time // Update timing snd_pcm_sframes_t delay; snd_pcm_delay(get_output(), &delay); snd_pcm_avail_update(get_output()); device->Thread::enable_cancel(); if(snd_pcm_writei(get_output(), buffer, samples) < 0) { device->Thread::disable_cancel(); printf("AudioALSA::write_buffer underrun at sample %" PRId64 "\n", device->current_position()); // snd_pcm_resume(get_output()); close_output(); open_output(); attempts++; } else { device->Thread::disable_cancel(); done = 1; } } if(done) { timer_lock->lock("AudioALSA::write_buffer"); this->delay = delay; timer->update(); samples_written += samples; timer_lock->unlock(); } return 0; }