diff --git a/src/modules/bluetooth/a2dp-codec-api.h b/src/modules/bluetooth/a2dp-codec-api.h index a3123f4ca..61c66de88 100644 --- a/src/modules/bluetooth/a2dp-codec-api.h +++ b/src/modules/bluetooth/a2dp-codec-api.h @@ -48,6 +48,9 @@ typedef struct pa_a2dp_codec { /* True if codec is bi-directional and supports backchannel */ bool support_backchannel; + /* Returns true if the codec can be supported on the system */ + bool (*can_be_supported)(void); + /* Returns true if codec accepts capabilities, for_encoding is true when * capabilities are used for encoding */ bool (*can_accept_capabilities)(const uint8_t *capabilities_buffer, uint8_t capabilities_size, bool for_encoding); diff --git a/src/modules/bluetooth/a2dp-codec-aptx-gst.c b/src/modules/bluetooth/a2dp-codec-aptx-gst.c index 11132162b..600ee99d3 100644 --- a/src/modules/bluetooth/a2dp-codec-aptx-gst.c +++ b/src/modules/bluetooth/a2dp-codec-aptx-gst.c @@ -33,6 +33,28 @@ #include "a2dp-codec-gst.h" #include "rtp.h" +static bool can_be_supported(void) { + GstElementFactory *element_factory; + + element_factory = gst_element_factory_find("openaptxenc"); + if (element_factory == NULL) { + pa_log_info("aptX encoder not found"); + return false; + } + + gst_object_unref(element_factory); + + element_factory = gst_element_factory_find("openaptxdec"); + if (element_factory == NULL) { + pa_log_info("aptX decoder not found"); + return false; + } + + gst_object_unref(element_factory); + + return true; +} + static bool can_accept_capabilities_common(const a2dp_aptx_t *capabilities, uint32_t vendor_id, uint16_t codec_id) { if (A2DP_GET_VENDOR_ID(capabilities->info) != vendor_id || A2DP_GET_CODEC_ID(capabilities->info) != codec_id) return false; @@ -359,6 +381,7 @@ const pa_a2dp_codec pa_a2dp_codec_aptx = { .description = "aptX", .id = { A2DP_CODEC_VENDOR, APTX_VENDOR_ID, APTX_CODEC_ID }, .support_backchannel = false, + .can_be_supported = can_be_supported, .can_accept_capabilities = can_accept_capabilities, .choose_remote_endpoint = choose_remote_endpoint, .fill_capabilities = fill_capabilities, @@ -379,6 +402,7 @@ const pa_a2dp_codec pa_a2dp_codec_aptx_hd = { .description = "aptX HD", .id = { A2DP_CODEC_VENDOR, APTX_HD_VENDOR_ID, APTX_HD_CODEC_ID }, .support_backchannel = false, + .can_be_supported = can_be_supported, .can_accept_capabilities = can_accept_capabilities_hd, .choose_remote_endpoint = choose_remote_endpoint_hd, .fill_capabilities = fill_capabilities_hd, diff --git a/src/modules/bluetooth/a2dp-codec-gst.c b/src/modules/bluetooth/a2dp-codec-gst.c index c714c1d34..958f6ec20 100644 --- a/src/modules/bluetooth/a2dp-codec-gst.c +++ b/src/modules/bluetooth/a2dp-codec-gst.c @@ -575,15 +575,8 @@ fail: void *gst_codec_init(enum a2dp_codec_type codec_type, const uint8_t *config_buffer, uint8_t config_size, pa_sample_spec *ss) { struct gst_info *info = NULL; - GError *error = NULL; bool ret; - if (!gst_init_check(NULL, NULL, &error)) { - pa_log_error("Could not initialise GStreamer: %s", error->message); - g_error_free(error); - goto fail; - } - info = pa_xnew0(struct gst_info, 1); pa_assert(info); diff --git a/src/modules/bluetooth/a2dp-codec-ldac-gst.c b/src/modules/bluetooth/a2dp-codec-ldac-gst.c index 724275293..2f8e729d2 100644 --- a/src/modules/bluetooth/a2dp-codec-ldac-gst.c +++ b/src/modules/bluetooth/a2dp-codec-ldac-gst.c @@ -33,6 +33,20 @@ #include "a2dp-codec-gst.h" #include "rtp.h" +static bool can_be_supported(void) { + GstElementFactory *element_factory; + + element_factory = gst_element_factory_find("ldacenc"); + if (element_factory == NULL) { + pa_log_info("LDAC encoder not found"); + return false; + } + + gst_object_unref(element_factory); + + return true; +} + static bool can_accept_capabilities_common(const a2dp_ldac_t *capabilities, uint32_t vendor_id, uint16_t codec_id) { if (A2DP_GET_VENDOR_ID(capabilities->info) != vendor_id || A2DP_GET_CODEC_ID(capabilities->info) != codec_id) return false; @@ -276,6 +290,7 @@ const pa_a2dp_codec pa_a2dp_codec_ldac_eqmid_hq = { .description = "LDAC (High Quality)", .id = { A2DP_CODEC_VENDOR, LDAC_VENDOR_ID, LDAC_CODEC_ID }, .support_backchannel = false, + .can_be_supported = can_be_supported, .can_accept_capabilities = can_accept_capabilities, .choose_remote_endpoint = choose_remote_endpoint, .fill_capabilities = fill_capabilities, @@ -295,6 +310,7 @@ const pa_a2dp_codec pa_a2dp_codec_ldac_eqmid_sq = { .description = "LDAC (Standard Quality)", .id = { A2DP_CODEC_VENDOR, LDAC_VENDOR_ID, LDAC_CODEC_ID }, .support_backchannel = false, + .can_be_supported = can_be_supported, .can_accept_capabilities = can_accept_capabilities, .choose_remote_endpoint = choose_remote_endpoint, .fill_capabilities = fill_capabilities, @@ -314,6 +330,7 @@ const pa_a2dp_codec pa_a2dp_codec_ldac_eqmid_mq = { .description = "LDAC (Mobile Quality)", .id = { A2DP_CODEC_VENDOR, LDAC_VENDOR_ID, LDAC_CODEC_ID }, .support_backchannel = false, + .can_be_supported = can_be_supported, .can_accept_capabilities = can_accept_capabilities, .choose_remote_endpoint = choose_remote_endpoint, .fill_capabilities = fill_capabilities, diff --git a/src/modules/bluetooth/a2dp-codec-sbc.c b/src/modules/bluetooth/a2dp-codec-sbc.c index 89c647fbe..660f01100 100644 --- a/src/modules/bluetooth/a2dp-codec-sbc.c +++ b/src/modules/bluetooth/a2dp-codec-sbc.c @@ -53,6 +53,10 @@ struct sbc_info { uint8_t max_bitpool; }; +static bool can_be_supported(void) { + return true; +} + static bool can_accept_capabilities(const uint8_t *capabilities_buffer, uint8_t capabilities_size, bool for_encoding) { const a2dp_sbc_t *capabilities = (const a2dp_sbc_t *) capabilities_buffer; @@ -666,6 +670,7 @@ const pa_a2dp_codec pa_a2dp_codec_sbc = { .description = "SBC", .id = { A2DP_CODEC_SBC, 0, 0 }, .support_backchannel = false, + .can_be_supported = can_be_supported, .can_accept_capabilities = can_accept_capabilities, .choose_remote_endpoint = choose_remote_endpoint, .fill_capabilities = fill_capabilities, diff --git a/src/modules/bluetooth/a2dp-codec-util.c b/src/modules/bluetooth/a2dp-codec-util.c index 28109988f..71482cdbf 100644 --- a/src/modules/bluetooth/a2dp-codec-util.c +++ b/src/modules/bluetooth/a2dp-codec-util.c @@ -23,6 +23,9 @@ #include #include +#if defined(HAVE_GSTAPTX) || defined(HAVE_GSTLDAC) +#include +#endif #include "a2dp-codec-util.h" @@ -72,3 +75,16 @@ const pa_a2dp_codec *pa_bluetooth_get_a2dp_codec(const char *name) { return NULL; } + +void pa_bluetooth_a2dp_codec_gst_init(void) { +#if defined(HAVE_GSTAPTX) || defined(HAVE_GSTLDAC) + GError *error = NULL; + + if (!gst_init_check(NULL, NULL, &error)) { + pa_log_error("Could not initialise GStreamer: %s", error->message); + g_error_free(error); + return; + } + pa_log_info("GStreamer initialisation done"); +#endif +} diff --git a/src/modules/bluetooth/a2dp-codec-util.h b/src/modules/bluetooth/a2dp-codec-util.h index 86f233a21..22fa8f65f 100644 --- a/src/modules/bluetooth/a2dp-codec-util.h +++ b/src/modules/bluetooth/a2dp-codec-util.h @@ -31,4 +31,7 @@ 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); +/* Initialise GStreamer */ +void pa_bluetooth_a2dp_codec_gst_init(void); + #endif diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c index f46ad5c8e..76c53c21d 100644 --- a/src/modules/bluetooth/bluez5-util.c +++ b/src/modules/bluetooth/bluez5-util.c @@ -2150,6 +2150,7 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c, int headset_backe const pa_a2dp_codec *a2dp_codec; char *endpoint; + pa_bluetooth_a2dp_codec_gst_init(); y = pa_xnew0(pa_bluetooth_discovery, 1); PA_REFCNT_INIT(y); y->core = c;