mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
aptX-LL sink devices may send back mSBC encoded data corresponding to microphone input. It appears to be enabled when the bidirectional link is set in the caps, and the device also supports this. Implement mSBC decoding in the duplex channel. Tested to be working on Avantree Aria Pro.
166 lines
3.5 KiB
C
166 lines
3.5 KiB
C
/*
|
|
* BlueALSA - bluez-a2dp.c
|
|
* Copyright (c) 2016-2017 Arkadiusz Bokowy
|
|
*
|
|
* This file is a part of bluez-alsa.
|
|
*
|
|
* This project is licensed under the terms of the MIT license.
|
|
*
|
|
*/
|
|
|
|
#include "a2dp-codecs.h"
|
|
|
|
int a2dp_codec_select_config(const struct a2dp_codec_config configs[], size_t n,
|
|
uint32_t cap, int preferred_value)
|
|
{
|
|
size_t i;
|
|
int *scores, res;
|
|
unsigned int max_priority;
|
|
|
|
if (n == 0)
|
|
return -EINVAL;
|
|
|
|
scores = calloc(n, sizeof(int));
|
|
if (scores == NULL)
|
|
return -errno;
|
|
|
|
max_priority = configs[0].priority;
|
|
for (i = 1; i < n; ++i) {
|
|
if (configs[i].priority > max_priority)
|
|
max_priority = configs[i].priority;
|
|
}
|
|
|
|
for (i = 0; i < n; ++i) {
|
|
if (!(configs[i].config & cap)) {
|
|
scores[i] = -1;
|
|
continue;
|
|
}
|
|
if (configs[i].value == preferred_value)
|
|
scores[i] = 100 * (max_priority + 1);
|
|
else if (configs[i].value > preferred_value)
|
|
scores[i] = 10 * (max_priority + 1);
|
|
else
|
|
scores[i] = 1;
|
|
|
|
scores[i] *= configs[i].priority + 1;
|
|
}
|
|
|
|
res = 0;
|
|
for (i = 1; i < n; ++i) {
|
|
if (scores[i] > scores[res])
|
|
res = i;
|
|
}
|
|
|
|
if (scores[res] < 0)
|
|
res = -EINVAL;
|
|
|
|
free(scores);
|
|
return res;
|
|
}
|
|
|
|
bool a2dp_codec_check_caps(const struct a2dp_codec *codec, unsigned int codec_id,
|
|
const void *caps, size_t caps_size,
|
|
const struct a2dp_codec_audio_info *info)
|
|
{
|
|
uint8_t config[A2DP_MAX_CAPS_SIZE];
|
|
int res;
|
|
|
|
if (codec_id != codec->codec_id)
|
|
return false;
|
|
|
|
if (caps == NULL)
|
|
return false;
|
|
|
|
res = codec->select_config(codec, 0, caps, caps_size, info, NULL, config);
|
|
if (res < 0)
|
|
return false;
|
|
|
|
return ((size_t)res == caps_size);
|
|
}
|
|
|
|
#if ENABLE_MP3
|
|
const a2dp_mpeg_t bluez_a2dp_mpeg = {
|
|
.layer =
|
|
MPEG_LAYER_MP1 |
|
|
MPEG_LAYER_MP2 |
|
|
MPEG_LAYER_MP3,
|
|
.crc = 1,
|
|
.channel_mode =
|
|
MPEG_CHANNEL_MODE_MONO |
|
|
MPEG_CHANNEL_MODE_DUAL_CHANNEL |
|
|
MPEG_CHANNEL_MODE_STEREO |
|
|
MPEG_CHANNEL_MODE_JOINT_STEREO,
|
|
.mpf = 1,
|
|
.frequency =
|
|
MPEG_SAMPLING_FREQ_16000 |
|
|
MPEG_SAMPLING_FREQ_22050 |
|
|
MPEG_SAMPLING_FREQ_24000 |
|
|
MPEG_SAMPLING_FREQ_32000 |
|
|
MPEG_SAMPLING_FREQ_44100 |
|
|
MPEG_SAMPLING_FREQ_48000,
|
|
.bitrate =
|
|
MPEG_BIT_RATE_VBR |
|
|
MPEG_BIT_RATE_320000 |
|
|
MPEG_BIT_RATE_256000 |
|
|
MPEG_BIT_RATE_224000 |
|
|
MPEG_BIT_RATE_192000 |
|
|
MPEG_BIT_RATE_160000 |
|
|
MPEG_BIT_RATE_128000 |
|
|
MPEG_BIT_RATE_112000 |
|
|
MPEG_BIT_RATE_96000 |
|
|
MPEG_BIT_RATE_80000 |
|
|
MPEG_BIT_RATE_64000 |
|
|
MPEG_BIT_RATE_56000 |
|
|
MPEG_BIT_RATE_48000 |
|
|
MPEG_BIT_RATE_40000 |
|
|
MPEG_BIT_RATE_32000 |
|
|
MPEG_BIT_RATE_FREE,
|
|
};
|
|
#endif
|
|
|
|
extern struct a2dp_codec a2dp_codec_sbc;
|
|
extern struct a2dp_codec a2dp_codec_sbc_xq;
|
|
#if ENABLE_LDAC
|
|
extern struct a2dp_codec a2dp_codec_ldac;
|
|
#endif
|
|
#if ENABLE_AAC
|
|
extern struct a2dp_codec a2dp_codec_aac;
|
|
#endif
|
|
#if ENABLE_MP3
|
|
extern struct a2dp_codec a2dp_codec_mpeg;
|
|
#endif
|
|
#if ENABLE_APTX
|
|
extern struct a2dp_codec a2dp_codec_aptx;
|
|
extern struct a2dp_codec a2dp_codec_aptx_hd;
|
|
extern struct a2dp_codec a2dp_codec_aptx_ll_0;
|
|
extern struct a2dp_codec a2dp_codec_aptx_ll_1;
|
|
extern struct a2dp_codec a2dp_codec_aptx_ll_duplex_0;
|
|
extern struct a2dp_codec a2dp_codec_aptx_ll_duplex_1;
|
|
#endif
|
|
|
|
static const struct a2dp_codec * const a2dp_codec_list[] = {
|
|
#if ENABLE_LDAC
|
|
&a2dp_codec_ldac,
|
|
#endif
|
|
#if ENABLE_APTX
|
|
&a2dp_codec_aptx_hd,
|
|
&a2dp_codec_aptx,
|
|
#endif
|
|
#if ENABLE_AAC
|
|
&a2dp_codec_aac,
|
|
#endif
|
|
#if ENABLE_MP3
|
|
&a2dp_codec_mpeg,
|
|
#endif
|
|
&a2dp_codec_sbc,
|
|
&a2dp_codec_sbc_xq,
|
|
#if ENABLE_APTX
|
|
&a2dp_codec_aptx_ll_0,
|
|
&a2dp_codec_aptx_ll_1,
|
|
&a2dp_codec_aptx_ll_duplex_0,
|
|
&a2dp_codec_aptx_ll_duplex_1,
|
|
#endif
|
|
NULL
|
|
};
|
|
|
|
const struct a2dp_codec * const * const a2dp_codecs = a2dp_codec_list;
|