From be3e87f485a438dbed08e5ff912fbd94c928b6be Mon Sep 17 00:00:00 2001 From: Silviu Florian Barbulescu Date: Fri, 10 May 2024 16:25:50 +0300 Subject: [PATCH] Add code to fix problem found at review --- doc/dox/config/pipewire-devices.7.md | 25 ++++ spa/plugins/bluez5/bap-codec-lc3.c | 198 ++++++++++++++------------- spa/plugins/bluez5/bluez5-dbus.c | 88 ++++++++---- spa/plugins/bluez5/media-codecs.h | 6 +- 4 files changed, 189 insertions(+), 128 deletions(-) diff --git a/doc/dox/config/pipewire-devices.7.md b/doc/dox/config/pipewire-devices.7.md index 22400beb7..8dadfbab2 100644 --- a/doc/dox/config/pipewire-devices.7.md +++ b/doc/dox/config/pipewire-devices.7.md @@ -423,6 +423,31 @@ PipeWire Opus Pro audio profile duplex max bitrate. @PAR@ device-param bluez5.a2dp.opus.pro.bidi.frame-dms = 400 # integer PipeWire Opus Pro audio profile duplex frame duration (1/10 ms). +@PAR@ device-param bluez5.bcast_source.config # JSON +\parblock +example JSON +{ + "broadcast_code": [ // broadcast code + 1, 2, 104, 5, 83, 241, 65, 90, 162, 101, 187, 175, 198, 234, 3, 184 + ], + "bis": [ + { // BIS configuration + "qos_preset": "16_2_1", // QOS preset name from table Table 6.4 from BAP_v1.0.1. + "audio_channel_allocation": 1, // audio channel allocation configuration for the BIS + "metadata": [ // metadata configurations for the BIS + { + "length": 3, + "type": 1, + "value": [ + 1, 1 + ] + } + ] + } + ] +} +\endparblock + ## Device properties @PAR@ device-param bluez5.auto-connect # boolean diff --git a/spa/plugins/bluez5/bap-codec-lc3.c b/spa/plugins/bluez5/bap-codec-lc3.c index 56eb62873..6d996a733 100644 --- a/spa/plugins/bluez5/bap-codec-lc3.c +++ b/spa/plugins/bluez5/bap-codec-lc3.c @@ -48,6 +48,7 @@ struct pac_data { }; struct bap_qos { + char *name; uint8_t rate; uint8_t frame_duration; bool framing; @@ -103,100 +104,91 @@ static const struct { { BAP_CHANNEL_RS, SPA_AUDIO_CHANNEL_SR }, /* is it the right mapping? */ }; -struct bap_qos_preset { - char *name; - struct bap_qos qos; -}; - -#define BAP_QOS(rate_, duration_, framing_, framelen_, rtn_, latency_, delay_, priority_) \ - ((struct bap_qos){ .rate = (rate_), .frame_duration = (duration_), .framing = (framing_), \ +#define BAP_QOS(name_, rate_, duration_, framing_, framelen_, rtn_, latency_, delay_, priority_) \ + ((struct bap_qos){ .name = (name_), .rate = (rate_), .frame_duration = (duration_), .framing = (framing_), \ .framelen = (framelen_), .retransmission = (rtn_), .latency = (latency_), \ .delay = (delay_), .priority = (priority_) }) -#define BAP_PRESET_QOS(name_, rate_, duration_, framing_, framelen_, rtn_, latency_, delay_, priority_) \ - ((struct bap_qos_preset){ .name = name_, .qos = BAP_QOS(rate_, duration_, framing_, framelen_, \ - rtn_, latency_, delay_, priority_)}) - static const struct bap_qos bap_qos_configs[] = { /* Priority: low-latency > high-reliability, 7.5ms > 10ms, * bigger frequency and sdu better */ /* BAP v1.0.1 Table 5.2; low-latency */ - BAP_QOS(LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 2, 8, 40000, 30), /* 8_1_1 */ - BAP_QOS(LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 2, 10, 40000, 20), /* 8_2_1 */ - BAP_QOS(LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 2, 8, 40000, 31), /* 16_1_1 */ - BAP_QOS(LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 2, 10, 40000, 21), /* 16_2_1 (mandatory) */ - BAP_QOS(LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 2, 8, 40000, 32), /* 24_1_1 */ - BAP_QOS(LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 2, 10, 40000, 22), /* 24_2_1 */ - BAP_QOS(LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 2, 8, 40000, 33), /* 32_1_1 */ - BAP_QOS(LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 2, 10, 40000, 23), /* 32_2_1 */ - BAP_QOS(LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 5, 24, 40000, 34), /* 441_1_1 */ - BAP_QOS(LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 5, 31, 40000, 24), /* 441_2_1 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 5, 15, 40000, 35), /* 48_1_1 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 5, 20, 40000, 25), /* 48_2_1 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 5, 15, 40000, 36), /* 48_3_1 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 5, 20, 40000, 26), /* 48_4_1 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 5, 15, 40000, 37), /* 48_5_1 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 5, 20, 40000, 27), /* 48_6_1 */ + BAP_QOS("8_1_1", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 2, 8, 40000, 30), /* 8_1_1 */ + BAP_QOS("8_2_1", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 2, 10, 40000, 20), /* 8_2_1 */ + BAP_QOS("16_1_1", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 2, 8, 40000, 31), /* 16_1_1 */ + BAP_QOS("16_2_1", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 2, 10, 40000, 21), /* 16_2_1 (mandatory) */ + BAP_QOS("24_1_1", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 2, 8, 40000, 32), /* 24_1_1 */ + BAP_QOS("24_2_1", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 2, 10, 40000, 22), /* 24_2_1 */ + BAP_QOS("32_1_1", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 2, 8, 40000, 33), /* 32_1_1 */ + BAP_QOS("32_2_1", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 2, 10, 40000, 23), /* 32_2_1 */ + BAP_QOS("441_1_1", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 5, 24, 40000, 34), /* 441_1_1 */ + BAP_QOS("441_2_1", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 5, 31, 40000, 24), /* 441_2_1 */ + BAP_QOS("48_1_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 5, 15, 40000, 35), /* 48_1_1 */ + BAP_QOS("48_2_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 5, 20, 40000, 25), /* 48_2_1 */ + BAP_QOS("48_3_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 5, 15, 40000, 36), /* 48_3_1 */ + BAP_QOS("48_4_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 5, 20, 40000, 26), /* 48_4_1 */ + BAP_QOS("48_5_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 5, 15, 40000, 37), /* 48_5_1 */ + BAP_QOS("48_6_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 5, 20, 40000, 27), /* 48_6_1 */ /* BAP v1.0.1 Table 5.2; high-reliability */ - BAP_QOS(LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 13, 75, 40000, 10), /* 8_1_2 */ - BAP_QOS(LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 13, 95, 40000, 0), /* 8_2_2 */ - BAP_QOS(LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 13, 75, 40000, 11), /* 16_1_2 */ - BAP_QOS(LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 13, 95, 40000, 1), /* 16_2_2 */ - BAP_QOS(LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 13, 75, 40000, 12), /* 24_1_2 */ - BAP_QOS(LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 13, 95, 40000, 2), /* 24_2_2 */ - BAP_QOS(LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 13, 75, 40000, 13), /* 32_1_2 */ - BAP_QOS(LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 13, 95, 40000, 3), /* 32_2_2 */ - BAP_QOS(LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 13, 80, 40000, 14), /* 441_1_2 */ - BAP_QOS(LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 13, 85, 40000, 4), /* 441_2_2 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 13, 75, 40000, 15), /* 48_1_2 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 13, 95, 40000, 5), /* 48_2_2 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 13, 75, 40000, 16), /* 48_3_2 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 13, 100, 40000, 6), /* 48_4_2 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 13, 75, 40000, 17), /* 48_5_2 */ - BAP_QOS(LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 13, 100, 40000, 7), /* 48_6_2 */ + BAP_QOS("8_1_2", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 13, 75, 40000, 10), /* 8_1_2 */ + BAP_QOS("8_2_2", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 13, 95, 40000, 0), /* 8_2_2 */ + BAP_QOS("16_1_2", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 13, 75, 40000, 11), /* 16_1_2 */ + BAP_QOS("16_2_2", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 13, 95, 40000, 1), /* 16_2_2 */ + BAP_QOS("24_1_2", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 13, 75, 40000, 12), /* 24_1_2 */ + BAP_QOS("24_2_2", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 13, 95, 40000, 2), /* 24_2_2 */ + BAP_QOS("32_1_2", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 13, 75, 40000, 13), /* 32_1_2 */ + BAP_QOS("32_2_2", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 13, 95, 40000, 3), /* 32_2_2 */ + BAP_QOS("441_1_2", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 13, 80, 40000, 14), /* 441_1_2 */ + BAP_QOS("441_2_2", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 13, 85, 40000, 4), /* 441_2_2 */ + BAP_QOS("48_1_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 13, 75, 40000, 15), /* 48_1_2 */ + BAP_QOS("48_2_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 13, 95, 40000, 5), /* 48_2_2 */ + BAP_QOS("48_3_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 13, 75, 40000, 16), /* 48_3_2 */ + BAP_QOS("48_4_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 13, 100, 40000, 6), /* 48_4_2 */ + BAP_QOS("48_5_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 13, 75, 40000, 17), /* 48_5_2 */ + BAP_QOS("48_6_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 13, 100, 40000, 7), /* 48_6_2 */ }; -static const struct bap_qos_preset bap_bcast_qos_configs[] = { +static const struct bap_qos bap_bcast_qos_configs[] = { /* Priority: low-latency > high-reliability, 7.5ms > 10ms, * bigger frequency and sdu better */ /* BAP v1.0.1 Table 6.4; low-latency */ - BAP_PRESET_QOS("8_1_1", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 2, 8, 40000, 30), /* 8_1_1 */ - BAP_PRESET_QOS("8_2_1", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 2, 10, 40000, 20), /* 8_2_1 */ - BAP_PRESET_QOS("16_1_1", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 2, 8, 40000, 31), /* 16_1_1 */ - BAP_PRESET_QOS("16_2_1", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 2, 10, 40000, 21), /* 16_2_1 (mandatory) */ - BAP_PRESET_QOS("24_1_1", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 2, 8, 40000, 32), /* 24_1_1 */ - BAP_PRESET_QOS("24_2_1", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 2, 10, 40000, 22), /* 24_2_1 */ - BAP_PRESET_QOS("32_1_1", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 2, 8, 40000, 33), /* 32_1_1 */ - BAP_PRESET_QOS("32_2_1", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 2, 10, 40000, 23), /* 32_2_1 */ - BAP_PRESET_QOS("441_1_1", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 4, 24, 40000, 34), /* 441_1_1 */ - BAP_PRESET_QOS("441_2_1", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 4, 31, 40000, 24), /* 441_2_1 */ - BAP_PRESET_QOS("48_1_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 4, 15, 40000, 35), /* 48_1_1 */ - BAP_PRESET_QOS("48_2_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 4, 20, 40000, 25), /* 48_2_1 */ - BAP_PRESET_QOS("48_3_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 4, 15, 40000, 36), /* 48_3_1 */ - BAP_PRESET_QOS("48_4_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 4, 20, 40000, 26), /* 48_4_1 */ - BAP_PRESET_QOS("48_5_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 4, 15, 40000, 37), /* 48_5_1 */ - BAP_PRESET_QOS("48_6_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 4, 20, 40000, 27), /* 48_6_1 */ + BAP_QOS("8_1_1", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 2, 8, 40000, 30), /* 8_1_1 */ + BAP_QOS("8_2_1", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 2, 10, 40000, 20), /* 8_2_1 */ + BAP_QOS("16_1_1", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 2, 8, 40000, 31), /* 16_1_1 */ + BAP_QOS("16_2_1", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 2, 10, 40000, 21), /* 16_2_1 (mandatory) */ + BAP_QOS("24_1_1", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 2, 8, 40000, 32), /* 24_1_1 */ + BAP_QOS("24_2_1", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 2, 10, 40000, 22), /* 24_2_1 */ + BAP_QOS("32_1_1", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 2, 8, 40000, 33), /* 32_1_1 */ + BAP_QOS("32_2_1", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 2, 10, 40000, 23), /* 32_2_1 */ + BAP_QOS("441_1_1", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 4, 24, 40000, 34), /* 441_1_1 */ + BAP_QOS("441_2_1", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 4, 31, 40000, 24), /* 441_2_1 */ + BAP_QOS("48_1_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 4, 15, 40000, 35), /* 48_1_1 */ + BAP_QOS("48_2_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 4, 20, 40000, 25), /* 48_2_1 */ + BAP_QOS("48_3_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 4, 15, 40000, 36), /* 48_3_1 */ + BAP_QOS("48_4_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 4, 20, 40000, 26), /* 48_4_1 */ + BAP_QOS("48_5_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 4, 15, 40000, 37), /* 48_5_1 */ + BAP_QOS("48_6_1", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 4, 20, 40000, 27), /* 48_6_1 */ /* BAP v1.0.1 Table 6.4; high-reliability */ - BAP_PRESET_QOS("8_1_2", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 4, 45, 40000, 10), /* 8_1_2 */ - BAP_PRESET_QOS("8_1_2", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 4, 60, 40000, 0), /* 8_1_2 */ - BAP_PRESET_QOS("16_1_2", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 4, 45, 40000, 11), /* 16_1_2 */ - BAP_PRESET_QOS("16_2_2", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 4, 60, 40000, 1), /* 16_2_2 */ - BAP_PRESET_QOS("24_1_2", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 4, 45, 40000, 12), /* 24_1_2 */ - BAP_PRESET_QOS("24_2_2", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 4, 60, 40000, 2), /* 24_2_2 */ - BAP_PRESET_QOS("32_1_2", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 4, 45, 40000, 13), /* 32_1_2 */ - BAP_PRESET_QOS("32_2_2", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 4, 60, 40000, 3), /* 32_2_2 */ - BAP_PRESET_QOS("441_1_2", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 4, 54, 40000, 14), /* 441_1_2 */ - BAP_PRESET_QOS("441_2_2", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 4, 60, 40000, 4), /* 441_2_2 */ - BAP_PRESET_QOS("48_1_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 4, 50, 40000, 15), /* 48_1_2 */ - BAP_PRESET_QOS("48_2_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 4, 65, 40000, 5), /* 48_2_2 */ - BAP_PRESET_QOS("48_3_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 4, 50, 40000, 16), /* 48_3_2 */ - BAP_PRESET_QOS("48_4_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 4, 65, 40000, 6), /* 48_4_2 */ - BAP_PRESET_QOS("48_5_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 4, 50, 40000, 17), /* 48_5_2 */ - BAP_PRESET_QOS("48_6_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 4, 65, 40000, 7), /* 48_6_2 */ + BAP_QOS("8_1_2", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_7_5, false, 26, 4, 45, 40000, 10), /* 8_1_2 */ + BAP_QOS("8_2_2", LC3_CONFIG_FREQ_8KHZ, LC3_CONFIG_DURATION_10, false, 30, 4, 60, 40000, 0), /* 8_2_2 */ + BAP_QOS("16_1_2", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_7_5, false, 30, 4, 45, 40000, 11), /* 16_1_2 */ + BAP_QOS("16_2_2", LC3_CONFIG_FREQ_16KHZ, LC3_CONFIG_DURATION_10, false, 40, 4, 60, 40000, 1), /* 16_2_2 */ + BAP_QOS("24_1_2", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_7_5, false, 45, 4, 45, 40000, 12), /* 24_1_2 */ + BAP_QOS("24_2_2", LC3_CONFIG_FREQ_24KHZ, LC3_CONFIG_DURATION_10, false, 60, 4, 60, 40000, 2), /* 24_2_2 */ + BAP_QOS("32_1_2", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_7_5, false, 60, 4, 45, 40000, 13), /* 32_1_2 */ + BAP_QOS("32_2_2", LC3_CONFIG_FREQ_32KHZ, LC3_CONFIG_DURATION_10, false, 80, 4, 60, 40000, 3), /* 32_2_2 */ + BAP_QOS("441_1_2", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_7_5, true, 97, 4, 54, 40000, 14), /* 441_1_2 */ + BAP_QOS("441_2_2", LC3_CONFIG_FREQ_44KHZ, LC3_CONFIG_DURATION_10, true, 130, 4, 60, 40000, 4), /* 441_2_2 */ + BAP_QOS("48_1_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 75, 4, 50, 40000, 15), /* 48_1_2 */ + BAP_QOS("48_2_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 100, 4, 65, 40000, 5), /* 48_2_2 */ + BAP_QOS("48_3_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 90, 4, 50, 40000, 16), /* 48_3_2 */ + BAP_QOS("48_4_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 120, 4, 65, 40000, 6), /* 48_4_2 */ + BAP_QOS("48_5_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_7_5, false, 117, 4, 50, 40000, 17), /* 48_5_2 */ + BAP_QOS("48_6_2", LC3_CONFIG_FREQ_48KHZ, LC3_CONFIG_DURATION_10, false, 155, 4, 65, 40000, 7), /* 48_6_2 */ }; static unsigned int get_rate_mask(uint8_t rate) { @@ -1158,25 +1150,41 @@ static void codec_set_log(struct spa_log *global_log) } static int codec_get_bis_config(const struct media_codec *codec, uint8_t *caps, - uint8_t *caps_size, char *preset, int channel_allocation, + uint8_t *caps_size, struct spa_dict *settings, struct bap_codec_qos *qos) { int index = 0x0; - - if (!codec) - return -ENOTSUP; - + bool preset_found = false; + const char *preset = NULL; + int channel_allocation = 0; uint8_t *data = caps; *caps_size = 0; + int i; + + if (settings) { + for (i = 0; i < (int)settings->n_items; ++i) { + if (spa_streq(settings->items[i].key, "channel_allocation")) + sscanf(settings->items[i].value, "%"PRIu32, &channel_allocation); + if (spa_streq(settings->items[i].key, "preset")) + preset = spa_dict_lookup(settings, "preset"); + } + } + + if ((preset == NULL) || (channel_allocation == 0)) + return -EINVAL; SPA_FOR_EACH_ELEMENT_VAR(bap_bcast_qos_configs, c) { if (strcmp(c->name, preset) == 0) { + preset_found = true; break; } index++; } - switch (bap_bcast_qos_configs[index].qos.rate) { + if (!preset_found) + return -EINVAL; + + switch (bap_bcast_qos_configs[index].rate) { case LC3_CONFIG_FREQ_48KHZ: data += write_ltv_uint8(data, LC3_TYPE_FREQ, LC3_CONFIG_FREQ_48KHZ); break; @@ -1195,26 +1203,26 @@ static int codec_get_bis_config(const struct media_codec *codec, uint8_t *caps, default: return -EINVAL; } - *caps_size = *caps_size + 3; + *caps_size += 3; - data += write_ltv_uint16(data, LC3_TYPE_FRAMELEN, htobs(bap_bcast_qos_configs[index].qos.framelen)); - *caps_size = *caps_size + 4; - data += write_ltv_uint8(data, LC3_TYPE_DUR, bap_bcast_qos_configs[index].qos.frame_duration); - *caps_size = *caps_size + 3; + data += write_ltv_uint16(data, LC3_TYPE_FRAMELEN, htobs(bap_bcast_qos_configs[index].framelen)); + *caps_size += 4; + data += write_ltv_uint8(data, LC3_TYPE_DUR, bap_bcast_qos_configs[index].frame_duration); + *caps_size += 3; data += write_ltv_uint32(data, LC3_TYPE_CHAN, htobl(channel_allocation)); - *caps_size = *caps_size + 6; + *caps_size += 6; - if(bap_bcast_qos_configs[index].qos.framing) + if(bap_bcast_qos_configs[index].framing) qos->framing = 1; else qos->framing = 0; - qos->sdu = bap_bcast_qos_configs[index].qos.framelen * get_channel_count(channel_allocation); - qos->retransmission = bap_bcast_qos_configs[index].qos.retransmission; - qos->latency = bap_bcast_qos_configs[index].qos.latency; - qos->delay = bap_bcast_qos_configs[index].qos.delay; + qos->sdu = bap_bcast_qos_configs[index].framelen * get_channel_count(channel_allocation); + qos->retransmission = bap_bcast_qos_configs[index].retransmission; + qos->latency = bap_bcast_qos_configs[index].latency; + qos->delay = bap_bcast_qos_configs[index].delay; qos->phy = 2; - qos->interval = 10000; - + qos->interval = (bap_bcast_qos_configs[index].frame_duration == LC3_CONFIG_DURATION_7_5 ? 7500 : 10000); + return true; } diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index dcc07c029..97cf654c2 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -1428,7 +1428,7 @@ static void bis_entry_free(struct spa_bt_bis *bis_entry) static void big_entry_free(struct spa_bt_big *big_entry) { struct spa_bt_bis *b; - + spa_list_consume(b, &big_entry->bis_list, link) bis_entry_free(b); spa_list_remove(&big_entry->link); @@ -5259,7 +5259,7 @@ static void configure_bis(struct spa_bt_monitor *monitor, const char *local_endpoint) { DBusMessageIter iter, entry, variant, qos_dict; - DBusMessage *msg; + spa_autoptr(DBusMessage) msg = NULL; DBusMessageIter dict; const char *entry_key = "QoS"; int bis_id = 0xFF; @@ -5269,7 +5269,10 @@ static void configure_bis(struct spa_bt_monitor *monitor, struct bap_codec_qos qos; int presentation_delay; struct spa_bt_metadata *metadata_entry; - + struct spa_dict settings; + struct spa_dict_item setting_items[2]; + char channel_allocation[64] = {0}; + int mse = 0; int options = 0; int skip = 0; @@ -5277,8 +5280,14 @@ static void configure_bis(struct spa_bt_monitor *monitor, int sync_factor = 1; int sync_timeout = 2000; int timeout = 2000; + /* Configure each BIS from a BIG */ spa_list_for_each(metadata_entry, &bis->metadata_list, link) { + if ((metadata_size + metadata_entry->length + 1) > METADATA_MAX_LEN) { + spa_log_warn(monitor->log, "Metadata configured for the BIS exceeds the maximum metadata size"); + return; + } + metadata[metadata_size] = (uint8_t)metadata_entry->length; metadata_size++; metadata[metadata_size] = (uint8_t)metadata_entry->type; @@ -5287,7 +5296,14 @@ static void configure_bis(struct spa_bt_monitor *monitor, metadata_size += metadata_entry->length - 1; } - codec->get_bis_config(codec, caps, &caps_size, bis->qos_preset, bis->channel_allocation, &qos); + spa_log_debug(monitor->log, "bis->channel_allocation %d", bis->channel_allocation); + if (bis->channel_allocation) + spa_scnprintf(channel_allocation, sizeof(channel_allocation), "%"PRIu32, bis->channel_allocation); + setting_items[0] = SPA_DICT_ITEM_INIT("channel_allocation", channel_allocation); + setting_items[1] = SPA_DICT_ITEM_INIT("preset", bis->qos_preset); + settings = SPA_DICT_INIT(setting_items, 2); + + codec->get_bis_config(codec, caps, &caps_size, &settings, &qos); msg = dbus_message_new_method_call(BLUEZ_SERVICE, object_path, @@ -5339,7 +5355,6 @@ static void configure_bis(struct spa_bt_monitor *monitor, if (!dbus_connection_send(conn, msg, NULL)) { spa_log_error(monitor->log, "sending SetConfiguration failed"); } - dbus_message_unref(msg); } static void configure_bcast_source(struct spa_bt_monitor *monitor, @@ -5450,6 +5465,7 @@ static void interface_added(struct spa_bt_monitor *monitor, if (spa_streq(ep->uuid, SPA_BT_UUID_BAP_BROADCAST_SINK)) { int ret, i; + bool codec_found = false; spa_autofree char *local_endpoint = NULL; /* get local endpoint */ @@ -5460,10 +5476,18 @@ static void interface_added(struct spa_bt_monitor *monitor, continue; if (monitor->media_codecs[i]->codec_id == ep->codec){ ret = media_codec_to_endpoint(monitor->media_codecs[i], SPA_BT_MEDIA_SOURCE_BROADCAST, &local_endpoint); - if (ret == 0) + if (ret == 0) { + codec_found = true; break; + } } } + + if (!codec_found) { + spa_log_warn(monitor->log, "endpoint codec not found"); + return; + } + if (local_endpoint != NULL) configure_bcast_source(monitor, monitor->media_codecs[i], conn, object_path, interface_name, local_endpoint); } @@ -6047,32 +6071,31 @@ done: static void parse_broadcast_source_config(struct spa_bt_monitor *monitor, const struct spa_dict *info) { - const char *str, *val; + const char *str; char key[256]; char bis_key[256]; char qos_key[256]; int cursor; int big_id = 0; - int len; struct spa_json it[4], it_array[4]; struct spa_bt_big *big_entry = NULL; struct spa_bt_bis *bis_entry = NULL; struct spa_bt_metadata *metadata_entry = NULL; int temp_val = 0; + struct spa_list big_list = SPA_LIST_INIT(&big_list); /* Search for bluez5.bcast_source.config */ if (info && (str = spa_dict_lookup(info, "bluez5.bcast_source.config"))) { spa_json_init(&it[0], str, strlen(str)); /* Verify is an array of BIGS */ - if (spa_json_enter_array(&it[0], &it_array[0]) <= 0) { - spa_log_warn(monitor->log, "malformed bluez5.bcast_source.config setting ignored"); - return; - } - spa_log_debug(monitor->log, "Here "); + if (spa_json_enter_array(&it[0], &it_array[0]) <= 0) + goto parse_failed; + /* Iterate on all BIG objects */ while (spa_json_enter_object(&it_array[0], &it[1]) > 0) { big_entry = calloc(1, sizeof(struct spa_bt_big)); spa_list_init(&big_entry->bis_list); + spa_list_append(&big_list, &big_entry->link); /* Iterate on all BIG values */ while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { if (spa_streq(key, "broadcast_code")) { @@ -6113,21 +6136,18 @@ static void parse_broadcast_source_config(struct spa_bt_monitor *monitor, const goto parse_failed; spa_log_debug(monitor->log, "metadata_entry->type %d", metadata_entry->type); } else if (spa_streq(qos_key, "value")) { - if ((len = spa_json_next(&it[3], &val)) <= 0) + if (spa_json_enter_array(&it[3], &it_array[3]) <= 0) goto parse_failed; - if (spa_json_is_array(val, len)) { - spa_json_enter(&it[3], &it_array[3]); - cursor = 0; - for (cursor = 0; cursor < metadata_entry->length; cursor++) { - if (spa_json_get_int(&it_array[3], &temp_val) <= 0) - break; - metadata_entry->value[cursor] = (uint8_t)temp_val; - spa_log_debug(monitor->log, "metadata_entry->value[cursor] %d", metadata_entry->value[cursor]); - } - spa_log_debug(monitor->log, "metadata_entry->value_size %d", cursor); - spa_list_append(&bis_entry->metadata_list, &metadata_entry->link); - metadata_entry = NULL; - } + cursor = 0; + for (cursor = 0; cursor < METADATA_MAX_LEN; cursor++) { + if (spa_json_get_int(&it_array[3], &temp_val) <= 0) + break; + metadata_entry->value[cursor] = (uint8_t)temp_val; + spa_log_debug(monitor->log, "metadata_entry->value[cursor] %d", metadata_entry->value[cursor]); + } + spa_log_debug(monitor->log, "metadata_entry->value_size %d", cursor); + spa_list_append(&bis_entry->metadata_list, &metadata_entry->link); + metadata_entry = NULL; } } @@ -6140,16 +6160,23 @@ static void parse_broadcast_source_config(struct spa_bt_monitor *monitor, const } } big_entry->big_id = big_id; - spa_list_append(&monitor->bcast_source_config_list, &big_entry->link); big_id ++; big_entry = NULL; } } + spa_list_insert_list(&monitor->bcast_source_config_list, &big_list); return; parse_failed: - spa_log_debug(monitor->log, "Here failed"); + struct spa_error_location loc; + + str = spa_dict_lookup(info, "bluez5.bcast_source.config"); + if (spa_json_get_error(&it[0], str, &loc)) { + spa_debug_log_error_location(monitor->log, SPA_LOG_LEVEL_WARN, + &loc, "malformed bluez5.bcast_source.config: %s", loc.reason); + } + if (metadata_entry) free(metadata_entry); @@ -6164,7 +6191,8 @@ parse_failed: bis_entry_free(bis_entry); free(big_entry); } - spa_list_consume(big_entry, &monitor->bcast_source_config_list, link) + + spa_list_consume(big_entry, &big_list, link) big_entry_free(big_entry); } diff --git a/spa/plugins/bluez5/media-codecs.h b/spa/plugins/bluez5/media-codecs.h index 648a9f1df..a1b0a9f2a 100644 --- a/spa/plugins/bluez5/media-codecs.h +++ b/spa/plugins/bluez5/media-codecs.h @@ -26,7 +26,7 @@ #define SPA_TYPE_INTERFACE_Bluez5CodecMedia SPA_TYPE_INFO_INTERFACE_BASE "Bluez5:Codec:Media:Private" -#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 8 +#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 9 struct spa_bluez5_codec_a2dp { struct spa_interface iface; @@ -82,8 +82,8 @@ struct media_codec { const struct media_codec *duplex_codec; /**< Codec for non-standard A2DP duplex channel */ int (*get_bis_config)(const struct media_codec *codec, uint8_t *caps, - uint8_t *caps_size, char *preset, int channel_allocation, - struct bap_codec_qos *qos); + 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). */ int (*fill_caps) (const struct media_codec *codec, uint32_t flags,