From 06dd7095fc2b01b7e5bb438b1c86a7e3099b9e6a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 19 Apr 2018 20:12:24 +0200 Subject: [PATCH] audioconvert: various fixes --- spa/plugins/audioconvert/audioconvert.c | 17 +++++-- spa/plugins/audioconvert/fmtconvert.c | 1 - spa/plugins/audioconvert/resample.c | 68 ++++++++++++++++--------- spa/plugins/audioconvert/splitter.c | 19 +++++-- 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 285aa1903..78e2b3610 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -783,7 +783,7 @@ impl_node_port_send_command(struct spa_node *node, static int impl_node_process(struct spa_node *node) { struct impl *this; - int i; + int i, res = SPA_STATUS_OK; spa_return_val_if_fail(node != NULL, -EINVAL); @@ -791,10 +791,19 @@ static int impl_node_process(struct spa_node *node) spa_log_trace(this->log, NAME " %p: process %d", this, this->n_links); - for (i = 1; i < this->n_links; i++) - spa_node_process(this->links[i].out_node); + for (i = 1; i < this->n_links; i++) { + res = spa_node_process(this->links[i].out_node); + if (!SPA_FLAG_CHECK(res, SPA_STATUS_HAVE_BUFFER)) { + if (SPA_FLAG_CHECK(res, SPA_STATUS_NEED_BUFFER) && i == 1) + break; + i = 0; + continue; + } + } - return SPA_STATUS_OK; + spa_log_trace(this->log, NAME " %p: process result: %d", this, res); + + return res; } static const struct spa_node impl_node = { diff --git a/spa/plugins/audioconvert/fmtconvert.c b/spa/plugins/audioconvert/fmtconvert.c index 3b40bdff1..459f0fed6 100644 --- a/spa/plugins/audioconvert/fmtconvert.c +++ b/spa/plugins/audioconvert/fmtconvert.c @@ -852,7 +852,6 @@ static int impl_node_process(struct spa_node *node) inio->status = SPA_STATUS_NEED_BUFFER; inport->offset = 0; } - } outio->status = SPA_STATUS_HAVE_BUFFER; diff --git a/spa/plugins/audioconvert/resample.c b/spa/plugins/audioconvert/resample.c index 7578cfbe4..309d94d9e 100644 --- a/spa/plugins/audioconvert/resample.c +++ b/spa/plugins/audioconvert/resample.c @@ -73,6 +73,7 @@ struct port { uint32_t n_buffers; struct spa_list queue; + uint32_t offset; }; struct type { @@ -632,6 +633,8 @@ impl_node_port_use_buffers(struct spa_node *node, spa_list_append(&port->queue, &b->link); else SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); + + port->offset = 0; } port->n_buffers = n_buffers; port->size = size; @@ -689,7 +692,7 @@ static void recycle_buffer(struct impl *this, uint32_t id) } } -static struct buffer *dequeue_buffer(struct impl *this, struct port *port) +static struct buffer *peek_buffer(struct impl *this, struct port *port) { struct buffer *b; @@ -697,12 +700,14 @@ static struct buffer *dequeue_buffer(struct impl *this, struct port *port) return NULL; b = spa_list_first(&port->queue, struct buffer, link); - spa_list_remove(&b->link); - SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); - return b; } +static void dequeue_buffer(struct impl *this, struct buffer *b) +{ + spa_list_remove(&b->link); + SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUT); +} static int impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t buffer_id) { @@ -734,6 +739,9 @@ static int impl_node_process(struct spa_node *node) struct port *outport, *inport; struct spa_io_buffers *outio, *inio; struct buffer *sbuf, *dbuf; + struct spa_buffer *sb, *db; + uint32_t i, size, in_len, out_len, maxsize; + int res = 0; spa_return_val_if_fail(node != NULL, -EINVAL); @@ -751,7 +759,7 @@ static int impl_node_process(struct spa_node *node) spa_log_trace(this->log, NAME " %p: status %d %d", this, inio->status, outio->status); if (outio->status == SPA_STATUS_HAVE_BUFFER) - return outio->status; + return SPA_STATUS_HAVE_BUFFER; if (inio->status != SPA_STATUS_HAVE_BUFFER) return SPA_STATUS_NEED_BUFFER; @@ -765,35 +773,47 @@ static int impl_node_process(struct spa_node *node) if (inio->buffer_id >= inport->n_buffers) return inio->status = -EINVAL; - if ((dbuf = dequeue_buffer(this, outport)) == NULL) + if ((dbuf = peek_buffer(this, outport)) == NULL) return outio->status = -EPIPE; sbuf = &inport->buffers[inio->buffer_id]; - { - int i; - struct spa_buffer *sb = sbuf->outbuf, *db = dbuf->outbuf; + sb = sbuf->outbuf; + db = dbuf->outbuf; - for (i = 0; i < sb->n_datas; i++) { - uint32_t in_len, out_len; + size = sb->datas[0].chunk->size; + maxsize = db->datas[0].maxsize; - in_len = sb->datas[i].chunk->size / sizeof(float); - out_len = db->datas[i].maxsize / sizeof(float); + in_len = (size - inport->offset) / sizeof(float); + out_len = (maxsize - outport->offset) / sizeof(float); - speex_resampler_process_float(this->state, i, - sb->datas[i].data, &in_len, - db->datas[i].data, &out_len); + for (i = 0; i < sb->n_datas; i++) { + speex_resampler_process_float(this->state, i, + SPA_MEMBER(sb->datas[i].data, inport->offset, void), &in_len, + SPA_MEMBER(db->datas[i].data, outport->offset, void), &out_len); - db->datas[i].chunk->size = out_len * sizeof(float); - } + spa_log_trace(this->log, NAME " %p: in %d/%ld %d out %d/%ld %d", + this, in_len, size / sizeof(float), inport->offset, + out_len, maxsize / sizeof(float), outport->offset); + + db->datas[i].chunk->size = outport->offset + (out_len * sizeof(float)); } - outio->status = SPA_STATUS_HAVE_BUFFER; - outio->buffer_id = dbuf->outbuf->id; - - inio->status = SPA_STATUS_NEED_BUFFER; - - return outio->status; + inport->offset += in_len * sizeof(float); + if (inport->offset >= size) { + inio->status = SPA_STATUS_NEED_BUFFER; + inport->offset = 0; + SPA_FLAG_SET(res, SPA_STATUS_NEED_BUFFER); + } + outport->offset += out_len * sizeof(float); + if (outport->offset >= maxsize) { + outio->status = SPA_STATUS_HAVE_BUFFER; + outio->buffer_id = dbuf->outbuf->id; + dequeue_buffer(this, dbuf); + outport->offset = 0; + SPA_FLAG_SET(res, SPA_STATUS_HAVE_BUFFER); + } + return res; } static const struct spa_node impl_node = { diff --git a/spa/plugins/audioconvert/splitter.c b/spa/plugins/audioconvert/splitter.c index 3852e2c43..f8b65826e 100644 --- a/spa/plugins/audioconvert/splitter.c +++ b/spa/plugins/audioconvert/splitter.c @@ -114,6 +114,8 @@ struct port { int32_t *io_mute; struct spa_port_info info; + struct spa_dict info_props; + struct spa_dict_item info_props_items[2]; bool have_format; @@ -283,6 +285,10 @@ static int impl_node_add_port(struct spa_node *node, enum spa_direction directio port->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_REMOVABLE; + port->info_props_items[0] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio"); + port->info_props = SPA_DICT_INIT(port->info_props_items, 1); + port->info.props = &port->info_props; + this->port_count++; if (this->last_port <= port_id) this->last_port = port_id + 1; @@ -588,15 +594,16 @@ static int port_set_format(struct spa_node *node, info.info.raw.rate != this->format.info.raw.rate) return -EINVAL; + this->bpf = sizeof(float); if (direction == SPA_DIRECTION_INPUT) { if (info.info.raw.channels != this->port_count) return -EINVAL; + this->bpf *= this->port_count; } else { if (info.info.raw.channels != 1) return -EINVAL; } - this->bpf = sizeof(float); this->have_format = true; this->format = info; @@ -779,7 +786,7 @@ static int impl_node_process(struct spa_node *node) struct impl *this; struct port *inport; struct spa_io_buffers *inio; - int i, size = 0; + int i, size = 0, res = 0; struct spa_data *sd, *dd; struct buffer *sbuf, *dbuf; @@ -791,6 +798,8 @@ static int impl_node_process(struct spa_node *node) inio = inport->io; spa_return_val_if_fail(inio != NULL, -EIO); + spa_log_trace(this->log, NAME " %p: status %d", this, inio->status); + if (inio->status != SPA_STATUS_HAVE_BUFFER) return SPA_STATUS_NEED_BUFFER; @@ -799,8 +808,6 @@ static int impl_node_process(struct spa_node *node) sbuf = &inport->buffers[inio->buffer_id]; - spa_log_trace(this->log, NAME " %p: status %d", this, inio->status); - /* produce more output if possible */ for (i = 0; i < this->last_port; i++) { struct port *outport = GET_OUT_PORT(this, i); @@ -831,14 +838,16 @@ static int impl_node_process(struct spa_node *node) outio->buffer_id = dbuf->buf->id; outio->status = SPA_STATUS_HAVE_BUFFER; + SPA_FLAG_SET(res, SPA_STATUS_HAVE_BUFFER); } inport->offset += size; if (inport->offset >= sbuf->buf->datas[0].chunk->size) { inport->offset = 0; inio->status = SPA_STATUS_NEED_BUFFER; + SPA_FLAG_SET(res, SPA_STATUS_NEED_BUFFER); } - return SPA_STATUS_HAVE_BUFFER; + return res; } static const struct spa_node impl_node = {