mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-10 13:30:05 -05:00
spi: implement processing
Implement processing with writing to provided buffer or in-place Fix types. Add more PortInfo flags Remove release-id, we now use a callback, which is more practical and still allows deallocation out of the rt-threads if needed as well as recycling the buffers into an atomic pool Add more comments Allow NULL in set_params to reset params
This commit is contained in:
parent
b44d2d86b6
commit
03046301bf
5 changed files with 333 additions and 109 deletions
|
|
@ -43,6 +43,7 @@ struct _SpiVolume {
|
|||
SpiNode node;
|
||||
|
||||
SpiVolumeParams params;
|
||||
SpiVolumeParams tmp_params;
|
||||
|
||||
SpiEvent *event;
|
||||
SpiEvent last_event;
|
||||
|
|
@ -161,15 +162,24 @@ get_param (const SpiParams *params,
|
|||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_volume_params (SpiVolumeParams *params)
|
||||
{
|
||||
params->volume = default_volume;
|
||||
params->mute = default_mute;
|
||||
}
|
||||
|
||||
static SpiResult
|
||||
spi_volume_node_get_params (SpiNode *node,
|
||||
SpiParams **params)
|
||||
{
|
||||
static SpiVolumeParams p;
|
||||
SpiVolume *this = (SpiVolume *) node;
|
||||
|
||||
memcpy (&p, &this->params, sizeof (p));
|
||||
*params = &p.param;
|
||||
if (node == NULL || params == NULL)
|
||||
return SPI_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
memcpy (&this->tmp_params, &this->params, sizeof (this->tmp_params));
|
||||
*params = &this->tmp_params.param;
|
||||
|
||||
return SPI_RESULT_OK;
|
||||
}
|
||||
|
|
@ -184,6 +194,14 @@ spi_volume_node_set_params (SpiNode *node,
|
|||
size_t size;
|
||||
const void *value;
|
||||
|
||||
if (node == NULL)
|
||||
return SPI_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
if (params == NULL) {
|
||||
reset_volume_params (p);
|
||||
return SPI_RESULT_OK;
|
||||
}
|
||||
|
||||
if (params->get_param (params, 0, &type, &size, &value) == 0) {
|
||||
if (type != SPI_PARAM_TYPE_DOUBLE)
|
||||
return SPI_RESULT_WRONG_PARAM_TYPE;
|
||||
|
|
@ -204,6 +222,9 @@ spi_volume_node_send_command (SpiNode *node,
|
|||
SpiVolume *this = (SpiVolume *) node;
|
||||
SpiResult res = SPI_RESULT_NOT_IMPLEMENTED;
|
||||
|
||||
if (node == NULL || command == NULL)
|
||||
return SPI_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
switch (command->type) {
|
||||
case SPI_COMMAND_INVALID:
|
||||
res = SPI_RESULT_INVALID_COMMAND;
|
||||
|
|
@ -266,24 +287,32 @@ spi_volume_node_set_event_callback (SpiNode *node,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_get_n_ports (SpiNode *node,
|
||||
int *n_input_ports,
|
||||
int *max_input_ports,
|
||||
int *n_output_ports,
|
||||
int *max_output_ports)
|
||||
unsigned int *n_input_ports,
|
||||
unsigned int *max_input_ports,
|
||||
unsigned int *n_output_ports,
|
||||
unsigned int *max_output_ports)
|
||||
{
|
||||
*n_input_ports = 1;
|
||||
*n_output_ports = 1;
|
||||
*max_input_ports = 1;
|
||||
*max_output_ports = 1;
|
||||
if (node == NULL)
|
||||
return SPI_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
if (n_input_ports)
|
||||
*n_input_ports = 1;
|
||||
if (n_output_ports)
|
||||
*n_output_ports = 1;
|
||||
if (max_input_ports)
|
||||
*max_input_ports = 1;
|
||||
if (max_output_ports)
|
||||
*max_output_ports = 1;
|
||||
|
||||
return SPI_RESULT_OK;
|
||||
}
|
||||
|
||||
static SpiResult
|
||||
spi_volume_node_get_port_ids (SpiNode *node,
|
||||
int n_input_ports,
|
||||
int *input_ids,
|
||||
int n_output_ports,
|
||||
int *output_ids)
|
||||
unsigned int n_input_ports,
|
||||
uint32_t *input_ids,
|
||||
unsigned int n_output_ports,
|
||||
uint32_t *output_ids)
|
||||
{
|
||||
if (n_input_ports > 0)
|
||||
input_ids[0] = 0;
|
||||
|
|
@ -297,14 +326,14 @@ spi_volume_node_get_port_ids (SpiNode *node,
|
|||
static SpiResult
|
||||
spi_volume_node_add_port (SpiNode *node,
|
||||
SpiDirection direction,
|
||||
int *port_id)
|
||||
uint32_t *port_id)
|
||||
{
|
||||
return SPI_RESULT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static SpiResult
|
||||
spi_volume_node_remove_port (SpiNode *node,
|
||||
int port_id)
|
||||
uint32_t port_id)
|
||||
{
|
||||
return SPI_RESULT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
@ -504,8 +533,8 @@ get_format_param (const SpiParams *params,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_get_port_formats (SpiNode *node,
|
||||
int port_id,
|
||||
int format_idx,
|
||||
uint32_t port_id,
|
||||
unsigned int format_idx,
|
||||
SpiParams **format)
|
||||
{
|
||||
static SpiVolumeFormat fmt;
|
||||
|
|
@ -531,7 +560,7 @@ spi_volume_node_get_port_formats (SpiNode *node,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_set_port_format (SpiNode *node,
|
||||
int port_id,
|
||||
uint32_t port_id,
|
||||
int test_only,
|
||||
const SpiParams *format)
|
||||
{
|
||||
|
|
@ -600,7 +629,7 @@ spi_volume_node_set_port_format (SpiNode *node,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_get_port_format (SpiNode *node,
|
||||
int port_id,
|
||||
uint32_t port_id,
|
||||
const SpiParams **format)
|
||||
{
|
||||
SpiVolume *this = (SpiVolume *) node;
|
||||
|
|
@ -618,20 +647,28 @@ spi_volume_node_get_port_format (SpiNode *node,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_get_port_info (SpiNode *node,
|
||||
int port_id,
|
||||
uint32_t port_id,
|
||||
SpiPortInfo *info)
|
||||
{
|
||||
if (port_id != 0)
|
||||
return SPI_RESULT_INVALID_PORT;
|
||||
|
||||
info->flags = SPI_PORT_INFO_FLAG_NONE;
|
||||
|
||||
switch (port_id) {
|
||||
case 0:
|
||||
info->flags = SPI_PORT_INFO_FLAG_CAN_USE_BUFFER |
|
||||
SPI_PORT_INFO_FLAG_IN_PLACE;
|
||||
break;
|
||||
case 1:
|
||||
info->flags = SPI_PORT_INFO_FLAG_CAN_GIVE_BUFFER |
|
||||
SPI_PORT_INFO_FLAG_CAN_USE_BUFFER |
|
||||
SPI_PORT_INFO_FLAG_NO_REF;
|
||||
break;
|
||||
default:
|
||||
return SPI_RESULT_INVALID_PORT;
|
||||
}
|
||||
return SPI_RESULT_OK;
|
||||
}
|
||||
|
||||
static SpiResult
|
||||
spi_volume_node_get_port_params (SpiNode *node,
|
||||
int port_id,
|
||||
uint32_t port_id,
|
||||
SpiParams **params)
|
||||
{
|
||||
return SPI_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -639,7 +676,7 @@ spi_volume_node_get_port_params (SpiNode *node,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_set_port_params (SpiNode *node,
|
||||
int port_id,
|
||||
uint32_t port_id,
|
||||
const SpiParams *params)
|
||||
{
|
||||
return SPI_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -647,7 +684,7 @@ spi_volume_node_set_port_params (SpiNode *node,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_get_port_status (SpiNode *node,
|
||||
int port_id,
|
||||
uint32_t port_id,
|
||||
SpiPortStatus *status)
|
||||
{
|
||||
SpiVolume *this = (SpiVolume *) node;
|
||||
|
|
@ -659,7 +696,7 @@ spi_volume_node_get_port_status (SpiNode *node,
|
|||
switch (port_id) {
|
||||
case 0:
|
||||
if (this->input_buffer == NULL)
|
||||
flags |= SPI_PORT_STATUS_FLAG_ACCEPT_INPUT;
|
||||
flags |= SPI_PORT_STATUS_FLAG_NEED_INPUT;
|
||||
break;
|
||||
case 1:
|
||||
if (this->input_buffer != NULL)
|
||||
|
|
@ -678,12 +715,18 @@ spi_volume_node_send_port_data (SpiNode *node,
|
|||
SpiDataInfo *data)
|
||||
{
|
||||
SpiVolume *this = (SpiVolume *) node;
|
||||
SpiBuffer *buffer = data->buffer;
|
||||
SpiEvent *event = data->event;
|
||||
SpiBuffer *buffer;
|
||||
SpiEvent *event;
|
||||
|
||||
if (node == NULL || data == NULL)
|
||||
return SPI_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
if (data->port_id != 0)
|
||||
return SPI_RESULT_INVALID_PORT;
|
||||
|
||||
event = data->event;
|
||||
buffer = data->buffer;
|
||||
|
||||
if (buffer == NULL && event == NULL)
|
||||
return SPI_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
|
|
@ -694,8 +737,7 @@ spi_volume_node_send_port_data (SpiNode *node,
|
|||
if (this->input_buffer != NULL)
|
||||
return SPI_RESULT_HAVE_ENOUGH_INPUT;
|
||||
|
||||
buffer->refcount++;
|
||||
this->input_buffer = buffer;
|
||||
this->input_buffer = spi_buffer_ref (buffer);
|
||||
}
|
||||
if (event) {
|
||||
switch (event->type) {
|
||||
|
|
@ -709,11 +751,18 @@ spi_volume_node_send_port_data (SpiNode *node,
|
|||
|
||||
static SpiResult
|
||||
spi_volume_node_receive_port_data (SpiNode *node,
|
||||
int n_data,
|
||||
unsigned int n_data,
|
||||
SpiDataInfo *data)
|
||||
{
|
||||
SpiVolume *this = (SpiVolume *) node;
|
||||
int i, n_samples;
|
||||
unsigned int si, di, i, n_samples, n_bytes, soff, doff ;
|
||||
SpiBuffer *sbuf, *dbuf;
|
||||
SpiData *sd, *dd;
|
||||
uint16_t *src, *dst;
|
||||
double volume;
|
||||
|
||||
if (node == NULL || n_data == 0 || data == NULL)
|
||||
return SPI_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
if (data->port_id != 1)
|
||||
return SPI_RESULT_INVALID_PORT;
|
||||
|
|
@ -724,13 +773,56 @@ spi_volume_node_receive_port_data (SpiNode *node,
|
|||
if (this->input_buffer == NULL)
|
||||
return SPI_RESULT_NEED_MORE_INPUT;
|
||||
|
||||
n_samples = 4096;
|
||||
volume = this->params.volume;
|
||||
|
||||
for (i = 0; i < n_samples; i++) {
|
||||
sbuf = this->input_buffer;
|
||||
dbuf = data->buffer ? data->buffer : this->input_buffer;
|
||||
|
||||
si = di = 0;
|
||||
soff = doff = 0;
|
||||
|
||||
while (TRUE) {
|
||||
if (si == sbuf->n_datas || di == dbuf->n_datas)
|
||||
break;
|
||||
|
||||
sd = &sbuf->datas[si];
|
||||
dd = &dbuf->datas[di];
|
||||
|
||||
if (sd->type != SPI_DATA_TYPE_MEMPTR) {
|
||||
si++;
|
||||
continue;
|
||||
}
|
||||
if (dd->type != SPI_DATA_TYPE_MEMPTR) {
|
||||
di++;
|
||||
continue;
|
||||
}
|
||||
src = (uint16_t*) ((uint8_t*)sd->data + soff);
|
||||
dst = (uint16_t*) ((uint8_t*)dd->data + doff);
|
||||
|
||||
n_bytes = MIN (sd->size - soff, dd->size - doff);
|
||||
n_samples = n_bytes / sizeof (uint16_t);
|
||||
|
||||
for (i = 0; i < n_samples; i++)
|
||||
*src++ = *dst++ * volume;
|
||||
|
||||
soff += n_bytes;
|
||||
doff += n_bytes;
|
||||
|
||||
if (soff >= sd->size) {
|
||||
si++;
|
||||
soff = 0;
|
||||
}
|
||||
if (doff >= dd->size) {
|
||||
di++;
|
||||
doff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
data->buffer = this->input_buffer;
|
||||
if (sbuf != dbuf)
|
||||
spi_buffer_unref (sbuf);
|
||||
|
||||
this->input_buffer = NULL;
|
||||
data->buffer = dbuf;
|
||||
|
||||
return SPI_RESULT_OK;
|
||||
}
|
||||
|
|
@ -766,6 +858,7 @@ spi_volume_new (void)
|
|||
this->params.param.get_param_info = get_param_info;
|
||||
this->params.param.set_param = set_param;
|
||||
this->params.param.get_param = get_param;
|
||||
reset_volume_params (&this->params);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ inspect_node (SpiNode *node)
|
|||
{
|
||||
SpiResult res;
|
||||
SpiParams *params;
|
||||
int n_input, max_input, n_output, max_output, i;
|
||||
unsigned int n_input, max_input, n_output, max_output, i;
|
||||
SpiParams *format;
|
||||
const SpiParams *cformat;
|
||||
uint32_t samplerate;
|
||||
|
|
@ -235,9 +235,6 @@ handle_event (SpiNode *node)
|
|||
case SPI_EVENT_TYPE_REQUEST_DATA:
|
||||
printf ("got request-data notify\n");
|
||||
break;
|
||||
case SPI_EVENT_TYPE_RELEASE_ID:
|
||||
printf ("got release-id notify\n");
|
||||
break;
|
||||
case SPI_EVENT_TYPE_DRAINED:
|
||||
printf ("got drained notify\n");
|
||||
break;
|
||||
|
|
@ -315,8 +312,7 @@ push_input (SpiNode *node)
|
|||
mybuf = free_list;
|
||||
free_list = mybuf->next;
|
||||
|
||||
printf ("alloc buffer %p\n", mybuf);
|
||||
|
||||
printf ("alloc input buffer %p\n", mybuf);
|
||||
mybuf->buffer.refcount = 1;
|
||||
|
||||
info.port_id = 0;
|
||||
|
|
@ -324,11 +320,9 @@ push_input (SpiNode *node)
|
|||
info.buffer = &mybuf->buffer;
|
||||
info.event = NULL;
|
||||
|
||||
if ((res = node->send_port_data (node, &info)) < 0)
|
||||
printf ("got error %d\n", res);
|
||||
res = node->send_port_data (node, &info);
|
||||
|
||||
if (--mybuf->buffer.refcount == 0)
|
||||
mybuf->buffer.notify (mybuf);
|
||||
spi_buffer_unref (&mybuf->buffer);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -338,20 +332,24 @@ pull_output (SpiNode *node)
|
|||
{
|
||||
SpiDataInfo info[1] = { { 0, }, };
|
||||
SpiResult res;
|
||||
MyBuffer *mybuf;
|
||||
SpiBuffer *buf;
|
||||
|
||||
mybuf = free_list;
|
||||
free_list = mybuf->next;
|
||||
|
||||
printf ("alloc output buffer %p\n", mybuf);
|
||||
mybuf->buffer.refcount = 1;
|
||||
|
||||
info[0].port_id = 1;
|
||||
info[0].buffer = NULL;
|
||||
info[0].buffer = &mybuf->buffer;
|
||||
info[0].event = NULL;
|
||||
|
||||
if ((res = node->receive_port_data (node, 1, info)) < 0)
|
||||
printf ("got error %d\n", res);
|
||||
res = node->receive_port_data (node, 1, info);
|
||||
|
||||
buf = info[0].buffer;
|
||||
if (buf) {
|
||||
if (--buf->refcount == 0)
|
||||
buf->notify (buf);
|
||||
}
|
||||
spi_buffer_unref (buf);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -387,6 +385,8 @@ main (gint argc, gchar *argv[])
|
|||
state = 0;
|
||||
|
||||
while (TRUE) {
|
||||
SpiPortStatus status;
|
||||
|
||||
if (state == 0) {
|
||||
if ((res = push_input (node)) < 0) {
|
||||
if (res == SPI_RESULT_HAVE_ENOUGH_INPUT)
|
||||
|
|
@ -396,6 +396,10 @@ main (gint argc, gchar *argv[])
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ((res = node->get_port_status (node, 1, &status)) < 0)
|
||||
printf ("got error %d\n", res);
|
||||
else if (status.flags & SPI_PORT_STATUS_FLAG_HAVE_OUTPUT)
|
||||
state = 1;
|
||||
}
|
||||
if (state == 1) {
|
||||
if ((res = pull_output (node)) < 0) {
|
||||
|
|
@ -406,6 +410,10 @@ main (gint argc, gchar *argv[])
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ((res = node->get_port_status (node, 0, &status)) < 0)
|
||||
printf ("got error %d\n", res);
|
||||
else if (status.flags & SPI_PORT_STATUS_FLAG_NEED_INPUT)
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue