diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/bt-rtp.h | 76 | ||||
-rw-r--r-- | src/modules/module-bt-device.c | 32 |
2 files changed, 94 insertions, 14 deletions
diff --git a/src/modules/bt-rtp.h b/src/modules/bt-rtp.h new file mode 100644 index 00000000..690bd43a --- /dev/null +++ b/src/modules/bt-rtp.h @@ -0,0 +1,76 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#if __BYTE_ORDER == __LITTLE_ENDIAN + +struct rtp_header { + uint8_t cc:4; + uint8_t x:1; + uint8_t p:1; + uint8_t v:2; + + uint8_t pt:7; + uint8_t m:1; + + uint16_t sequence_number; + uint32_t timestamp; + uint32_t ssrc; + uint32_t csrc[0]; +} __attribute__ ((packed)); + +struct rtp_payload { + uint8_t frame_count:4; + uint8_t rfa0:1; + uint8_t is_last_fragment:1; + uint8_t is_first_fragment:1; + uint8_t is_fragmented:1; +} __attribute__ ((packed)); + +#elif __BYTE_ORDER == __BIG_ENDIAN + +struct rtp_header { + uint8_t v:2; + uint8_t p:1; + uint8_t x:1; + uint8_t cc:4; + + uint8_t m:1; + uint8_t pt:7; + + uint16_t sequence_number; + uint32_t timestamp; + uint32_t ssrc; + uint32_t csrc[0]; +} __attribute__ ((packed)); + +struct rtp_payload { + uint8_t is_fragmented:1; + uint8_t is_first_fragment:1; + uint8_t is_last_fragment:1; + uint8_t rfa0:1; + uint8_t frame_count:4; +} __attribute__ ((packed)); + +#else +#error "Unknown byte order" +#endif diff --git a/src/modules/module-bt-device.c b/src/modules/module-bt-device.c index e808cfb7..87d6ea60 100644 --- a/src/modules/module-bt-device.c +++ b/src/modules/module-bt-device.c @@ -44,11 +44,15 @@ #include "module-bt-device-symdef.h" #include "bt-ipc.h" #include "bt-sbc.h" +#include "bt-rtp.h" #define DEFAULT_SINK_NAME "bluetooth_sink" #define BUFFER_SIZE 2048 #define MAX_BITPOOL 64 #define MIN_BITPOOL 2 +#define SOL_SCO 17 +#define SCO_TXBUFS 0x03 +#define SCO_RXBUFS 0x04 PA_MODULE_AUTHOR("Joao Paulo Rechi Vita"); PA_MODULE_DESCRIPTION("Bluetooth audio sink and source"); @@ -244,7 +248,7 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) { static int bt_a2dp_init(struct userdata *u) { sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities; - unsigned int max_bitpool, min_bitpool, rate, channels; + unsigned int max_bitpool, min_bitpool; switch (u->rate) { case 48000: @@ -260,14 +264,14 @@ static int bt_a2dp_init(struct userdata *u) { cap->frequency = BT_SBC_SAMPLING_FREQ_16000; break; default: - pa_log_error("Rate %d not supported", rate); + pa_log_error("Rate %d not supported", u->rate); return -1; } // if (cfg->has_channel_mode) // cap->channel_mode = cfg->channel_mode; // else - if (channels == 2) { + if (u->channels == 2) { if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) @@ -364,7 +368,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) { if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; - a2dp->sbc.allocation = active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS; + a2dp->sbc.allocation = (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS); switch (active_capabilities.subbands) { case BT_A2DP_SUBBANDS_4: @@ -392,7 +396,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) { a2dp->sbc.bitpool = active_capabilities.max_bitpool; a2dp->codesize = sbc_get_codesize(&a2dp->sbc); -// a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); + a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); } static int bt_setconf(struct userdata *u) { @@ -457,7 +461,9 @@ static int bt_setconf(struct userdata *u) { } static int bt_getstreamfd(struct userdata *u) { - int e/*, opt_name*/; + int e; +// uint32_t period_count = io->buffer_size / io->period_size; +// struct timeval t = { 0, period_count }; char buf[BT_AUDIO_IPC_PACKET_SIZE]; struct bt_streamstart_req *start_req = (void*) buf; bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; @@ -494,23 +500,20 @@ static int bt_getstreamfd(struct userdata *u) { u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd); if (u->stream_fd < 0) { - pa_log_error("failed to get data fd"); + pa_log_error("failed to get data fd: %s (%d)",pa_cstrerror(errno), errno); return -errno; } // if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { -// opt_name = SO_SNDTIMEO; -// if (setsockopt(u->stream_fd, SOL_SOCKET, opt_name, &t, sizeof(t)) < 0) { -// pa_log_error("failed to set socket options for A2DP"); +// if (setsockopt(u->stream_fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t)) < 0) { +// pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno); // return -errno; // } // } // else { -// opt_name = SCO_TXBUFS; -// if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0) +// if (setsockopt(u->stream_fd, SOL_SCO, SCO_TXBUFS, &period_count, sizeof(period_count)) == 0) // return 0; -// opt_name = SO_SNDBUF; -// if (setsockopt(u->stream_fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0) +// if (setsockopt(u->stream_fd, SOL_SCO, SO_SNDBUF, &period_count, sizeof(period_count)) == 0) // return 0; // /* FIXME : handle error codes */ // } @@ -703,6 +706,7 @@ int pa__init(pa_module* m) { u->transport = -1; u->offset = 0; u->latency = 0; + u->a2dp.sbc_initialized = 0; u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); u->mempool = pa_mempool_new(FALSE); pa_memchunk_reset(&u->memchunk); |