bluetooth: Keep track of the first codec to use in every endpoint

This commit is contained in:
Marijn Suijten 2021-01-20 00:29:16 +01:00
parent 173c3e6100
commit 2ff659f882
5 changed files with 34 additions and 18 deletions

View file

@ -25,7 +25,10 @@
#define MAX_A2DP_CAPS_SIZE 254 #define MAX_A2DP_CAPS_SIZE 254
#define DEFAULT_OUTPUT_RATE_REFRESH_INTERVAL_MS 500 #define DEFAULT_OUTPUT_RATE_REFRESH_INTERVAL_MS 500
typedef struct pa_a2dp_codec pa_a2dp_codec;
typedef struct pa_a2dp_codec_capabilities { typedef struct pa_a2dp_codec_capabilities {
const pa_a2dp_codec *first_codec; /* First codec to use */
uint8_t size; uint8_t size;
uint8_t buffer[]; /* max size is 254 bytes */ uint8_t buffer[]; /* max size is 254 bytes */
} pa_a2dp_codec_capabilities; } pa_a2dp_codec_capabilities;

View file

@ -109,3 +109,20 @@ bool pa_bluetooth_a2dp_codec_is_available(const pa_a2dp_codec_id *id, bool is_a2
return false; return false;
} }
const pa_a2dp_codec *pa_bluetooth_a2dp_codec_find_with_capabilities(const pa_a2dp_codec_id *id, const uint8_t *capabilities, int capabilities_size, bool for_encoding) {
for (unsigned i = 0; i < pa_bluetooth_a2dp_codec_count(); ++i) {
const pa_a2dp_codec *a2dp_codec = pa_bluetooth_a2dp_codec_iter(i);
if (!memcmp(id, &a2dp_codec->id, sizeof(pa_a2dp_codec_id)) == 0)
continue;
if (!a2dp_codec->can_be_supported(for_encoding))
continue;
if (a2dp_codec->can_accept_capabilities(capabilities, capabilities_size, for_encoding))
return a2dp_codec;
}
return NULL;
}

View file

@ -34,6 +34,9 @@ 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 */ /* Check if the given codec can be supported in A2DP_SINK or A2DP_SOURCE */
bool pa_bluetooth_a2dp_codec_is_available(const pa_a2dp_codec_id *id, bool is_a2dp_sink); bool pa_bluetooth_a2dp_codec_is_available(const pa_a2dp_codec_id *id, bool is_a2dp_sink);
/* Check if the given codec and capability pair can be supported in A2DP_SINK or A2DP_SOURCE */
const pa_a2dp_codec *pa_bluetooth_a2dp_codec_find_with_capabilities(const pa_a2dp_codec_id *id, const uint8_t *capabilities, int capabilities_size, bool for_encoding);
/* Initialise GStreamer */ /* Initialise GStreamer */
void pa_bluetooth_a2dp_codec_gst_init(void); void pa_bluetooth_a2dp_codec_gst_init(void);

View file

@ -1357,12 +1357,16 @@ static void parse_remote_endpoint_properties(pa_bluetooth_discovery *y, const ch
a2dp_codec_id->vendor_codec_id = 0; a2dp_codec_id->vendor_codec_id = 0;
} }
if (!pa_bluetooth_a2dp_codec_is_available(a2dp_codec_id, pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK))) { const pa_a2dp_codec *codec = pa_bluetooth_a2dp_codec_find_with_capabilities(a2dp_codec_id, capabilities, capabilities_size, pa_streq(uuid, PA_BLUETOOTH_UUID_A2DP_SINK));
if (!codec) {
// TODO: We should pretty-print `a2dp_codec_id` here!
pa_xfree(a2dp_codec_id); pa_xfree(a2dp_codec_id);
return; return;
} }
a2dp_codec_capabilities = pa_xmalloc0(sizeof(*a2dp_codec_capabilities) + capabilities_size); a2dp_codec_capabilities = pa_xmalloc0(sizeof(*a2dp_codec_capabilities) + capabilities_size);
a2dp_codec_capabilities->first_codec = codec;
a2dp_codec_capabilities->size = capabilities_size; a2dp_codec_capabilities->size = capabilities_size;
memcpy(a2dp_codec_capabilities->buffer, capabilities, capabilities_size); memcpy(a2dp_codec_capabilities->buffer, capabilities, capabilities_size);

View file

@ -2460,7 +2460,6 @@ static char *list_codecs(struct userdata *u) {
pa_hashmap *a2dp_endpoints; pa_hashmap *a2dp_endpoints;
pa_hashmap *a2dp_capabilities; pa_hashmap *a2dp_capabilities;
pa_json_encoder *encoder; pa_json_encoder *encoder;
unsigned int i;
bool is_a2dp_sink; bool is_a2dp_sink;
void *state, *state2; void *state, *state2;
@ -2473,25 +2472,15 @@ static char *list_codecs(struct userdata *u) {
pa_json_encoder_begin_element_array(encoder); pa_json_encoder_begin_element_array(encoder);
PA_HASHMAP_FOREACH_KV(key, a2dp_capabilities, a2dp_endpoints, state) { PA_HASHMAP_FOREACH_KV(key, a2dp_capabilities, a2dp_endpoints, state) {
for (i = 0; i < pa_bluetooth_a2dp_codec_count(); i++) {
const pa_a2dp_codec *a2dp_codec;
a2dp_codec = pa_bluetooth_a2dp_codec_iter(i);
if (memcmp(key, &a2dp_codec->id, sizeof(pa_a2dp_codec_id)) == 0) {
PA_HASHMAP_FOREACH(a2dp_capability, a2dp_capabilities, state2) { PA_HASHMAP_FOREACH(a2dp_capability, a2dp_capabilities, state2) {
if (a2dp_codec->can_accept_capabilities(a2dp_capability->buffer, a2dp_capability->size, /* For encoding */ is_a2dp_sink)) { const pa_a2dp_codec *a2dp_codec = a2dp_capability->first_codec;
pa_json_encoder_begin_element_object(encoder); pa_json_encoder_begin_element_object(encoder);
pa_json_encoder_add_member_string(encoder, "name", a2dp_codec->name); pa_json_encoder_add_member_string(encoder, "name", a2dp_codec->name);
pa_json_encoder_add_member_string(encoder, "description", a2dp_codec->description); pa_json_encoder_add_member_string(encoder, "description", a2dp_codec->description);
pa_json_encoder_end_object(encoder); pa_json_encoder_end_object(encoder);
break;
}
}
}
} }
} }