mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
Improve upload
Only send a buffer when we have received a NEED_DATA message. Add a signal to pulla buffer from the sink. Restructure the sink to use a queue like the source and only push a buffer when we can. Improve SpaData. Offset and size should be between 0 and maxsize, make sure we clamp correctly when needed. node_process_output completes the processing of the output after receiving HAVE_OUTPUT for async elements. It instructs the node that it now can produce more output.
This commit is contained in:
parent
8ce3f949e2
commit
5b0b9c43d0
18 changed files with 201 additions and 112 deletions
|
|
@ -192,6 +192,7 @@ pinos_stream_new (PinosContext *context,
|
||||||
pinos_signal_init (&this->add_buffer);
|
pinos_signal_init (&this->add_buffer);
|
||||||
pinos_signal_init (&this->remove_buffer);
|
pinos_signal_init (&this->remove_buffer);
|
||||||
pinos_signal_init (&this->new_buffer);
|
pinos_signal_init (&this->new_buffer);
|
||||||
|
pinos_signal_init (&this->need_buffer);
|
||||||
|
|
||||||
this->state = PINOS_STREAM_STATE_UNCONNECTED;
|
this->state = PINOS_STREAM_STATE_UNCONNECTED;
|
||||||
|
|
||||||
|
|
@ -473,6 +474,9 @@ on_rtsocket_condition (SpaSource *source,
|
||||||
handle_rtnode_event (stream, ev);
|
handle_rtnode_event (stream, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cmd & PINOS_TRANSPORT_CMD_NEED_DATA) {
|
||||||
|
pinos_signal_emit (&stream->need_buffer, stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1080,16 +1084,15 @@ pinos_stream_send_buffer (PinosStream *stream,
|
||||||
{
|
{
|
||||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||||
BufferId *bid;
|
BufferId *bid;
|
||||||
|
uint8_t cmd = PINOS_TRANSPORT_CMD_HAVE_DATA;
|
||||||
|
|
||||||
if ((bid = find_buffer (stream, id))) {
|
if ((bid = find_buffer (stream, id))) {
|
||||||
uint8_t cmd = PINOS_TRANSPORT_CMD_HAVE_DATA;
|
|
||||||
|
|
||||||
bid->used = true;
|
bid->used = true;
|
||||||
impl->trans->outputs[0].buffer_id = id;
|
impl->trans->outputs[0].buffer_id = id;
|
||||||
impl->trans->outputs[0].status = SPA_RESULT_OK;
|
impl->trans->outputs[0].status = SPA_RESULT_OK;
|
||||||
write (impl->rtfd, &cmd, 1);
|
if (write (impl->rtfd, &cmd, 1) < 1)
|
||||||
return true;
|
perror ("write");
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ struct _PinosStream {
|
||||||
PINOS_SIGNAL (new_buffer, (PinosListener *listener,
|
PINOS_SIGNAL (new_buffer, (PinosListener *listener,
|
||||||
PinosStream *stream,
|
PinosStream *stream,
|
||||||
uint32_t id));
|
uint32_t id));
|
||||||
|
PINOS_SIGNAL (need_buffer, (PinosListener *listener,
|
||||||
|
PinosStream *stream));
|
||||||
};
|
};
|
||||||
|
|
||||||
PinosStream * pinos_stream_new (PinosContext *context,
|
PinosStream * pinos_stream_new (PinosContext *context,
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
|
||||||
|
|
||||||
GST_OBJECT_LOCK (pool);
|
GST_OBJECT_LOCK (pool);
|
||||||
while (p->available.length == 0) {
|
while (p->available.length == 0) {
|
||||||
|
GST_WARNING ("queue empty");
|
||||||
g_cond_wait (&p->cond, GST_OBJECT_GET_LOCK (pool));
|
g_cond_wait (&p->cond, GST_OBJECT_GET_LOCK (pool));
|
||||||
}
|
}
|
||||||
*buffer = g_queue_pop_head (&p->available);
|
*buffer = g_queue_pop_head (&p->available);
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,8 @@ gst_pinos_sink_init (GstPinosSink * sink)
|
||||||
sink->buf_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
|
sink->buf_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
|
||||||
(GDestroyNotify) gst_buffer_unref);
|
(GDestroyNotify) gst_buffer_unref);
|
||||||
|
|
||||||
|
g_queue_init (&sink->queue);
|
||||||
|
|
||||||
sink->loop = pinos_loop_new ();
|
sink->loop = pinos_loop_new ();
|
||||||
sink->main_loop = pinos_thread_main_loop_new (sink->loop, "pinos-sink-loop");
|
sink->main_loop = pinos_thread_main_loop_new (sink->loop, "pinos-sink-loop");
|
||||||
GST_DEBUG ("loop %p %p", sink->loop, sink->main_loop);
|
GST_DEBUG ("loop %p %p", sink->loop, sink->main_loop);
|
||||||
|
|
@ -347,6 +349,7 @@ typedef struct {
|
||||||
SpaBuffer *buf;
|
SpaBuffer *buf;
|
||||||
SpaMetaHeader *header;
|
SpaMetaHeader *header;
|
||||||
guint flags;
|
guint flags;
|
||||||
|
goffset offset;
|
||||||
} ProcessMemData;
|
} ProcessMemData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -403,13 +406,15 @@ on_add_buffer (PinosListener *listener,
|
||||||
case SPA_DATA_TYPE_DMABUF:
|
case SPA_DATA_TYPE_DMABUF:
|
||||||
{
|
{
|
||||||
gmem = gst_fd_allocator_alloc (pinossink->allocator, dup (d->fd),
|
gmem = gst_fd_allocator_alloc (pinossink->allocator, dup (d->fd),
|
||||||
d->size, GST_FD_MEMORY_FLAG_NONE);
|
d->mapoffset + d->maxsize, GST_FD_MEMORY_FLAG_NONE);
|
||||||
gst_memory_resize (gmem, d->chunk->offset, d->chunk->size);
|
gst_memory_resize (gmem, d->chunk->offset + d->mapoffset, d->chunk->size);
|
||||||
|
data.offset = d->mapoffset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_DATA_TYPE_MEMPTR:
|
case SPA_DATA_TYPE_MEMPTR:
|
||||||
gmem = gst_memory_new_wrapped (0, d->data, d->size, d->chunk->offset,
|
gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, d->chunk->offset,
|
||||||
d->chunk->size, NULL, NULL);
|
d->chunk->size, NULL, NULL);
|
||||||
|
data.offset = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -466,6 +471,51 @@ on_new_buffer (PinosListener *listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_send_buffer (GstPinosSink *pinossink)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
ProcessMemData *data;
|
||||||
|
gboolean res;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
buffer = g_queue_pop_head (&pinossink->queue);
|
||||||
|
if (buffer == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
data = gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
|
||||||
|
process_mem_data_quark);
|
||||||
|
|
||||||
|
if (data->header) {
|
||||||
|
data->header->seq = GST_BUFFER_OFFSET (buffer);
|
||||||
|
data->header->pts = GST_BUFFER_PTS (buffer);
|
||||||
|
data->header->dts_offset = GST_BUFFER_DTS (buffer);
|
||||||
|
}
|
||||||
|
for (i = 0; i < data->buf->n_datas; i++) {
|
||||||
|
SpaData *d = &data->buf->datas[i];
|
||||||
|
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
|
||||||
|
d->chunk->offset = mem->offset - data->offset;
|
||||||
|
d->chunk->size = mem->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(res = pinos_stream_send_buffer (pinossink->stream, data->id)))
|
||||||
|
g_warning ("can't send buffer");
|
||||||
|
|
||||||
|
pinossink->need_ready--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_need_buffer (PinosListener *listener,
|
||||||
|
PinosStream *stream)
|
||||||
|
{
|
||||||
|
GstPinosSink *pinossink = SPA_CONTAINER_OF (listener, GstPinosSink, stream_need_buffer);
|
||||||
|
|
||||||
|
pinossink->need_ready++;
|
||||||
|
GST_DEBUG ("need buffer %u", pinossink->need_ready);
|
||||||
|
do_send_buffer (pinossink);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_state_changed (PinosListener *listener,
|
on_state_changed (PinosListener *listener,
|
||||||
PinosStream *stream)
|
PinosStream *stream)
|
||||||
|
|
@ -610,9 +660,6 @@ static GstFlowReturn
|
||||||
gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstPinosSink *pinossink;
|
GstPinosSink *pinossink;
|
||||||
gboolean res;
|
|
||||||
ProcessMemData *data;
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
pinossink = GST_PINOS_SINK (bsink);
|
pinossink = GST_PINOS_SINK (bsink);
|
||||||
|
|
||||||
|
|
@ -633,25 +680,11 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
buffer = b;
|
buffer = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer),
|
|
||||||
process_mem_data_quark);
|
|
||||||
|
|
||||||
if (data->header) {
|
|
||||||
data->header->seq = GST_BUFFER_OFFSET (buffer);
|
|
||||||
data->header->pts = GST_BUFFER_PTS (buffer);
|
|
||||||
data->header->dts_offset = GST_BUFFER_DTS (buffer);
|
|
||||||
}
|
|
||||||
for (i = 0; i < data->buf->n_datas; i++) {
|
|
||||||
SpaData *d = &data->buf->datas[i];
|
|
||||||
GstMemory *mem = gst_buffer_peek_memory (buffer, i);
|
|
||||||
d->chunk->offset = mem->offset;
|
|
||||||
d->chunk->size = mem->size;
|
|
||||||
}
|
|
||||||
gst_buffer_ref (buffer);
|
gst_buffer_ref (buffer);
|
||||||
|
g_queue_push_tail (&pinossink->queue, buffer);
|
||||||
|
|
||||||
if (!(res = pinos_stream_send_buffer (pinossink->stream, data->id)))
|
if (pinossink->need_ready)
|
||||||
g_warning ("can't send buffer");
|
do_send_buffer (pinossink);
|
||||||
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
pinos_thread_main_loop_unlock (pinossink->main_loop);
|
pinos_thread_main_loop_unlock (pinossink->main_loop);
|
||||||
|
|
@ -707,6 +740,7 @@ gst_pinos_sink_start (GstBaseSink * basesink)
|
||||||
pinos_signal_add (&pinossink->stream->add_buffer, &pinossink->stream_add_buffer, on_add_buffer);
|
pinos_signal_add (&pinossink->stream->add_buffer, &pinossink->stream_add_buffer, on_add_buffer);
|
||||||
pinos_signal_add (&pinossink->stream->remove_buffer, &pinossink->stream_remove_buffer, on_remove_buffer);
|
pinos_signal_add (&pinossink->stream->remove_buffer, &pinossink->stream_remove_buffer, on_remove_buffer);
|
||||||
pinos_signal_add (&pinossink->stream->new_buffer, &pinossink->stream_new_buffer, on_new_buffer);
|
pinos_signal_add (&pinossink->stream->new_buffer, &pinossink->stream_new_buffer, on_new_buffer);
|
||||||
|
pinos_signal_add (&pinossink->stream->need_buffer, &pinossink->stream_need_buffer, on_need_buffer);
|
||||||
pinos_thread_main_loop_unlock (pinossink->main_loop);
|
pinos_thread_main_loop_unlock (pinossink->main_loop);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ struct _GstPinosSink {
|
||||||
PinosListener stream_add_buffer;
|
PinosListener stream_add_buffer;
|
||||||
PinosListener stream_remove_buffer;
|
PinosListener stream_remove_buffer;
|
||||||
PinosListener stream_new_buffer;
|
PinosListener stream_new_buffer;
|
||||||
|
PinosListener stream_need_buffer;
|
||||||
|
|
||||||
GstAllocator *allocator;
|
GstAllocator *allocator;
|
||||||
GstStructure *properties;
|
GstStructure *properties;
|
||||||
|
|
@ -96,6 +97,8 @@ struct _GstPinosSink {
|
||||||
|
|
||||||
GstPinosPool *pool;
|
GstPinosPool *pool;
|
||||||
GHashTable *buf_ids;
|
GHashTable *buf_ids;
|
||||||
|
GQueue queue;
|
||||||
|
guint need_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstPinosSinkClass {
|
struct _GstPinosSinkClass {
|
||||||
|
|
|
||||||
|
|
@ -173,13 +173,19 @@ clock_disabled:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_queue (GstPinosSrc *pinossrc)
|
||||||
|
{
|
||||||
|
g_queue_foreach (&pinossrc->queue, (GFunc) gst_mini_object_unref, NULL);
|
||||||
|
g_queue_clear (&pinossrc->queue);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_pinos_src_finalize (GObject * object)
|
gst_pinos_src_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
GstPinosSrc *pinossrc = GST_PINOS_SRC (object);
|
GstPinosSrc *pinossrc = GST_PINOS_SRC (object);
|
||||||
|
|
||||||
g_queue_foreach (&pinossrc->queue, (GFunc) gst_mini_object_unref, NULL);
|
clear_queue (pinossrc);
|
||||||
g_queue_clear (&pinossrc->queue);
|
|
||||||
|
|
||||||
pinos_thread_main_loop_destroy (pinossrc->main_loop);
|
pinos_thread_main_loop_destroy (pinossrc->main_loop);
|
||||||
pinossrc->main_loop = NULL;
|
pinossrc->main_loop = NULL;
|
||||||
|
|
@ -340,6 +346,7 @@ typedef struct {
|
||||||
SpaBuffer *buf;
|
SpaBuffer *buf;
|
||||||
SpaMetaHeader *header;
|
SpaMetaHeader *header;
|
||||||
guint flags;
|
guint flags;
|
||||||
|
goffset offset;
|
||||||
} ProcessMemData;
|
} ProcessMemData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -417,13 +424,15 @@ on_add_buffer (PinosListener *listener,
|
||||||
case SPA_DATA_TYPE_DMABUF:
|
case SPA_DATA_TYPE_DMABUF:
|
||||||
{
|
{
|
||||||
gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (d->fd),
|
gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (d->fd),
|
||||||
d->size, GST_FD_MEMORY_FLAG_NONE);
|
d->maxsize, GST_FD_MEMORY_FLAG_NONE);
|
||||||
gst_memory_resize (gmem, d->chunk->offset, d->chunk->size);
|
gst_memory_resize (gmem, d->chunk->offset + d->mapoffset, d->chunk->size);
|
||||||
|
data.offset = d->mapoffset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_DATA_TYPE_MEMPTR:
|
case SPA_DATA_TYPE_MEMPTR:
|
||||||
gmem = gst_memory_new_wrapped (0, d->data, d->size, d->chunk->offset,
|
gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, d->chunk->offset + d->mapoffset,
|
||||||
d->chunk->size, NULL, NULL);
|
d->chunk->size, NULL, NULL);
|
||||||
|
data.offset = 0;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -488,7 +497,7 @@ on_new_buffer (PinosListener *listener,
|
||||||
for (i = 0; i < data->buf->n_datas; i++) {
|
for (i = 0; i < data->buf->n_datas; i++) {
|
||||||
SpaData *d = &data->buf->datas[i];
|
SpaData *d = &data->buf->datas[i];
|
||||||
GstMemory *mem = gst_buffer_peek_memory (buf, i);
|
GstMemory *mem = gst_buffer_peek_memory (buf, i);
|
||||||
mem->offset = d->chunk->offset;
|
mem->offset = d->chunk->offset + data->offset;
|
||||||
mem->size = d->chunk->size;
|
mem->size = d->chunk->size;
|
||||||
}
|
}
|
||||||
g_queue_push_tail (&pinossrc->queue, buf);
|
g_queue_push_tail (&pinossrc->queue, buf);
|
||||||
|
|
@ -937,13 +946,6 @@ gst_pinos_src_start (GstBaseSrc * basesrc)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clear_queue (GstPinosSrc *pinossrc)
|
|
||||||
{
|
|
||||||
g_queue_foreach (&pinossrc->queue, (GFunc) gst_mini_object_unref, NULL);
|
|
||||||
g_queue_clear (&pinossrc->queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_pinos_src_stop (GstBaseSrc * basesrc)
|
gst_pinos_src_stop (GstBaseSrc * basesrc)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,11 @@ spa_proxy_node_send_command (SpaNode *node,
|
||||||
PINOS_MESSAGE_NODE_COMMAND,
|
PINOS_MESSAGE_NODE_COMMAND,
|
||||||
&cnc,
|
&cnc,
|
||||||
true);
|
true);
|
||||||
|
if (command->type == SPA_NODE_COMMAND_START) {
|
||||||
|
uint8_t cmd = PINOS_TRANSPORT_CMD_NEED_DATA;
|
||||||
|
write (this->data_source.fd, &cmd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
res = SPA_RESULT_RETURN_ASYNC (cnc.seq);
|
res = SPA_RESULT_RETURN_ASYNC (cnc.seq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -686,8 +691,8 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||||
am.type = d->type;
|
am.type = d->type;
|
||||||
am.memfd = d->fd;
|
am.memfd = d->fd;
|
||||||
am.flags = d->flags;
|
am.flags = d->flags;
|
||||||
am.offset = d->offset;
|
am.offset = d->mapoffset;
|
||||||
am.size = d->size;
|
am.size = d->maxsize;
|
||||||
pinos_resource_send_message (this->resource,
|
pinos_resource_send_message (this->resource,
|
||||||
PINOS_MESSAGE_ADD_MEM,
|
PINOS_MESSAGE_ADD_MEM,
|
||||||
&am,
|
&am,
|
||||||
|
|
@ -698,7 +703,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
||||||
break;
|
break;
|
||||||
case SPA_DATA_TYPE_MEMPTR:
|
case SPA_DATA_TYPE_MEMPTR:
|
||||||
b->buffer.datas[j].data = SPA_INT_TO_PTR (b->size);
|
b->buffer.datas[j].data = SPA_INT_TO_PTR (b->size);
|
||||||
b->size += d->size;
|
b->size += d->maxsize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
b->buffer.datas[j].type = SPA_DATA_TYPE_INVALID;
|
b->buffer.datas[j].type = SPA_DATA_TYPE_INVALID;
|
||||||
|
|
@ -863,8 +868,6 @@ static SpaResult
|
||||||
spa_proxy_node_process_input (SpaNode *node)
|
spa_proxy_node_process_input (SpaNode *node)
|
||||||
{
|
{
|
||||||
SpaProxy *this;
|
SpaProxy *this;
|
||||||
unsigned int i;
|
|
||||||
bool have_error = false;
|
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
|
|
@ -872,22 +875,29 @@ spa_proxy_node_process_input (SpaNode *node)
|
||||||
|
|
||||||
this = SPA_CONTAINER_OF (node, SpaProxy, node);
|
this = SPA_CONTAINER_OF (node, SpaProxy, node);
|
||||||
|
|
||||||
for (i = 0; i < this->n_inputs; i++) {
|
#if 0
|
||||||
SpaProxyPort *port = &this->in_ports[i];
|
{
|
||||||
SpaPortInput *input;
|
unsigned int i;
|
||||||
|
bool have_error = false;
|
||||||
|
|
||||||
if ((input = port->io) == NULL)
|
for (i = 0; i < this->n_inputs; i++) {
|
||||||
continue;
|
SpaProxyPort *port = &this->in_ports[i];
|
||||||
|
SpaPortInput *input;
|
||||||
|
|
||||||
if (!CHECK_PORT_BUFFER (this, input->buffer_id, port)) {
|
if ((input = port->io) == NULL)
|
||||||
input->status = SPA_RESULT_INVALID_BUFFER_ID;
|
continue;
|
||||||
have_error = true;
|
|
||||||
continue;
|
if (!CHECK_PORT_BUFFER (this, input->buffer_id, port)) {
|
||||||
|
input->status = SPA_RESULT_INVALID_BUFFER_ID;
|
||||||
|
have_error = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
copy_meta_out (this, port, input->buffer_id);
|
||||||
}
|
}
|
||||||
copy_meta_out (this, port, input->buffer_id);
|
if (have_error)
|
||||||
|
return SPA_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
if (have_error)
|
#endif
|
||||||
return SPA_RESULT_ERROR;
|
|
||||||
|
|
||||||
cmd = PINOS_TRANSPORT_CMD_HAVE_DATA;
|
cmd = PINOS_TRANSPORT_CMD_HAVE_DATA;
|
||||||
write (this->data_source.fd, &cmd, 1);
|
write (this->data_source.fd, &cmd, 1);
|
||||||
|
|
@ -899,28 +909,37 @@ static SpaResult
|
||||||
spa_proxy_node_process_output (SpaNode *node)
|
spa_proxy_node_process_output (SpaNode *node)
|
||||||
{
|
{
|
||||||
SpaProxy *this;
|
SpaProxy *this;
|
||||||
unsigned int i;
|
uint8_t cmd;
|
||||||
bool have_error = false;
|
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
this = SPA_CONTAINER_OF (node, SpaProxy, node);
|
this = SPA_CONTAINER_OF (node, SpaProxy, node);
|
||||||
|
|
||||||
for (i = 0; i < this->n_outputs; i++) {
|
#if 0
|
||||||
SpaProxyPort *port = &this->out_ports[i];
|
{
|
||||||
SpaPortOutput *output;
|
unsigned int i;
|
||||||
|
bool have_error = false;
|
||||||
|
|
||||||
if ((output = port->io) == NULL)
|
for (i = 0; i < this->n_outputs; i++) {
|
||||||
continue;
|
SpaProxyPort *port = &this->out_ports[i];
|
||||||
|
SpaPortOutput *output;
|
||||||
|
|
||||||
copy_meta_in (this, port, output->buffer_id);
|
if ((output = port->io) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (output->status != SPA_RESULT_OK)
|
copy_meta_in (this, port, output->buffer_id);
|
||||||
have_error = true;
|
|
||||||
|
if (output->status != SPA_RESULT_OK)
|
||||||
|
have_error = true;
|
||||||
|
}
|
||||||
|
if (have_error)
|
||||||
|
return SPA_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
if (have_error)
|
#endif
|
||||||
return SPA_RESULT_ERROR;
|
|
||||||
|
cmd = PINOS_TRANSPORT_CMD_NEED_DATA;
|
||||||
|
write (this->data_source.fd, &cmd, 1);
|
||||||
|
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -1052,6 +1071,17 @@ proxy_on_data_fd_events (SpaSource *source)
|
||||||
}
|
}
|
||||||
if (cmd & PINOS_TRANSPORT_CMD_HAVE_DATA) {
|
if (cmd & PINOS_TRANSPORT_CMD_HAVE_DATA) {
|
||||||
SpaNodeEventHaveOutput ho;
|
SpaNodeEventHaveOutput ho;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < this->n_outputs; i++) {
|
||||||
|
SpaProxyPort *port = &this->out_ports[i];
|
||||||
|
SpaPortOutput *output;
|
||||||
|
|
||||||
|
if ((output = port->io) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
copy_meta_in (this, port, output->buffer_id);
|
||||||
|
}
|
||||||
ho.event.type = SPA_NODE_EVENT_TYPE_HAVE_OUTPUT;
|
ho.event.type = SPA_NODE_EVENT_TYPE_HAVE_OUTPUT;
|
||||||
ho.event.size = sizeof (ho);
|
ho.event.size = sizeof (ho);
|
||||||
ho.port_id = 0;
|
ho.port_id = 0;
|
||||||
|
|
|
||||||
|
|
@ -324,10 +324,10 @@ alloc_buffers (PinosLink *this,
|
||||||
d->type = SPA_DATA_TYPE_MEMFD;
|
d->type = SPA_DATA_TYPE_MEMFD;
|
||||||
d->flags = 0;
|
d->flags = 0;
|
||||||
d->fd = mem->fd;
|
d->fd = mem->fd;
|
||||||
d->offset = 0;
|
d->mapoffset = SPA_PTRDIFF (ddp, mem->ptr);
|
||||||
d->size = mem->size;
|
d->maxsize = data_sizes[j];
|
||||||
d->data = mem->ptr;
|
d->data = SPA_MEMBER (mem->ptr, d->mapoffset, void);
|
||||||
d->chunk->offset = SPA_PTRDIFF (ddp, d->data);
|
d->chunk->offset = 0;
|
||||||
d->chunk->size = data_sizes[j];
|
d->chunk->size = data_sizes[j];
|
||||||
d->chunk->stride = data_strides[j];
|
d->chunk->stride = data_strides[j];
|
||||||
ddp += data_sizes[j];
|
ddp += data_sizes[j];
|
||||||
|
|
|
||||||
|
|
@ -328,11 +328,6 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
|
||||||
PinosPort *port = this->output_port_map[ho->port_id];
|
PinosPort *port = this->output_port_map[ho->port_id];
|
||||||
PinosLink *link;
|
PinosLink *link;
|
||||||
|
|
||||||
if ((res = spa_node_process_output (node)) < 0) {
|
|
||||||
pinos_log_warn ("node %p: got pull error %d, %d", this, res, po->status);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
spa_list_for_each (link, &port->rt.links, rt.output_link) {
|
spa_list_for_each (link, &port->rt.links, rt.output_link) {
|
||||||
size_t offset;
|
size_t offset;
|
||||||
|
|
||||||
|
|
@ -356,6 +351,10 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
|
||||||
if ((res = spa_node_port_reuse_buffer (node, ho->port_id, po->buffer_id)) < 0)
|
if ((res = spa_node_port_reuse_buffer (node, ho->port_id, po->buffer_id)) < 0)
|
||||||
pinos_log_warn ("node %p: error reuse buffer: %d", node, res);
|
pinos_log_warn ("node %p: error reuse buffer: %d", node, res);
|
||||||
}
|
}
|
||||||
|
if ((res = spa_node_process_output (node)) < 0) {
|
||||||
|
pinos_log_warn ("node %p: got pull error %d, %d", this, res, po->status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_NODE_EVENT_TYPE_REUSE_BUFFER:
|
case SPA_NODE_EVENT_TYPE_REUSE_BUFFER:
|
||||||
|
|
|
||||||
|
|
@ -174,8 +174,8 @@ typedef struct {
|
||||||
SpaDataType type;
|
SpaDataType type;
|
||||||
int flags;
|
int flags;
|
||||||
int fd;
|
int fd;
|
||||||
off_t offset;
|
off_t mapoffset;
|
||||||
size_t size;
|
size_t maxsize;
|
||||||
void *data;
|
void *data;
|
||||||
SpaChunk *chunk;
|
SpaChunk *chunk;
|
||||||
} SpaData;
|
} SpaData;
|
||||||
|
|
|
||||||
|
|
@ -568,8 +568,8 @@ struct _SpaNode {
|
||||||
* Returns: #SPA_RESULT_OK on success
|
* Returns: #SPA_RESULT_OK on success
|
||||||
* #SPA_RESULT_HAVE_ENOUGH_INPUT when output can be produced.
|
* #SPA_RESULT_HAVE_ENOUGH_INPUT when output can be produced.
|
||||||
*/
|
*/
|
||||||
SpaResult (*process_input) (SpaNode *node);
|
SpaResult (*process_input) (SpaNode *node);
|
||||||
SpaResult (*process_output) (SpaNode *node);
|
SpaResult (*process_output) (SpaNode *node);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -196,11 +196,11 @@ spa_debug_buffer (const SpaBuffer *buffer)
|
||||||
fprintf (stderr, " flags: %d\n", d->flags);
|
fprintf (stderr, " flags: %d\n", d->flags);
|
||||||
fprintf (stderr, " data: %p\n", d->data);
|
fprintf (stderr, " data: %p\n", d->data);
|
||||||
fprintf (stderr, " fd: %d\n", d->fd);
|
fprintf (stderr, " fd: %d\n", d->fd);
|
||||||
fprintf (stderr, " offset: %zd\n", d->offset);
|
fprintf (stderr, " offset: %zd\n", d->mapoffset);
|
||||||
fprintf (stderr, " maxsize: %zd\n", d->size);
|
fprintf (stderr, " maxsize: %zu\n", d->maxsize);
|
||||||
fprintf (stderr, " chunk: %p\n", d->chunk);
|
fprintf (stderr, " chunk: %p\n", d->chunk);
|
||||||
fprintf (stderr, " offset: %zd\n", d->chunk->offset);
|
fprintf (stderr, " offset: %zd\n", d->chunk->offset);
|
||||||
fprintf (stderr, " size: %zd\n", d->chunk->size);
|
fprintf (stderr, " size: %zu\n", d->chunk->size);
|
||||||
fprintf (stderr, " stride: %zd\n", d->chunk->stride);
|
fprintf (stderr, " stride: %zd\n", d->chunk->stride);
|
||||||
}
|
}
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
|
|
|
||||||
|
|
@ -268,22 +268,35 @@ pull_frames_queue (SpaALSAState *state,
|
||||||
snd_pcm_uframes_t offset,
|
snd_pcm_uframes_t offset,
|
||||||
snd_pcm_uframes_t frames)
|
snd_pcm_uframes_t frames)
|
||||||
{
|
{
|
||||||
|
if (spa_list_is_empty (&state->ready)) {
|
||||||
|
SpaNodeEventNeedInput ni;
|
||||||
|
|
||||||
|
ni.event.type = SPA_NODE_EVENT_TYPE_NEED_INPUT;
|
||||||
|
ni.event.size = sizeof (ni);
|
||||||
|
ni.port_id = 0;
|
||||||
|
state->event_cb (&state->node, &ni.event, state->user_data);
|
||||||
|
}
|
||||||
if (!spa_list_is_empty (&state->ready)) {
|
if (!spa_list_is_empty (&state->ready)) {
|
||||||
uint8_t *src, *dst;
|
uint8_t *src, *dst;
|
||||||
size_t n_bytes;
|
size_t n_bytes, size;
|
||||||
|
off_t offs;
|
||||||
SpaALSABuffer *b;
|
SpaALSABuffer *b;
|
||||||
|
|
||||||
b = spa_list_first (&state->ready, SpaALSABuffer, list);
|
b = spa_list_first (&state->ready, SpaALSABuffer, list);
|
||||||
|
|
||||||
src = SPA_MEMBER (b->outbuf->datas[0].data, b->outbuf->datas[0].offset + state->ready_offset, uint8_t);
|
offs = SPA_MIN (b->outbuf->datas[0].chunk->offset, b->outbuf->datas[0].maxsize);
|
||||||
|
src = SPA_MEMBER (b->outbuf->datas[0].data, offs, uint8_t);
|
||||||
|
size = SPA_MIN (b->outbuf->datas[0].chunk->size, b->outbuf->datas[0].maxsize - offs);
|
||||||
|
|
||||||
|
src = SPA_MEMBER (src, state->ready_offset, uint8_t);
|
||||||
dst = SPA_MEMBER (my_areas[0].addr, offset * state->frame_size, uint8_t);
|
dst = SPA_MEMBER (my_areas[0].addr, offset * state->frame_size, uint8_t);
|
||||||
n_bytes = SPA_MIN (b->outbuf->datas[0].size - state->ready_offset, frames * state->frame_size);
|
n_bytes = SPA_MIN (size - state->ready_offset, frames * state->frame_size);
|
||||||
frames = SPA_MIN (frames, n_bytes / state->frame_size);
|
frames = SPA_MIN (frames, n_bytes / state->frame_size);
|
||||||
|
|
||||||
memcpy (dst, src, n_bytes);
|
memcpy (dst, src, n_bytes);
|
||||||
|
|
||||||
state->ready_offset += n_bytes;
|
state->ready_offset += n_bytes;
|
||||||
if (state->ready_offset >= b->outbuf->datas[0].size) {
|
if (state->ready_offset >= size) {
|
||||||
SpaNodeEventReuseBuffer rb;
|
SpaNodeEventReuseBuffer rb;
|
||||||
|
|
||||||
spa_list_remove (&b->list);
|
spa_list_remove (&b->list);
|
||||||
|
|
@ -298,7 +311,7 @@ pull_frames_queue (SpaALSAState *state,
|
||||||
state->ready_offset = 0;
|
state->ready_offset = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
spa_log_warn (state->log, "underrun");
|
spa_log_warn (state->log, "underrun, want %zd frames", frames);
|
||||||
snd_pcm_areas_silence (my_areas, offset, state->channels, frames, state->format);
|
snd_pcm_areas_silence (my_areas, offset, state->channels, frames, state->format);
|
||||||
}
|
}
|
||||||
return frames;
|
return frames;
|
||||||
|
|
@ -318,7 +331,7 @@ pull_frames_ringbuffer (SpaALSAState *state,
|
||||||
|
|
||||||
b = state->ringbuffer;
|
b = state->ringbuffer;
|
||||||
|
|
||||||
src = SPA_MEMBER (b->outbuf->datas[0].data, b->outbuf->datas[0].offset, void);
|
src = b->outbuf->datas[0].data;
|
||||||
dst = SPA_MEMBER (my_areas[0].addr, offset * state->frame_size, uint8_t);
|
dst = SPA_MEMBER (my_areas[0].addr, offset * state->frame_size, uint8_t);
|
||||||
|
|
||||||
avail = spa_ringbuffer_get_read_areas (&b->rb->ringbuffer, areas);
|
avail = spa_ringbuffer_get_read_areas (&b->rb->ringbuffer, areas);
|
||||||
|
|
@ -442,8 +455,8 @@ mmap_read (SpaALSAState *state)
|
||||||
b = spa_list_first (&state->free, SpaALSABuffer, list);
|
b = spa_list_first (&state->free, SpaALSABuffer, list);
|
||||||
spa_list_remove (&b->list);
|
spa_list_remove (&b->list);
|
||||||
|
|
||||||
dest = SPA_MEMBER (b->outbuf->datas[0].data, b->outbuf->datas[0].offset, void);
|
dest = b->outbuf->datas[0].data;
|
||||||
destsize = b->outbuf->datas[0].size;
|
destsize = b->outbuf->datas[0].maxsize;
|
||||||
|
|
||||||
if (b->h) {
|
if (b->h) {
|
||||||
b->h->seq = state->sample_count;
|
b->h->seq = state->sample_count;
|
||||||
|
|
@ -484,7 +497,9 @@ mmap_read (SpaALSAState *state)
|
||||||
SpaData *d;
|
SpaData *d;
|
||||||
|
|
||||||
d = b->outbuf->datas;
|
d = b->outbuf->datas;
|
||||||
d[0].size = avail * state->frame_size;
|
d[0].chunk->offset = 0;
|
||||||
|
d[0].chunk->size = avail * state->frame_size;
|
||||||
|
d[0].chunk->stride = 0;
|
||||||
|
|
||||||
spa_list_insert (state->ready.prev, &b->list);
|
spa_list_insert (state->ready.prev, &b->list);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -598,12 +598,12 @@ add_port_data (SpaAudioMixer *this, SpaBuffer *out, SpaAudioMixerPort *port)
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (op == NULL) {
|
if (op == NULL) {
|
||||||
op = (uint8_t*)odatas[oi].data + odatas[oi].offset;
|
op = (uint8_t*)odatas[oi].data + odatas[oi].chunk->offset;
|
||||||
os = odatas[oi].size;
|
os = odatas[oi].chunk->size;
|
||||||
}
|
}
|
||||||
if (ip == NULL) {
|
if (ip == NULL) {
|
||||||
ip = (uint8_t*)idatas[port->buffer_index].data + idatas[port->buffer_index].offset;
|
ip = (uint8_t*)idatas[port->buffer_index].data + idatas[port->buffer_index].chunk->offset;
|
||||||
is = idatas[port->buffer_index].size;
|
is = idatas[port->buffer_index].chunk->size;
|
||||||
ip += port->buffer_offset;
|
ip += port->buffer_offset;
|
||||||
is -= port->buffer_offset;
|
is -= port->buffer_offset;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -690,8 +690,8 @@ spa_audiotestsrc_node_port_use_buffers (SpaNode *node,
|
||||||
spa_log_error (this->log, "audiotestsrc %p: invalid memory on buffer %p", this, buffers[i]);
|
spa_log_error (this->log, "audiotestsrc %p: invalid memory on buffer %p", this, buffers[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
b->ptr = SPA_MEMBER (d[0].data, d[0].offset, void);
|
b->ptr = d[0].data;
|
||||||
b->size = d[0].size;
|
b->size = d[0].maxsize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ spa_v4l2_clear_buffers (SpaV4l2Source *this)
|
||||||
}
|
}
|
||||||
if (b->allocated) {
|
if (b->allocated) {
|
||||||
if (b->outbuf->datas[0].data)
|
if (b->outbuf->datas[0].data)
|
||||||
munmap (b->outbuf->datas[0].data, b->outbuf->datas[0].size);
|
munmap (b->outbuf->datas[0].data, b->outbuf->datas[0].maxsize);
|
||||||
if (b->outbuf->datas[0].fd != -1)
|
if (b->outbuf->datas[0].fd != -1)
|
||||||
close (b->outbuf->datas[0].fd);
|
close (b->outbuf->datas[0].fd);
|
||||||
b->outbuf->datas[0].type = SPA_DATA_TYPE_INVALID;
|
b->outbuf->datas[0].type = SPA_DATA_TYPE_INVALID;
|
||||||
|
|
@ -973,7 +973,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
b->v4l2_buffer.m.userptr = (unsigned long) d[0].data;
|
b->v4l2_buffer.m.userptr = (unsigned long) d[0].data;
|
||||||
b->v4l2_buffer.length = d[0].size;
|
b->v4l2_buffer.length = d[0].maxsize;
|
||||||
break;
|
break;
|
||||||
case SPA_DATA_TYPE_DMABUF:
|
case SPA_DATA_TYPE_DMABUF:
|
||||||
b->v4l2_buffer.m.fd = d[0].fd;
|
b->v4l2_buffer.m.fd = d[0].fd;
|
||||||
|
|
@ -1047,8 +1047,8 @@ mmap_init (SpaV4l2Source *this,
|
||||||
}
|
}
|
||||||
|
|
||||||
d = buffers[i]->datas;
|
d = buffers[i]->datas;
|
||||||
d[0].offset = 0;
|
d[0].mapoffset = 0;
|
||||||
d[0].size = b->v4l2_buffer.length;
|
d[0].maxsize = b->v4l2_buffer.length;
|
||||||
d[0].chunk->offset = 0;
|
d[0].chunk->offset = 0;
|
||||||
d[0].chunk->size = b->v4l2_buffer.length;
|
d[0].chunk->size = b->v4l2_buffer.length;
|
||||||
d[0].chunk->stride = state->fmt.fmt.pix.bytesperline;
|
d[0].chunk->stride = state->fmt.fmt.pix.bytesperline;
|
||||||
|
|
|
||||||
|
|
@ -657,7 +657,7 @@ spa_videotestsrc_node_port_use_buffers (SpaNode *node,
|
||||||
spa_log_error (this->log, "videotestsrc %p: invalid memory on buffer %p", this, buffers[i]);
|
spa_log_error (this->log, "videotestsrc %p: invalid memory on buffer %p", this, buffers[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
b->ptr = SPA_MEMBER (d[0].data, d[0].offset, void);
|
b->ptr = SPA_MEMBER (d[0].data, d[0].chunk->offset, void);
|
||||||
b->stride = d[0].chunk->stride;
|
b->stride = d[0].chunk->stride;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -582,10 +582,10 @@ spa_volume_node_process_output (SpaNode *node)
|
||||||
sd = &sbuf->datas[si];
|
sd = &sbuf->datas[si];
|
||||||
dd = &dbuf->datas[di];
|
dd = &dbuf->datas[di];
|
||||||
|
|
||||||
src = (uint16_t*) ((uint8_t*)sd->data + sd->offset + soff);
|
src = (uint16_t*) ((uint8_t*)sd->data + sd->chunk->offset + soff);
|
||||||
dst = (uint16_t*) ((uint8_t*)dd->data + dd->offset + doff);
|
dst = (uint16_t*) ((uint8_t*)dd->data + dd->chunk->offset + doff);
|
||||||
|
|
||||||
n_bytes = SPA_MIN (sd->size - soff, dd->size - doff);
|
n_bytes = SPA_MIN (sd->chunk->size - soff, dd->chunk->size - doff);
|
||||||
n_samples = n_bytes / sizeof (uint16_t);
|
n_samples = n_bytes / sizeof (uint16_t);
|
||||||
|
|
||||||
for (i = 0; i < n_samples; i++)
|
for (i = 0; i < n_samples; i++)
|
||||||
|
|
@ -594,11 +594,11 @@ spa_volume_node_process_output (SpaNode *node)
|
||||||
soff += n_bytes;
|
soff += n_bytes;
|
||||||
doff += n_bytes;
|
doff += n_bytes;
|
||||||
|
|
||||||
if (soff >= sd->size) {
|
if (soff >= sd->chunk->size) {
|
||||||
si++;
|
si++;
|
||||||
soff = 0;
|
soff = 0;
|
||||||
}
|
}
|
||||||
if (doff >= dd->size) {
|
if (doff >= dd->chunk->size) {
|
||||||
di++;
|
di++;
|
||||||
doff = 0;
|
doff = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue