summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/a2dp.c30
-rw-r--r--audio/a2dp.h77
-rw-r--r--audio/ipc.h8
-rw-r--r--audio/sink.c88
-rw-r--r--audio/unix.c19
5 files changed, 139 insertions, 83 deletions
diff --git a/audio/a2dp.c b/audio/a2dp.c
index 74699cd5..1c59374f 100644
--- a/audio/a2dp.c
+++ b/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;
diff --git a/audio/a2dp.h b/audio/a2dp.h
index 8227296f..cfd1c47d 100644
--- a/audio/a2dp.h
+++ b/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 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 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 A2DP_SUBBANDS_4 (1 << 1)
-#define A2DP_SUBBANDS_8 1
-
-#define A2DP_ALLOCATION_SNR (1 << 1)
-#define A2DP_ALLOCATION_LOUDNESS 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 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 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 SBC_SUBBANDS_4 (1 << 1)
+#define SBC_SUBBANDS_8 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
diff --git a/audio/ipc.h b/audio/ipc.h
index 3e1200fa..64ed65a7 100644
--- a/audio/ipc.h
+++ b/audio/ipc.h
@@ -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 {
diff --git a/audio/sink.c b/audio/sink.c
index 259abf8f..a95c2e45 100644
--- a/audio/sink.c
+++ b/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),
diff --git a/audio/unix.c b/audio/unix.c
index d9f7c670..2226579d 100644
--- a/audio/unix.c
+++ b/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;