示例#1
0
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;
}
示例#2
0
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);
}
示例#3
0
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;
}
示例#4
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;
}
示例#5
0
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;
}
示例#6
0
size_t
audio_offset()
{
  snd_pcm_delay(playback_handle, &delay);

  return written - delay;
}
示例#7
0
文件: dsoutput.c 项目: r6144/wine
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);
    }
}
示例#8
0
文件: alsa.c 项目: kernelOfTruth/dsp
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);
}
示例#9
0
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;
}
示例#10
0
文件: alsa.c 项目: kernelOfTruth/dsp
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;
}
示例#11
0
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;
}
示例#12
0
            float delay()
            {
               if (!runnable)
                  return 0.0;

               snd_pcm_sframes_t delay;
               snd_pcm_delay(pcm, &delay);

               return (float)delay / fps;
            }
示例#13
0
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 );
}
示例#14
0
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;
}
示例#15
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;
}
示例#16
0
文件: tsmf_alsa.c 项目: BUGgs/FreeRDP
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;
}
示例#17
0
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;
}
示例#18
0
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);
}
示例#19
0
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;
}
示例#20
0
/**
 * \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;
}
示例#21
0
/* 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;
}
示例#22
0
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;
}
示例#23
0
/*----------------------------------------------------------------------
|    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;
}
示例#24
0
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;
}
示例#25
0
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;
}
示例#26
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;
}
示例#27
0
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;
}
示例#28
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;
}
示例#30
0
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;
}