bluetooth: Register an endpoint according to encode or decode support
authorSanchayan Maity <sanchayan@asymptotic.io>
Thu, 7 Jan 2021 12:22:22 +0000 (17:52 +0530)
committerSanchayan Maity <sanchayan@asymptotic.io>
Tue, 19 Jan 2021 08:13:42 +0000 (13:43 +0530)
As we now support codecs other than SBC, we might have codec which does
not have an encode or a decode capability. Specifically, in the case of
LDAC there isn't a known decoder implementation available. For such a
case, we should not register the corresponding endpoint.

In case of LDAC, as decoding cannot be supported, we should not register
a sink endpoint or vice versa in the other scenario.

To do this, we check if encode_buffer or decode_buffer entry for a codec
has been set in pa_a2dp_codec and accordingly prevent or allow it's
registration.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/440>

src/modules/bluetooth/a2dp-codec-util.c
src/modules/bluetooth/a2dp-codec-util.h
src/modules/bluetooth/bluez5-util.c

index 71482cd..d3d763b 100644 (file)
@@ -88,3 +88,17 @@ void pa_bluetooth_a2dp_codec_gst_init(void) {
     pa_log_info("GStreamer initialisation done");
 #endif
 }
+
+bool pa_bluetooth_a2dp_codec_is_codec_available(const pa_a2dp_codec_id *id, bool is_a2dp_sink) {
+    unsigned int i;
+    unsigned int count = pa_bluetooth_a2dp_codec_count();
+
+    for (i = 0; i < count; i++) {
+        if (memcmp(id, &pa_a2dp_codecs[i]->id, sizeof(pa_a2dp_codec_id)) == 0) {
+            return (is_a2dp_sink && pa_a2dp_codecs[i]->encode_buffer != NULL)
+                || (!is_a2dp_sink && pa_a2dp_codecs[i]->decode_buffer != NULL);
+        }
+    }
+
+    return false;
+}
index 22fa8f6..3c6b800 100644 (file)
@@ -31,6 +31,9 @@ const pa_a2dp_codec *pa_bluetooth_a2dp_codec_iter(unsigned int i);
 /* Get codec by name */
 const pa_a2dp_codec *pa_bluetooth_get_a2dp_codec(const char *name);
 
+/* Check if the given codec can be supported in A2DP_SINK or A2DP_SOURCE */
+bool pa_bluetooth_a2dp_codec_is_codec_available(const pa_a2dp_codec_id *id, bool is_a2dp_sink);
+
 /* Initialise GStreamer */
 void pa_bluetooth_a2dp_codec_gst_init(void);
 
index 4d0180a..5017e45 100644 (file)
@@ -1335,6 +1335,11 @@ static void parse_remote_endpoint_properties(pa_bluetooth_discovery *y, const ch
         a2dp_codec_id->vendor_codec_id = 0;
     }
 
+    if (!pa_bluetooth_a2dp_codec_is_codec_available(a2dp_codec_id, pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK))) {
+        pa_xfree(a2dp_codec_id);
+        return;
+    }
+
     a2dp_codec_capabilities = pa_xmalloc0(sizeof(*a2dp_codec_capabilities) + capabilities_size);
     a2dp_codec_capabilities->size = capabilities_size;
     memcpy(a2dp_codec_capabilities->buffer, capabilities, capabilities_size);
@@ -2108,15 +2113,19 @@ static DBusHandlerResult object_manager_handler(DBusConnection *c, DBusMessage *
             capabilities_size = a2dp_codec->fill_capabilities(capabilities);
             pa_assert(capabilities_size != 0);
 
-            endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
-            append_a2dp_object(&array, endpoint, PA_BLUETOOTH_UUID_A2DP_SINK, codec_id,
-                    capabilities, capabilities_size);
-            pa_xfree(endpoint);
+            if (a2dp_codec->decode_buffer != NULL) {
+                endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
+                append_a2dp_object(&array, endpoint, PA_BLUETOOTH_UUID_A2DP_SINK, codec_id,
+                        capabilities, capabilities_size);
+                pa_xfree(endpoint);
+            }
 
-            endpoint = pa_sprintf_malloc("%s/%s", A2DP_SOURCE_ENDPOINT, a2dp_codec->name);
-            append_a2dp_object(&array, endpoint, PA_BLUETOOTH_UUID_A2DP_SOURCE, codec_id,
-                    capabilities, capabilities_size);
-            pa_xfree(endpoint);
+            if (a2dp_codec->encode_buffer != NULL) {
+                endpoint = pa_sprintf_malloc("%s/%s", A2DP_SOURCE_ENDPOINT, a2dp_codec->name);
+                append_a2dp_object(&array, endpoint, PA_BLUETOOTH_UUID_A2DP_SOURCE, codec_id,
+                        capabilities, capabilities_size);
+                pa_xfree(endpoint);
+            }
         }
 
         dbus_message_iter_close_container(&iter, &array);
@@ -2214,13 +2223,17 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c, int headset_backe
         if (!a2dp_codec->can_be_supported())
             continue;
 
-        endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
-        endpoint_init(y, endpoint);
-        pa_xfree(endpoint);
+        if (a2dp_codec->decode_buffer != NULL) {
+            endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
+            endpoint_init(y, endpoint);
+            pa_xfree(endpoint);
+        }
 
-        endpoint = pa_sprintf_malloc("%s/%s", A2DP_SOURCE_ENDPOINT, a2dp_codec->name);
-        endpoint_init(y, endpoint);
-        pa_xfree(endpoint);
+        if (a2dp_codec->encode_buffer != NULL) {
+            endpoint = pa_sprintf_malloc("%s/%s", A2DP_SOURCE_ENDPOINT, a2dp_codec->name);
+            endpoint_init(y, endpoint);
+            pa_xfree(endpoint);
+        }
     }
 
     get_managed_objects(y);
@@ -2304,13 +2317,17 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
             if (!a2dp_codec->can_be_supported())
                 continue;
 
-            endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
-            endpoint_done(y, endpoint);
-            pa_xfree(endpoint);
+            if (a2dp_codec->decode_buffer != NULL) {
+                endpoint = pa_sprintf_malloc("%s/%s", A2DP_SINK_ENDPOINT, a2dp_codec->name);
+                endpoint_done(y, endpoint);
+                pa_xfree(endpoint);
+            }
 
-            endpoint = pa_sprintf_malloc("%s/%s", A2DP_SOURCE_ENDPOINT, a2dp_codec->name);
-            endpoint_done(y, endpoint);
-            pa_xfree(endpoint);
+            if (a2dp_codec->encode_buffer != NULL) {
+                endpoint = pa_sprintf_malloc("%s/%s", A2DP_SOURCE_ENDPOINT, a2dp_codec->name);
+                endpoint_done(y, endpoint);
+                pa_xfree(endpoint);
+            }
         }
 
         pa_dbus_connection_unref(y->connection);