bluez5: sources should produce full buffer every cycle

On underflow in sources, pad with explicit silence.  This avoids the
audioadapter from getting off sync from the cycle. That causes problems
as driver when we want to produce a buffer only a the start of the
cycle.

In some cases, it's also possible that the io already has buffer at the
start of the cycle when rate matching as driver. Currently, we don't
produce buffer in this case, but we should.  Fix that by doing things in
the exact same way as ALSA sources do.
This commit is contained in:
Pauli Virtanen 2023-02-04 15:49:13 +02:00 committed by P V
parent 5ab1d898ca
commit 34d8466c8c
2 changed files with 26 additions and 11 deletions

View file

@ -628,8 +628,9 @@ static void media_on_timeout(struct spa_source *source)
}
if (port->io) {
int io_status = port->io->status;
int status = produce_buffer(this);
spa_log_trace(this->log, "%p: io:%d status:%d", this, port->io->status, status);
spa_log_trace(this->log, "%p: io:%d->%d status:%d", this, io_status, port->io->status, status);
}
spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA);
@ -1392,7 +1393,7 @@ static void process_buffering(struct impl *this)
buf = spa_bt_decode_buffer_get_read(&port->buffer, &avail);
/* copy data to buffers */
if (!spa_list_is_empty(&port->free) && avail > 0) {
if (!spa_list_is_empty(&port->free)) {
struct buffer *buffer;
struct spa_data *datas;
uint32_t data_size;
@ -1419,15 +1420,19 @@ static void process_buffering(struct impl *this)
spa_assert(datas[0].maxsize >= data_size);
datas[0].chunk->offset = 0;
datas[0].chunk->size = avail;
datas[0].chunk->size = data_size;
datas[0].chunk->stride = port->frame_size;
memcpy(datas[0].data, buf, avail);
this->sample_count += avail / port->frame_size;
/* pad with silence */
if (avail < data_size)
memset(SPA_PTROFF(datas[0].data, avail, void), 0, data_size - avail);
this->sample_count += samples;
/* ready buffer if full */
spa_log_trace(this->log, "queue %d frames:%d", buffer->id, (int)avail / port->frame_size);
spa_log_trace(this->log, "queue %d frames:%d", buffer->id, (int)samples);
spa_list_append(&port->ready, &buffer->link);
}
}
@ -1442,7 +1447,8 @@ static int produce_buffer(struct impl *this)
return -EIO;
/* Return if we already have a buffer */
if (io->status == SPA_STATUS_HAVE_DATA)
if (io->status == SPA_STATUS_HAVE_DATA &&
(this->following || port->rate_match == NULL))
return SPA_STATUS_HAVE_DATA;
/* Recycle */

View file

@ -622,8 +622,9 @@ static void sco_on_timeout(struct spa_source *source)
}
if (port->io) {
int io_status = port->io->status;
int status = produce_buffer(this);
spa_log_trace(this->log, "%p: io:%d status:%d", this, port->io->status, status);
spa_log_trace(this->log, "%p: io:%d->%d status:%d", this, io_status, port->io->status, status);
}
spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA);
@ -1258,7 +1259,7 @@ static void process_buffering(struct impl *this)
buf = spa_bt_decode_buffer_get_read(&port->buffer, &avail);
/* copy data to buffers */
if (!spa_list_is_empty(&port->free) && avail > 0) {
if (!spa_list_is_empty(&port->free)) {
struct buffer *buffer;
struct spa_data *datas;
uint32_t data_size;
@ -1279,12 +1280,17 @@ static void process_buffering(struct impl *this)
spa_assert(datas[0].maxsize >= data_size);
datas[0].chunk->offset = 0;
datas[0].chunk->size = avail;
datas[0].chunk->size = data_size;
datas[0].chunk->stride = port->frame_size;
memcpy(datas[0].data, buf, avail);
/* pad with silence */
if (avail < data_size)
memset(SPA_PTROFF(datas[0].data, avail, void), 0, data_size - avail);
/* ready buffer if full */
spa_log_trace(this->log, "queue %d frames:%d", buffer->id, (int)avail / port->frame_size);
spa_log_trace(this->log, "queue %d frames:%d", buffer->id, (int)samples);
spa_list_append(&port->ready, &buffer->link);
}
}
@ -1299,7 +1305,8 @@ static int produce_buffer(struct impl *this)
return -EIO;
/* Return if we already have a buffer */
if (io->status == SPA_STATUS_HAVE_DATA)
if (io->status == SPA_STATUS_HAVE_DATA &&
(this->following || port->rate_match == NULL))
return SPA_STATUS_HAVE_DATA;
/* Recycle */
@ -1340,6 +1347,8 @@ static int impl_node_process(void *object)
if ((io = port->io) == NULL)
return -EIO;
spa_log_trace(this->log, "%p status:%d", this, io->status);
/* Return if we already have a buffer */
if (io->status == SPA_STATUS_HAVE_DATA)
return SPA_STATUS_HAVE_DATA;