buffer: improve memory management

Add refcounting to buffers.
Use static memory on ports for buffer input and output memory.
Improve negotiation, let format and properties be negotiated on ports as
the data passes.
Improve some debug info.
This commit is contained in:
Wim Taymans 2016-05-17 20:14:06 +02:00
parent 4a5ed1e1f5
commit 0f67434ae8
21 changed files with 368 additions and 334 deletions

View file

@ -251,7 +251,8 @@ gst_pinos_depay_chain (GstPad *pad, GstObject * parent, GstBuffer * buffer)
break;
}
}
pinos_buffer_clear (&pbuf);
pinos_buffer_iter_init (&it, &pbuf);
pinos_buffer_unref (&pbuf);
gst_buffer_unmap (buffer, &info);
gst_buffer_unref (buffer);

View file

@ -254,8 +254,9 @@ client_buffer_received (GstPinosPay *pay, GstBuffer *buffer,
break;
}
}
pinos_buffer_iter_end (&it);
pinos_buffer_unref (&pbuf);
gst_buffer_unmap (buffer, &info);
pinos_buffer_clear (&pbuf);
if (pay->pinos_input) {
GstBuffer *outbuf;
@ -440,8 +441,9 @@ gst_pinos_pay_chain_pinos (GstPinosPay *pay, GstBuffer * buffer)
break;
}
}
pinos_buffer_iter_end (&it);
pinos_buffer_unref (&pbuf);
gst_buffer_unmap (buffer, &info);
pinos_buffer_clear (&pbuf);
if (fdids != NULL) {
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
@ -490,6 +492,7 @@ gst_pinos_pay_chain_other (GstPinosPay *pay, GstBuffer * buffer)
data = pinos_buffer_steal_data (&pbuf, &size);
fds = pinos_buffer_steal_fds (&pbuf, &n_fds);
pinos_buffer_unref (&pbuf);
outbuf = gst_buffer_new_wrapped (data, size);
GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buffer);

View file

@ -84,7 +84,7 @@ on_received_buffer (PinosPort *port, gpointer user_data)
PinosBufferBuilder b;
gboolean have_out = FALSE;
pbuf = pinos_port_get_buffer (port);
pbuf = pinos_port_peek_buffer (port);
if (this->pinos_input) {
pinos_buffer_builder_init (&b);
@ -93,7 +93,7 @@ on_received_buffer (PinosPort *port, gpointer user_data)
pinos_buffer_iter_init (&it, pbuf);
while (pinos_buffer_iter_next (&it)) {
switch (pinos_buffer_iter_get_type (&it)) {
case PINOS_PACKET_TYPE_REFRESH_REQUEST:
case PINOS_PACKET_TYPE_REFRESH_REQUEST:
{
PinosPacketRefreshRequest p;
@ -115,7 +115,7 @@ on_received_buffer (PinosPort *port, gpointer user_data)
break;
}
}
pinos_buffer_clear (pbuf);
pinos_buffer_iter_end (&it);
if (this->pinos_input) {
GstBuffer *outbuf;
@ -225,16 +225,23 @@ gst_pinos_port_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
str = gst_caps_get_structure (caps, 0);
this->pinos_input = gst_structure_has_name (str, "application/x-pinos");
if (!this->pinos_input) {
GBytes *format;
GError *error = NULL;
PinosBufferBuilder builder;
PinosBuffer pbuf;
PinosPacketFormatChange fc;
cstr = gst_caps_to_string (caps);
format = g_bytes_new_take (cstr, strlen (cstr) + 1);
pinos_port_buffer_builder_init (this->port, &builder);
fc.id = 0;
fc.format = cstr = gst_caps_to_string (caps);
pinos_buffer_builder_add_format_change (&builder, &fc);
pinos_buffer_builder_end (&builder, &pbuf);
g_free (cstr);
if (!pinos_port_update_format (this->port, format, &error)) {
GST_WARNING ("update failed: %s", error->message);
if (!pinos_port_send_buffer (this->port, &pbuf, &error)) {
GST_WARNING ("format update failed: %s", error->message);
g_clear_error (&error);
}
pinos_buffer_unref (&pbuf);
}
return GST_BASE_SINK_CLASS (parent_class)->set_caps (bsink, caps);
@ -249,12 +256,13 @@ gst_pinos_port_sink_render_pinos (GstPinosPortSink * this, GstBuffer * buffer)
gst_buffer_map (buffer, &info, GST_MAP_READ);
pinos_buffer_init_data (&pbuf, info.data, info.size, NULL, 0);
gst_buffer_unmap (buffer, &info);
if (!pinos_port_send_buffer (this->port, &pbuf, &error)) {
GST_WARNING ("send failed: %s", error->message);
g_clear_error (&error);
}
gst_buffer_unmap (buffer, &info);
pinos_buffer_unref (&pbuf);
return GST_FLOW_OK;
}
@ -293,17 +301,19 @@ gst_pinos_port_sink_render_other (GstPinosPortSink * this, GstBuffer * buffer)
PinosPacketHeader hdr;
PinosPacketFDPayload p;
gboolean tmpfile = TRUE;
gint fd;
hdr.flags = 0;
hdr.seq = GST_BUFFER_OFFSET (buffer);
hdr.pts = GST_BUFFER_PTS (buffer) + GST_ELEMENT_CAST (this)->base_time;
hdr.dts_offset = 0;
pinos_buffer_builder_init (&builder);
pinos_port_buffer_builder_init (this->port, &builder);
pinos_buffer_builder_add_header (&builder, &hdr);
fdmem = gst_pinos_port_sink_get_fd_memory (this, buffer, &tmpfile);
p.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (fdmem));
fd = gst_fd_memory_get_fd (fdmem);
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd);
p.id = pinos_fd_manager_get_id (this->fdmanager);
p.offset = fdmem->offset;
p.size = fdmem->size;
@ -318,6 +328,8 @@ gst_pinos_port_sink_render_other (GstPinosPortSink * this, GstBuffer * buffer)
GST_WARNING ("send failed: %s", error->message);
g_clear_error (&error);
}
pinos_buffer_steal_fds (&pbuf, NULL);
pinos_buffer_unref (&pbuf);
gst_memory_unref(fdmem);

View file

@ -99,12 +99,12 @@ fdpayload_data_destroy (gpointer user_data)
GST_DEBUG_OBJECT (this, "destroy %d", r.id);
pinos_buffer_builder_init (&b);
pinos_port_buffer_builder_init (this->port, &b);
pinos_buffer_builder_add_release_fd_payload (&b, &r);
pinos_buffer_builder_end (&b, &pbuf);
pinos_port_send_buffer (this->port, &pbuf, NULL);
pinos_buffer_clear (&pbuf);
pinos_buffer_unref (&pbuf);
gst_object_unref (this);
g_slice_free (FDPayloadData, data);
@ -120,7 +120,7 @@ on_received_buffer (PinosPort *port,
GstBuffer *buf = NULL;
GST_LOG_OBJECT (this, "got new buffer");
pbuf = pinos_port_get_buffer (port);
pbuf = pinos_port_peek_buffer (port);
pinos_buffer_iter_init (&it, pbuf);
while (pinos_buffer_iter_next (&it)) {
@ -130,7 +130,7 @@ on_received_buffer (PinosPort *port,
PinosPacketHeader hdr;
if (!pinos_buffer_iter_parse_header (&it, &hdr))
goto parse_failed;
break;
if (buf == NULL)
buf = gst_buffer_new ();
@ -152,17 +152,17 @@ on_received_buffer (PinosPort *port,
int fd;
if (!pinos_buffer_iter_parse_fd_payload (&it, &data.p))
goto parse_failed;
break;
GST_DEBUG ("got fd payload id %d", data.p.id);
fd = pinos_buffer_get_fd (pbuf, data.p.fd_index);
if (fd == -1)
goto no_fds;
break;
if (buf == NULL)
buf = gst_buffer_new ();
fdmem = gst_fd_allocator_alloc (this->fd_allocator, fd,
fdmem = gst_fd_allocator_alloc (this->fd_allocator, dup (fd),
data.p.offset + data.p.size, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (fdmem, data.p.offset, data.p.size);
gst_buffer_append_memory (buf, fdmem);
@ -180,7 +180,7 @@ on_received_buffer (PinosPort *port,
GstCaps *caps;
if (!pinos_buffer_iter_parse_format_change (&it, &change))
goto parse_failed;
break;
GST_DEBUG ("got format change %d %s", change.id, change.format);
caps = gst_caps_from_string (change.format);
@ -192,27 +192,14 @@ on_received_buffer (PinosPort *port,
break;
}
}
pinos_buffer_iter_end (&it);
if (buf) {
g_queue_push_tail (&this->queue, buf);
g_cond_signal (&this->cond);
}
return;
/* ERRORS */
parse_failed:
{
gst_buffer_unref (buf);
GST_ELEMENT_ERROR (this, RESOURCE, FAILED, ("buffer parse failure"), (NULL));
return;
}
no_fds:
{
gst_buffer_unref (buf);
GST_ELEMENT_ERROR (this, RESOURCE, FAILED, ("fd not found in buffer"), (NULL));
return;
}
}
static void
@ -443,7 +430,7 @@ gst_pinos_port_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
g_object_get (this->port, "format", &format, NULL);
if (format) {
GST_DEBUG ("have format %s", g_bytes_get_data (format, NULL));
GST_DEBUG ("have format %s", (gchar *)g_bytes_get_data (format, NULL));
caps = gst_caps_from_string (g_bytes_get_data (format, NULL));
g_bytes_unref (format);
}
@ -475,13 +462,13 @@ gst_pinos_port_src_event (GstBaseSrc * src, GstEvent * event)
refresh.request_type = all_headers ? 1 : 0;
refresh.pts = running_time;
pinos_buffer_builder_init (&b);
pinos_port_buffer_builder_init (this->port, &b);
pinos_buffer_builder_add_refresh_request (&b, &refresh);
pinos_buffer_builder_end (&b, &pbuf);
GST_DEBUG_OBJECT (this, "send refresh request");
pinos_port_send_buffer (this->port, &pbuf, NULL);
pinos_buffer_clear (&pbuf);
pinos_buffer_unref (&pbuf);
res = TRUE;
} else {
res = GST_BASE_SRC_CLASS (parent_class)->event (src, event);

View file

@ -412,6 +412,7 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
gsize size;
GError *err = NULL;
gboolean tmpfile, res;
int fd;
pinossink = GST_PINOS_SINK (bsink);
@ -455,7 +456,8 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
pinos_buffer_builder_init (&builder);
pinos_buffer_builder_add_header (&builder, &hdr);
p.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (mem), &err);
fd = gst_fd_memory_get_fd (mem);
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd, &err);
if (p.fd_index == -1)
goto add_fd_failed;
p.id = pinossink->id_counter++;
@ -464,15 +466,17 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
pinos_buffer_builder_add_fd_payload (&builder, &p);
pinos_buffer_builder_end (&builder, &pbuf);
gst_memory_unref (mem);
pinos_main_loop_lock (pinossink->loop);
if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING)
goto streaming_error;
res = pinos_stream_send_buffer (pinossink->stream, &pbuf);
pinos_buffer_steal_fds (&pbuf, NULL);
pinos_buffer_clear (&pbuf);
pinos_main_loop_unlock (pinossink->loop);
gst_memory_unref (mem);
if (res && !tmpfile) {
/* keep the buffer around until we get the release fd message */
g_hash_table_insert (pinossink->fdids, GINT_TO_POINTER (p.id), gst_buffer_ref (buffer));

View file

@ -337,7 +337,7 @@ on_new_buffer (GObject *gobject,
return;
}
if (!pinos_stream_get_buffer (pinossink->stream, &pbuf)) {
if (!(pbuf = pinos_stream_peek_buffer (pinossink->stream))) {
g_warning ("failed to capture buffer");
return;
}
@ -373,6 +373,7 @@ on_new_buffer (GObject *gobject,
break;
}
}
pinos_buffer_iter_end (&it);
}
static void
@ -471,7 +472,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
PinosPacketFormatChange change;
PinosBuffer pbuf;
pinos_buffer_builder_init (&builder);
pinos_stream_buffer_builder_init (pinossink->stream, &builder);
change.id = 1;
change.format = g_bytes_get_data (format, NULL);
@ -480,7 +481,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
g_debug ("sending format");
res = pinos_stream_send_buffer (pinossink->stream, &pbuf);
pinos_buffer_clear (&pbuf);
pinos_buffer_unref (&pbuf);
}
pinos_main_loop_unlock (pinossink->loop);
@ -552,10 +553,14 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
tmpfile = TRUE;
}
pinos_buffer_builder_init (&builder);
pinos_main_loop_lock (pinossink->loop);
if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING)
goto streaming_error;
pinos_stream_buffer_builder_init (pinossink->stream, &builder);
pinos_buffer_builder_add_header (&builder, &hdr);
fd = dup (gst_fd_memory_get_fd (mem));
fd = gst_fd_memory_get_fd (mem);
p.fd_index = pinos_buffer_builder_add_fd (&builder, fd);
p.id = pinossink->id_counter++;
p.offset = 0;
@ -565,11 +570,9 @@ gst_pinos_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
GST_LOG ("sending fd index %d %d %d", p.id, p.fd_index, fd);
pinos_main_loop_lock (pinossink->loop);
if (pinos_stream_get_state (pinossink->stream) != PINOS_STREAM_STATE_STREAMING)
goto streaming_error;
res = pinos_stream_send_buffer (pinossink->stream, &pbuf);
pinos_buffer_clear (&pbuf);
pinos_buffer_steal_fds (&pbuf, NULL);
pinos_buffer_unref (&pbuf);
pinos_main_loop_unlock (pinossink->loop);
gst_memory_unref (mem);

View file

@ -262,8 +262,9 @@ gst_pinos_socket_sink_render_pinos (GstPinosSocketSink * this, GstBuffer * buffe
break;
}
}
pinos_buffer_iter_end (&it);
pinos_buffer_unref (&pbuf);
gst_buffer_unmap (buffer, &info);
pinos_buffer_clear (&pbuf);
if (fdids != NULL) {
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer),
@ -338,6 +339,7 @@ gst_pinos_socket_sink_render_other (GstPinosSocketSink * this, GstBuffer * buffe
data = pinos_buffer_steal_data (&pbuf, &size);
fds = pinos_buffer_steal_fds (&pbuf, &n_fds);
pinos_buffer_unref (&pbuf);
outbuf = gst_buffer_new_wrapped (data, size);
GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buffer);
@ -582,7 +584,8 @@ myreader_receive_buffer (GstPinosSocketSink *this, MyReader *myreader)
break;
}
}
pinos_buffer_clear (&pbuf);
pinos_buffer_iter_end (&it);
pinos_buffer_unref (&pbuf);
g_free (mem);
if (this->pinos_input) {

View file

@ -332,19 +332,18 @@ fdpayload_data_destroy (gpointer user_data)
GST_DEBUG_OBJECT (pinossrc, "destroy %d", r.id);
pinos_buffer_builder_init (&b);
pinos_buffer_builder_add_release_fd_payload (&b, &r);
pinos_buffer_builder_end (&b, &pbuf);
GST_OBJECT_LOCK (pinossrc);
if (pinossrc->stream_state == PINOS_STREAM_STATE_STREAMING) {
pinos_stream_buffer_builder_init (pinossrc->stream, &b);
pinos_buffer_builder_add_release_fd_payload (&b, &r);
pinos_buffer_builder_end (&b, &pbuf);
GST_DEBUG_OBJECT (pinossrc, "send release-fd for %d", r.id);
pinos_stream_send_buffer (pinossrc->stream, &pbuf);
pinos_buffer_unref (&pbuf);
}
GST_OBJECT_UNLOCK (pinossrc);
pinos_buffer_clear (&pbuf);
gst_object_unref (pinossrc);
g_slice_free (FDPayloadData, data);
}
@ -359,7 +358,7 @@ on_new_buffer (GObject *gobject,
GstBuffer *buf = NULL;
GST_LOG_OBJECT (pinossrc, "got new buffer");
if (!pinos_stream_get_buffer (pinossrc->stream, &pbuf)) {
if (!(pbuf = pinos_stream_peek_buffer (pinossrc->stream))) {
g_warning ("failed to capture buffer");
return;
}
@ -404,7 +403,7 @@ on_new_buffer (GObject *gobject,
if (buf == NULL)
buf = gst_buffer_new ();
fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, fd,
fdmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd),
data.p.offset + data.p.size, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (fdmem, data.p.offset, data.p.size);
gst_buffer_append_memory (buf, fdmem);
@ -434,6 +433,7 @@ on_new_buffer (GObject *gobject,
break;
}
}
pinos_buffer_iter_end (&it);
if (buf) {
g_queue_push_tail (&pinossrc->queue, buf);
@ -445,6 +445,8 @@ on_new_buffer (GObject *gobject,
/* ERRORS */
parse_failed:
{
pinos_buffer_iter_end (&it);
pinos_buffer_unref (pbuf);
gst_buffer_unref (buf);
GST_ELEMENT_ERROR (pinossrc, RESOURCE, FAILED, ("buffer parse failure"), (NULL));
pinos_main_loop_signal (pinossrc->loop, FALSE);
@ -452,6 +454,8 @@ parse_failed:
}
no_fds:
{
pinos_buffer_iter_end (&it);
pinos_buffer_unref (pbuf);
gst_buffer_unref (buf);
GST_ELEMENT_ERROR (pinossrc, RESOURCE, FAILED, ("fd not found in buffer"), (NULL));
pinos_main_loop_signal (pinossrc->loop, FALSE);
@ -745,12 +749,13 @@ gst_pinos_src_event (GstBaseSrc * src, GstEvent * event)
gst_video_event_parse_upstream_force_key_unit (event,
&running_time, &all_headers, &count);
pinos_buffer_builder_init (&b);
refresh.last_id = 0;
refresh.request_type = all_headers ? 1 : 0;
refresh.pts = running_time;
pinos_buffer_builder_init (&b);
pinos_buffer_builder_add_refresh_request (&b, &refresh);
pinos_buffer_builder_end (&b, &pbuf);
GST_OBJECT_LOCK (pinossrc);
@ -760,7 +765,7 @@ gst_pinos_src_event (GstBaseSrc * src, GstEvent * event)
}
GST_OBJECT_UNLOCK (pinossrc);
pinos_buffer_clear (&pbuf);
pinos_buffer_unref (&pbuf);
res = TRUE;
} else {
res = GST_BASE_SRC_CLASS (parent_class)->event (src, event);