jack: Add low-latency property for automatic latency-optimized setting
authorSeungha Yang <seungha@centricular.com>
Mon, 26 Jul 2021 11:14:32 +0000 (20:14 +0900)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 28 Jul 2021 10:53:48 +0000 (10:53 +0000)
Similar to wasapi/wasapi2 plugins on Windows, adding low-latency
option so that jack element can optimize GstAudioRingBufferSpec
setting for low latency.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/1034>

docs/gst_plugins_cache.json
ext/jack/gstjackaudiosink.c
ext/jack/gstjackaudiosink.h
ext/jack/gstjackaudiosrc.c
ext/jack/gstjackaudiosrc.h

index 77f0e57..44f006d 100644 (file)
                         "type": "GstJackConnect",
                         "writable": true
                     },
+                    "low-latency": {
+                        "blurb": "Optimize all settings for lowest latency. When enabled, \"buffer-time\" and \"latency-time\" will be ignored",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
                     "port-pattern": {
                         "blurb": "A pattern to select which ports to connect to (NULL = first physical ports)",
                         "conditionally-available": false,
                         "type": "GstJackConnect",
                         "writable": true
                     },
+                    "low-latency": {
+                        "blurb": "Optimize all settings for lowest latency. When enabled, \"buffer-time\" and \"latency-time\" will be ignored",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "ready",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
                     "port-pattern": {
                         "blurb": "A pattern to select which ports to connect to (NULL = first physical ports)",
                         "conditionally-available": false,
index 856674f..ccdca5a 100644 (file)
@@ -435,7 +435,9 @@ gst_jack_ring_buffer_acquire (GstAudioRingBuffer * buf,
       (GST_SECOND / GST_USECOND), rate * bpf);
   /* segtotal based on buffer-time latency */
   spec->segtotal = spec->buffer_time / spec->latency_time;
-  if (spec->segtotal < 2) {
+
+  /* Use small period when low-latency is enabled regardless of buffer-time */
+  if (spec->segtotal < 2 || sink->low_latency) {
     spec->segtotal = 2;
     spec->buffer_time = spec->latency_time * spec->segtotal;
   }
@@ -685,6 +687,7 @@ enum
 #define DEFAULT_PROP_CLIENT_NAME       NULL
 #define DEFAULT_PROP_PORT_PATTERN              NULL
 #define DEFAULT_PROP_TRANSPORT GST_JACK_TRANSPORT_AUTONOMOUS
+#define DEFAULT_PROP_LOW_LATENCY  FALSE
 
 enum
 {
@@ -695,6 +698,7 @@ enum
   PROP_CLIENT_NAME,
   PROP_PORT_PATTERN,
   PROP_TRANSPORT,
+  PROP_LOW_LATENCY,
   PROP_LAST
 };
 
@@ -786,6 +790,23 @@ gst_jack_audio_sink_class_init (GstJackAudioSinkClass * klass)
           GST_TYPE_JACK_TRANSPORT, DEFAULT_PROP_TRANSPORT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstJackAudioSink:low-latency:
+   *
+   * Optimize all settings for lowest latency. When enabled,
+   * #GstAudioBaseSink:buffer-time and #GstAudioBaseSink:latency-time will be
+   * ignored.
+   *
+   * Since: 1.20
+   */
+  g_object_class_install_property (gobject_class, PROP_LOW_LATENCY,
+      g_param_spec_boolean ("low-latency", "Low latency",
+          "Optimize all settings for lowest latency. When enabled, "
+          "\"buffer-time\" and \"latency-time\" will be ignored",
+          DEFAULT_PROP_LOW_LATENCY,
+          GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
+          G_PARAM_STATIC_STRINGS));
+
   gst_element_class_set_static_metadata (gstelement_class, "Audio Sink (Jack)",
       "Sink/Audio", "Output audio to a JACK server",
       "Wim Taymans <wim.taymans@gmail.com>");
@@ -816,6 +837,7 @@ gst_jack_audio_sink_init (GstJackAudioSink * sink)
   sink->buffers = NULL;
   sink->client_name = g_strdup (DEFAULT_PROP_CLIENT_NAME);
   sink->transport = DEFAULT_PROP_TRANSPORT;
+  sink->low_latency = DEFAULT_PROP_LOW_LATENCY;
 }
 
 static void
@@ -871,6 +893,9 @@ gst_jack_audio_sink_set_property (GObject * object, guint prop_id,
     case PROP_TRANSPORT:
       sink->transport = g_value_get_flags (value);
       break;
+    case PROP_LOW_LATENCY:
+      sink->low_latency = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -904,6 +929,9 @@ gst_jack_audio_sink_get_property (GObject * object, guint prop_id,
     case PROP_TRANSPORT:
       g_value_set_flags (value, sink->transport);
       break;
+    case PROP_LOW_LATENCY:
+      g_value_set_boolean (value, sink->low_latency);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 4be821c..ffba824 100644 (file)
@@ -55,6 +55,7 @@ struct _GstJackAudioSink {
   gchar           *client_name;
   gchar           *port_pattern;
   guint            transport;
+  gboolean         low_latency;
 
   /* our client */
   GstJackAudioClient *client;
index fa8ad9f..11f4f91 100644 (file)
@@ -443,7 +443,9 @@ gst_jack_ring_buffer_acquire (GstAudioRingBuffer * buf,
       (GST_SECOND / GST_USECOND), rate * bpf);
   /* segtotal based on buffer-time latency */
   spec->segtotal = spec->buffer_time / spec->latency_time;
-  if (spec->segtotal < 2) {
+
+  /* Use small period when low-latency is enabled regardless of buffer-time */
+  if (spec->segtotal < 2 || src->low_latency) {
     spec->segtotal = 2;
     spec->buffer_time = spec->latency_time * spec->segtotal;
   }
@@ -687,6 +689,8 @@ enum
 #define DEFAULT_PROP_CLIENT_NAME       NULL
 #define DEFAULT_PROP_TRANSPORT GST_JACK_TRANSPORT_AUTONOMOUS
 #define DEFAULT_PROP_PORT_PATTERN      NULL
+#define DEFAULT_PROP_LOW_LATENCY  FALSE
+
 enum
 {
   PROP_0,
@@ -696,6 +700,7 @@ enum
   PROP_CLIENT_NAME,
   PROP_PORT_PATTERN,
   PROP_TRANSPORT,
+  PROP_LOW_LATENCY,
   PROP_LAST
 };
 
@@ -803,6 +808,23 @@ gst_jack_audio_src_class_init (GstJackAudioSrcClass * klass)
           GST_TYPE_JACK_TRANSPORT, DEFAULT_PROP_TRANSPORT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstJackAudioSrc:low-latency:
+   *
+   * Optimize all settings for lowest latency. When enabled,
+   * #GstAudioBaseSrc:buffer-time and #GstAudioBaseSrc:latency-time will be
+   * ignored.
+   *
+   * Since: 1.20
+   */
+  g_object_class_install_property (gobject_class, PROP_LOW_LATENCY,
+      g_param_spec_boolean ("low-latency", "Low latency",
+          "Optimize all settings for lowest latency. When enabled, "
+          "\"buffer-time\" and \"latency-time\" will be ignored",
+          DEFAULT_PROP_LOW_LATENCY,
+          GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
+          G_PARAM_STATIC_STRINGS));
+
   gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
 
   gst_element_class_set_static_metadata (gstelement_class,
@@ -833,6 +855,7 @@ gst_jack_audio_src_init (GstJackAudioSrc * src)
   src->buffers = NULL;
   src->client_name = g_strdup (DEFAULT_PROP_CLIENT_NAME);
   src->transport = DEFAULT_PROP_TRANSPORT;
+  src->low_latency = DEFAULT_PROP_LOW_LATENCY;
 }
 
 static void
@@ -886,6 +909,9 @@ gst_jack_audio_src_set_property (GObject * object, guint prop_id,
     case PROP_TRANSPORT:
       src->transport = g_value_get_flags (value);
       break;
+    case PROP_LOW_LATENCY:
+      src->low_latency = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -917,6 +943,9 @@ gst_jack_audio_src_get_property (GObject * object, guint prop_id,
     case PROP_TRANSPORT:
       g_value_set_flags (value, src->transport);
       break;
+    case PROP_LOW_LATENCY:
+      g_value_set_boolean (value, src->low_latency);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 52209b6..d6b08b9 100644 (file)
@@ -72,6 +72,7 @@ struct _GstJackAudioSrc
     gchar           *client_name;
     gchar           *port_pattern;
     guint            transport;
+    gboolean         low_latency;
 
     /* our client */
     GstJackAudioClient *client;