From 9ae63b37bb909c66a931ee3934af1ad87047f326 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 23 Jan 2008 13:11:07 +0000 Subject: Initial support of mpeg12 codec. --- audio/a2dp.c | 30 ++++++++++----------- audio/a2dp.h | 77 ++++++++++++++++++++++++++++++++++++++-------------- audio/ipc.h | 8 +++++- audio/sink.c | 88 ++++++++++++++++++++++++++++++------------------------------ audio/unix.c | 19 ++++++++++--- 5 files changed, 139 insertions(+), 83 deletions(-) (limited to 'audio') 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; -- cgit