more work on audioconvert

Implement audioconvert as a complex element of fmtconver,
channelmix and resample.
Make copying resample just to test.
Plug the converter into pw_stream.
This commit is contained in:
Wim Taymans 2018-04-10 15:54:29 +02:00
parent de36330917
commit b3b47d3fe9
9 changed files with 1454 additions and 542 deletions

View file

@ -73,6 +73,8 @@ struct port {
uint32_t blocks;
uint32_t size;
uint32_t offset;
struct buffer buffers[MAX_BUFFERS];
uint32_t n_buffers;
@ -153,22 +155,6 @@ struct impl {
#define GET_OUT_PORT(this,id) (&this->out_port)
#define GET_PORT(this,d,id) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,id) : GET_OUT_PORT(this,id))
static void convert_generic (void *data, int n_dst, void *dst[n_dst],
int n_src, const void *src[n_src], int n_bytes)
{
#if 0
struct port *inport, *outport;
inport = GET_PORT(this, SPA_DIRECTION_INPUT, 0);
outport = GET_PORT(this, SPA_DIRECTION_OUTPUT, 0);
if (inport->format.info.raw.layout == SPA_AUDIO_LAYOUT_INTERLEAVED) {
}
else {
}
#endif
}
static int setup_convert(struct impl *this)
{
struct port *inport, *outport;
@ -181,12 +167,12 @@ static int setup_convert(struct impl *this)
src_fmt = inport->format.info.raw.format;
dst_fmt = outport->format.info.raw.format;
spa_log_info(this->log, NAME " %p: %d/%d@%d.%d->%d/%d@%d.%d", this,
src_fmt,
spa_log_info(this->log, NAME " %p: %s/%d@%d.%d->%s/%d@%d.%d", this,
spa_type_map_get_type(this->map, src_fmt),
inport->format.info.raw.channels,
inport->format.info.raw.rate,
inport->format.info.raw.layout,
dst_fmt,
spa_type_map_get_type(this->map, dst_fmt),
outport->format.info.raw.channels,
outport->format.info.raw.rate,
outport->format.info.raw.layout);
@ -214,16 +200,7 @@ static int setup_convert(struct impl *this)
}
return 0;
}
/* go through intermediate format */
this->conv[0] = find_conv_info(&t->audio_format, src_fmt, t->audio_format.F32);
this->conv[1] = find_conv_info(&t->audio_format, t->audio_format.F32, dst_fmt);
if (this->conv[0] == NULL || this->conv[1] == NULL)
return -ENOTSUP;
this->convert = convert_generic;
return 0;
return -ENOTSUP;
}
static int impl_node_enum_params(struct spa_node *node,
@ -368,17 +345,9 @@ static int port_enum_formats(struct spa_node *node,
"I", t->media_type.audio,
"I", t->media_subtype.raw,
":", t->format_audio.format, "Ieu", other->format.info.raw.format,
SPA_POD_PROP_ENUM(11, t->audio_format.U8,
t->audio_format.S16,
t->audio_format.S16_OE,
t->audio_format.F32,
t->audio_format.F32_OE,
t->audio_format.S32,
t->audio_format.S32_OE,
t->audio_format.S24,
t->audio_format.S24_OE,
t->audio_format.S24_32,
t->audio_format.S24_32_OE),
SPA_POD_PROP_ENUM(3, other->format.info.raw.format,
t->audio_format.F32,
t->audio_format.F32_OE),
":", t->format_audio.layout, "ieu", other->format.info.raw.layout,
SPA_POD_PROP_ENUM(2, SPA_AUDIO_LAYOUT_INTERLEAVED,
SPA_AUDIO_LAYOUT_NON_INTERLEAVED),
@ -834,7 +803,7 @@ static int impl_node_process(struct spa_node *node)
spa_return_val_if_fail(outio != NULL, -EIO);
spa_return_val_if_fail(inio != NULL, -EIO);
spa_log_trace(this->log, NAME " %p: status %d", this, outio->status);
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;
@ -857,24 +826,33 @@ static int impl_node_process(struct spa_node *node)
sbuf = &inport->buffers[inio->buffer_id];
{
int i, n_bytes;
int i, n_bytes, maxsize;
struct spa_buffer *sb = sbuf->outbuf, *db = dbuf->outbuf;
uint32_t n_src_datas = sb->n_datas;
uint32_t n_dst_datas = db->n_datas;
const void *src_datas[n_src_datas];
void *dst_datas[n_dst_datas];
uint32_t size;
n_bytes = sb->datas[0].chunk->size;
size = sb->datas[0].chunk->size;
maxsize = (db->datas[0].maxsize / outport->stride) * inport->stride;
n_bytes = SPA_MIN(size - inport->offset, maxsize);
for (i = 0; i < n_src_datas; i++)
src_datas[i] = sb->datas[i].data;
src_datas[i] = SPA_MEMBER(sb->datas[i].data, inport->offset, void);
for (i = 0; i < n_dst_datas; i++) {
dst_datas[i] = db->datas[i].data;
db->datas[i].chunk->size =
(n_bytes / inport->stride) * outport->stride;
db->datas[i].chunk->size = (n_bytes / inport->stride) * outport->stride;
}
this->convert(this, n_dst_datas, dst_datas, n_src_datas, src_datas, n_bytes);
inport->offset += n_bytes;
if (inport->offset >= size) {
inio->status = SPA_STATUS_NEED_BUFFER;
inport->offset = 0;
}
}
outio->status = SPA_STATUS_HAVE_BUFFER;