[pulseaudio-discuss] [PATCH v6 14/25] source.c, sink.c: Implement pa_{source, sink}_get_raw_latency_within_thread() calls

Georg Chini georg at chini.tk
Sun Jun 5 19:05:17 UTC 2016


In certain situations, the reported sink or source latency may become negative.
This does not indicate that the latency is indeed negative but can be considered
merely an offset error. The current get_latency() calls truncate negative latencies
because they do not make sense from a physical point of view.
In the context of module loopback, negative source or sink latencies are acceptable
because the overall latency never becomes negative. Truncating negative values leads
to discontinuities in the latency reports, therefore this patch implements functions
in source.c and sink.c which can return the raw value without truncation.
The corresponding PA_SINK_MESSAGE_GET_RAW_LATENCY needs to be handled by the driver.

---
 src/pulsecore/sink.c   | 30 ++++++++++++++++++++++++++++++
 src/pulsecore/sink.h   |  2 ++
 src/pulsecore/source.c | 30 ++++++++++++++++++++++++++++++
 src/pulsecore/source.h |  2 ++
 4 files changed, 64 insertions(+)

diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 3f1ef72..2b72279 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1550,6 +1550,35 @@ pa_usec_t pa_sink_get_latency_within_thread(pa_sink *s) {
     return usec;
 }
 
+/* Called from IO thread */
+int64_t pa_sink_get_raw_latency_within_thread(pa_sink *s) {
+    int64_t usec = 0;
+    pa_msgobject *o;
+
+    pa_sink_assert_ref(s);
+    pa_sink_assert_io_context(s);
+    pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
+
+    /* The returned value is supposed to be in the time domain of the sound card! */
+
+    if (s->thread_info.state == PA_SINK_SUSPENDED)
+        return 0;
+
+    if (!(s->flags & PA_SINK_LATENCY))
+        return 0;
+
+    o = PA_MSGOBJECT(s);
+
+    /* FIXME: We probably should make this a proper vtable callback instead of going through process_msg() */
+
+    if (o->process_msg(o, PA_SINK_MESSAGE_GET_RAW_LATENCY, &usec, 0, NULL) < 0) {
+       if (o->process_msg(o, PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+          return 0;
+    }
+
+    return usec + s->thread_info.latency_offset;
+}
+
 /* Called from the main thread (and also from the IO thread while the main
  * thread is waiting).
  *
@@ -2894,6 +2923,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             return 0;
 
         case PA_SINK_MESSAGE_GET_LATENCY:
+        case PA_SINK_MESSAGE_GET_RAW_LATENCY:
         case PA_SINK_MESSAGE_MAX:
             ;
     }
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index b64a666..6b901c6 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -338,6 +338,7 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_SET_PORT,
     PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE,
     PA_SINK_MESSAGE_SET_LATENCY_OFFSET,
+    PA_SINK_MESSAGE_GET_RAW_LATENCY,
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 
@@ -520,6 +521,7 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes);
 void pa_sink_invalidate_requested_latency(pa_sink *s, bool dynamic);
 
 pa_usec_t pa_sink_get_latency_within_thread(pa_sink *s);
+int64_t pa_sink_get_raw_latency_within_thread(pa_sink *s);
 
 /* Called from the main thread, from sink-input.c only. The normal way to set
  * the sink reference volume is to call pa_sink_set_volume(), but the flat
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 98374ae..0e33fb2 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -1145,6 +1145,35 @@ pa_usec_t pa_source_get_latency_within_thread(pa_source *s) {
     return usec;
 }
 
+/* Called from IO thread */
+int64_t pa_source_get_raw_latency_within_thread(pa_source *s) {
+    int64_t usec = 0;
+    pa_msgobject *o;
+
+    pa_source_assert_ref(s);
+    pa_source_assert_io_context(s);
+    pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
+
+    /* The returned value is supposed to be in the time domain of the sound card! */
+
+    if (s->thread_info.state == PA_SOURCE_SUSPENDED)
+        return 0;
+
+    if (!(s->flags & PA_SOURCE_LATENCY))
+        return 0;
+
+    o = PA_MSGOBJECT(s);
+
+    /* FIXME: We probably should make this a proper vtable callback instead of going through process_msg() */
+
+    if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_RAW_LATENCY, &usec, 0, NULL) < 0) {
+       if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+          return 0;
+    }
+
+    return usec + s->thread_info.latency_offset;
+}
+
 /* Called from the main thread (and also from the IO thread while the main
  * thread is waiting).
  *
@@ -2214,6 +2243,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             return 0;
 
         case PA_SOURCE_MESSAGE_GET_LATENCY:
+        case PA_SOURCE_MESSAGE_GET_RAW_LATENCY:
 
             if (s->monitor_of) {
                 *((pa_usec_t*) userdata) = 0;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 91e8674..e5a6b38 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -276,6 +276,7 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_SET_PORT,
     PA_SOURCE_MESSAGE_UPDATE_VOLUME_AND_MUTE,
     PA_SOURCE_MESSAGE_SET_LATENCY_OFFSET,
+    PA_SOURCE_MESSAGE_GET_RAW_LATENCY,
     PA_SOURCE_MESSAGE_MAX
 } pa_source_message_t;
 
@@ -444,6 +445,7 @@ bool pa_source_volume_change_apply(pa_source *s, pa_usec_t *usec_to_next);
 
 void pa_source_invalidate_requested_latency(pa_source *s, bool dynamic);
 pa_usec_t pa_source_get_latency_within_thread(pa_source *s);
+int64_t pa_source_get_raw_latency_within_thread(pa_source *s);
 
 /* Called from the main thread, from source-output.c only. The normal way to
  * set the source reference volume is to call pa_source_set_volume(), but the
-- 
2.8.1



More information about the pulseaudio-discuss mailing list