Initial support of mpeg12 codec.

This commit is contained in:
Luiz Augusto von Dentz 2008-01-23 13:11:07 +00:00
parent f67d81062c
commit 9ae63b37bb
5 changed files with 135 additions and 79 deletions

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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),

View File

@ -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;