2014-02-03 15:44:47

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH 1/6] android/hal-audio: Remove unsupported mono channel mode

AudioFlinger can only provide PCM 16bit Stereo data for A2DP track so
we should not advertise mono channel mode in capabilities since we
can't downmix this internally.
---
android/hal-audio.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 8ef5bff..4578c53 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -227,8 +227,7 @@ struct a2dp_audio_dev {
static const a2dp_sbc_t sbc_presets[] = {
{
.frequency = SBC_SAMPLING_FREQ_44100 | SBC_SAMPLING_FREQ_48000,
- .channel_mode = SBC_CHANNEL_MODE_MONO |
- SBC_CHANNEL_MODE_DUAL_CHANNEL |
+ .channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL |
SBC_CHANNEL_MODE_STEREO |
SBC_CHANNEL_MODE_JOINT_STEREO,
.subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8,
--
1.8.5.3



2014-02-03 15:44:48

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH 2/6] android/hal-audio: Be more verbose on SBC errors

---
android/hal-audio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 4578c53..bccaf15 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -466,7 +466,7 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
&written);

if (ret < 0) {
- error("SBC: failed to encode block");
+ error("SBC: failed to encode block (%zd)", bytes_read);
break;
}

--
1.8.5.3


2014-02-03 15:44:52

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH 6/6] android/hal-audio: Add RTP timestamps

---
android/hal-audio.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index ff42136..efdf823 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -133,6 +133,7 @@ struct sbc_data {

struct timespec start;
unsigned frames_sent;
+ uint32_t timestamp;

uint16_t seq;
};
@@ -404,6 +405,7 @@ static void sbc_resume(void *codec_data)
clock_gettime(CLOCK_MONOTONIC, &sbc_data->start);

sbc_data->frames_sent = 0;
+ sbc_data->timestamp = 0;
}

static int write_media_packet(int fd, struct sbc_data *sbc_data,
@@ -455,31 +457,38 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
struct media_packet *mp = (struct media_packet *) sbc_data->out_buf;
size_t free_space = sbc_data->out_buf_size - sizeof(*mp);
int ret;
+ ssize_t bytes_read;

mp->hdr.v = 2;
mp->hdr.pt = 1;
mp->hdr.ssrc = htonl(1);
+ mp->hdr.timestamp = htonl(sbc_data->timestamp);
mp->payload.frame_count = 0;

while (bytes - consumed >= sbc_data->in_frame_len) {
ssize_t written = 0;

- ret = sbc_encode(&sbc_data->enc, buffer + consumed,
+ bytes_read = sbc_encode(&sbc_data->enc, buffer + consumed,
sbc_data->in_frame_len,
mp->data + encoded, free_space,
&written);

- if (ret < 0) {
+ if (bytes_read < 0) {
error("SBC: failed to encode block (%zd)", bytes_read);
break;
}

mp->payload.frame_count++;

- consumed += ret;
+ consumed += bytes_read;
encoded += written;
free_space -= written;

+ /* AudioFlinger provides PCM 16bit stereo only, thus sample size
+ * is always 4 bytes
+ */
+ sbc_data->timestamp += (bytes_read / 4);
+
/* write data if we either filled media packed or encoded all
* input data
*/
@@ -495,6 +504,7 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,

encoded = 0;
free_space = sbc_data->out_buf_size - sizeof(*mp);
+ mp->hdr.timestamp = htonl(sbc_data->timestamp);
mp->payload.frame_count = 0;
}
}
--
1.8.5.3


2014-02-03 15:44:51

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH 5/6] android/hal-audio: Fix RTP sequence numbers

---
android/hal-audio.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index eb064bc..ff42136 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -458,7 +458,6 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,

mp->hdr.v = 2;
mp->hdr.pt = 1;
- mp->hdr.sequence_number = htons(sbc_data->seq++);
mp->hdr.ssrc = htonl(1);
mp->payload.frame_count = 0;

@@ -488,6 +487,8 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
bytes == consumed ||
mp->payload.frame_count ==
MAX_FRAMES_IN_PAYLOAD) {
+ mp->hdr.sequence_number = htons(sbc_data->seq++);
+
ret = write_media_packet(fd, sbc_data, mp, encoded);
if (ret < 0)
return ret;
--
1.8.5.3


2014-02-03 15:44:50

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH 4/6] android/hal-audio: Fix audio with large omtu value

This patch fixes media packet construction with devices which use large
omtu value. In such cases it's possible that we will try to fit more
than 15 SBC frames in single media packet (which is maximum possible
value as it's encoded using 4 bits) which will cause frame counter to
wrap around and provide incorrect data to SBC encoder.

This behaviour was seen on UPF with one of carkit devices which set
omtu=2688.
---
android/hal-audio.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index cda1359..eb064bc 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -39,6 +39,8 @@

#define FIXED_A2DP_PLAYBACK_LATENCY_MS 25

+#define MAX_FRAMES_IN_PAYLOAD 15
+
static const uint8_t a2dp_src_uuid[] = {
0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };
@@ -483,7 +485,9 @@ static ssize_t sbc_write_data(void *codec_data, const void *buffer,
* input data
*/
if (mp->payload.frame_count == sbc_data->frames_per_packet ||
- bytes == consumed) {
+ bytes == consumed ||
+ mp->payload.frame_count ==
+ MAX_FRAMES_IN_PAYLOAD) {
ret = write_media_packet(fd, sbc_data, mp, encoded);
if (ret < 0)
return ret;
--
1.8.5.3


2014-02-03 15:44:49

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH 3/6] android/hal-audio: Print calculated SBC parameters

---
android/hal-audio.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index bccaf15..cda1359 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -332,6 +332,9 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
sbc_data->frames_per_packet = num_frames;

+ DBG("mtu=%u in_frame_len=%zu out_frame_len=%zu frames_per_packet=%zu",
+ mtu, in_frame_len, out_frame_len, num_frames);
+
*codec_data = sbc_data;

return AUDIO_STATUS_SUCCESS;
--
1.8.5.3