2014-01-20 14:58:54

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 0/9] android: Add SBC encoding

Hi,

v1 -> v2
- fixed comments
- added dependency to libsbc shared library on Android

Note that configure.ac requires SBC 1.2 which does not exist at the
moment, but I added this since now sbc_init_a2dp() is used which
does not exist in SBC 1.1 and requires patches from Luiz to be
merged so I expect that we'll have SBC 1,2 once this is done (if
accepted, of course).


Andrzej Kaczmarek (9):
android: Add MTU data to Open Stream Audio IPC
android: Build Audio HAL with SBC
android/hal-audio: Rename sbc_init to avoid collision with libsbc
android/hal-audio: Initialize SBC encoder
android/hal-audio: Calculate SBC stream parameters
android/hal-audio: Add resume to codec callbacks
android/hal-audio: Return proper buffer size to AudioFlinger
android/hal-audio: Read fd from Output Stream response
android/hal-audio: Add proper SBC encoding

android/Android.mk | 7 +-
android/Makefile.am | 2 +
android/a2dp.c | 8 +-
android/audio-msg.h | 1 +
android/hal-audio.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++---
configure.ac | 7 ++
6 files changed, 278 insertions(+), 17 deletions(-)

--
1.8.5.2



2014-01-20 14:59:00

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 6/9] android/hal-audio: Add resume to codec callbacks

Once stream is resumed it may be required to reset some state of codec,
i.e. in case of SBC we need to reset monotonic clock and frames count
which are used for synchronization.
---
android/hal-audio.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 22dff53..adceab8 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -124,6 +124,9 @@ struct sbc_data {
uint8_t *out_buf;

unsigned frame_duration;
+
+ struct timespec start;
+ unsigned frames_sent;
};

static int sbc_get_presets(struct audio_preset *preset, size_t *len);
@@ -132,6 +135,7 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
static int sbc_cleanup(void *codec_data);
static int sbc_get_config(void *codec_data,
struct audio_input_config *config);
+static void sbc_resume(void *codec_data);

struct audio_codec {
uint8_t type;
@@ -143,6 +147,7 @@ struct audio_codec {
int (*cleanup) (void *codec_data);
int (*get_config) (void *codec_data,
struct audio_input_config *config);
+ void (*resume) (void *codec_data);
ssize_t (*write_data) (void *codec_data, const void *buffer,
size_t bytes);
};
@@ -156,6 +161,7 @@ static const struct audio_codec audio_codecs[] = {
.init = sbc_codec_init,
.cleanup = sbc_cleanup,
.get_config = sbc_get_config,
+ .resume = sbc_resume,
}
};

@@ -351,6 +357,17 @@ static int sbc_get_config(void *codec_data,
return AUDIO_STATUS_SUCCESS;
}

+static void sbc_resume(void *codec_data)
+{
+ struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
+ DBG("");
+
+ clock_gettime(CLOCK_MONOTONIC, &sbc_data->start);
+
+ sbc_data->frames_sent = 0;
+}
+
static void audio_ipc_cleanup(void)
{
if (audio_sk >= 0) {
@@ -673,6 +690,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
if (ipc_resume_stream_cmd(out->ep->id) != AUDIO_STATUS_SUCCESS)
return -1;

+ out->ep->codec->resume(out->ep->codec_data);
+
out->audio_state = AUDIO_A2DP_STATE_STARTED;
}

--
1.8.5.2


2014-01-20 14:59:03

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 9/9] android/hal-audio: Add proper SBC encoding

Input and output stream is configured in a way that each input buffer
can be encoded to exactly one output buffer.

Reading from AudioFlinger is synchronized based on amounts of frames
which were expected to be sent since stream was resumed, i.e. as long
as we sent enough data we can wait for period of single media packet
before we need another buffer from input. Without synchronization
we'd receive next input buffer as soon as we process current one.
---
android/hal-audio.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 93 insertions(+), 3 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index f99476d..1f0d22c 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -24,6 +24,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
+#include <arpa/inet.h>

#include <hardware/audio.h>
#include <hardware/hardware.h>
@@ -127,8 +128,22 @@ struct sbc_data {

struct timespec start;
unsigned frames_sent;
+
+ uint16_t seq;
};

+static inline void timespec_diff(struct timespec *a, struct timespec *b,
+ struct timespec *res)
+{
+ res->tv_sec = a->tv_sec - b->tv_sec;
+ res->tv_nsec = a->tv_nsec - b->tv_nsec;
+
+ if (res->tv_nsec < 0) {
+ res->tv_sec--;
+ res->tv_nsec += 1000000000; /* 1sec */
+ }
+}
+
static int sbc_get_presets(struct audio_preset *preset, size_t *len);
static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
void **codec_data);
@@ -137,6 +152,8 @@ static int sbc_get_config(void *codec_data,
struct audio_input_config *config);
static size_t sbc_get_buffer_size(void *codec_data);
static void sbc_resume(void *codec_data);
+static ssize_t sbc_write_data(void *codec_data, const void *buffer,
+ size_t bytes, int fd);

struct audio_codec {
uint8_t type;
@@ -151,7 +168,7 @@ struct audio_codec {
size_t (*get_buffer_size) (void *codec_data);
void (*resume) (void *codec_data);
ssize_t (*write_data) (void *codec_data, const void *buffer,
- size_t bytes);
+ size_t bytes, int fd);
};

static const struct audio_codec audio_codecs[] = {
@@ -165,6 +182,7 @@ static const struct audio_codec audio_codecs[] = {
.get_config = sbc_get_config,
.get_buffer_size = sbc_get_buffer_size,
.resume = sbc_resume,
+ .write_data = sbc_write_data,
}
};

@@ -380,6 +398,74 @@ static void sbc_resume(void *codec_data)
sbc_data->frames_sent = 0;
}

+static ssize_t sbc_write_data(void *codec_data, const void *buffer,
+ size_t bytes, int fd)
+{
+ struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+ size_t consumed = 0;
+ size_t encoded = 0;
+ struct media_packet *mp = (struct media_packet *) sbc_data->out_buf;
+ size_t free_space = sbc_data->out_buf_size - sizeof(*mp);
+ struct timespec cur;
+ struct timespec diff;
+ unsigned expected_frames;
+ int ret;
+
+ 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;
+
+ while (bytes - consumed >= sbc_data->in_frame_len) {
+ ssize_t written = 0;
+
+ ret = sbc_encode(&sbc_data->enc, buffer + consumed,
+ sbc_data->in_frame_len,
+ mp->data + encoded, free_space,
+ &written);
+
+ if (ret < 0) {
+ DBG("failed to encode block");
+ break;
+ }
+
+ mp->payload.frame_count++;
+
+ consumed += ret;
+ encoded += written;
+ free_space -= written;
+ }
+
+ ret = write(fd, mp, sizeof(*mp) + encoded);
+ if (ret < 0) {
+ int err = errno;
+ DBG("error writing data: %d (%s)", err, strerror(err));
+ }
+
+ if (consumed != bytes || free_space != 0) {
+ /*
+ * we should encode all input data and fill output buffer
+ * if we did not, something went wrong but we can't really
+ * handle this so this is just sanity check
+ */
+ DBG("some data were not encoded");
+ }
+
+ sbc_data->frames_sent += mp->payload.frame_count;
+
+ clock_gettime(CLOCK_MONOTONIC, &cur);
+ timespec_diff(&cur, &sbc_data->start, &diff);
+ expected_frames = (diff.tv_sec * 1000000 + diff.tv_nsec / 1000) /
+ sbc_data->frame_duration;
+
+ if (sbc_data->frames_sent >= expected_frames)
+ usleep(sbc_data->frame_duration * mp->payload.frame_count);
+
+ /* we always assume that all data was processed and sent */
+ return bytes;
+}
+
static void audio_ipc_cleanup(void)
{
if (audio_sk >= 0) {
@@ -712,9 +798,13 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
return -1;
}

- /* TODO: encode data using codec */
+ if (out->ep->fd < 0) {
+ DBG("no transport");
+ return -1;
+ }

- return bytes;
+ return out->ep->codec->write_data(out->ep->codec_data, buffer,
+ bytes, out->ep->fd);
}

static uint32_t out_get_sample_rate(const struct audio_stream *stream)
--
1.8.5.2


2014-01-20 14:58:59

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 5/9] android/hal-audio: Calculate SBC stream parameters

This patch adds necessary calculations for SBC stream parameters.

Both input and output buffers are expected to have exact amount of
data to fill single media packet (based on transport channel MTU).

Frame duration will be used to synchronize input and output streams.
---
android/hal-audio.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 97 insertions(+), 6 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 8e932ef..22dff53 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -46,6 +46,66 @@ static pthread_t ipc_th = 0;
static pthread_mutex_t close_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t sk_mutex = PTHREAD_MUTEX_INITIALIZER;

+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct rtp_header {
+ unsigned cc:4;
+ unsigned x:1;
+ unsigned p:1;
+ unsigned v:2;
+
+ unsigned pt:7;
+ unsigned m:1;
+
+ uint16_t sequence_number;
+ uint32_t timestamp;
+ uint32_t ssrc;
+ uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+ unsigned frame_count:4;
+ unsigned rfa0:1;
+ unsigned is_last_fragment:1;
+ unsigned is_first_fragment:1;
+ unsigned is_fragmented:1;
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct rtp_header {
+ unsigned v:2;
+ unsigned p:1;
+ unsigned x:1;
+ unsigned cc:4;
+
+ unsigned m:1;
+ unsigned pt:7;
+
+ uint16_t sequence_number;
+ uint32_t timestamp;
+ uint32_t ssrc;
+ uint32_t csrc[0];
+} __attribute__ ((packed));
+
+struct rtp_payload {
+ unsigned is_fragmented:1;
+ unsigned is_first_fragment:1;
+ unsigned is_last_fragment:1;
+ unsigned rfa0:1;
+ unsigned frame_count:4;
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
+
+struct media_packet {
+ struct rtp_header hdr;
+ struct rtp_payload payload;
+ uint8_t data[0];
+};
+
struct audio_input_config {
uint32_t rate;
uint32_t channels;
@@ -56,10 +116,19 @@ struct sbc_data {
a2dp_sbc_t sbc;

sbc_t enc;
+
+ size_t in_frame_len;
+ size_t in_buf_size;
+
+ size_t out_buf_size;
+ uint8_t *out_buf;
+
+ unsigned frame_duration;
};

static int sbc_get_presets(struct audio_preset *preset, size_t *len);
-static int sbc_codec_init(struct audio_preset *preset, void **codec_data);
+static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
+ void **codec_data);
static int sbc_cleanup(void *codec_data);
static int sbc_get_config(void *codec_data,
struct audio_input_config *config);
@@ -69,7 +138,8 @@ struct audio_codec {

int (*get_presets) (struct audio_preset *preset, size_t *len);

- int (*init) (struct audio_preset *preset, void **codec_data);
+ int (*init) (struct audio_preset *preset, uint16_t mtu,
+ void **codec_data);
int (*cleanup) (void *codec_data);
int (*get_config) (void *codec_data,
struct audio_input_config *config);
@@ -200,9 +270,14 @@ static void sbc_init_encoder(struct sbc_data *sbc_data)
out->bitpool = in->max_bitpool;
}

-static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
+static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
+ void **codec_data)
{
struct sbc_data *sbc_data;
+ size_t hdr_len = sizeof(struct media_packet);
+ size_t in_frame_len;
+ size_t out_frame_len;
+ size_t num_frames;

DBG("");

@@ -217,6 +292,18 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)

sbc_init_encoder(sbc_data);

+ in_frame_len = sbc_get_codesize(&sbc_data->enc);
+ out_frame_len = sbc_get_frame_length(&sbc_data->enc);
+ num_frames = (mtu - hdr_len) / out_frame_len;
+
+ sbc_data->in_frame_len = in_frame_len;
+ sbc_data->in_buf_size = num_frames * in_frame_len;
+
+ sbc_data->out_buf_size = hdr_len + num_frames * out_frame_len;
+ sbc_data->out_buf = calloc(1, sbc_data->out_buf_size);
+
+ sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
+
*codec_data = sbc_data;

return AUDIO_STATUS_SUCCESS;
@@ -229,6 +316,7 @@ static int sbc_cleanup(void *codec_data)
DBG("");

sbc_finish(&sbc_data->enc);
+ free(sbc_data->out_buf);
free(codec_data);

return AUDIO_STATUS_SUCCESS;
@@ -460,7 +548,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
return result;
}

-static int ipc_open_stream_cmd(uint8_t endpoint_id,
+static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
struct audio_preset **caps)
{
char buf[BLUEZ_AUDIO_MTU];
@@ -483,6 +571,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id,
if (result == AUDIO_STATUS_SUCCESS) {
size_t buf_len = sizeof(struct audio_preset) +
rsp->preset[0].len;
+ *mtu = rsp->mtu;
*caps = malloc(buf_len);
memcpy(*caps, &rsp->preset, buf_len);
} else {
@@ -868,6 +957,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
struct a2dp_stream_out *out;
struct audio_preset *preset;
const struct audio_codec *codec;
+ uint16_t mtu;

out = calloc(1, sizeof(struct a2dp_stream_out));
if (!out)
@@ -895,7 +985,8 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
/* TODO: for now we always use endpoint 0 */
out->ep = &audio_endpoints[0];

- if (ipc_open_stream_cmd(out->ep->id, &preset) != AUDIO_STATUS_SUCCESS)
+ if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
+ AUDIO_STATUS_SUCCESS)
goto fail;

if (!preset)
@@ -903,7 +994,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,

codec = out->ep->codec;

- codec->init(preset, &out->ep->codec_data);
+ codec->init(preset, mtu, &out->ep->codec_data);
codec->get_config(out->ep->codec_data, &out->cfg);

DBG("rate=%d channels=%d format=%d", out->cfg.rate,
--
1.8.5.2


2014-01-20 14:58:56

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 2/9] android: Build Audio HAL with SBC

Build for Android requires libsbc to be built as shared library and
includes to be available in external/bluetooth/sbc. Build for host
requires libsbc package to be installed.
---
android/Android.mk | 7 +++++--
android/Makefile.am | 2 ++
configure.ac | 7 +++++++
3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index afa3a51..cf7a224 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -3,8 +3,9 @@ LOCAL_PATH := $(call my-dir)
# Retrieve BlueZ version from configure.ac file
BLUEZ_VERSION := $(shell grep ^AC_INIT $(LOCAL_PATH)/../configure.ac | cpp -P -D'AC_INIT(_,v)=v')

-# Specify pathmap for glib
-pathmap_INCL += glib:external/bluetooth/glib
+# Specify pathmap for glib and sbc
+pathmap_INCL += glib:external/bluetooth/glib \
+ sbc:external/bluetooth/sbc

# Specify common compiler flags
BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
@@ -225,9 +226,11 @@ LOCAL_SRC_FILES := hal-audio.c
LOCAL_C_INCLUDES = \
$(call include-path-for, system-core) \
$(call include-path-for, libhardware) \
+ $(call include-path-for, sbc) \

LOCAL_SHARED_LIBRARIES := \
libcutils \
+ libsbc \

LOCAL_CFLAGS := $(BLUEZ_COMMON_CFLAGS) \

diff --git a/android/Makefile.am b/android/Makefile.am
index 924917a..69ea6d5 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -130,6 +130,8 @@ android_audio_a2dp_default_la_SOURCES = android/audio-msg.h \

android_audio_a2dp_default_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android

+android_audio_a2dp_default_la_LIBADD = @SBC_LIBS@
+
android_audio_a2dp_default_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \
-no-undefined -pthread

diff --git a/configure.ac b/configure.ac
index c85f208..8e4053f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -252,6 +252,13 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
[enable_android=${enableval}])
AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")

+if (test "${enable_android}" = "yes"); then
+ PKG_CHECK_MODULES(SBC, sbc >= 1.2, dummy=yes,
+ AC_MSG_ERROR(SBC library >= 1.2 is required))
+ AC_SUBST(SBC_CFLAGS)
+ AC_SUBST(SBC_LIBS)
+fi
+
AC_DEFINE_UNQUOTED(ANDROID_STORAGEDIR, "${storagedir}/android",
[Directory for the Android daemon storage files])

--
1.8.5.2


2014-01-20 14:59:02

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 8/9] android/hal-audio: Read fd from Output Stream response

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

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 498ca48..f99476d 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -577,7 +577,7 @@ static int ipc_close_cmd(uint8_t endpoint_id)
return result;
}

-static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
+static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu, int *fd,
struct audio_preset **caps)
{
char buf[BLUEZ_AUDIO_MTU];
@@ -595,7 +595,7 @@ static int ipc_open_stream_cmd(uint8_t endpoint_id, uint16_t *mtu,
cmd.id = endpoint_id;

result = audio_ipc_cmd(AUDIO_SERVICE_ID, AUDIO_OP_OPEN_STREAM,
- sizeof(cmd), &cmd, &rsp_len, rsp, NULL);
+ sizeof(cmd), &cmd, &rsp_len, rsp, fd);

if (result == AUDIO_STATUS_SUCCESS) {
size_t buf_len = sizeof(struct audio_preset) +
@@ -992,6 +992,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
struct audio_preset *preset;
const struct audio_codec *codec;
uint16_t mtu;
+ int fd;

out = calloc(1, sizeof(struct a2dp_stream_out));
if (!out)
@@ -1019,13 +1020,15 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
/* TODO: for now we always use endpoint 0 */
out->ep = &audio_endpoints[0];

- if (ipc_open_stream_cmd(out->ep->id, &mtu, &preset) !=
+ if (ipc_open_stream_cmd(out->ep->id, &mtu, &fd, &preset) !=
AUDIO_STATUS_SUCCESS)
goto fail;

- if (!preset)
+ if (!preset || fd < 0)
goto fail;

+ out->ep->fd = fd;
+
codec = out->ep->codec;

codec->init(preset, mtu, &out->ep->codec_data);
@@ -1059,6 +1062,11 @@ static void audio_close_output_stream(struct audio_hw_device *dev,

ipc_close_stream_cmd(ep->id);

+ if (ep->fd >= 0) {
+ close(ep->fd);
+ ep->fd = -1;
+ }
+
ep->codec->cleanup(ep->codec_data);
ep->codec_data = NULL;

--
1.8.5.2


2014-01-20 14:59:01

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 7/9] android/hal-audio: Return proper buffer size to AudioFlinger

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

diff --git a/android/hal-audio.c b/android/hal-audio.c
index adceab8..498ca48 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -135,6 +135,7 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
static int sbc_cleanup(void *codec_data);
static int sbc_get_config(void *codec_data,
struct audio_input_config *config);
+static size_t sbc_get_buffer_size(void *codec_data);
static void sbc_resume(void *codec_data);

struct audio_codec {
@@ -147,6 +148,7 @@ struct audio_codec {
int (*cleanup) (void *codec_data);
int (*get_config) (void *codec_data,
struct audio_input_config *config);
+ size_t (*get_buffer_size) (void *codec_data);
void (*resume) (void *codec_data);
ssize_t (*write_data) (void *codec_data, const void *buffer,
size_t bytes);
@@ -161,6 +163,7 @@ static const struct audio_codec audio_codecs[] = {
.init = sbc_codec_init,
.cleanup = sbc_cleanup,
.get_config = sbc_get_config,
+ .get_buffer_size = sbc_get_buffer_size,
.resume = sbc_resume,
}
};
@@ -357,6 +360,15 @@ static int sbc_get_config(void *codec_data,
return AUDIO_STATUS_SUCCESS;
}

+static size_t sbc_get_buffer_size(void *codec_data)
+{
+ struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
+ DBG("");
+
+ return sbc_data->in_buf_size;
+}
+
static void sbc_resume(void *codec_data)
{
struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
@@ -730,8 +742,11 @@ static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)

static size_t out_get_buffer_size(const struct audio_stream *stream)
{
+ struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+
DBG("");
- return 20 * 512;
+
+ return out->ep->codec->get_buffer_size(out->ep->codec_data);
}

static uint32_t out_get_channels(const struct audio_stream *stream)
--
1.8.5.2


2014-01-20 14:58:58

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 4/9] android/hal-audio: Initialize SBC encoder

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

diff --git a/android/hal-audio.c b/android/hal-audio.c
index f53dba0..8e932ef 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -32,6 +32,7 @@
#include "hal-log.h"
#include "hal-msg.h"
#include "../profiles/audio/a2dp-codecs.h"
+#include <sbc/sbc.h>

static const uint8_t a2dp_src_uuid[] = {
0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
@@ -53,6 +54,8 @@ struct audio_input_config {

struct sbc_data {
a2dp_sbc_t sbc;
+
+ sbc_t enc;
};

static int sbc_get_presets(struct audio_preset *preset, size_t *len);
@@ -184,6 +187,19 @@ static int sbc_get_presets(struct audio_preset *preset, size_t *len)
return i;
}

+static void sbc_init_encoder(struct sbc_data *sbc_data)
+{
+ a2dp_sbc_t *in = &sbc_data->sbc;
+ sbc_t *out = &sbc_data->enc;
+
+ DBG("");
+
+ sbc_init_a2dp(out, 0L, in);
+
+ out->endian = SBC_LE;
+ out->bitpool = in->max_bitpool;
+}
+
static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
{
struct sbc_data *sbc_data;
@@ -199,6 +215,8 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)

memcpy(&sbc_data->sbc, preset->data, preset->len);

+ sbc_init_encoder(sbc_data);
+
*codec_data = sbc_data;

return AUDIO_STATUS_SUCCESS;
@@ -206,8 +224,11 @@ static int sbc_codec_init(struct audio_preset *preset, void **codec_data)

static int sbc_cleanup(void *codec_data)
{
+ struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
DBG("");

+ sbc_finish(&sbc_data->enc);
free(codec_data);

return AUDIO_STATUS_SUCCESS;
--
1.8.5.2


2014-01-20 14:58:57

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 3/9] android/hal-audio: Rename sbc_init to avoid collision with libsbc

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

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 2f6f8c2..f53dba0 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -56,7 +56,7 @@ struct sbc_data {
};

static int sbc_get_presets(struct audio_preset *preset, size_t *len);
-static int sbc_init(struct audio_preset *preset, void **codec_data);
+static int sbc_codec_init(struct audio_preset *preset, void **codec_data);
static int sbc_cleanup(void *codec_data);
static int sbc_get_config(void *codec_data,
struct audio_input_config *config);
@@ -80,7 +80,7 @@ static const struct audio_codec audio_codecs[] = {

.get_presets = sbc_get_presets,

- .init = sbc_init,
+ .init = sbc_codec_init,
.cleanup = sbc_cleanup,
.get_config = sbc_get_config,
}
@@ -184,7 +184,7 @@ static int sbc_get_presets(struct audio_preset *preset, size_t *len)
return i;
}

-static int sbc_init(struct audio_preset *preset, void **codec_data)
+static int sbc_codec_init(struct audio_preset *preset, void **codec_data)
{
struct sbc_data *sbc_data;

--
1.8.5.2


2014-01-20 14:58:55

by Andrzej Kaczmarek

[permalink] [raw]
Subject: [PATCH v2 1/9] android: Add MTU data to Open Stream Audio IPC

MTU value for transport channel is sent in Open Stream response, which
is required to calculate number of frames which can be packed into
single media packet.

This is to avoid including GPLv2 licensed headers in Audio HAL
implementation.
---
android/a2dp.c | 8 ++++++--
android/audio-msg.h | 1 +
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/android/a2dp.c b/android/a2dp.c
index 8ec03c8..5562ba5 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -1297,6 +1297,7 @@ static void bt_stream_open(const void *buf, uint16_t len)
struct audio_rsp_open_stream *rsp;
struct a2dp_setup *setup;
int fd;
+ uint16_t omtu;

DBG("");

@@ -1307,14 +1308,17 @@ static void bt_stream_open(const void *buf, uint16_t len)
return;
}

- if (!avdtp_stream_get_transport(setup->stream, &fd, NULL, NULL, NULL)) {
+ if (!avdtp_stream_get_transport(setup->stream, &fd, NULL, &omtu,
+ NULL)) {
error("avdtp_stream_get_transport: failed");
audio_ipc_send_rsp(AUDIO_OP_OPEN_STREAM, AUDIO_STATUS_FAILED);
return;
}

- len = sizeof(struct audio_preset) + setup->preset->len;
+ len = sizeof(struct audio_rsp_open_stream) +
+ sizeof(struct audio_preset) + setup->preset->len;
rsp = g_malloc0(len);
+ rsp->mtu = omtu;
rsp->preset->len = setup->preset->len;
memcpy(rsp->preset->data, setup->preset->data, setup->preset->len);

diff --git a/android/audio-msg.h b/android/audio-msg.h
index 8f03274..17cde09 100644
--- a/android/audio-msg.h
+++ b/android/audio-msg.h
@@ -63,6 +63,7 @@ struct audio_cmd_open_stream {
} __attribute__((packed));

struct audio_rsp_open_stream {
+ uint16_t mtu;
struct audio_preset preset[0];
} __attribute__((packed));

--
1.8.5.2