From ff5f6d908b3158edd75f4d970a74e5160cd8da9e Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Mon, 3 Jul 2023 13:00:07 +0300 Subject: [PATCH] bluez: allow buffers with maxsize < duration*frame_size Buffer sizes smaller than one cycle are possible, so don't assert that. Instead, just provide as much samples as fits to the buffer. If we are driver when this happens, emit a warning (once). Similarly to ALSA, as driver we produce only one buffer at cycle start, and no new buffers in process. If the whole cycle doesn't fit into the buffer, recording probably will be broken and we want some debug when there will be a bug report about that. --- spa/plugins/bluez5/media-source.c | 17 ++++++++++++----- spa/plugins/bluez5/sco-source.c | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/spa/plugins/bluez5/media-source.c b/spa/plugins/bluez5/media-source.c index 1f82d2d41..b36d5f573 100644 --- a/spa/plugins/bluez5/media-source.c +++ b/spa/plugins/bluez5/media-source.c @@ -1342,6 +1342,9 @@ static void update_target_latency(struct impl *this) spa_bt_decode_buffer_set_target_latency(&port->buffer, samples); } +#define WARN_ONCE(cond, ...) \ + if (SPA_UNLIKELY(cond)) { static bool __once; if (!__once) { __once = true; spa_log_warn(__VA_ARGS__); } } + static void process_buffering(struct impl *this) { struct port *port = &this->port; @@ -1364,13 +1367,21 @@ static void process_buffering(struct impl *this) struct spa_data *datas; uint32_t data_size; + buffer = spa_list_first(&port->free, struct buffer, link); + datas = buffer->buf->datas; + data_size = samples * port->frame_size; + WARN_ONCE(datas[0].maxsize < data_size && !this->following, + this->log, "source buffer too small (%u < %u)", + datas[0].maxsize, data_size); + + data_size = SPA_MIN(data_size, SPA_ROUND_DOWN(datas[0].maxsize, port->frame_size)); + avail = SPA_MIN(avail, data_size); spa_bt_decode_buffer_read(&port->buffer, avail); - buffer = spa_list_first(&port->free, struct buffer, link); spa_list_remove(&buffer->link); spa_log_trace(this->log, "dequeue %d", buffer->id); @@ -1381,10 +1392,6 @@ static void process_buffering(struct impl *this) buffer->h->dts_offset = 0; } - datas = buffer->buf->datas; - - spa_assert(datas[0].maxsize >= data_size); - datas[0].chunk->offset = 0; datas[0].chunk->size = data_size; datas[0].chunk->stride = port->frame_size; diff --git a/spa/plugins/bluez5/sco-source.c b/spa/plugins/bluez5/sco-source.c index b6573d81e..7ed406600 100644 --- a/spa/plugins/bluez5/sco-source.c +++ b/spa/plugins/bluez5/sco-source.c @@ -1298,6 +1298,9 @@ static uint32_t get_samples(struct impl *this, uint32_t *result_duration) return samples; } +#define WARN_ONCE(cond, ...) \ + if (SPA_UNLIKELY(cond)) { static bool __once; if (!__once) { __once = true; spa_log_warn(__VA_ARGS__); } } + static void process_buffering(struct impl *this) { struct port *port = &this->port; @@ -1318,21 +1321,25 @@ static void process_buffering(struct impl *this) struct spa_data *datas; uint32_t data_size; + buffer = spa_list_first(&port->free, struct buffer, link); + datas = buffer->buf->datas; + data_size = samples * port->frame_size; + WARN_ONCE(datas[0].maxsize < data_size && !this->following, + this->log, "source buffer too small (%u < %u)", + datas[0].maxsize, data_size); + + data_size = SPA_MIN(data_size, SPA_ROUND_DOWN(datas[0].maxsize, port->frame_size)); + avail = SPA_MIN(avail, data_size); spa_bt_decode_buffer_read(&port->buffer, avail); - buffer = spa_list_first(&port->free, struct buffer, link); spa_list_remove(&buffer->link); spa_log_trace(this->log, "dequeue %d", buffer->id); - datas = buffer->buf->datas; - - spa_assert(datas[0].maxsize >= data_size); - datas[0].chunk->offset = 0; datas[0].chunk->size = data_size; datas[0].chunk->stride = port->frame_size;