[alsa] Try to measure latency

This commit is contained in:
ejurgensen 2016-04-06 09:09:28 +02:00
parent 857055a18d
commit eca41e306e
1 changed files with 34 additions and 6 deletions

View File

@ -92,6 +92,7 @@ struct alsa_session
extern struct event_base *evbase_player; extern struct event_base *evbase_player;
static struct alsa_session *sessions; static struct alsa_session *sessions;
static int sync_counter;
/* Forwards */ /* Forwards */
static void static void
@ -382,7 +383,7 @@ mixer_open(void)
} }
static int static int
device_open(void) device_open(struct alsa_session *as)
{ {
snd_pcm_hw_params_t *hw_params; snd_pcm_hw_params_t *hw_params;
snd_pcm_uframes_t bufsize; snd_pcm_uframes_t bufsize;
@ -548,7 +549,7 @@ playback_start(struct alsa_session *as, uint64_t pos, uint64_t start_pos)
} }
as->pos = pos; as->pos = pos;
as->start_pos = start_pos; as->start_pos = start_pos - AIRTUNES_V2_PACKET_SAMPLES;
// Dump PCM config data for E_DBG logging // Dump PCM config data for E_DBG logging
ret = snd_output_buffer_open(&output); ret = snd_output_buffer_open(&output);
@ -571,11 +572,17 @@ playback_write(struct alsa_session *as, uint8_t *buf, uint64_t rtptime)
{ {
snd_pcm_sframes_t ret; snd_pcm_sframes_t ret;
snd_pcm_sframes_t avail; snd_pcm_sframes_t avail;
snd_pcm_sframes_t delay;
snd_pcm_sframes_t nsamp; snd_pcm_sframes_t nsamp;
struct timespec now;
uint64_t pb_pos;
uint64_t cur_pos;
uint8_t *pkt; uint8_t *pkt;
int prebuffering; int prebuffering;
int prebuf_empty; int prebuf_empty;
int npackets; int npackets;
int latency;
int diff;
prebuffering = (as->pos < as->start_pos); prebuffering = (as->pos < as->start_pos);
prebuf_empty = (as->prebuf_head == as->prebuf_tail); prebuf_empty = (as->prebuf_head == as->prebuf_tail);
@ -596,14 +603,35 @@ playback_write(struct alsa_session *as, uint8_t *buf, uint64_t rtptime)
if (prebuffering) if (prebuffering)
return; return;
ret = snd_pcm_avail_update(hdl); ret = snd_pcm_avail_delay(hdl, &avail, &delay);
if (ret < 0) if (ret < 0)
goto alsa_error; goto alsa_error;
avail = ret;
if (avail < AIRTUNES_V2_PACKET_SAMPLES) if (avail < AIRTUNES_V2_PACKET_SAMPLES)
return; return;
sync_counter++;
if (sync_counter >= 126)
{
sync_counter = 0;
if (!prebuf_empty)
npackets = (as->prebuf_head - (as->prebuf_tail + 1) + as->prebuf_len) % as->prebuf_len + 1;
else
npackets = 0;
pb_pos = rtptime - delay - AIRTUNES_V2_PACKET_SAMPLES * npackets;
ret = player_get_current_pos(&cur_pos, &now, 0); // TODO commit?
if (ret == 0)
latency = cur_pos - pb_pos;
else
latency = 0;
diff = cur_pos - as->pos;
if (latency)
DPRINTF(E_DBG, L_LAUDIO, "Sync to cur_pos %" PRIu64 ", pb_pos %" PRIu64 " (diff %d, delay %li), pos %" PRIu64 " (diff %d)\n", cur_pos, pb_pos, latency, delay, as->pos, diff);
}
// If we have data in prebuf we send as much as we can // If we have data in prebuf we send as much as we can
if (!prebuf_empty) if (!prebuf_empty)
{ {
@ -690,7 +718,7 @@ alsa_device_start(struct output_device *device, output_status_cb cb, uint64_t rt
if (!as) if (!as)
return -1; return -1;
ret = device_open(); ret = device_open(as);
if (ret < 0) if (ret < 0)
return -1; return -1;
@ -721,7 +749,7 @@ alsa_device_probe(struct output_device *device, output_status_cb cb)
if (!as) if (!as)
return -1; return -1;
ret = device_open(); ret = device_open(as);
if (ret < 0) if (ret < 0)
{ {
alsa_session_cleanup(as); alsa_session_cleanup(as);