mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-07-05 00:06:16 -04:00
bluez5: fix shared A2DP endpoint caps including disabled companion codecs
Codecs that share an A2DP endpoint (e.g. aac + aac_eld) previously used an asymmetric pattern: one codec (the "owner") had fill_caps and quietly advertised the union of all siblings' capability bits; companions had fill_caps = NULL. This caused a bug: when aac_eld is absent from bluez5.codecs, the "aac" endpoint still advertised the ELD object-type bit because a2dp_codec_aac's fill_caps emitted it unconditionally (gated only by eld_supported(), never by enabled_codecs). A remote could then select ELD; SetConfiguration resolved the transport to a2dp_codec_aac (the only fill_caps holder for "aac") Refactor to a symmetric, composable model: - Add bool endpoint_companion to struct media_codec (default false = owner). Companion codec objects set this flag instead of fill_caps = NULL. - Add combine_caps() function to struct media_codec. Owners that share an endpoint implement this to union two capability blobs of the same codec_id. - Each codec's fill_caps now describes only its own bits. AAC LC advertises only LC object types; AAC ELD advertises only the ELD type (or returns -ENOTSUP when FDK-AAC lacks ELD support). - Bump SPA_VERSION_BLUEZ5_CODEC_MEDIA 16 -> 17. On the monitor side (bluez5-dbus.c): - New media_codec_fill_endpoint_caps() helper fills the owner's caps then walks enabled companions on the same endpoint and merges each via combine_caps. All five endpoint-registration fill_caps call sites are routed through this helper. - endpoint_should_be_registered() gates on !endpoint_companion (not on fill_caps != NULL), so companions correctly skip endpoint registration. - media_endpoint_to_codec() now filters by is_media_codec_enabled and prefers owners as a tiebreaker. - New media_endpoint_to_codec_for_config() resolves SetConfiguration by calling each enabled candidate's validate_config against the negotiated config bytes. This ensures that an "aac" endpoint carrying ELD bytes is mapped to a2dp_codec_aac_eld (not a2dp_codec_aac). - AAC validate_config and codec_init are id-gated so a stale ELD config can never be decoded by the LC codec object. Assisted-by: Claude Opus 4.7
This commit is contained in:
parent
0a413c866c
commit
4e46489964
6 changed files with 281 additions and 78 deletions
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#define SPA_TYPE_INTERFACE_Bluez5CodecMedia SPA_TYPE_INFO_INTERFACE_BASE "Bluez5:Codec:Media:Private"
|
||||
|
||||
#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 16
|
||||
#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 17
|
||||
|
||||
struct spa_bluez5_codec_a2dp {
|
||||
struct spa_interface iface;
|
||||
|
|
@ -93,14 +93,37 @@ struct media_codec {
|
|||
* After successful decode, start_decode() should be
|
||||
* called again to parse the remaining data. */
|
||||
|
||||
/** True for codecs that share an endpoint with another codec and let
|
||||
* that other codec own the endpoint registration. The owner's caps
|
||||
* are advertised, with enabled companions merged in via combine_caps.
|
||||
* The default (false) means this codec owns its endpoint; set this
|
||||
* to true only on companion codec objects (e.g. aac_eld, sbc_xq).
|
||||
*/
|
||||
bool endpoint_companion;
|
||||
|
||||
int (*get_bis_config)(const struct media_codec *codec, uint8_t *caps,
|
||||
uint8_t *caps_size, struct spa_dict *settings,
|
||||
struct bap_codec_qos *qos);
|
||||
|
||||
/** If fill_caps is NULL, no endpoint is registered (for sharing with another codec). */
|
||||
/** Fill in this codec's own capability bits.
|
||||
* For codecs that share an endpoint, only the bits belonging to this
|
||||
* codec object are advertised; the monitor merges siblings using
|
||||
* combine_caps on the endpoint owner. May be NULL on a companion
|
||||
* codec whose advertised caps are identical to the owner's.
|
||||
*/
|
||||
int (*fill_caps) (const struct media_codec *codec, uint32_t flags,
|
||||
const struct spa_dict *settings, uint8_t caps[A2DP_MAX_CAPS_SIZE]);
|
||||
|
||||
/** Merge another sibling codec's caps blob (same codec_id) into caps.
|
||||
* Only required on the endpoint owner when an enabled companion's
|
||||
* caps differ from the owner's. If NULL, only the owner's caps are
|
||||
* advertised and companions' fill_caps is not called.
|
||||
* Returns the new caps_size, or < 0 on error.
|
||||
*/
|
||||
int (*combine_caps) (const struct media_codec *codec, uint32_t flags,
|
||||
uint8_t caps[A2DP_MAX_CAPS_SIZE], int caps_size,
|
||||
const uint8_t *other, int other_size);
|
||||
|
||||
int (*select_config) (const struct media_codec *codec, uint32_t flags,
|
||||
const void *caps, size_t caps_size,
|
||||
const struct media_codec_audio_info *info,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue