linuxOS_AP05/external/bluez-alsa/src/bluez-a2dp.c
2025-06-02 13:59:07 +08:00

343 lines
9.5 KiB
C

/*
* BlueALSA - bluez-a2dp.c
* Copyright (c) 2016-2018 Arkadiusz Bokowy
*
* This file is a part of bluez-alsa.
*
* This project is licensed under the terms of the MIT license.
*
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "bluez-a2dp.h"
#include "shared/defs.h"
static const a2dp_sbc_t a2dp_sbc = {
.frequency =
SBC_SAMPLING_FREQ_16000 |
SBC_SAMPLING_FREQ_32000 |
SBC_SAMPLING_FREQ_44100 |
SBC_SAMPLING_FREQ_48000,
.channel_mode =
SBC_CHANNEL_MODE_MONO |
SBC_CHANNEL_MODE_DUAL_CHANNEL |
SBC_CHANNEL_MODE_STEREO |
SBC_CHANNEL_MODE_JOINT_STEREO,
.block_length =
SBC_BLOCK_LENGTH_4 |
SBC_BLOCK_LENGTH_8 |
SBC_BLOCK_LENGTH_12 |
SBC_BLOCK_LENGTH_16,
.subbands =
SBC_SUBBANDS_4 |
SBC_SUBBANDS_8,
.allocation_method =
SBC_ALLOCATION_SNR |
SBC_ALLOCATION_LOUDNESS,
.min_bitpool = SBC_MIN_BITPOOL,
.max_bitpool = SBC_MAX_BITPOOL,
};
static const struct bluez_a2dp_channel_mode a2dp_sbc_channels[] = {
{ BLUEZ_A2DP_CHM_MONO, SBC_CHANNEL_MODE_MONO },
{ BLUEZ_A2DP_CHM_DUAL_CHANNEL, SBC_CHANNEL_MODE_DUAL_CHANNEL },
{ BLUEZ_A2DP_CHM_STEREO, SBC_CHANNEL_MODE_STEREO },
{ BLUEZ_A2DP_CHM_JOINT_STEREO, SBC_CHANNEL_MODE_JOINT_STEREO },
};
static const struct bluez_a2dp_sampling_freq a2dp_sbc_samplings[] = {
{ 16000, SBC_SAMPLING_FREQ_16000 },
{ 32000, SBC_SAMPLING_FREQ_32000 },
{ 44100, SBC_SAMPLING_FREQ_44100 },
{ 48000, SBC_SAMPLING_FREQ_48000 },
};
static const a2dp_mpeg_t 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,
};
static const struct bluez_a2dp_channel_mode a2dp_mpeg_channels[] = {
{ BLUEZ_A2DP_CHM_MONO, MPEG_CHANNEL_MODE_MONO },
{ BLUEZ_A2DP_CHM_DUAL_CHANNEL, MPEG_CHANNEL_MODE_DUAL_CHANNEL },
{ BLUEZ_A2DP_CHM_STEREO, MPEG_CHANNEL_MODE_STEREO },
{ BLUEZ_A2DP_CHM_JOINT_STEREO, MPEG_CHANNEL_MODE_JOINT_STEREO },
};
static const struct bluez_a2dp_sampling_freq a2dp_mpeg_samplings[] = {
{ 16000, MPEG_SAMPLING_FREQ_16000 },
{ 22050, MPEG_SAMPLING_FREQ_22050 },
{ 24000, MPEG_SAMPLING_FREQ_24000 },
{ 32000, MPEG_SAMPLING_FREQ_32000 },
{ 44100, MPEG_SAMPLING_FREQ_44100 },
{ 48000, MPEG_SAMPLING_FREQ_48000 },
};
static const a2dp_aac_t a2dp_aac = {
.object_type =
/* NOTE: AAC Long Term Prediction and AAC Scalable are
* not supported by the FDK-AAC library. */
AAC_OBJECT_TYPE_MPEG2_AAC_LC |
AAC_OBJECT_TYPE_MPEG4_AAC_LC,
AAC_INIT_FREQUENCY(
AAC_SAMPLING_FREQ_8000 |
AAC_SAMPLING_FREQ_11025 |
AAC_SAMPLING_FREQ_12000 |
AAC_SAMPLING_FREQ_16000 |
AAC_SAMPLING_FREQ_22050 |
AAC_SAMPLING_FREQ_24000 |
AAC_SAMPLING_FREQ_32000 |
AAC_SAMPLING_FREQ_44100 |
AAC_SAMPLING_FREQ_48000 |
AAC_SAMPLING_FREQ_64000 |
AAC_SAMPLING_FREQ_88200 |
AAC_SAMPLING_FREQ_96000)
.channels =
AAC_CHANNELS_1 |
AAC_CHANNELS_2,
.vbr = 1,
AAC_INIT_BITRATE(320000)
};
static const struct bluez_a2dp_channel_mode a2dp_aac_channels[] = {
{ BLUEZ_A2DP_CHM_MONO, AAC_CHANNELS_1 },
{ BLUEZ_A2DP_CHM_STEREO, AAC_CHANNELS_2 },
};
static const struct bluez_a2dp_sampling_freq a2dp_aac_samplings[] = {
{ 8000, AAC_SAMPLING_FREQ_8000 },
{ 11025, AAC_SAMPLING_FREQ_11025 },
{ 12000, AAC_SAMPLING_FREQ_12000 },
{ 16000, AAC_SAMPLING_FREQ_16000 },
{ 22050, AAC_SAMPLING_FREQ_22050 },
{ 24000, AAC_SAMPLING_FREQ_24000 },
{ 32000, AAC_SAMPLING_FREQ_32000 },
{ 44100, AAC_SAMPLING_FREQ_44100 },
{ 48000, AAC_SAMPLING_FREQ_48000 },
{ 64000, AAC_SAMPLING_FREQ_64000 },
{ 88200, AAC_SAMPLING_FREQ_88200 },
{ 96000, AAC_SAMPLING_FREQ_96000 },
};
static const a2dp_aptx_t a2dp_aptx = {
.info.vendor_id = APTX_VENDOR_ID,
.info.codec_id = APTX_CODEC_ID,
.channel_mode =
/* NOTE: Used apt-X library does not support
* single channel (mono) mode. */
APTX_CHANNEL_MODE_STEREO,
.frequency =
APTX_SAMPLING_FREQ_16000 |
APTX_SAMPLING_FREQ_32000 |
APTX_SAMPLING_FREQ_44100 |
APTX_SAMPLING_FREQ_48000,
};
static const struct bluez_a2dp_channel_mode a2dp_aptx_channels[] = {
{ BLUEZ_A2DP_CHM_STEREO, APTX_CHANNEL_MODE_STEREO },
};
static const struct bluez_a2dp_sampling_freq a2dp_aptx_samplings[] = {
{ 16000, APTX_SAMPLING_FREQ_16000 },
{ 32000, APTX_SAMPLING_FREQ_32000 },
{ 44100, APTX_SAMPLING_FREQ_44100 },
{ 48000, APTX_SAMPLING_FREQ_48000 },
};
static const a2dp_ldac_t a2dp_ldac = {
.info.vendor_id = LDAC_VENDOR_ID,
.info.codec_id = LDAC_CODEC_ID,
.channel_mode =
LDAC_CHANNEL_MODE_MONO |
LDAC_CHANNEL_MODE_DUAL_CHANNEL |
LDAC_CHANNEL_MODE_STEREO,
.frequency =
/* NOTE: Used LDAC library does not support
* frequencies higher than 96 kHz. */
LDAC_SAMPLING_FREQ_44100 |
LDAC_SAMPLING_FREQ_48000 |
LDAC_SAMPLING_FREQ_88200 |
LDAC_SAMPLING_FREQ_96000,
};
static const struct bluez_a2dp_channel_mode a2dp_ldac_channels[] = {
{ BLUEZ_A2DP_CHM_MONO, LDAC_CHANNEL_MODE_MONO },
{ BLUEZ_A2DP_CHM_DUAL_CHANNEL, LDAC_CHANNEL_MODE_DUAL_CHANNEL },
{ BLUEZ_A2DP_CHM_STEREO, LDAC_CHANNEL_MODE_STEREO },
};
static const struct bluez_a2dp_sampling_freq a2dp_ldac_samplings[] = {
{ 44100, LDAC_SAMPLING_FREQ_44100 },
{ 48000, LDAC_SAMPLING_FREQ_48000 },
{ 88200, LDAC_SAMPLING_FREQ_88200 },
{ 96000, LDAC_SAMPLING_FREQ_96000 },
};
static const struct bluez_a2dp_codec a2dp_codec_source_sbc = {
.dir = BLUEZ_A2DP_SOURCE,
.id = A2DP_CODEC_SBC,
.cfg = &a2dp_sbc,
.cfg_size = sizeof(a2dp_sbc),
.channels = a2dp_sbc_channels,
.channels_size = ARRAYSIZE(a2dp_sbc_channels),
.samplings = a2dp_sbc_samplings,
.samplings_size = ARRAYSIZE(a2dp_sbc_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_sink_sbc = {
.dir = BLUEZ_A2DP_SINK,
.id = A2DP_CODEC_SBC,
.cfg = &a2dp_sbc,
.cfg_size = sizeof(a2dp_sbc),
.channels = a2dp_sbc_channels,
.channels_size = ARRAYSIZE(a2dp_sbc_channels),
.samplings = a2dp_sbc_samplings,
.samplings_size = ARRAYSIZE(a2dp_sbc_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_source_mpeg = {
.dir = BLUEZ_A2DP_SOURCE,
.id = A2DP_CODEC_MPEG12,
.cfg = &a2dp_mpeg,
.cfg_size = sizeof(a2dp_mpeg),
.channels = a2dp_mpeg_channels,
.channels_size = ARRAYSIZE(a2dp_mpeg_channels),
.samplings = a2dp_mpeg_samplings,
.samplings_size = ARRAYSIZE(a2dp_mpeg_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_sink_mpeg = {
.dir = BLUEZ_A2DP_SINK,
.id = A2DP_CODEC_MPEG12,
.cfg = &a2dp_mpeg,
.cfg_size = sizeof(a2dp_mpeg),
.channels = a2dp_mpeg_channels,
.channels_size = ARRAYSIZE(a2dp_mpeg_channels),
.samplings = a2dp_mpeg_samplings,
.samplings_size = ARRAYSIZE(a2dp_mpeg_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_source_aac = {
.dir = BLUEZ_A2DP_SOURCE,
.id = A2DP_CODEC_MPEG24,
.cfg = &a2dp_aac,
.cfg_size = sizeof(a2dp_aac),
.channels = a2dp_aac_channels,
.channels_size = ARRAYSIZE(a2dp_aac_channels),
.samplings = a2dp_aac_samplings,
.samplings_size = ARRAYSIZE(a2dp_aac_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_sink_aac = {
.dir = BLUEZ_A2DP_SINK,
.id = A2DP_CODEC_MPEG24,
.cfg = &a2dp_aac,
.cfg_size = sizeof(a2dp_aac),
.channels = a2dp_aac_channels,
.channels_size = ARRAYSIZE(a2dp_aac_channels),
.samplings = a2dp_aac_samplings,
.samplings_size = ARRAYSIZE(a2dp_aac_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_source_aptx = {
.dir = BLUEZ_A2DP_SOURCE,
.id = A2DP_CODEC_VENDOR_APTX,
.cfg = &a2dp_aptx,
.cfg_size = sizeof(a2dp_aptx),
.channels = a2dp_aptx_channels,
.channels_size = ARRAYSIZE(a2dp_aptx_channels),
.samplings = a2dp_aptx_samplings,
.samplings_size = ARRAYSIZE(a2dp_aptx_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_sink_aptx = {
.dir = BLUEZ_A2DP_SINK,
.id = A2DP_CODEC_VENDOR_APTX,
.cfg = &a2dp_aptx,
.cfg_size = sizeof(a2dp_aptx),
.channels = a2dp_aptx_channels,
.channels_size = ARRAYSIZE(a2dp_aptx_channels),
.samplings = a2dp_aptx_samplings,
.samplings_size = ARRAYSIZE(a2dp_aptx_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_source_ldac = {
.dir = BLUEZ_A2DP_SOURCE,
.id = A2DP_CODEC_VENDOR_LDAC,
.cfg = &a2dp_ldac,
.cfg_size = sizeof(a2dp_ldac),
.channels = a2dp_ldac_channels,
.channels_size = ARRAYSIZE(a2dp_ldac_channels),
.samplings = a2dp_ldac_samplings,
.samplings_size = ARRAYSIZE(a2dp_ldac_samplings),
};
static const struct bluez_a2dp_codec a2dp_codec_sink_ldac = {
.dir = BLUEZ_A2DP_SINK,
.id = A2DP_CODEC_VENDOR_LDAC,
.cfg = &a2dp_ldac,
.cfg_size = sizeof(a2dp_ldac),
.channels = a2dp_ldac_channels,
.channels_size = ARRAYSIZE(a2dp_ldac_channels),
.samplings = a2dp_ldac_samplings,
.samplings_size = ARRAYSIZE(a2dp_ldac_samplings),
};
static const struct bluez_a2dp_codec *a2dp_codecs[] = {
#if ENABLE_LDAC
&a2dp_codec_source_ldac,
#endif
#if ENABLE_APTX
&a2dp_codec_source_aptx,
#endif
#if ENABLE_AAC
&a2dp_codec_source_aac,
&a2dp_codec_sink_aac,
#endif
#if ENABLE_MPEG
&a2dp_codec_source_mpeg,
&a2dp_codec_sink_mpeg,
#endif
&a2dp_codec_source_sbc,
&a2dp_codec_sink_sbc,
NULL,
};
const struct bluez_a2dp_codec **bluez_a2dp_codecs = a2dp_codecs;