[PATCH v2 2/5] android/hal-audio: Add encode_mediapacket function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch moves code which encodes data for media packet into single
function. It will simply try to put as much encoded frames as will fit
in provided media packet buffer. This is first step to make common code
responsible for media stream write and synchronizarion instead of codec
abstraction code as it is handled now.
---
 android/hal-audio.c | 102 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 57 insertions(+), 45 deletions(-)

diff --git a/android/hal-audio.c b/android/hal-audio.c
index f6bc998..cf49514 100644
--- a/android/hal-audio.c
+++ b/android/hal-audio.c
@@ -129,6 +129,7 @@ struct sbc_data {
 	size_t in_frame_len;
 	size_t in_buf_size;
 
+	size_t out_frame_len;
 	size_t out_buf_size;
 	uint8_t *out_buf;
 
@@ -417,6 +418,7 @@ static int sbc_codec_init(struct audio_preset *preset, uint16_t mtu,
 	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->out_buf_size = hdr_len + num_frames * out_frame_len;
 	sbc_data->out_buf = calloc(1, sbc_data->out_buf_size);
 
@@ -536,75 +538,85 @@ static int write_media_packet(int fd, struct sbc_data *sbc_data,
 	return ret;
 }
 
+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)
+{
+	struct sbc_data *sbc_data = (struct sbc_data *) codec_data;
+	size_t consumed = 0;
+	size_t encoded = 0;
+	uint8_t frame_count = 0;
+
+	while (len - consumed >= sbc_data->in_frame_len &&
+			mp_data_len - encoded >= sbc_data->out_frame_len &&
+			frame_count < MAX_FRAMES_IN_PAYLOAD) {
+		ssize_t read;
+		ssize_t written = 0;
+
+		read = sbc_encode(&sbc_data->enc, buffer + consumed,
+				sbc_data->in_frame_len, mp->data + encoded,
+				mp_data_len - encoded, &written);
+
+		if (read < 0) {
+			error("SBC: failed to encode block at frame %d (%zd)",
+							frame_count, read);
+			break;
+		}
+
+		frame_count++;
+		consumed += read;
+		encoded += written;
+	}
+
+	*written = encoded;
+	mp->payload.frame_count = frame_count;
+
+	return consumed;
+}
+
 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);
-	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;
+	while (consumed < bytes) {
+		size_t written = 0;
+		ssize_t read;
+		int ret;
 
-		bytes_read = sbc_encode(&sbc_data->enc, buffer + consumed,
-					sbc_data->in_frame_len,
-					mp->data + encoded, free_space,
-					&written);
+		read = sbc_encode_mediapacket(codec_data, buffer + consumed,
+						bytes - consumed, mp,
+						free_space,
+						&written);
 
-		if (bytes_read < 0) {
-			error("SBC: failed to encode block (%zd)", bytes_read);
-			break;
+		if (read <= 0) {
+			error("sbc_encode_mediapacket failed (%zd)", read);
+			goto done;
 		}
 
-		mp->payload.frame_count++;
+		consumed += read;
 
-		consumed += bytes_read;
-		encoded += written;
-		free_space -= written;
+		mp->hdr.sequence_number = htons(sbc_data->seq++);
+		mp->hdr.timestamp = htonl(sbc_data->timestamp);
 
 		/* AudioFlinger provides PCM 16bit stereo only, thus sample size
 		 * is always 4 bytes
 		 */
-		sbc_data->timestamp += (bytes_read / 4);
+		sbc_data->timestamp += (read / 4);
 
-		/* write data if we either filled media packed or encoded all
-		 * input data
-		 */
-		if (mp->payload.frame_count == sbc_data->frames_per_packet ||
-				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;
-
-			encoded = 0;
-			free_space = sbc_data->out_buf_size - sizeof(*mp);
-			mp->hdr.timestamp = htonl(sbc_data->timestamp);
-			mp->payload.frame_count = 0;
-		}
-	}
-
-	if (consumed != bytes) {
-		/* we should encode all input data
-		 * if we did not, something went wrong but we can't really
-		 * handle this so this is just sanity check
-		 */
-		error("SBC: failed to encode complete input buffer");
+		ret = write_media_packet(fd, sbc_data, mp, written);
+		if (ret < 0)
+			return ret;
 	}
 
+done:
 	/* we always assume that all data was processed and sent */
 	return bytes;
 }
-- 
1.8.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux