bluez5: allow codecs to share endpoints

AVDTP in principle allows 62 endpoints, but in practice it appears some
devices (Samsung Galaxy Buds2 Pro, Redmi Buds 3 Lite, probably others)
fail to connect A2DP when the number is somewhere above 24.  A2DP
connection works when initiated from the Central, but not when the
device itself does it, so these devices are not fully broken.  We should
reduce the number of registered A2DP endpoints to avoid running into
problems with such broken devices.

Some of our source codecs are the same actual codec with the same
configuration, and don't need separate source endpoints.

Allow codecs to not have a registered endpoint (fill_caps == NULL), and
tolerate codecs with the same endpoint name.  In codec switch, keep
track separately which of the codecs with the same endpoint name the
local endpoint is currently associated with.
This commit is contained in:
Pauli Virtanen 2022-10-23 14:05:05 +03:00
parent 99406aefea
commit d94832942e
4 changed files with 100 additions and 52 deletions

View file

@ -126,8 +126,12 @@ static int load_media_codecs_from(struct impl *impl, const char *factory_name, c
for (i = 0; bluez5_codec_a2dp->codecs[i]; ++i) {
const struct media_codec *c = bluez5_codec_a2dp->codecs[i];
const char *ep = c->endpoint_name ? c->endpoint_name : c->name;
size_t j;
if (!ep)
goto next_codec;
if (impl->n_codecs >= MAX_CODECS) {
spa_log_error(impl->log, "too many A2DP codecs");
break;
@ -136,13 +140,16 @@ static int load_media_codecs_from(struct impl *impl, const char *factory_name, c
/* Don't load duplicate endpoints */
for (j = 0; j < impl->n_codecs; ++j) {
const struct media_codec *c2 = impl->codecs[j];
const char *ep1 = c->endpoint_name ? c->endpoint_name : c->name;
const char *ep2 = c2->endpoint_name ? c2->endpoint_name : c2->name;
if (spa_streq(ep1, ep2))
if (spa_streq(ep, ep2) && c->fill_caps && c2->fill_caps) {
spa_log_debug(impl->log, "media codec %s from %s duplicate endpoint %s",
c->name, factory_name, ep);
goto next_codec;
}
}
spa_log_debug(impl->log, "loaded media codec %s from %s", c->name, factory_name);
spa_log_debug(impl->log, "loaded media codec %s from %s, endpoint:%s",
c->name, factory_name, ep);
if (c->set_log)
c->set_log(impl->log);