[RFC 3/3] android/hal-sco: Add SCO packet cache

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

 



From: Andrei Emeltchenko <andrei.emeltchenko@xxxxxxxxx>

SCO cached is used when Android writes with packet sizes which cannot
fit to 48 bytes SCO frames. Remaining frames are cached and written next
time Android perform out->write().
---
 android/hal-sco.c | 38 +++++++++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/android/hal-sco.c b/android/hal-sco.c
index 3c6e5bf..5cd63c2 100644
--- a/android/hal-sco.c
+++ b/android/hal-sco.c
@@ -64,6 +64,9 @@ struct sco_stream_out {
 	int fd;
 
 	uint8_t *downmix_buf;
+	uint8_t *cache;
+	size_t cache_len;
+
 	size_t samples;
 	struct timespec start;
 
@@ -301,6 +304,7 @@ static bool write_data(struct sco_stream_out *out, const uint8_t *buffer,
 	size_t len, written = 0;
 	int ret;
 	uint16_t mtu = out->cfg.mtu;
+	uint8_t *p;
 	uint64_t audio_sent_us, audio_passed_us;
 
 	pfd.fd = out->fd;
@@ -320,6 +324,7 @@ static bool write_data(struct sco_stream_out *out, const uint8_t *buffer,
 			return false;
 		}
 
+		len = bytes - written > mtu ? mtu : bytes - written;
 
 		clock_gettime(CLOCK_REALTIME, &now);
 		/* Mark start of the stream */
@@ -341,12 +346,30 @@ static bool write_data(struct sco_stream_out *out, const uint8_t *buffer,
 			memcpy(&out->start, &now, sizeof(out->start));
 		}
 
+		if (out->cache_len) {
+			DBG("First packet cache_len %zd", out->cache_len);
+			memcpy(out->cache + out->cache_len, buffer,
+							mtu - out->cache_len);
+			p = out->cache;
+		}
 
-		len = bytes - written > mtu ? mtu : bytes - written;
+		if (bytes - written >= mtu)
+			p = (void *) buffer + written;
+		else {
+			memcpy(out->cache, buffer + written, bytes - written);
+			out->cache_len = bytes - written;
+			DBG("Last packet, cache %zd bytes", bytes - written);
+			written += bytes - written;
+			continue;
+		}
 
-		ret = write(out->fd, buffer + written, len);
+		ret = write(out->fd, p, len);
 		if (ret > 0) {
-			written += ret;
+			if (out->cache_len) {
+				written = mtu - out->cache_len;
+				out->cache_len = 0;
+			} else
+				written += ret;
 
 			out->samples += ret / 2;
 
@@ -604,6 +627,13 @@ static int sco_open_output_stream(struct audio_hw_device *dev,
 		return -ENOMEM;
 	}
 
+	out->cache = malloc(out->cfg.mtu);
+	if (!out->cache) {
+		free(out->downmix_buf);
+		free(out);
+		return -ENOMEM;
+	}
+
 	DBG("size %zd", out_get_buffer_size(&out->stream.common));
 
 	/* Channel numbers for resampler */
@@ -647,6 +677,7 @@ static int sco_open_output_stream(struct audio_hw_device *dev,
 
 	return 0;
 failed:
+	free(out->cache);
 	free(out->downmix_buf);
 	free(out);
 	stream_out = NULL;
@@ -668,6 +699,7 @@ static void sco_close_output_stream(struct audio_hw_device *dev,
 		sco_dev->out->fd = -1;
 	}
 
+	free(out->cache);
 	free(out->downmix_buf);
 	free(out);
 	sco_dev->out = NULL;
-- 
1.8.3.2

--
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