bluez5: Set BAP QoS depending on selected configuration

This move the QoS setup to be codec specific and fills it depending on the
selected codec configuration.
This commit is contained in:
Frédéric Danis 2022-07-19 16:09:18 +02:00 committed by Wim Taymans
parent 284da66deb
commit f428b13d06
3 changed files with 61 additions and 23 deletions

View file

@ -475,6 +475,40 @@ static int codec_validate_config(const struct media_codec *codec, uint32_t flags
return 0; return 0;
} }
static void codec_get_qos(const struct media_codec *codec,
const void *config, size_t config_size,
struct codec_qos *qos)
{
bap_lc3_t conf;
memset(qos, 0, sizeof(*qos));
if (!parse_conf(&conf, config, config_size))
return;
qos->framing = false;
qos->phy = "2M";
qos->retransmission = 2; /* default */
qos->sdu = conf.framelen * conf.n_blks;
qos->latency = 20; /* default */
qos->delay = 40000U;
qos->interval = (conf.frame_duration == LC3_CONFIG_DURATION_7_5 ? 7500 : 10000);
switch (conf.rate) {
case LC3_CONFIG_FREQ_8KHZ:
case LC3_CONFIG_FREQ_16KHZ:
case LC3_CONFIG_FREQ_24KHZ:
case LC3_CONFIG_FREQ_32KHZ:
qos->retransmission = 2;
qos->latency = (conf.frame_duration == LC3_CONFIG_DURATION_7_5 ? 8 : 10);
break;
case LC3_CONFIG_FREQ_48KHZ:
qos->retransmission = 5;
qos->latency = (conf.frame_duration == LC3_CONFIG_DURATION_7_5 ? 15 : 20);
break;
}
}
static void *codec_init(const struct media_codec *codec, uint32_t flags, static void *codec_init(const struct media_codec *codec, uint32_t flags,
void *config, size_t config_len, const struct spa_audio_info *info, void *config, size_t config_len, const struct spa_audio_info *info,
void *props, size_t mtu) void *props, size_t mtu)
@ -688,6 +722,7 @@ const struct media_codec bap_codec_lc3 = {
.select_config = codec_select_config, .select_config = codec_select_config,
.enum_config = codec_enum_config, .enum_config = codec_enum_config,
.validate_config = codec_validate_config, .validate_config = codec_validate_config,
.get_qos = codec_get_qos,
.caps_preference_cmp = codec_caps_preference_cmp, .caps_preference_cmp = codec_caps_preference_cmp,
.init = codec_init, .init = codec_init,
.deinit = codec_deinit, .deinit = codec_deinit,

View file

@ -664,31 +664,21 @@ static DBusHandlerResult endpoint_select_properties(DBusConnection *conn, DBusMe
&dict); &dict);
append_basic_array_variant_dict_entry(&dict, "Capabilities", "ay", "y", DBUS_TYPE_BYTE, &config, size); append_basic_array_variant_dict_entry(&dict, "Capabilities", "ay", "y", DBUS_TYPE_BYTE, &config, size);
if (codec->get_qos)
{ {
/*TBD: QoS Params are not coming from BlueZ now. Hard code it struct codec_qos qos;
* for now dbus_bool_t framing;
*/
uint32_t interval = 10000U; codec->get_qos(codec, config, size, &qos);
dbus_bool_t framing = FALSE;
char *phy = "2M"; append_basic_variant_dict_entry(&dict, "Interval", DBUS_TYPE_UINT32, "u", &qos.interval);
uint16_t sdu = 120; framing = (qos.framing ? TRUE : FALSE);
uint8_t retransmissions;
uint16_t latency = 20;
uint32_t delay = 40000U;
spa_log_debug(monitor->log, "packing interval");
append_basic_variant_dict_entry(&dict, "Interval", DBUS_TYPE_UINT32, "u", &interval);
spa_log_debug(monitor->log, "packing framing");
append_basic_variant_dict_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, "b", &framing); append_basic_variant_dict_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN, "b", &framing);
spa_log_debug(monitor->log, "packing PHY"); append_basic_variant_dict_entry(&dict, "PHY", DBUS_TYPE_STRING, "s", &qos.phy);
append_basic_variant_dict_entry(&dict, "PHY", DBUS_TYPE_STRING, "s", &phy); append_basic_variant_dict_entry(&dict, "SDU", DBUS_TYPE_UINT16, "q", &qos.sdu);
spa_log_debug(monitor->log, "packing SDU"); append_basic_variant_dict_entry(&dict, "Retransmissions", DBUS_TYPE_BYTE, "y", &qos.retransmission);
append_basic_variant_dict_entry(&dict, "SDU", DBUS_TYPE_UINT16, "q", &sdu); append_basic_variant_dict_entry(&dict, "Latency", DBUS_TYPE_UINT16, "q", &qos.latency);
spa_log_debug(monitor->log, "packing RTN"); append_basic_variant_dict_entry(&dict, "Delay", DBUS_TYPE_UINT32, "u", &qos.delay);
append_basic_variant_dict_entry(&dict, "Retransmissions", DBUS_TYPE_BYTE, "y", &retransmissions);
spa_log_debug(monitor->log, "packing Lat");
append_basic_variant_dict_entry(&dict, "Latency", DBUS_TYPE_UINT16, "q", &latency);
spa_log_debug(monitor->log, "packing Delay");
append_basic_variant_dict_entry(&dict, "Delay", DBUS_TYPE_UINT32, "u", &delay);
} }
dbus_message_iter_close_container(&iter, &dict); dbus_message_iter_close_container(&iter, &dict);

View file

@ -79,6 +79,16 @@ struct media_codec_audio_info {
uint32_t channels; uint32_t channels;
}; };
struct codec_qos {
uint32_t interval;
bool framing;
char *phy;
uint16_t sdu;
uint8_t retransmission;
uint16_t latency;
uint32_t delay;
};
struct media_codec { struct media_codec {
enum spa_bluetooth_audio_codec id; enum spa_bluetooth_audio_codec id;
uint8_t codec_id; uint8_t codec_id;
@ -109,6 +119,9 @@ struct media_codec {
int (*validate_config) (const struct media_codec *codec, uint32_t flags, int (*validate_config) (const struct media_codec *codec, uint32_t flags,
const void *caps, size_t caps_size, const void *caps, size_t caps_size,
struct spa_audio_info *info); struct spa_audio_info *info);
void (*get_qos)(const struct media_codec *codec,
const void *config, size_t config_size,
struct codec_qos *qos);
/** qsort comparison sorting caps in order of preference for the codec. /** qsort comparison sorting caps in order of preference for the codec.
* Used in codec switching to select best remote endpoints. * Used in codec switching to select best remote endpoints.