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