Improve memory handling

Reserve 0,0 for stack allocated mem that we never free
Improve allocation in the link
Parse format and properties in-line, there is no need to allocate
memory.
Improve buffer cleanup in alsa
Add timestamps and offset to alsa
This commit is contained in:
Wim Taymans 2016-09-20 19:52:05 +02:00
parent 77f93e37ed
commit 27acab7532
7 changed files with 155 additions and 69 deletions

View file

@ -48,8 +48,8 @@ update_state (SpaALSASource *this, SpaNodeState state)
}
static const char default_device[] = "hw:0";
static const uint32_t default_buffer_time = 1000;
static const uint32_t default_period_time = 100;
static const uint32_t default_buffer_time = 100000;
static const uint32_t default_period_time = 10000;
static const bool default_period_event = 0;
static void
@ -310,6 +310,49 @@ spa_alsa_source_node_port_enum_formats (SpaNode *node,
return SPA_RESULT_OK;
}
static void
recycle_buffer (SpaALSASource *this, uint32_t buffer_id)
{
SpaALSABuffer *b;
b = &this->alloc_buffers[buffer_id];
if (!b->outstanding)
return;
b->outstanding = false;
SPA_QUEUE_PUSH_TAIL (&this->free, SpaALSABuffer, next, b);
}
static SpaResult
spa_alsa_clear_buffers (SpaALSASource *this)
{
int i;
if (!this->have_buffers)
return SPA_RESULT_OK;
for (i = 0; i < this->n_buffers; i++) {
SpaALSABuffer *b;
b = &this->alloc_buffers[i];
if (b->outstanding) {
fprintf (stderr, "queueing outstanding buffer %p\n", b);
recycle_buffer (this, i);
}
}
if (this->alloc_bufmem)
spa_memory_unref (&this->alloc_bufmem->mem);
if (this->alloc_mem)
spa_memory_unref (&this->alloc_mem->mem);
this->alloc_mem = NULL;
this->alloc_bufmem = NULL;
this->n_buffers = 0;
this->have_buffers = false;
return SPA_RESULT_OK;
}
static SpaResult
spa_alsa_source_node_port_set_format (SpaNode *node,
uint32_t port_id,
@ -329,6 +372,7 @@ spa_alsa_source_node_port_set_format (SpaNode *node,
if (format == NULL) {
this->have_format = false;
spa_alsa_clear_buffers (this);
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}
@ -351,7 +395,7 @@ spa_alsa_source_node_port_set_format (SpaNode *node,
this->param_buffers.minsize = this->period_frames * this->frame_size;
this->param_buffers.stride = 0;
this->param_buffers.min_buffers = 1;
this->param_buffers.max_buffers = 16;
this->param_buffers.max_buffers = 32;
this->param_buffers.align = 16;
this->info.features = NULL;
@ -423,25 +467,39 @@ spa_alsa_source_node_port_set_props (SpaNode *node,
static SpaResult
spa_alsa_source_node_port_use_buffers (SpaNode *node,
uint32_t port_id,
SpaBuffer **buffers,
uint32_t n_buffers)
uint32_t port_id,
SpaBuffer **buffers,
uint32_t n_buffers)
{
return SPA_RESULT_NOT_IMPLEMENTED;
SpaALSASource *this;
SpaResult res;
if (node == NULL || node->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
if (port_id != 0)
return SPA_RESULT_INVALID_PORT;
this = (SpaALSASource *) node->handle;
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->have_buffers) {
if ((res = spa_alsa_clear_buffers (this)) < 0)
return res;
}
if (buffers != NULL)
return SPA_RESULT_NOT_IMPLEMENTED;
if (this->have_buffers)
update_state (this, SPA_NODE_STATE_PAUSED);
else
update_state (this, SPA_NODE_STATE_READY);
return SPA_RESULT_OK;
}
static void
recycle_buffer (SpaALSASource *this, uint32_t buffer_id)
{
SpaALSABuffer *b;
b = &this->alloc_buffers[buffer_id];
if (!b->outstanding)
return;
b->outstanding = false;
SPA_QUEUE_PUSH_TAIL (&this->free, SpaALSABuffer, next, b);
}
static SpaResult
spa_alsa_source_node_port_alloc_buffers (SpaNode *node,
@ -521,6 +579,7 @@ spa_alsa_source_node_port_alloc_buffers (SpaNode *node,
b->datas[0].mem.size = buffer_size;
b->datas[0].stride = 0;
b->ptr = bufmem + buffer_size * i;
b->h = &b->header;
buffers[i] = b->outbuf = &b->buffer;

View file

@ -318,15 +318,25 @@ mmap_read (SpaALSAState *state)
avail = snd_pcm_status_get_avail (status);
snd_pcm_status_get_htstamp (status, &htstamp);
now = (int64_t)htstamp.tv_sec * 1000000000ll + (int64_t)htstamp.tv_nsec;
now = (int64_t)htstamp.tv_sec * SPA_NSEC_PER_SEC + (int64_t)htstamp.tv_nsec;
state->last_ticks = state->sample_count * SPA_USEC_PER_SEC / state->rate;
state->last_monotonic = now;
SPA_QUEUE_POP_HEAD (&state->free, SpaALSABuffer, next, b);
if (b == NULL) {
fprintf (stderr, "no more buffers\n");
} else {
dest = b->ptr;
if (b->h) {
b->h->seq = state->sample_count;
b->h->pts = state->last_monotonic;
b->h->dts_offset = 0;
}
}
state->sample_count += avail;
size = avail;
while (size > 0) {
frames = size;
@ -358,6 +368,7 @@ mmap_read (SpaALSAState *state)
size -= frames;
}
if (b) {
SpaNodeEvent event;
SpaNodeEventHaveOutput ho;

View file

@ -52,6 +52,7 @@ struct _SpaALSABuffer {
SpaMetaRingbuffer ringbuffer;
SpaData datas[1];
SpaBuffer *outbuf;
SpaMetaHeader *h;
void *ptr;
bool outstanding;
SpaALSABuffer *next;
@ -89,7 +90,6 @@ struct _SpaALSAState {
SpaPortStatus status;
bool have_buffers;
SpaMemory *alloc_bufmem;
SpaMemory *alloc_mem;
SpaALSABuffer *alloc_buffers;
@ -102,6 +102,7 @@ struct _SpaALSAState {
SpaPollFd fds[16];
SpaPollItem poll;
int64_t sample_count;
int64_t last_ticks;
int64_t last_monotonic;
};