[vlc-commits] pulse: compute latency correctly if negative (fixes #15046)

Rémi Denis-Courmont git at videolan.org
Sat Aug 22 11:26:03 CEST 2015


vlc/vlc-2.2 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Aug 22 12:21:35 2015 +0300| [790c706d9f90358628b18b346b0cea74efd80aec] | committer: Rémi Denis-Courmont

pulse: compute latency correctly if negative (fixes #15046)

This occurs in case of large buffer underflow, such as if stopping the
VLC process.

(cherry picked from commit 887bda11d23665416bd9403151ad1acced68b267)

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=790c706d9f90358628b18b346b0cea74efd80aec
---

 modules/audio_output/vlcpulse.c |   32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/modules/audio_output/vlcpulse.c b/modules/audio_output/vlcpulse.c
index feecfa7..0952cb0 100644
--- a/modules/audio_output/vlcpulse.c
+++ b/modules/audio_output/vlcpulse.c
@@ -252,13 +252,33 @@ void vlc_pa_rttime_free (pa_threaded_mainloop *mainloop, pa_time_event *e)
  */
 mtime_t vlc_pa_get_latency(vlc_object_t *obj, pa_context *ctx, pa_stream *s)
 {
-    pa_usec_t latency;
-    int negative;
+    /* NOTE: pa_stream_get_latency() will report 0 rather than negative latency
+     * when the write index of a playback stream is behind its read index.
+     * playback streams. So use the lower-level pa_stream_get_timing_info()
+     * directly to obtain the correct write index and convert it to a time,
+     * and compute the correct latency value by substracting the stream (read)
+     * time.
+     *
+     * On the read side, pa_stream_get_time() is used instead of
+     * pa_stream_get_timing_info() for the sake of interpolation. */
+    const pa_sample_spec *ss = pa_stream_get_sample_spec(s);
+    const pa_timing_info *ti = pa_stream_get_timing_info(s);
+
+    if (ti->write_index_corrupt) {
+        msg_Dbg(obj, "write index corrupt");
+        return VLC_TS_INVALID;
+    }
 
-    if (pa_stream_get_latency(s, &latency, &negative)) {
-        if (pa_context_errno (ctx) != PA_ERR_NODATA)
-            vlc_pa_error(obj, "unknown latency", ctx);
+    pa_usec_t wt = pa_bytes_to_usec((uint64_t)ti->write_index, ss);
+    pa_usec_t rt;
+
+    if (pa_stream_get_time(s, &rt)) {
+        if (pa_context_errno(ctx) != PA_ERR_NODATA)
+            vlc_pa_error(obj, "unknown time", ctx);
         return VLC_TS_INVALID;
     }
-    return negative ? -latency : +latency;
+
+    union { uint64_t u; int64_t s; } d;
+    d.u = wt - rt;
+    return d.s; /* non-overflowing unsigned to signed conversion */
 }



More information about the vlc-commits mailing list