Diff between 068c5e3f8158adc3a50517e9436371e5d465798a and 51ca1c6c923bcca2b66d60cffec72dfd2e442551

Changed Files

File Additions Deletions Status
android/hal-audio.c +102 -6 modified

Full Patch

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 60d66c1..9d94f91 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -51,7 +51,15 @@ struct audio_input_config {
 	audio_format_t format;
 };
 
+struct sbc_data {
+	a2dp_sbc_t sbc;
+};
+
 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_cleanup(void *codec_data);
+static int sbc_get_config(void *codec_data,
+					struct audio_input_config *config);
 
 struct audio_codec {
 	uint8_t type;
@@ -71,6 +79,10 @@ static const struct audio_codec audio_codecs[] = {
 		.type = A2DP_CODEC_SBC,
 
 		.get_presets = sbc_get_presets,
+
+		.init = sbc_init,
+		.cleanup = sbc_cleanup,
+		.get_config = sbc_get_config,
 	}
 };
 
@@ -99,6 +111,7 @@ struct a2dp_stream_out {
 
 	struct audio_endpoint *ep;
 	enum a2dp_state_t audio_state;
+	struct audio_input_config cfg;
 };
 
 struct a2dp_audio_dev {
@@ -171,6 +184,64 @@ 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)
+{
+	struct sbc_data *sbc_data;
+
+	DBG("");
+
+	if (preset->len != sizeof(a2dp_sbc_t)) {
+		DBG("preset size mismatch");
+		return AUDIO_STATUS_FAILED;
+	}
+
+	sbc_data = calloc(sizeof(struct sbc_data), 1);
+
+	memcpy(&sbc_data->sbc, preset->data, preset->len);
+
+	*codec_data = sbc_data;
+
+	return AUDIO_STATUS_SUCCESS;
+}
+
+static int sbc_cleanup(void *codec_data)
+{
+	DBG("");
+
+	free(codec_data);
+
+	return AUDIO_STATUS_SUCCESS;
+}
+
+static int sbc_get_config(void *codec_data,
+					struct audio_input_config *config)
+{
+	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+
+	switch (sbc_data->sbc.frequency) {
+	case SBC_SAMPLING_FREQ_16000:
+		config->rate = 16000;
+		break;
+	case SBC_SAMPLING_FREQ_32000:
+		config->rate = 32000;
+		break;
+	case SBC_SAMPLING_FREQ_44100:
+		config->rate = 44100;
+		break;
+	case SBC_SAMPLING_FREQ_48000:
+		config->rate = 48000;
+		break;
+	default:
+		return AUDIO_STATUS_FAILED;
+	}
+	config->channels = sbc_data->sbc.channel_mode == SBC_CHANNEL_MODE_MONO ?
+				AUDIO_CHANNEL_OUT_MONO :
+				AUDIO_CHANNEL_OUT_STEREO;
+	config->format = AUDIO_FORMAT_PCM_16_BIT;
+
+	return AUDIO_STATUS_SUCCESS;
+}
+
 static void audio_ipc_cleanup(void)
 {
 	if (audio_sk >= 0) {
@@ -507,14 +578,25 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
 
 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
 {
+	struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+
 	DBG("");
-	return -ENOSYS;
+
+	return out->cfg.rate;
 }
 
 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
 {
+	struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+
 	DBG("");
-	return -ENOSYS;
+
+	if (rate != out->cfg.rate) {
+		DBG("cannot set sample rate to %d", rate);
+		return -1;
+	}
+
+	return 0;
 }
 
 static size_t out_get_buffer_size(const struct audio_stream *stream)
@@ -525,14 +607,20 @@ static size_t out_get_buffer_size(const struct audio_stream *stream)
 
 static uint32_t out_get_channels(const struct audio_stream *stream)
 {
+	struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+
 	DBG("");
-	return -ENOSYS;
+
+	return out->cfg.channels;
 }
 
 static audio_format_t out_get_format(const struct audio_stream *stream)
 {
+	struct a2dp_stream_out *out = (struct a2dp_stream_out *) stream;
+
 	DBG("");
-	return -ENOSYS;
+
+	return out->cfg.format;
 }
 
 static int out_set_format(struct audio_stream *stream, audio_format_t format)
@@ -758,6 +846,7 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 	struct a2dp_audio_dev *a2dp_dev = (struct a2dp_audio_dev *) dev;
 	struct a2dp_stream_out *out;
 	struct audio_preset *preset;
+	const struct audio_codec *codec;
 
 	out = calloc(1, sizeof(struct a2dp_stream_out));
 	if (!out)
@@ -791,7 +880,13 @@ static int audio_open_output_stream(struct audio_hw_device *dev,
 	if (!preset)
 		goto fail;
 
-	/* TODO: initialize codec using received audio_preset */
+	codec = out->ep->codec;
+
+	codec->init(preset, &out->ep->codec_data);
+	codec->get_config(out->ep->codec_data, &out->cfg);
+
+	DBG("rate=%d channels=%d format=%d", out->cfg.rate,
+			out->cfg.channels, out->cfg.format);
 
 	free(preset);
 
@@ -818,7 +913,8 @@ static void audio_close_output_stream(struct audio_hw_device *dev,
 
 	ipc_close_stream_cmd(ep->id);
 
-	/* TODO: cleanup codec */
+	ep->codec->cleanup(ep->codec_data);
+	ep->codec_data = NULL;
 
 	free(stream);
 	a2dp_dev->out = NULL;