mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-26 05:34:23 +08:00
Initial support of mpeg12 codec.
This commit is contained in:
parent
f67d81062c
commit
9ae63b37bb
30
audio/a2dp.c
30
audio/a2dp.c
@ -355,25 +355,25 @@ static gboolean getcap_ind(struct avdtp *session, struct avdtp_local_sep *sep,
|
||||
sbc_cap.cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
|
||||
sbc_cap.cap.media_codec_type = A2DP_CODEC_SBC;
|
||||
|
||||
sbc_cap.frequency = ( A2DP_SAMPLING_FREQ_48000 |
|
||||
A2DP_SAMPLING_FREQ_44100 |
|
||||
A2DP_SAMPLING_FREQ_32000 |
|
||||
A2DP_SAMPLING_FREQ_16000 );
|
||||
sbc_cap.frequency = ( SBC_SAMPLING_FREQ_48000 |
|
||||
SBC_SAMPLING_FREQ_44100 |
|
||||
SBC_SAMPLING_FREQ_32000 |
|
||||
SBC_SAMPLING_FREQ_16000 );
|
||||
|
||||
sbc_cap.channel_mode = ( A2DP_CHANNEL_MODE_JOINT_STEREO |
|
||||
A2DP_CHANNEL_MODE_STEREO |
|
||||
A2DP_CHANNEL_MODE_DUAL_CHANNEL |
|
||||
A2DP_CHANNEL_MODE_MONO );
|
||||
sbc_cap.channel_mode = ( SBC_CHANNEL_MODE_JOINT_STEREO |
|
||||
SBC_CHANNEL_MODE_STEREO |
|
||||
SBC_CHANNEL_MODE_DUAL_CHANNEL |
|
||||
SBC_CHANNEL_MODE_MONO );
|
||||
|
||||
sbc_cap.block_length = ( A2DP_BLOCK_LENGTH_16 |
|
||||
A2DP_BLOCK_LENGTH_12 |
|
||||
A2DP_BLOCK_LENGTH_8 |
|
||||
A2DP_BLOCK_LENGTH_4 );
|
||||
sbc_cap.block_length = ( SBC_BLOCK_LENGTH_16 |
|
||||
SBC_BLOCK_LENGTH_12 |
|
||||
SBC_BLOCK_LENGTH_8 |
|
||||
SBC_BLOCK_LENGTH_4 );
|
||||
|
||||
sbc_cap.subbands = ( A2DP_SUBBANDS_8 | A2DP_SUBBANDS_4 );
|
||||
sbc_cap.subbands = ( SBC_SUBBANDS_8 | SBC_SUBBANDS_4 );
|
||||
|
||||
sbc_cap.allocation_method = ( A2DP_ALLOCATION_LOUDNESS |
|
||||
A2DP_ALLOCATION_SNR );
|
||||
sbc_cap.allocation_method = ( SBC_ALLOCATION_LOUDNESS |
|
||||
SBC_ALLOCATION_SNR );
|
||||
|
||||
sbc_cap.min_bitpool = MIN_BITPOOL;
|
||||
sbc_cap.max_bitpool = MAX_BITPOOL;
|
||||
|
69
audio/a2dp.h
69
audio/a2dp.h
@ -27,26 +27,37 @@
|
||||
#define A2DP_CODEC_MPEG24 0x02
|
||||
#define A2DP_CODEC_ATRAC 0x03
|
||||
|
||||
#define A2DP_SAMPLING_FREQ_16000 (1 << 3)
|
||||
#define A2DP_SAMPLING_FREQ_32000 (1 << 2)
|
||||
#define A2DP_SAMPLING_FREQ_44100 (1 << 1)
|
||||
#define A2DP_SAMPLING_FREQ_48000 1
|
||||
#define SBC_SAMPLING_FREQ_16000 (1 << 3)
|
||||
#define SBC_SAMPLING_FREQ_32000 (1 << 2)
|
||||
#define SBC_SAMPLING_FREQ_44100 (1 << 1)
|
||||
#define SBC_SAMPLING_FREQ_48000 1
|
||||
|
||||
#define A2DP_CHANNEL_MODE_MONO (1 << 3)
|
||||
#define A2DP_CHANNEL_MODE_DUAL_CHANNEL (1 << 2)
|
||||
#define A2DP_CHANNEL_MODE_STEREO (1 << 1)
|
||||
#define A2DP_CHANNEL_MODE_JOINT_STEREO 1
|
||||
#define SBC_CHANNEL_MODE_MONO (1 << 3)
|
||||
#define SBC_CHANNEL_MODE_DUAL_CHANNEL (1 << 2)
|
||||
#define SBC_CHANNEL_MODE_STEREO (1 << 1)
|
||||
#define SBC_CHANNEL_MODE_JOINT_STEREO 1
|
||||
|
||||
#define A2DP_BLOCK_LENGTH_4 (1 << 3)
|
||||
#define A2DP_BLOCK_LENGTH_8 (1 << 2)
|
||||
#define A2DP_BLOCK_LENGTH_12 (1 << 1)
|
||||
#define A2DP_BLOCK_LENGTH_16 1
|
||||
#define SBC_BLOCK_LENGTH_4 (1 << 3)
|
||||
#define SBC_BLOCK_LENGTH_8 (1 << 2)
|
||||
#define SBC_BLOCK_LENGTH_12 (1 << 1)
|
||||
#define SBC_BLOCK_LENGTH_16 1
|
||||
|
||||
#define A2DP_SUBBANDS_4 (1 << 1)
|
||||
#define A2DP_SUBBANDS_8 1
|
||||
#define SBC_SUBBANDS_4 (1 << 1)
|
||||
#define SBC_SUBBANDS_8 1
|
||||
|
||||
#define A2DP_ALLOCATION_SNR (1 << 1)
|
||||
#define A2DP_ALLOCATION_LOUDNESS 1
|
||||
#define SBC_ALLOCATION_SNR (1 << 1)
|
||||
#define SBC_ALLOCATION_LOUDNESS 1
|
||||
|
||||
#define MPEG_LAYER_MP1 (1 << 2)
|
||||
#define MPEG_LAYER_MP2 (1 << 1)
|
||||
#define MPEG_LAYER_MP3 1
|
||||
|
||||
#define MPEG_SAMPLING_FREQ_16000 (1 << 5)
|
||||
#define MPEG_SAMPLING_FREQ_22050 (1 << 4)
|
||||
#define MPEG_SAMPLING_FREQ_24000 (1 << 3)
|
||||
#define MPEG_SAMPLING_FREQ_32000 (1 << 2)
|
||||
#define MPEG_SAMPLING_FREQ_44100 (1 << 1)
|
||||
#define MPEG_SAMPLING_FREQ_48000 1
|
||||
|
||||
#define MAX_BITPOOL 64
|
||||
#define MIN_BITPOOL 2
|
||||
@ -64,6 +75,19 @@ struct sbc_codec_cap {
|
||||
uint8_t max_bitpool;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mpeg_codec_cap {
|
||||
struct avdtp_media_codec_capability cap;
|
||||
uint8_t channel_mode:4;
|
||||
uint8_t crc:1;
|
||||
uint8_t layer:3;
|
||||
uint8_t frequency:6;
|
||||
uint8_t mpf:1;
|
||||
uint8_t rfa:1;
|
||||
uint8_t bitrate0:7;
|
||||
uint8_t vbr:1;
|
||||
uint8_t bitrate1;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
|
||||
struct sbc_codec_cap {
|
||||
@ -77,6 +101,19 @@ struct sbc_codec_cap {
|
||||
uint8_t max_bitpool;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mpeg_codec_cap {
|
||||
struct avdtp_media_codec_capability cap;
|
||||
uint8_t layer:3;
|
||||
uint8_t crc:1;
|
||||
uint8_t channel_mode:4;
|
||||
uint8_t rfa:1;
|
||||
uint8_t mpf:1;
|
||||
uint8_t frequency:6;
|
||||
uint8_t vbr:1;
|
||||
uint8_t bitrate0:7;
|
||||
uint8_t bitrate1;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#else
|
||||
#error "Unknown byte order"
|
||||
#endif
|
||||
|
@ -162,8 +162,14 @@ typedef struct {
|
||||
uint8_t max_bitpool;
|
||||
} __attribute__ ((packed)) sbc_capabilities_t;
|
||||
|
||||
/* To be defined */
|
||||
typedef struct {
|
||||
uint8_t channel_mode;
|
||||
uint8_t crc;
|
||||
uint8_t layer;
|
||||
uint8_t frequency;
|
||||
uint8_t mpf;
|
||||
uint8_t vbr;
|
||||
uint16_t bitrate;
|
||||
} __attribute__ ((packed)) mpeg_capabilities_t;
|
||||
|
||||
struct bt_getcapabilities_rsp {
|
||||
|
88
audio/sink.c
88
audio/sink.c
@ -193,28 +193,28 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep,
|
||||
static uint8_t default_bitpool(uint8_t freq, uint8_t mode)
|
||||
{
|
||||
switch (freq) {
|
||||
case A2DP_SAMPLING_FREQ_16000:
|
||||
case A2DP_SAMPLING_FREQ_32000:
|
||||
case SBC_SAMPLING_FREQ_16000:
|
||||
case SBC_SAMPLING_FREQ_32000:
|
||||
return 53;
|
||||
case A2DP_SAMPLING_FREQ_44100:
|
||||
case SBC_SAMPLING_FREQ_44100:
|
||||
switch (mode) {
|
||||
case A2DP_CHANNEL_MODE_MONO:
|
||||
case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
|
||||
case SBC_CHANNEL_MODE_MONO:
|
||||
case SBC_CHANNEL_MODE_DUAL_CHANNEL:
|
||||
return 31;
|
||||
case A2DP_CHANNEL_MODE_STEREO:
|
||||
case A2DP_CHANNEL_MODE_JOINT_STEREO:
|
||||
case SBC_CHANNEL_MODE_STEREO:
|
||||
case SBC_CHANNEL_MODE_JOINT_STEREO:
|
||||
return 53;
|
||||
default:
|
||||
error("Invalid channel mode %u", mode);
|
||||
return 53;
|
||||
}
|
||||
case A2DP_SAMPLING_FREQ_48000:
|
||||
case SBC_SAMPLING_FREQ_48000:
|
||||
switch (mode) {
|
||||
case A2DP_CHANNEL_MODE_MONO:
|
||||
case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
|
||||
case SBC_CHANNEL_MODE_MONO:
|
||||
case SBC_CHANNEL_MODE_DUAL_CHANNEL:
|
||||
return 29;
|
||||
case A2DP_CHANNEL_MODE_STEREO:
|
||||
case A2DP_CHANNEL_MODE_JOINT_STEREO:
|
||||
case SBC_CHANNEL_MODE_STEREO:
|
||||
case SBC_CHANNEL_MODE_JOINT_STEREO:
|
||||
return 51;
|
||||
default:
|
||||
error("Invalid channel mode %u", mode);
|
||||
@ -236,58 +236,58 @@ static gboolean select_sbc_params(struct sbc_codec_cap *cap,
|
||||
cap->cap.media_type = AVDTP_MEDIA_TYPE_AUDIO;
|
||||
cap->cap.media_codec_type = A2DP_CODEC_SBC;
|
||||
|
||||
if (supported->frequency & A2DP_SAMPLING_FREQ_44100)
|
||||
cap->frequency = A2DP_SAMPLING_FREQ_44100;
|
||||
else if (supported->frequency & A2DP_SAMPLING_FREQ_48000)
|
||||
cap->frequency = A2DP_SAMPLING_FREQ_48000;
|
||||
else if (supported->frequency & A2DP_SAMPLING_FREQ_32000)
|
||||
cap->frequency = A2DP_SAMPLING_FREQ_32000;
|
||||
else if (supported->frequency & A2DP_SAMPLING_FREQ_16000)
|
||||
cap->frequency = A2DP_SAMPLING_FREQ_16000;
|
||||
if (supported->frequency & SBC_SAMPLING_FREQ_44100)
|
||||
cap->frequency = SBC_SAMPLING_FREQ_44100;
|
||||
else if (supported->frequency & SBC_SAMPLING_FREQ_48000)
|
||||
cap->frequency = SBC_SAMPLING_FREQ_48000;
|
||||
else if (supported->frequency & SBC_SAMPLING_FREQ_32000)
|
||||
cap->frequency = SBC_SAMPLING_FREQ_32000;
|
||||
else if (supported->frequency & SBC_SAMPLING_FREQ_16000)
|
||||
cap->frequency = SBC_SAMPLING_FREQ_16000;
|
||||
else {
|
||||
error("No supported frequencies");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (supported->channel_mode & A2DP_CHANNEL_MODE_JOINT_STEREO)
|
||||
cap->channel_mode = A2DP_CHANNEL_MODE_JOINT_STEREO;
|
||||
else if (supported->channel_mode & A2DP_CHANNEL_MODE_STEREO)
|
||||
cap->channel_mode = A2DP_CHANNEL_MODE_STEREO;
|
||||
else if (supported->channel_mode & A2DP_CHANNEL_MODE_DUAL_CHANNEL)
|
||||
cap->channel_mode = A2DP_CHANNEL_MODE_DUAL_CHANNEL;
|
||||
else if (supported->channel_mode & A2DP_CHANNEL_MODE_MONO)
|
||||
cap->channel_mode = A2DP_CHANNEL_MODE_MONO;
|
||||
if (supported->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO)
|
||||
cap->channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO;
|
||||
else if (supported->channel_mode & SBC_CHANNEL_MODE_STEREO)
|
||||
cap->channel_mode = SBC_CHANNEL_MODE_STEREO;
|
||||
else if (supported->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL)
|
||||
cap->channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL;
|
||||
else if (supported->channel_mode & SBC_CHANNEL_MODE_MONO)
|
||||
cap->channel_mode = SBC_CHANNEL_MODE_MONO;
|
||||
else {
|
||||
error("No supported channel modes");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (supported->block_length & A2DP_BLOCK_LENGTH_16)
|
||||
cap->block_length = A2DP_BLOCK_LENGTH_16;
|
||||
else if (supported->block_length & A2DP_BLOCK_LENGTH_12)
|
||||
cap->block_length = A2DP_BLOCK_LENGTH_12;
|
||||
else if (supported->block_length & A2DP_BLOCK_LENGTH_8)
|
||||
cap->block_length = A2DP_BLOCK_LENGTH_8;
|
||||
else if (supported->block_length & A2DP_BLOCK_LENGTH_4)
|
||||
cap->block_length = A2DP_BLOCK_LENGTH_4;
|
||||
if (supported->block_length & SBC_BLOCK_LENGTH_16)
|
||||
cap->block_length = SBC_BLOCK_LENGTH_16;
|
||||
else if (supported->block_length & SBC_BLOCK_LENGTH_12)
|
||||
cap->block_length = SBC_BLOCK_LENGTH_12;
|
||||
else if (supported->block_length & SBC_BLOCK_LENGTH_8)
|
||||
cap->block_length = SBC_BLOCK_LENGTH_8;
|
||||
else if (supported->block_length & SBC_BLOCK_LENGTH_4)
|
||||
cap->block_length = SBC_BLOCK_LENGTH_4;
|
||||
else {
|
||||
error("No supported block lengths");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (supported->subbands & A2DP_SUBBANDS_8)
|
||||
cap->subbands = A2DP_SUBBANDS_8;
|
||||
else if (supported->subbands & A2DP_SUBBANDS_4)
|
||||
cap->subbands = A2DP_SUBBANDS_4;
|
||||
if (supported->subbands & SBC_SUBBANDS_8)
|
||||
cap->subbands = SBC_SUBBANDS_8;
|
||||
else if (supported->subbands & SBC_SUBBANDS_4)
|
||||
cap->subbands = SBC_SUBBANDS_4;
|
||||
else {
|
||||
error("No supported subbands");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (supported->allocation_method & A2DP_ALLOCATION_LOUDNESS)
|
||||
cap->allocation_method = A2DP_ALLOCATION_LOUDNESS;
|
||||
else if (supported->allocation_method & A2DP_ALLOCATION_SNR)
|
||||
cap->allocation_method = A2DP_ALLOCATION_SNR;
|
||||
if (supported->allocation_method & SBC_ALLOCATION_LOUDNESS)
|
||||
cap->allocation_method = SBC_ALLOCATION_LOUDNESS;
|
||||
else if (supported->allocation_method & SBC_ALLOCATION_SNR)
|
||||
cap->allocation_method = SBC_ALLOCATION_SNR;
|
||||
|
||||
min_bitpool = MAX(MIN_BITPOOL, supported->min_bitpool);
|
||||
max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode),
|
||||
|
19
audio/unix.c
19
audio/unix.c
@ -341,6 +341,7 @@ static void a2dp_discovery_complete(struct avdtp *session, GSList *seps,
|
||||
struct bt_getcapabilities_rsp *rsp = (void *) buf;
|
||||
struct a2dp_data *a2dp = &client->d.a2dp;
|
||||
struct sbc_codec_cap *sbc_cap = NULL;
|
||||
struct mpeg_codec_cap *mpeg_cap = NULL;
|
||||
GSList *l;
|
||||
|
||||
if (err)
|
||||
@ -364,10 +365,11 @@ static void a2dp_discovery_complete(struct avdtp *session, GSList *seps,
|
||||
|
||||
codec_cap = (void *) cap->data;
|
||||
|
||||
if (codec_cap->media_codec_type == A2DP_CODEC_SBC && !sbc_cap) {
|
||||
if (codec_cap->media_codec_type == A2DP_CODEC_SBC && !sbc_cap)
|
||||
sbc_cap = (void *) codec_cap;
|
||||
break;
|
||||
}
|
||||
|
||||
if (codec_cap->media_codec_type == A2DP_CODEC_MPEG12 && !mpeg_cap)
|
||||
mpeg_cap = (void *) codec_cap;
|
||||
}
|
||||
|
||||
/* endianess prevent direct cast */
|
||||
@ -381,6 +383,17 @@ static void a2dp_discovery_complete(struct avdtp *session, GSList *seps,
|
||||
rsp->sbc_capabilities.max_bitpool = sbc_cap->max_bitpool;
|
||||
}
|
||||
|
||||
if (mpeg_cap) {
|
||||
rsp->mpeg_capabilities.channel_mode = mpeg_cap->channel_mode;
|
||||
rsp->mpeg_capabilities.crc = mpeg_cap->crc;
|
||||
rsp->mpeg_capabilities.layer = mpeg_cap->layer;
|
||||
rsp->mpeg_capabilities.frequency = mpeg_cap->frequency;
|
||||
rsp->mpeg_capabilities.mpf = mpeg_cap->mpf;
|
||||
rsp->mpeg_capabilities.vbr = mpeg_cap->vbr;
|
||||
rsp->mpeg_capabilities.bitrate = mpeg_cap->bitrate1 &
|
||||
mpeg_cap->bitrate0 << 8;
|
||||
}
|
||||
|
||||
unix_ipc_sendmsg(client, &rsp->rsp_h.msg_h);
|
||||
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user