Plug some leaks

Add maxsize to bufferdata in case the memory size can be variable such
as with encoded formats. Copy new size in the proxy.
This commit is contained in:
Wim Taymans 2016-09-30 19:56:41 +02:00
parent 9d4048e73a
commit b208e8b690
15 changed files with 117 additions and 57 deletions

View file

@ -73,7 +73,7 @@ struct _SpaAudioMixer {
int port_count;
int port_queued;
SpaAudioMixerPort ports[MAX_PORTS];
SpaAudioMixerPort ports[MAX_PORTS + 1];
};
enum {
@ -224,13 +224,13 @@ spa_audiomixer_node_get_port_ids (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (input_ids) {
for (i = 1, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) {
for (i = 0, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) {
if (this->ports[i].valid)
input_ids[idx++] = i;
}
}
if (n_output_ports > 0 && output_ids)
output_ids[0] = 0;
output_ids[0] = MAX_PORTS;
return SPA_RESULT_OK;
}
@ -261,7 +261,7 @@ spa_audiomixer_node_add_port (SpaNode *node,
SPA_PORT_INFO_FLAG_IN_PLACE;
this->ports[port_id].status.flags = SPA_PORT_STATUS_FLAG_NEED_INPUT;
this->ports[0].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
this->ports[MAX_PORTS].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
return SPA_RESULT_OK;
}
@ -277,7 +277,7 @@ spa_audiomixer_node_remove_port (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id == 0 || port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
this->ports[port_id].valid = false;
@ -287,7 +287,7 @@ spa_audiomixer_node_remove_port (SpaNode *node,
this->port_queued--;
}
if (this->port_count == this->port_queued)
this->ports[0].status.flags |= SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
this->ports[MAX_PORTS].status.flags |= SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
return SPA_RESULT_OK;
}
@ -377,7 +377,7 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id > MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[port_id];
@ -403,7 +403,7 @@ spa_audiomixer_node_port_get_info (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id > MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[port_id];
@ -469,7 +469,7 @@ spa_audiomixer_node_port_get_status (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id > MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[port_id];
@ -495,7 +495,7 @@ spa_audiomixer_node_port_push_input (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (this->ports[0].status.flags & SPA_PORT_STATUS_FLAG_HAVE_OUTPUT)
if (this->ports[MAX_PORTS].status.flags & SPA_PORT_STATUS_FLAG_HAVE_OUTPUT)
return SPA_RESULT_HAVE_ENOUGH_INPUT;
for (i = 0; i < n_info; i++) {
@ -673,7 +673,7 @@ spa_audiomixer_node_port_pull_output (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (info->port_id != 0)
if (info->port_id != MAX_PORTS)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[info->port_id];
@ -781,10 +781,10 @@ spa_audiomixer_init (const SpaHandleFactory *factory,
this->props[1].props.prop_info = prop_info;
reset_audiomixer_props (&this->props[1]);
this->ports[0].valid = true;
this->ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS |
SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
SPA_PORT_INFO_FLAG_NO_REF;
this->ports[MAX_PORTS].valid = true;
this->ports[MAX_PORTS].info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS |
SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
SPA_PORT_INFO_FLAG_NO_REF;
return SPA_RESULT_OK;
}

View file

@ -418,6 +418,27 @@ do_update_port (SpaProxy *this,
}
}
static void
clear_port (SpaProxy *this,
SpaProxyPort *port,
uint32_t port_id)
{
SpaControlCmdPortUpdate pu;
pu.change_mask = SPA_CONTROL_CMD_PORT_UPDATE_POSSIBLE_FORMATS |
SPA_CONTROL_CMD_PORT_UPDATE_FORMAT |
SPA_CONTROL_CMD_PORT_UPDATE_PROPS |
SPA_CONTROL_CMD_PORT_UPDATE_INFO;
pu.port_id = port_id;
pu.n_possible_formats = 0;
pu.possible_formats = NULL;
pu.format = NULL;
pu.props = NULL;
pu.info = NULL;
do_update_port (this, &pu);
clear_buffers (this, port);
}
static void
do_uninit_port (SpaProxy *this,
uint32_t port_id)
@ -432,10 +453,8 @@ do_uninit_port (SpaProxy *this,
else
this->n_outputs--;
clear_port (this, port, port_id);
port->valid = false;
if (port->format)
free (port->format);
port->format = NULL;
}
static SpaResult
@ -443,7 +462,7 @@ spa_proxy_node_add_port (SpaNode *node,
uint32_t port_id)
{
SpaProxy *this;
SpaControlCmdPortUpdate pu;
SpaProxyPort *port;
if (node == NULL || node->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -453,17 +472,8 @@ spa_proxy_node_add_port (SpaNode *node,
if (!CHECK_FREE_PORT_ID (this, port_id))
return SPA_RESULT_INVALID_PORT;
pu.change_mask = SPA_CONTROL_CMD_PORT_UPDATE_POSSIBLE_FORMATS |
SPA_CONTROL_CMD_PORT_UPDATE_FORMAT |
SPA_CONTROL_CMD_PORT_UPDATE_PROPS |
SPA_CONTROL_CMD_PORT_UPDATE_INFO;
pu.port_id = port_id;
pu.n_possible_formats = 0;
pu.possible_formats = NULL;
pu.format = NULL;
pu.props = NULL;
pu.info = NULL;
do_update_port (this, &pu);
port = &this->ports[port_id];
clear_port (this, port, port_id);
return SPA_RESULT_OK;
}
@ -714,7 +724,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
am.fd_index = spa_control_builder_add_fd (&builder, SPA_PTR_TO_INT (d->data), false);
am.flags = 0;
am.offset = d->offset;
am.size = d->size;
am.size = d->maxsize;
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am);
b->buffer.datas[j].data = SPA_UINT32_TO_PTR (n_mem);
@ -732,12 +742,14 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
close (port->buffer_mem_fd);
return SPA_RESULT_ERROR;
}
#if 0
{
unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
if (fcntl (port->buffer_mem_fd, F_ADD_SEALS, seals) == -1) {
fprintf (stderr, "Failed to add seals: %s\n", strerror (errno));
}
}
#endif
p = port->buffer_mem_ptr = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, port->buffer_mem_fd, 0);
for (i = 0; i < n_buffers; i++) {
@ -749,6 +761,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
len = spa_buffer_serialize (p, &b->buffer);
sb = p;
b->buffer.datas = SPA_MEMBER (sb, SPA_PTR_TO_INT (sb->datas), SpaData);
sbm = SPA_MEMBER (sb, SPA_PTR_TO_INT (sb->metas), SpaMeta);
for (j = 0; j < b->buffer.n_metas; j++)
@ -869,6 +882,9 @@ copy_meta (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
SpaMeta *dm = &b->buffer.metas[i];
memcpy (dm->data, sm->data, dm->size);
}
for (i = 0; i < b->outbuf->n_datas; i++) {
b->buffer.datas[i].size = b->outbuf->datas[i].size;
}
}
static SpaResult
@ -1223,6 +1239,19 @@ spa_proxy_get_interface (SpaHandle *handle,
static SpaResult
proxy_clear (SpaHandle *handle)
{
SpaProxy *this;
unsigned int i;
if (handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = (SpaProxy *) handle;
for (i = 0; i < MAX_PORTS; i++) {
if (this->ports[i].valid)
clear_port (this, &this->ports[i], i);
}
return SPA_RESULT_OK;
}

View file

@ -948,7 +948,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
b->v4l2_buffer.memory = state->memtype;
b->v4l2_buffer.index = i;
b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (d[0].data, d[0].offset, void *);
b->v4l2_buffer.length = d[0].size;
b->v4l2_buffer.length = d[0].maxsize;
spa_v4l2_buffer_recycle (this, buffers[i]->id);
}
@ -1017,6 +1017,7 @@ mmap_init (SpaV4l2Source *this,
d = buffers[i]->datas;
d[0].offset = 0;
d[0].size = b->v4l2_buffer.length;
d[0].maxsize = b->v4l2_buffer.length;
d[0].stride = state->fmt.fmt.pix.bytesperline;
if (state->export_buf) {