bluez5: driver should produce buffers before ready

The graph cycle goes: driver timeout -> process output nodes -> process
driver node.  Hence, driver should produce buffers in the timeout,
otherwise there's one quantum extra latency.

Make the bluez5 media/sco sources as drivers put a buffer to io before
indicating ready, and as follower do it in process. Also make checks if
io == NULL, and don't set io->status to HAVE_DATA unless there really is
a buffer ready.
This commit is contained in:
Pauli Virtanen 2022-10-19 18:38:07 +03:00
parent facf73b01c
commit 2fa3120486
2 changed files with 91 additions and 33 deletions

View file

@ -591,13 +591,14 @@ static int setup_matching(struct impl *this)
return 0;
}
static int produce_buffer(struct impl *this);
static void sco_on_timeout(struct spa_source *source)
{
struct impl *this = source->data;
struct port *port = &this->port;
uint64_t exp, duration;
uint32_t rate;
struct spa_io_buffers *io = port->io;
uint64_t prev_time, now_time;
if (this->transport == NULL)
@ -632,8 +633,11 @@ static void sco_on_timeout(struct spa_source *source)
this->clock->next_nsec = this->next_time;
}
spa_log_trace(this->log, "%p: %d", this, io->status);
io->status = SPA_STATUS_HAVE_DATA;
if (port->io) {
int status = produce_buffer(this);
spa_log_trace(this->log, "%p: io:%d status:%d", this, port->io->status, status);
}
spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA);
set_timeout(this, this->next_time);
@ -1286,17 +1290,13 @@ static void process_buffering(struct impl *this)
}
}
static int impl_node_process(void *object)
static int produce_buffer(struct impl *this)
{
struct impl *this = object;
struct port *port;
struct spa_io_buffers *io;
struct buffer *buffer;
struct port *port = &this->port;
struct spa_io_buffers *io = port->io;
spa_return_val_if_fail(this != NULL, -EINVAL);
port = &this->port;
if ((io = port->io) == NULL)
if (io == NULL)
return -EIO;
/* Return if we already have a buffer */
@ -1309,7 +1309,7 @@ static int impl_node_process(void *object)
io->buffer_id = SPA_ID_INVALID;
}
/* Produce data */
/* Handle buffering */
process_buffering(this);
/* Return if there are no buffers ready to be processed */
@ -1329,6 +1329,35 @@ static int impl_node_process(void *object)
return SPA_STATUS_HAVE_DATA;
}
static int impl_node_process(void *object)
{
struct impl *this = object;
struct port *port;
struct spa_io_buffers *io;
spa_return_val_if_fail(this != NULL, -EINVAL);
port = &this->port;
if ((io = port->io) == NULL)
return -EIO;
/* Return if we already have a buffer */
if (io->status == SPA_STATUS_HAVE_DATA)
return SPA_STATUS_HAVE_DATA;
/* Recycle */
if (io->buffer_id < port->n_buffers) {
recycle_buffer(this, port, io->buffer_id);
io->buffer_id = SPA_ID_INVALID;
}
/* Follower produces buffers here, driver in timeout */
if (this->following)
return produce_buffer(this);
else
return SPA_STATUS_OK;
}
static const struct spa_node_methods impl_node = {
SPA_VERSION_NODE_METHODS,
.add_listener = impl_node_add_listener,