All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrzej Kaczmarek <andrzej.kaczmarek@tieto.com>
To: linux-bluetooth@vger.kernel.org
Cc: Andrzej Kaczmarek <andrzej.kaczmarek@tieto.com>
Subject: [PATCH v2 5/6] android/hal-audio: Add support to control audio quality
Date: Thu, 17 Apr 2014 01:50:37 +0200	[thread overview]
Message-ID: <1397692238-18642-5-git-send-email-andrzej.kaczmarek@tieto.com> (raw)
In-Reply-To: <1397692238-18642-1-git-send-email-andrzej.kaczmarek@tieto.com>

This patch adds new codec abstraction call which can be used to adjust
audio quality while playing. As for now we can either decrease quality
or restore default one.

It's up to actual codec capabilities and implementation how this can be
handled. In case of SBC bitpool is decreased by fixed amount (5) until
min allowable value is reached (33) - the same values are used in
PulseAudio.
---
 android/hal-audio.c | 83 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 67 insertions(+), 16 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index 3ff3b9d..e25aa07 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -47,6 +47,9 @@
 
 #define MAX_DELAY	100000 /* 100ms */
 
+#define SBC_QUALITY_MIN_BITPOOL	33
+#define SBC_QUALITY_STEP	5
+
 static const uint8_t a2dp_src_uuid[] = {
 		0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x10, 0x00,
 		0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb };
@@ -128,6 +131,8 @@ struct sbc_data {
 
 	sbc_t enc;
 
+	uint16_t payload_len;
+
 	size_t in_frame_len;
 	size_t in_buf_size;
 
@@ -189,6 +194,10 @@ static size_t sbc_get_mediapacket_duration(void *codec_data);
 static ssize_t sbc_encode_mediapacket(void *codec_data, const uint8_t *buffer,
 					size_t len, struct media_packet *mp,
 					size_t mp_data_len, size_t *written);
+static bool sbc_update_qos(void *codec_data, uint8_t op);
+
+#define QOS_POLICY_DEFAULT	0x00
+#define QOS_POLICY_DECREASE	0x01
 
 struct audio_codec {
 	uint8_t type;
@@ -205,6 +214,7 @@ struct audio_codec {
 	ssize_t (*encode_mediapacket) (void *codec_data, const uint8_t *buffer,
 					size_t len, struct media_packet *mp,
 					size_t mp_data_len, size_t *written);
+	bool (*update_qos) (void *codec_data, uint8_t op);
 };
 
 static const struct audio_codec audio_codecs[] = {
@@ -219,6 +229,7 @@ static const struct audio_codec audio_codecs[] = {
 		.get_buffer_size = sbc_get_buffer_size,
 		.get_mediapacket_duration = sbc_get_mediapacket_duration,
 		.encode_mediapacket = sbc_encode_mediapacket,
+		.update_qos = sbc_update_qos,
 	}
 };
 
@@ -421,14 +432,33 @@ static void sbc_init_encoder(struct sbc_data *sbc_data)
 			in->min_bitpool, in->max_bitpool);
 }
 
-static int sbc_codec_init(struct audio_preset *preset, uint16_t payload_len,
-							void **codec_data)
+static void sbc_codec_calculate(struct sbc_data *sbc_data)
 {
-	struct sbc_data *sbc_data;
 	size_t in_frame_len;
 	size_t out_frame_len;
 	size_t num_frames;
 
+	in_frame_len = sbc_get_codesize(&sbc_data->enc);
+	out_frame_len = sbc_get_frame_length(&sbc_data->enc);
+	num_frames = sbc_data->payload_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_frame_len = out_frame_len;
+
+	sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
+	sbc_data->frames_per_packet = num_frames;
+
+	DBG("in_frame_len=%zu out_frame_len=%zu frames_per_packet=%zu",
+				in_frame_len, out_frame_len, num_frames);
+}
+
+static int sbc_codec_init(struct audio_preset *preset, uint16_t payload_len,
+							void **codec_data)
+{
+	struct sbc_data *sbc_data;
+
 	if (preset->len != sizeof(a2dp_sbc_t)) {
 		error("SBC: preset size mismatch");
 		return AUDIO_STATUS_FAILED;
@@ -442,20 +472,9 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t payload_len,
 
 	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 = payload_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_frame_len = out_frame_len;
-
-	sbc_data->frame_duration = sbc_get_frame_duration(&sbc_data->enc);
-	sbc_data->frames_per_packet = num_frames;
+	sbc_data->payload_len = payload_len;
 
-	DBG("in_frame_len=%zu out_frame_len=%zu frames_per_packet=%zu",
-				in_frame_len, out_frame_len, num_frames);
+	sbc_codec_calculate(sbc_data);
 
 	*codec_data = sbc_data;
 
@@ -550,6 +569,38 @@ static ssize_t sbc_encode_mediapacket(void *codec_data, const uint8_t *buffer,
 	return consumed;
 }
 
+static bool sbc_update_qos(void *codec_data, uint8_t op)
+{
+	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+	uint8_t curr_bitpool = sbc_data->enc.bitpool;
+	uint8_t new_bitpool = curr_bitpool;
+
+	switch (op) {
+	case QOS_POLICY_DEFAULT:
+		new_bitpool = sbc_data->sbc.max_bitpool;
+		break;
+
+	case QOS_POLICY_DECREASE:
+		if (curr_bitpool > SBC_QUALITY_MIN_BITPOOL) {
+			new_bitpool = curr_bitpool - SBC_QUALITY_STEP;
+			if (new_bitpool < SBC_QUALITY_MIN_BITPOOL)
+				new_bitpool = SBC_QUALITY_MIN_BITPOOL;
+		}
+		break;
+	}
+
+	if (new_bitpool == curr_bitpool)
+		return false;
+
+	sbc_data->enc.bitpool = new_bitpool;
+
+	sbc_codec_calculate(sbc_data);
+
+	info("SBC: bitpool chaged: %d -> %d", curr_bitpool, new_bitpool);
+
+	return true;
+}
+
 static int audio_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len,
 			void *param, size_t *rsp_len, void *rsp, int *fd)
 {
-- 
1.9.2


  parent reply	other threads:[~2014-04-16 23:50 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-16 23:50 [PATCH v2 1/6] android/a2dp: Prefer master role on incoming connections Andrzej Kaczmarek
2014-04-16 23:50 ` [PATCH v2 2/6] android/hal-audio: Add resume_endpoint helper Andrzej Kaczmarek
2014-04-16 23:50 ` [PATCH v2 3/6] android/hal-audio: Make audio socket non-blocking Andrzej Kaczmarek
2014-04-16 23:50 ` [PATCH v2 4/6] android/hal-audio: Resync audio when lagging too much Andrzej Kaczmarek
2014-04-16 23:50 ` Andrzej Kaczmarek [this message]
2014-04-16 23:50 ` [PATCH v2 6/6] android/hal-audio: Adjust audio quality automatically Andrzej Kaczmarek
2014-04-17  7:04 ` [PATCH v2 1/6] android/a2dp: Prefer master role on incoming connections Luiz Augusto von Dentz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1397692238-18642-5-git-send-email-andrzej.kaczmarek@tieto.com \
    --to=andrzej.kaczmarek@tieto.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.