Commit ce87f749 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

pulse: fix start time, do not confuse first and last PTS in buffer

parent 40b9ca96
...@@ -64,8 +64,9 @@ struct aout_sys_t ...@@ -64,8 +64,9 @@ struct aout_sys_t
pa_time_event *trigger; /**< Deferred stream trigger */ pa_time_event *trigger; /**< Deferred stream trigger */
pa_volume_t base_volume; /**< 0dB reference volume */ pa_volume_t base_volume; /**< 0dB reference volume */
pa_cvolume cvolume; /**< actual sink input volume */ pa_cvolume cvolume; /**< actual sink input volume */
mtime_t first_pts; /**< Play time of buffer start */
mtime_t last_pts; /**< Play time of buffer write offset */
mtime_t paused; /**< Time when (last) paused */ mtime_t paused; /**< Time when (last) paused */
mtime_t pts; /**< Play time of buffer write offset */
mtime_t desync; /**< Measured desynchronization */ mtime_t desync; /**< Measured desynchronization */
unsigned rate; /**< Current stream sample rate */ unsigned rate; /**< Current stream sample rate */
}; };
...@@ -181,7 +182,8 @@ static void stream_reset_sync(pa_stream *s, audio_output_t *aout) ...@@ -181,7 +182,8 @@ static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
const unsigned rate = aout->format.i_rate; const unsigned rate = aout->format.i_rate;
sys->pts = VLC_TS_INVALID; sys->first_pts = VLC_TS_INVALID;
sys->last_pts = VLC_TS_INVALID;
sys->desync = 0; sys->desync = 0;
pa_operation *op = pa_stream_update_sample_rate(s, rate, NULL, NULL); pa_operation *op = pa_stream_update_sample_rate(s, rate, NULL, NULL);
if (unlikely(op == NULL)) if (unlikely(op == NULL))
...@@ -190,7 +192,7 @@ static void stream_reset_sync(pa_stream *s, audio_output_t *aout) ...@@ -190,7 +192,7 @@ static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
sys->rate = rate; sys->rate = rate;
} }
static void stream_start(pa_stream *s, audio_output_t *aout) static void stream_start_now(pa_stream *s, audio_output_t *aout)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
pa_operation *op; pa_operation *op;
...@@ -231,7 +233,7 @@ static void stream_trigger_cb(pa_mainloop_api *api, pa_time_event *e, ...@@ -231,7 +233,7 @@ static void stream_trigger_cb(pa_mainloop_api *api, pa_time_event *e,
msg_Dbg(aout, "starting deferred"); msg_Dbg(aout, "starting deferred");
vlc_pa_rttime_free(sys->mainloop, sys->trigger); vlc_pa_rttime_free(sys->mainloop, sys->trigger);
sys->trigger = NULL; sys->trigger = NULL;
stream_start(sys->stream, aout); stream_start_now(sys->stream, aout);
(void) api; (void) e; (void) tv; (void) api; (void) e; (void) tv;
} }
...@@ -241,12 +243,12 @@ static void stream_trigger_cb(pa_mainloop_api *api, pa_time_event *e, ...@@ -241,12 +243,12 @@ static void stream_trigger_cb(pa_mainloop_api *api, pa_time_event *e,
* in order to minimize desync and resampling during early playback. * in order to minimize desync and resampling during early playback.
* @note PulseAudio lock required. * @note PulseAudio lock required.
*/ */
static void stream_resync(audio_output_t *aout, pa_stream *s) static void stream_start(pa_stream *s, audio_output_t *aout)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
mtime_t delta; mtime_t delta;
assert (sys->pts != VLC_TS_INVALID); assert (sys->first_pts != VLC_TS_INVALID);
if (sys->trigger != NULL) { if (sys->trigger != NULL) {
vlc_pa_rttime_free(sys->mainloop, sys->trigger); vlc_pa_rttime_free(sys->mainloop, sys->trigger);
...@@ -259,7 +261,7 @@ static void stream_resync(audio_output_t *aout, pa_stream *s) ...@@ -259,7 +261,7 @@ static void stream_resync(audio_output_t *aout, pa_stream *s)
delta = 0; /* screwed */ delta = 0; /* screwed */
} }
delta = (sys->pts - mdate()) - delta; delta = (sys->first_pts - mdate()) - delta;
if (delta > 0) { if (delta > 0) {
msg_Dbg(aout, "deferring start (%"PRId64" us)", delta); msg_Dbg(aout, "deferring start (%"PRId64" us)", delta);
delta += pa_rtclock_now(); delta += pa_rtclock_now();
...@@ -267,7 +269,7 @@ static void stream_resync(audio_output_t *aout, pa_stream *s) ...@@ -267,7 +269,7 @@ static void stream_resync(audio_output_t *aout, pa_stream *s)
stream_trigger_cb, aout); stream_trigger_cb, aout);
} else { } else {
msg_Warn(aout, "starting late (%"PRId64" us)", delta); msg_Warn(aout, "starting late (%"PRId64" us)", delta);
stream_start(s, aout); stream_start_now(s, aout);
} }
} }
...@@ -279,12 +281,13 @@ static void stream_latency_cb(pa_stream *s, void *userdata) ...@@ -279,12 +281,13 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
if (sys->paused != VLC_TS_INVALID) if (sys->paused != VLC_TS_INVALID)
return; /* nothing to do while paused */ return; /* nothing to do while paused */
if (sys->pts == VLC_TS_INVALID) { if (sys->last_pts == VLC_TS_INVALID) {
msg_Dbg(aout, "missing latency from input"); msg_Dbg(aout, "nothing to play");
assert (sys->first_pts == VLC_TS_INVALID);
return; return;
} }
if (pa_stream_is_corked(s) > 0) { if (pa_stream_is_corked(s) > 0) {
stream_resync(aout, s); stream_start(s, aout);
return; return;
} }
...@@ -293,7 +296,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata) ...@@ -293,7 +296,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
if (delta == VLC_TS_INVALID) if (delta == VLC_TS_INVALID)
return; return;
delta = (sys->pts - mdate()) - delta; delta = (sys->last_pts - mdate()) - delta;
change = delta - sys->desync; change = delta - sys->desync;
sys->desync = delta; sys->desync = delta;
//msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)", //msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
...@@ -542,9 +545,12 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift) ...@@ -542,9 +545,12 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
* will take place, and sooner or later a deadlock. */ * will take place, and sooner or later a deadlock. */
pa_threaded_mainloop_lock(sys->mainloop); pa_threaded_mainloop_lock(sys->mainloop);
sys->pts = pts; if (sys->first_pts == VLC_TS_INVALID)
sys->first_pts = block->i_pts;
sys->last_pts = pts;
if (pa_stream_is_corked(s) > 0) if (pa_stream_is_corked(s) > 0)
stream_resync(aout, s); stream_start(s, aout);
#if 0 /* Fault injector to test underrun recovery */ #if 0 /* Fault injector to test underrun recovery */
static volatile unsigned u = 0; static volatile unsigned u = 0;
...@@ -581,8 +587,12 @@ static void Pause(audio_output_t *aout, bool paused, mtime_t date) ...@@ -581,8 +587,12 @@ static void Pause(audio_output_t *aout, bool paused, mtime_t date)
date -= sys->paused; date -= sys->paused;
msg_Dbg(aout, "resuming after %"PRId64" us", date); msg_Dbg(aout, "resuming after %"PRId64" us", date);
sys->paused = VLC_TS_INVALID; sys->paused = VLC_TS_INVALID;
sys->pts += date;
stream_resync(aout, s); if (sys->last_pts != VLC_TS_INVALID) {
sys->first_pts += date;
sys->last_pts += date;
stream_start(s, aout);
}
} }
pa_threaded_mainloop_unlock(sys->mainloop); pa_threaded_mainloop_unlock(sys->mainloop);
...@@ -855,8 +865,9 @@ static int Open(vlc_object_t *obj) ...@@ -855,8 +865,9 @@ static int Open(vlc_object_t *obj)
sys->stream = NULL; sys->stream = NULL;
sys->context = ctx; sys->context = ctx;
sys->trigger = NULL; sys->trigger = NULL;
sys->first_pts = VLC_TS_INVALID;
sys->last_pts = VLC_TS_INVALID;
sys->paused = VLC_TS_INVALID; sys->paused = VLC_TS_INVALID;
sys->pts = VLC_TS_INVALID;
sys->desync = 0; sys->desync = 0;
sys->rate = ss.rate; sys->rate = ss.rate;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment