mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
Rework pay/depay elements
Rename the payloader and depayloader to pinospay/pinosdepay because they now store data in a pinos specific format. Subclass GstElement because they are not real transform elements. Rework/remove some buffer functions that are not used by some more performant ones.
This commit is contained in:
parent
eada50916a
commit
c2cf359076
13 changed files with 582 additions and 660 deletions
|
|
@ -150,8 +150,8 @@ pinos_monitor_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
|||
# Client library #
|
||||
###################################
|
||||
|
||||
pinosgstsource = gst/gstfdpay.h gst/gstfdpay.c \
|
||||
gst/gstfddepay.h gst/gstfddepay.c \
|
||||
pinosgstsource = gst/gstpinospay.h gst/gstpinospay.c \
|
||||
gst/gstpinosdepay.h gst/gstpinosdepay.c \
|
||||
gst/gsttmpfileallocator.h gst/gsttmpfileallocator.c \
|
||||
wire-protocol.h
|
||||
|
||||
|
|
@ -219,8 +219,8 @@ plugin_LTLIBRARIES = libgstpinos.la
|
|||
|
||||
libgstpinos_la_SOURCES = \
|
||||
gst/gstpinos.c \
|
||||
gst/gstfdpay.c \
|
||||
gst/gstfddepay.c \
|
||||
gst/gstpinospay.c \
|
||||
gst/gstpinosdepay.c \
|
||||
gst/gstpinosdeviceprovider.c \
|
||||
gst/gstpinossrc.c \
|
||||
gst/gstpinossink.c
|
||||
|
|
@ -231,7 +231,7 @@ libgstpinos_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GLIB_LIBS) $(LIBM) -lgst
|
|||
libpinos-@PINOS_MAJORMINOR@.la libpinoscore-@PINOS_MAJORMINOR@.la
|
||||
libgstpinos_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
||||
|
||||
noinst_HEADERS = gst/gstpinossrc.h gst/gstpinossink.h gst/gstfdpay.h gst/gstfddepay.h gst/gstpinosdeviceprovider.h
|
||||
noinst_HEADERS = gst/gstpinossrc.h gst/gstpinossink.h gst/gstpinospay.h gst/gstpinosdepay.h gst/gstpinosdeviceprovider.h
|
||||
|
||||
###################################
|
||||
# Some minor stuff #
|
||||
|
|
|
|||
|
|
@ -30,18 +30,30 @@
|
|||
|
||||
G_STATIC_ASSERT (sizeof (PinosStackBuffer) <= sizeof (PinosBuffer));
|
||||
|
||||
/**
|
||||
* pinos_buffer_init_data:
|
||||
* @buffer: a #PinosBuffer
|
||||
* @data: data
|
||||
* @size: size of @data
|
||||
* @message: (transfer full): a #GSocketControlMessage
|
||||
*
|
||||
* Initialize @buffer with @data and @size and @message. @data and size
|
||||
* must not be modified until pinos_buffer_clear() is called.
|
||||
*
|
||||
* Ownership is taken of @message.
|
||||
*/
|
||||
void
|
||||
pinos_buffer_init_take_data (PinosBuffer *buffer,
|
||||
gpointer data,
|
||||
gsize size,
|
||||
GSocketControlMessage *message)
|
||||
pinos_buffer_init_data (PinosBuffer *buffer,
|
||||
gpointer data,
|
||||
gsize size,
|
||||
GSocketControlMessage *message)
|
||||
{
|
||||
PinosStackBuffer *sb = PSB (buffer);
|
||||
|
||||
sb->magic = PSB_MAGIC;
|
||||
sb->data = data;
|
||||
sb->size = size;
|
||||
sb->allocated_size = size;
|
||||
sb->allocated_size = 0;
|
||||
sb->message = message;
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +64,9 @@ pinos_buffer_clear (PinosBuffer *buffer)
|
|||
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), -1);
|
||||
|
||||
g_free (sb->data);
|
||||
sb->magic = 0;
|
||||
if (sb->allocated_size)
|
||||
g_free (sb->data);
|
||||
sb->size = 0;
|
||||
sb->allocated_size = 0;
|
||||
g_clear_object (&sb->message);
|
||||
|
|
@ -120,59 +134,39 @@ not_found:
|
|||
}
|
||||
|
||||
/**
|
||||
* pinos_buffer_get_socket_control_message:
|
||||
* pinos_buffer_steal_data:
|
||||
* @buffer: a #PinosBuffer
|
||||
* @size: output size
|
||||
* @message: output #GSocketControlMessage
|
||||
*
|
||||
* Get the #GSocketControlMessage of @buffer
|
||||
* Take the data and control message from @buffer.
|
||||
*
|
||||
* Returns: the #GSocketControlMessage it remains valid as long as @buffer
|
||||
* is valid
|
||||
* Returns: the data of @buffer.
|
||||
*/
|
||||
GSocketControlMessage *
|
||||
pinos_buffer_get_socket_control_message (PinosBuffer *buffer)
|
||||
{
|
||||
PinosStackBuffer *sb = PSB (buffer);
|
||||
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), NULL);
|
||||
|
||||
return sb->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_buffer_get_size:
|
||||
* @buffer: a #PinosBuffer
|
||||
*
|
||||
* Get the total size needed to store @buffer with pinos_buffer_store().
|
||||
*
|
||||
* Returns: the serialized size of @buffer.
|
||||
*/
|
||||
gsize
|
||||
pinos_buffer_get_size (PinosBuffer *buffer)
|
||||
gpointer
|
||||
pinos_buffer_steal (PinosBuffer *buffer,
|
||||
gsize *size,
|
||||
GSocketControlMessage **message)
|
||||
{
|
||||
PinosStackBuffer *sb = PSB (buffer);
|
||||
gpointer data;
|
||||
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), 0);
|
||||
|
||||
return sizeof (PinosStackHeader) + sb->size;
|
||||
}
|
||||
if (size)
|
||||
*size = sb->size;
|
||||
if (message)
|
||||
*message = sb->message;
|
||||
|
||||
/**
|
||||
* pinos_buffer_store:
|
||||
* @buffer: a #PinosBuffer
|
||||
* @data: destination
|
||||
*
|
||||
* Store the contents of @buffer in @data. @data must be large enough, see
|
||||
* pinos_buffer_get_size().
|
||||
*/
|
||||
void
|
||||
pinos_buffer_store (PinosBuffer *buffer,
|
||||
gpointer data)
|
||||
{
|
||||
PinosStackBuffer *sb = PSB (buffer);
|
||||
data = sb->data;
|
||||
|
||||
g_return_val_if_fail (is_valid_buffer (buffer), 0);
|
||||
sb->magic = 0;
|
||||
sb->data = NULL;
|
||||
sb->size = 0;
|
||||
sb->allocated_size = 0;
|
||||
sb->message = NULL;
|
||||
|
||||
memcpy (data, sb->data, sizeof (PinosStackHeader) + sb->size);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ struct _PinosBuffer {
|
|||
gsize x[16];
|
||||
};
|
||||
|
||||
void pinos_buffer_init_take_data (PinosBuffer *buffer,
|
||||
void pinos_buffer_init_data (PinosBuffer *buffer,
|
||||
gpointer data,
|
||||
gsize size,
|
||||
GSocketControlMessage *message);
|
||||
|
|
@ -57,12 +57,10 @@ const PinosBufferHeader *
|
|||
int pinos_buffer_get_fd (PinosBuffer *buffer,
|
||||
gint index,
|
||||
GError **error);
|
||||
GSocketControlMessage *
|
||||
pinos_buffer_get_socket_control_message (PinosBuffer *buffer);
|
||||
|
||||
gsize pinos_buffer_get_size (PinosBuffer *buffer);
|
||||
void pinos_buffer_store (PinosBuffer *buffer,
|
||||
gpointer data);
|
||||
gpointer pinos_buffer_steal (PinosBuffer *buffer,
|
||||
gsize *size,
|
||||
GSocketControlMessage **message);
|
||||
|
||||
|
||||
typedef enum {
|
||||
|
|
|
|||
|
|
@ -1,233 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2014 William Manley <will@williammanley.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||
* Boston, MA 02110-1335, USA.
|
||||
*/
|
||||
/**
|
||||
* SECTION:element-gstfddepay
|
||||
*
|
||||
* The fddepay element does FIXME stuff.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch -v fakesrc ! fddepay ! FIXME ! fakesink
|
||||
* ]|
|
||||
* FIXME Describe what the pipeline does.
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstfddepay.h"
|
||||
#include <gst/net/gstnetcontrolmessagemeta.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/allocators/gstfdmemory.h>
|
||||
#include <gio/gunixfdmessage.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <client/pinos.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_fddepay_debug_category);
|
||||
#define GST_CAT_DEFAULT gst_fddepay_debug_category
|
||||
|
||||
/* prototypes */
|
||||
|
||||
|
||||
static GstCaps *gst_fddepay_transform_caps (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstCaps * caps, GstCaps * filter);
|
||||
static void gst_fddepay_dispose (GObject * object);
|
||||
|
||||
static GstFlowReturn gst_fddepay_transform_ip (GstBaseTransform * trans,
|
||||
GstBuffer * buf);
|
||||
|
||||
/* pad templates */
|
||||
|
||||
static GstStaticCaps fd_caps = GST_STATIC_CAPS ("application/x-fd");
|
||||
|
||||
static GstStaticPadTemplate gst_fddepay_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate gst_fddepay_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-fd"));
|
||||
|
||||
|
||||
/* class initialization */
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstFddepay, gst_fddepay, GST_TYPE_BASE_TRANSFORM,
|
||||
GST_DEBUG_CATEGORY_INIT (gst_fddepay_debug_category, "fddepay", 0,
|
||||
"debug category for fddepay element"));
|
||||
|
||||
static void
|
||||
gst_fddepay_class_init (GstFddepayClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstBaseTransformClass *base_transform_class =
|
||||
GST_BASE_TRANSFORM_CLASS (klass);
|
||||
|
||||
/* Setting up pads and setting metadata should be moved to
|
||||
base_class_init if you intend to subclass this class. */
|
||||
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||
gst_static_pad_template_get (&gst_fddepay_src_template));
|
||||
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||
gst_static_pad_template_get (&gst_fddepay_sink_template));
|
||||
|
||||
gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
|
||||
"Simple FD Deplayloder", "Generic",
|
||||
"Simple File-descriptor Depayloader for zero-copy video IPC",
|
||||
"William Manley <will@williammanley.net>");
|
||||
|
||||
gobject_class->dispose = gst_fddepay_dispose;
|
||||
base_transform_class->transform_caps =
|
||||
GST_DEBUG_FUNCPTR (gst_fddepay_transform_caps);
|
||||
base_transform_class->transform_ip =
|
||||
GST_DEBUG_FUNCPTR (gst_fddepay_transform_ip);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fddepay_init (GstFddepay * fddepay)
|
||||
{
|
||||
fddepay->fd_allocator = gst_fd_allocator_new ();
|
||||
}
|
||||
|
||||
void
|
||||
gst_fddepay_dispose (GObject * object)
|
||||
{
|
||||
GstFddepay *fddepay = GST_FDDEPAY (object);
|
||||
|
||||
GST_DEBUG_OBJECT (fddepay, "dispose");
|
||||
|
||||
/* clean up as possible. may be called multiple times */
|
||||
if (fddepay->fd_allocator != NULL) {
|
||||
g_object_unref (G_OBJECT (fddepay->fd_allocator));
|
||||
fddepay->fd_allocator = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gst_fddepay_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_fddepay_transform_caps (GstBaseTransform * trans, GstPadDirection direction,
|
||||
GstCaps * caps, GstCaps * filter)
|
||||
{
|
||||
GstFddepay *fddepay = GST_FDDEPAY (trans);
|
||||
GstCaps *othercaps;
|
||||
|
||||
GST_DEBUG_OBJECT (fddepay, "transform_caps");
|
||||
|
||||
|
||||
if (direction == GST_PAD_SRC) {
|
||||
/* transform caps going upstream */
|
||||
othercaps = gst_static_caps_get (&fd_caps);
|
||||
} else {
|
||||
/* transform caps going downstream */
|
||||
othercaps = gst_caps_new_any ();
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
GstCaps *intersect;
|
||||
|
||||
intersect = gst_caps_intersect (othercaps, filter);
|
||||
gst_caps_unref (othercaps);
|
||||
|
||||
return intersect;
|
||||
} else {
|
||||
return othercaps;
|
||||
}
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_fddepay_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
|
||||
{
|
||||
GstFddepay *fddepay = GST_FDDEPAY (trans);
|
||||
PinosBuffer pbuf;
|
||||
PinosBufferIter it;
|
||||
GstNetControlMessageMeta * meta;
|
||||
GSocketControlMessage *msg = NULL;
|
||||
const PinosBufferHeader *hdr;
|
||||
gpointer data;
|
||||
gsize size;
|
||||
GError *err = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (fddepay, "transform_ip");
|
||||
|
||||
gst_buffer_extract_dup (buf, 0, gst_buffer_get_size (buf), &data, &size);
|
||||
|
||||
meta = ((GstNetControlMessageMeta*) gst_buffer_get_meta (
|
||||
buf, GST_NET_CONTROL_MESSAGE_META_API_TYPE));
|
||||
|
||||
if (meta) {
|
||||
msg = meta->message;
|
||||
gst_buffer_remove_meta (buf, (GstMeta *) meta);
|
||||
meta = NULL;
|
||||
}
|
||||
|
||||
pinos_buffer_init_take_data (&pbuf, data, size, msg);
|
||||
|
||||
gst_buffer_remove_all_memory (buf);
|
||||
|
||||
pinos_buffer_iter_init (&it, &pbuf);
|
||||
while (pinos_buffer_iter_next (&it)) {
|
||||
switch (pinos_buffer_iter_get_type (&it)) {
|
||||
case PINOS_PACKET_TYPE_FD_PAYLOAD:
|
||||
{
|
||||
GstMemory *fdmem = NULL;
|
||||
PinosPacketFDPayload p;
|
||||
int fd;
|
||||
|
||||
pinos_buffer_iter_parse_fd_payload (&it, &p);
|
||||
fd = pinos_buffer_get_fd (&pbuf, p.fd_index, &err);
|
||||
if (fd == -1)
|
||||
goto error;
|
||||
|
||||
fdmem = gst_fd_allocator_alloc (fddepay->fd_allocator, fd,
|
||||
p.offset + p.size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (fdmem, p.offset, p.size);
|
||||
gst_buffer_append_memory (buf, fdmem);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
hdr = pinos_buffer_get_header (&pbuf, NULL);
|
||||
GST_BUFFER_OFFSET (buf) = hdr->seq;
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
error:
|
||||
{
|
||||
GST_ELEMENT_ERROR (fddepay, RESOURCE, SETTINGS, (NULL),
|
||||
("can't get fd: %s", err->message));
|
||||
g_clear_error (&err);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2014 William Manley <will@williammanley.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||
* Boston, MA 02110-1335, USA.
|
||||
*/
|
||||
/**
|
||||
* SECTION:element-gstfdpay
|
||||
*
|
||||
* The tmpfilepay element enables zero-copy passing of buffers between
|
||||
* processes by allocating memory in a temporary file. This is a proof of
|
||||
* concept example.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch-1.0 -v videotestsrc ! video/x-raw,format=RGB,width=1920,height=1080 \
|
||||
* ! fdpay ! fdsink fd=1 \
|
||||
* | gst-launch-1.0 fdsrc fd=0 ! fddepay \
|
||||
* ! video/x-raw,format=RGB,width=1920,height=1080 ! autovideosink
|
||||
* ]|
|
||||
* Video frames are created in the first gst-launch-1.0 process and displayed
|
||||
* by the second with no copying.
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/allocators/gstfdmemory.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include "gstfdpay.h"
|
||||
#include "gsttmpfileallocator.h"
|
||||
|
||||
#include <gst/net/gstnetcontrolmessagemeta.h>
|
||||
#include <gio/gunixfdmessage.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <client/pinos.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_fdpay_debug_category);
|
||||
#define GST_CAT_DEFAULT gst_fdpay_debug_category
|
||||
|
||||
#define GST_UNREF(x) \
|
||||
do { \
|
||||
if ( x ) \
|
||||
gst_object_unref ( x ); \
|
||||
x = NULL; \
|
||||
} while (0);
|
||||
|
||||
|
||||
/* prototypes */
|
||||
|
||||
static void gst_fdpay_dispose (GObject * object);
|
||||
|
||||
static GstCaps *gst_fdpay_transform_caps (GstBaseTransform * trans,
|
||||
GstPadDirection direction, GstCaps * caps, GstCaps * filter);
|
||||
static gboolean gst_fdpay_transform_size (GstBaseTransform *trans,
|
||||
GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps,
|
||||
gsize *othersize);
|
||||
static gboolean gst_fdpay_propose_allocation (GstBaseTransform * trans,
|
||||
GstQuery * decide_query, GstQuery * query);
|
||||
static GstFlowReturn gst_fdpay_transform (GstBaseTransform * trans,
|
||||
GstBuffer * inbuf, GstBuffer * outbuf);
|
||||
|
||||
/* pad templates */
|
||||
|
||||
static GstStaticCaps fd_caps = GST_STATIC_CAPS ("application/x-fd");
|
||||
|
||||
static GstStaticPadTemplate gst_fdpay_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-fd"));
|
||||
|
||||
static GstStaticPadTemplate gst_fdpay_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
|
||||
/* class initialization */
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstFdpay, gst_fdpay, GST_TYPE_BASE_TRANSFORM,
|
||||
GST_DEBUG_CATEGORY_INIT (gst_fdpay_debug_category, "fdpay", 0,
|
||||
"debug category for fdpay element"));
|
||||
|
||||
static void
|
||||
gst_fdpay_class_init (GstFdpayClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstBaseTransformClass *base_transform_class =
|
||||
GST_BASE_TRANSFORM_CLASS (klass);
|
||||
|
||||
/* Setting up pads and setting metadata should be moved to
|
||||
base_class_init if you intend to subclass this class. */
|
||||
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||
gst_static_pad_template_get (&gst_fdpay_src_template));
|
||||
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||
gst_static_pad_template_get (&gst_fdpay_sink_template));
|
||||
|
||||
gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
|
||||
"Simple FD Payloader", "Generic",
|
||||
"Simple File-descriptor Payloader for zero-copy video IPC",
|
||||
"William Manley <will@williammanley.net>");
|
||||
|
||||
gobject_class->dispose = gst_fdpay_dispose;
|
||||
base_transform_class->transform_caps =
|
||||
GST_DEBUG_FUNCPTR (gst_fdpay_transform_caps);
|
||||
base_transform_class->propose_allocation =
|
||||
GST_DEBUG_FUNCPTR (gst_fdpay_propose_allocation);
|
||||
base_transform_class->transform =
|
||||
GST_DEBUG_FUNCPTR (gst_fdpay_transform);
|
||||
base_transform_class->transform_size =
|
||||
GST_DEBUG_FUNCPTR (gst_fdpay_transform_size);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fdpay_init (GstFdpay * fdpay)
|
||||
{
|
||||
fdpay->allocator = gst_tmpfile_allocator_new ();
|
||||
}
|
||||
|
||||
void
|
||||
gst_fdpay_dispose (GObject * object)
|
||||
{
|
||||
GstFdpay *fdpay = GST_FDPAY (object);
|
||||
|
||||
GST_DEBUG_OBJECT (fdpay, "dispose");
|
||||
|
||||
/* clean up as possible. may be called multiple times */
|
||||
GST_UNREF(fdpay->allocator);
|
||||
|
||||
G_OBJECT_CLASS (gst_fdpay_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_fdpay_transform_caps (GstBaseTransform * trans, GstPadDirection direction,
|
||||
GstCaps * caps, GstCaps * filter)
|
||||
{
|
||||
GstFdpay *fdpay = GST_FDPAY (trans);
|
||||
GstCaps *othercaps;
|
||||
|
||||
GST_DEBUG_OBJECT (fdpay, "transform_caps");
|
||||
|
||||
|
||||
if (direction == GST_PAD_SRC) {
|
||||
/* transform caps going upstream */
|
||||
othercaps = gst_caps_new_any ();
|
||||
} else {
|
||||
/* transform caps going downstream */
|
||||
othercaps = gst_static_caps_get (&fd_caps);
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
GstCaps *intersect;
|
||||
|
||||
intersect = gst_caps_intersect (othercaps, filter);
|
||||
gst_caps_unref (othercaps);
|
||||
|
||||
return intersect;
|
||||
} else {
|
||||
return othercaps;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_fdpay_transform_size (GstBaseTransform *trans, GstPadDirection direction,
|
||||
GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize)
|
||||
{
|
||||
if (direction == GST_PAD_SRC) {
|
||||
/* transform size going upstream - don't know how to do this */
|
||||
return FALSE;
|
||||
} else {
|
||||
/* transform size going downstream */
|
||||
*othersize = sizeof (PinosBuffer) + 30;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* propose allocation query parameters for input buffers */
|
||||
static gboolean
|
||||
gst_fdpay_propose_allocation (GstBaseTransform * trans,
|
||||
GstQuery * decide_query, GstQuery * query)
|
||||
{
|
||||
GstFdpay *fdpay = GST_FDPAY (trans);
|
||||
|
||||
GST_DEBUG_OBJECT (fdpay, "propose_allocation");
|
||||
|
||||
gst_query_add_allocation_param (query, fdpay->allocator, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
gst_fdpay_get_fd_memory (GstFdpay * tmpfilepay, GstBuffer * buffer)
|
||||
{
|
||||
GstMemory *mem = NULL;
|
||||
|
||||
if (gst_buffer_n_memory (buffer) == 1
|
||||
&& gst_is_fd_memory (gst_buffer_peek_memory (buffer, 0)))
|
||||
mem = gst_buffer_get_memory (buffer, 0);
|
||||
else {
|
||||
GstMapInfo info;
|
||||
GstAllocationParams params = {0, 0, 0, 0, { NULL, }};
|
||||
gsize size = gst_buffer_get_size (buffer);
|
||||
GST_INFO_OBJECT (tmpfilepay, "Buffer cannot be payloaded without copying");
|
||||
mem = gst_allocator_alloc (tmpfilepay->allocator, size, ¶ms);
|
||||
if (!gst_memory_map (mem, &info, GST_MAP_WRITE))
|
||||
return NULL;
|
||||
gst_buffer_extract (buffer, 0, info.data, size);
|
||||
gst_memory_unmap (mem, &info);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_fdpay_transform (GstBaseTransform * trans, GstBuffer * inbuf,
|
||||
GstBuffer * outbuf)
|
||||
{
|
||||
GstFdpay *fdpay = GST_FDPAY (trans);
|
||||
GstMemory *fdmem = NULL;
|
||||
GstMapInfo info;
|
||||
GError *err = NULL;
|
||||
PinosBuffer pbuf;
|
||||
PinosBufferBuilder builder;
|
||||
PinosBufferHeader hdr;
|
||||
PinosPacketFDPayload p;
|
||||
gsize size;
|
||||
|
||||
GST_DEBUG_OBJECT (fdpay, "transform_ip");
|
||||
|
||||
fdmem = gst_fdpay_get_fd_memory (fdpay, inbuf);
|
||||
|
||||
hdr.flags = 0;
|
||||
hdr.seq = GST_BUFFER_OFFSET (inbuf);
|
||||
hdr.pts = GST_BUFFER_TIMESTAMP (inbuf) + GST_ELEMENT_CAST (trans)->base_time;
|
||||
hdr.dts_offset = 0;
|
||||
|
||||
pinos_buffer_builder_init (&builder);
|
||||
pinos_buffer_builder_set_header (&builder, &hdr);
|
||||
|
||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (fdmem), &err);
|
||||
if (p.fd_index == -1)
|
||||
goto add_fd_failed;
|
||||
p.id = 0;
|
||||
p.offset = fdmem->offset;
|
||||
p.size = fdmem->size;
|
||||
pinos_buffer_builder_add_fd_payload (&builder, &p);
|
||||
|
||||
pinos_buffer_builder_end (&builder, &pbuf);
|
||||
gst_memory_unref(fdmem);
|
||||
fdmem = NULL;
|
||||
|
||||
gst_buffer_add_net_control_message_meta (outbuf,
|
||||
pinos_buffer_get_socket_control_message (&pbuf));
|
||||
|
||||
size = pinos_buffer_get_size (&pbuf);
|
||||
|
||||
gst_buffer_map (outbuf, &info, GST_MAP_WRITE);
|
||||
pinos_buffer_store (&pbuf, info.data);
|
||||
gst_buffer_unmap (outbuf, &info);
|
||||
gst_buffer_resize (outbuf, 0, size);
|
||||
|
||||
pinos_buffer_clear (&pbuf);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
add_fd_failed:
|
||||
{
|
||||
GST_WARNING_OBJECT (trans, "Adding fd failed: %s", err->message);
|
||||
gst_memory_unref(fdmem);
|
||||
g_clear_error (&err);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2014 William Manley <will@williammanley.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GST_FDPAY_H_
|
||||
#define _GST_FDPAY_H_
|
||||
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define GST_TYPE_FDPAY (gst_fdpay_get_type())
|
||||
#define GST_FDPAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FDPAY,GstFdpay))
|
||||
#define GST_FDPAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FDPAY,GstFdpayClass))
|
||||
#define GST_IS_FDPAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FDPAY))
|
||||
#define GST_IS_FDPAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FDPAY))
|
||||
typedef struct _GstFdpay GstFdpay;
|
||||
typedef struct _GstFdpayClass GstFdpayClass;
|
||||
|
||||
struct _GstFdpay
|
||||
{
|
||||
GstBaseTransform base_fdpay;
|
||||
GstAllocator * allocator;
|
||||
|
||||
};
|
||||
|
||||
struct _GstFdpayClass
|
||||
{
|
||||
GstBaseTransformClass base_fdpay_class;
|
||||
};
|
||||
|
||||
GType gst_fdpay_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
#endif
|
||||
|
|
@ -35,18 +35,18 @@
|
|||
#include "gstpinossrc.h"
|
||||
#include "gstpinossink.h"
|
||||
#include "gstpinosdeviceprovider.h"
|
||||
#include "gstfdpay.h"
|
||||
#include "gstfddepay.h"
|
||||
#include "gstpinospay.h"
|
||||
#include "gstpinosdepay.h"
|
||||
|
||||
GST_DEBUG_CATEGORY (pinos_debug);
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
gst_element_register (plugin, "pinosfdpay", GST_RANK_NONE,
|
||||
GST_TYPE_FDPAY);
|
||||
gst_element_register (plugin, "pinosfddepay", GST_RANK_NONE,
|
||||
GST_TYPE_FDDEPAY);
|
||||
gst_element_register (plugin, "pinospay", GST_RANK_NONE,
|
||||
GST_TYPE_PINOS_PAY);
|
||||
gst_element_register (plugin, "pinosdepay", GST_RANK_NONE,
|
||||
GST_TYPE_PINOS_DEPAY);
|
||||
gst_element_register (plugin, "pinossrc", GST_RANK_PRIMARY + 1,
|
||||
GST_TYPE_PINOS_SRC);
|
||||
gst_element_register (plugin, "pinossink", GST_RANK_NONE,
|
||||
|
|
|
|||
192
src/gst/gstpinosdepay.c
Normal file
192
src/gst/gstpinosdepay.c
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2014 William Manley <will@williammanley.net>
|
||||
* (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||
* Boston, MA 02110-1335, USA.
|
||||
*/
|
||||
/**
|
||||
* SECTION:element-gstpinosdepay
|
||||
*
|
||||
* The pinosdepay element does FIXME stuff.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch -v fakesrc ! pinosdepay ! FIXME ! fakesink
|
||||
* ]|
|
||||
* FIXME Describe what the pipeline does.
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstpinosdepay.h"
|
||||
#include <gst/net/gstnetcontrolmessagemeta.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/allocators/gstfdmemory.h>
|
||||
#include <gio/gunixfdmessage.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <client/pinos.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_pinos_depay_debug_category);
|
||||
#define GST_CAT_DEFAULT gst_pinos_depay_debug_category
|
||||
|
||||
/* prototypes */
|
||||
|
||||
|
||||
/* pad templates */
|
||||
static GstStaticPadTemplate gst_pinos_depay_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate gst_pinos_depay_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-pinos"));
|
||||
|
||||
|
||||
/* class initialization */
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstPinosDepay, gst_pinos_depay, GST_TYPE_ELEMENT,
|
||||
GST_DEBUG_CATEGORY_INIT (gst_pinos_depay_debug_category, "pinosdepay", 0,
|
||||
"debug category for pinosdepay element"));
|
||||
|
||||
static GstFlowReturn
|
||||
gst_pinos_depay_chain (GstPad *pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstPinosDepay *depay = GST_PINOS_DEPAY (parent);
|
||||
GstBuffer *outbuf;
|
||||
GstMapInfo info;
|
||||
PinosBuffer pbuf;
|
||||
PinosBufferIter it;
|
||||
GstNetControlMessageMeta * meta;
|
||||
GSocketControlMessage *msg = NULL;
|
||||
const PinosBufferHeader *hdr;
|
||||
GError *err = NULL;
|
||||
|
||||
meta = ((GstNetControlMessageMeta*) gst_buffer_get_meta (
|
||||
buffer, GST_NET_CONTROL_MESSAGE_META_API_TYPE));
|
||||
if (meta) {
|
||||
msg = meta->message;
|
||||
gst_buffer_remove_meta (buffer, (GstMeta *) meta);
|
||||
meta = NULL;
|
||||
}
|
||||
|
||||
outbuf = gst_buffer_new ();
|
||||
|
||||
gst_buffer_map (buffer, &info, GST_MAP_READ);
|
||||
pinos_buffer_init_data (&pbuf, info.data, info.size, msg);
|
||||
|
||||
pinos_buffer_iter_init (&it, &pbuf);
|
||||
while (pinos_buffer_iter_next (&it)) {
|
||||
switch (pinos_buffer_iter_get_type (&it)) {
|
||||
case PINOS_PACKET_TYPE_FD_PAYLOAD:
|
||||
{
|
||||
GstMemory *fdmem = NULL;
|
||||
PinosPacketFDPayload p;
|
||||
int fd;
|
||||
|
||||
pinos_buffer_iter_parse_fd_payload (&it, &p);
|
||||
fd = pinos_buffer_get_fd (&pbuf, p.fd_index, &err);
|
||||
if (fd == -1)
|
||||
goto error;
|
||||
|
||||
fdmem = gst_fd_allocator_alloc (depay->fd_allocator, fd,
|
||||
p.offset + p.size, GST_FD_MEMORY_FLAG_NONE);
|
||||
gst_memory_resize (fdmem, p.offset, p.size);
|
||||
gst_buffer_append_memory (outbuf, fdmem);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
hdr = pinos_buffer_get_header (&pbuf, NULL);
|
||||
GST_BUFFER_OFFSET (buffer) = hdr->seq;
|
||||
pinos_buffer_clear (&pbuf);
|
||||
gst_buffer_unmap (buffer, &info);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
return gst_pad_push (depay->srcpad, outbuf);
|
||||
|
||||
error:
|
||||
{
|
||||
GST_ELEMENT_ERROR (depay, RESOURCE, SETTINGS, (NULL),
|
||||
("can't get fd: %s", err->message));
|
||||
g_clear_error (&err);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pinos_depay_finalize (GObject * object)
|
||||
{
|
||||
GstPinosDepay *depay = GST_PINOS_DEPAY (object);
|
||||
|
||||
GST_DEBUG_OBJECT (depay, "finalize");
|
||||
|
||||
g_object_unref (depay->fd_allocator);
|
||||
|
||||
G_OBJECT_CLASS (gst_pinos_depay_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pinos_depay_class_init (GstPinosDepayClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class =
|
||||
GST_ELEMENT_CLASS (klass);
|
||||
|
||||
/* Setting up pads and setting metadata should be moved to
|
||||
base_class_init if you intend to subclass this class. */
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&gst_pinos_depay_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&gst_pinos_depay_sink_template));
|
||||
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"Pinos Deplayloder", "Generic",
|
||||
"Pinos Depayloader for zero-copy IPC via Pinos",
|
||||
"Wim Taymans <wim.taymans@gmail.com>");
|
||||
|
||||
gobject_class->finalize = gst_pinos_depay_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pinos_depay_init (GstPinosDepay * depay)
|
||||
{
|
||||
depay->srcpad = gst_pad_new_from_static_template (&gst_pinos_depay_src_template, "src");
|
||||
gst_element_add_pad (GST_ELEMENT (depay), depay->srcpad);
|
||||
|
||||
depay->sinkpad = gst_pad_new_from_static_template (&gst_pinos_depay_sink_template, "sink");
|
||||
gst_pad_set_chain_function (depay->sinkpad, gst_pinos_depay_chain);
|
||||
gst_element_add_pad (GST_ELEMENT (depay), depay->sinkpad);
|
||||
|
||||
depay->fd_allocator = gst_fd_allocator_new ();
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2014 William Manley <will@williammanley.net>
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
|
@ -17,32 +18,37 @@
|
|||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GST_FDDEPAY_H_
|
||||
#define _GST_FDDEPAY_H_
|
||||
#ifndef _GST_PINOS_DEPAY_H_
|
||||
#define _GST_PINOS_DEPAY_H_
|
||||
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define GST_TYPE_FDDEPAY (gst_fddepay_get_type())
|
||||
#define GST_FDDEPAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FDDEPAY,GstFddepay))
|
||||
#define GST_FDDEPAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FDDEPAY,GstFddepayClass))
|
||||
#define GST_IS_FDDEPAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FDDEPAY))
|
||||
#define GST_IS_FDDEPAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FDDEPAY))
|
||||
typedef struct _GstFddepay GstFddepay;
|
||||
typedef struct _GstFddepayClass GstFddepayClass;
|
||||
|
||||
struct _GstFddepay
|
||||
#define GST_TYPE_PINOS_DEPAY (gst_pinos_depay_get_type())
|
||||
#define GST_PINOS_DEPAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_DEPAY,GstPinosDepay))
|
||||
#define GST_PINOS_DEPAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_DEPAY,GstPinosDepayClass))
|
||||
#define GST_IS_PINOS_DEPAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_DEPAY))
|
||||
#define GST_IS_PINOS_DEPAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_DEPAY))
|
||||
|
||||
typedef struct _GstPinosDepay GstPinosDepay;
|
||||
typedef struct _GstPinosDepayClass GstPinosDepayClass;
|
||||
|
||||
struct _GstPinosDepay
|
||||
{
|
||||
GstBaseTransform base_fddepay;
|
||||
GstElement parent;
|
||||
|
||||
GstPad *srcpad, *sinkpad;
|
||||
GstAllocator *fd_allocator;
|
||||
};
|
||||
|
||||
struct _GstFddepayClass
|
||||
struct _GstPinosDepayClass
|
||||
{
|
||||
GstBaseTransformClass base_fddepay_class;
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_fddepay_get_type (void);
|
||||
GType gst_pinos_depay_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
254
src/gst/gstpinospay.c
Normal file
254
src/gst/gstpinospay.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2014 William Manley <will@williammanley.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||
* Boston, MA 02110-1335, USA.
|
||||
*/
|
||||
/**
|
||||
* SECTION:element-gstpinospay
|
||||
*
|
||||
* The pinospay element converts regular GStreamer buffers into the format
|
||||
* expected by Pinos.
|
||||
*
|
||||
* <refsect2>
|
||||
* <title>Example launch line</title>
|
||||
* |[
|
||||
* gst-launch-1.0 -v videotestsrc ! video/x-raw,format=RGB,width=1920,height=1080 \
|
||||
* ! pinospay ! fdsink fd=1 \
|
||||
* | gst-launch-1.0 fdsrc fd=0 ! fddepay \
|
||||
* ! video/x-raw,format=RGB,width=1920,height=1080 ! autovideosink
|
||||
* ]|
|
||||
* Video frames are created in the first gst-launch-1.0 process and displayed
|
||||
* by the second with no copying.
|
||||
* </refsect2>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/allocators/gstfdmemory.h>
|
||||
#include <gst/base/gstbasetransform.h>
|
||||
#include "gstpinospay.h"
|
||||
#include "gsttmpfileallocator.h"
|
||||
|
||||
#include <gst/net/gstnetcontrolmessagemeta.h>
|
||||
#include <gio/gunixfdmessage.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <client/pinos.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_pinos_pay_debug_category);
|
||||
#define GST_CAT_DEFAULT gst_pinos_pay_debug_category
|
||||
|
||||
/* prototypes */
|
||||
|
||||
/* pad templates */
|
||||
static GstStaticPadTemplate gst_pinos_pay_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("application/x-pinos"));
|
||||
|
||||
static GstStaticPadTemplate gst_pinos_pay_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
/* class initialization */
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstPinosPay, gst_pinos_pay, GST_TYPE_ELEMENT,
|
||||
GST_DEBUG_CATEGORY_INIT (gst_pinos_pay_debug_category, "pinospay", 0,
|
||||
"debug category for pinospay element"));
|
||||
|
||||
/* propose allocation query parameters for input buffers */
|
||||
static gboolean
|
||||
gst_pinos_pay_query (GstPad * pad, GstObject * parent, GstQuery * query)
|
||||
{
|
||||
GstPinosPay *pay = GST_PINOS_PAY (parent);
|
||||
gboolean res = FALSE;
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_ALLOCATION:
|
||||
{
|
||||
GST_DEBUG_OBJECT (pay, "propose_allocation");
|
||||
gst_query_add_allocation_param (query, pay->allocator, NULL);
|
||||
res = TRUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res = gst_pad_query_default (pad, parent, query);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_pinos_pay_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
{
|
||||
GstPinosPay *pay = GST_PINOS_PAY (parent);
|
||||
gboolean res = FALSE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CAPS:
|
||||
{
|
||||
GstCaps *caps;
|
||||
|
||||
caps = gst_caps_new_empty_simple ("application/x-pinos");
|
||||
res = gst_pad_push_event (pay->srcpad, gst_event_new_caps (caps));
|
||||
gst_caps_unref (caps);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res = gst_pad_event_default (pad, parent, event);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstMemory *
|
||||
gst_pinos_pay_get_fd_memory (GstPinosPay * tmpfilepay, GstBuffer * buffer)
|
||||
{
|
||||
GstMemory *mem = NULL;
|
||||
|
||||
if (gst_buffer_n_memory (buffer) == 1
|
||||
&& gst_is_fd_memory (gst_buffer_peek_memory (buffer, 0)))
|
||||
mem = gst_buffer_get_memory (buffer, 0);
|
||||
else {
|
||||
GstMapInfo info;
|
||||
GstAllocationParams params = {0, 0, 0, 0, { NULL, }};
|
||||
gsize size = gst_buffer_get_size (buffer);
|
||||
GST_INFO_OBJECT (tmpfilepay, "Buffer cannot be payloaded without copying");
|
||||
mem = gst_allocator_alloc (tmpfilepay->allocator, size, ¶ms);
|
||||
if (!gst_memory_map (mem, &info, GST_MAP_WRITE))
|
||||
return NULL;
|
||||
gst_buffer_extract (buffer, 0, info.data, size);
|
||||
gst_memory_unmap (mem, &info);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_pinos_pay_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstPinosPay *pay = GST_PINOS_PAY (parent);
|
||||
GstMemory *fdmem = NULL;
|
||||
GError *err = NULL;
|
||||
GstBuffer *outbuf;
|
||||
PinosBuffer pbuf;
|
||||
PinosBufferBuilder builder;
|
||||
PinosBufferHeader hdr;
|
||||
PinosPacketFDPayload p;
|
||||
gsize size;
|
||||
gpointer data;
|
||||
GSocketControlMessage *msg;
|
||||
|
||||
hdr.flags = 0;
|
||||
hdr.seq = GST_BUFFER_OFFSET (buffer);
|
||||
hdr.pts = GST_BUFFER_PTS (buffer) + GST_ELEMENT_CAST (pay)->base_time;
|
||||
hdr.dts_offset = 0;
|
||||
|
||||
pinos_buffer_builder_init (&builder);
|
||||
pinos_buffer_builder_set_header (&builder, &hdr);
|
||||
|
||||
fdmem = gst_pinos_pay_get_fd_memory (pay, buffer);
|
||||
p.fd_index = pinos_buffer_builder_add_fd (&builder, gst_fd_memory_get_fd (fdmem), &err);
|
||||
if (p.fd_index == -1)
|
||||
goto add_fd_failed;
|
||||
p.id = 0;
|
||||
p.offset = fdmem->offset;
|
||||
p.size = fdmem->size;
|
||||
pinos_buffer_builder_add_fd_payload (&builder, &p);
|
||||
|
||||
pinos_buffer_builder_end (&builder, &pbuf);
|
||||
gst_memory_unref(fdmem);
|
||||
fdmem = NULL;
|
||||
|
||||
data = pinos_buffer_steal (&pbuf, &size, &msg);
|
||||
|
||||
outbuf = gst_buffer_new_wrapped (data, size);
|
||||
GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buffer);
|
||||
GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buffer);
|
||||
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
|
||||
GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer);
|
||||
GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buffer);
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
gst_buffer_add_net_control_message_meta (outbuf, msg);
|
||||
g_object_unref (msg);
|
||||
|
||||
return gst_pad_push (pay->srcpad, outbuf);
|
||||
|
||||
/* ERRORS */
|
||||
add_fd_failed:
|
||||
{
|
||||
GST_WARNING_OBJECT (pay, "Adding fd failed: %s", err->message);
|
||||
gst_memory_unref(fdmem);
|
||||
g_clear_error (&err);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
static void
|
||||
gst_pinos_pay_finalize (GObject * object)
|
||||
{
|
||||
GstPinosPay *pay = GST_PINOS_PAY (object);
|
||||
|
||||
GST_DEBUG_OBJECT (pay, "finalize");
|
||||
|
||||
g_object_unref (pay->allocator);
|
||||
|
||||
G_OBJECT_CLASS (gst_pinos_pay_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pinos_pay_init (GstPinosPay * pay)
|
||||
{
|
||||
pay->srcpad = gst_pad_new_from_static_template (&gst_pinos_pay_src_template, "src");
|
||||
gst_element_add_pad (GST_ELEMENT (pay), pay->srcpad);
|
||||
|
||||
pay->sinkpad = gst_pad_new_from_static_template (&gst_pinos_pay_sink_template, "sink");
|
||||
gst_pad_set_chain_function (pay->sinkpad, gst_pinos_pay_chain);
|
||||
gst_pad_set_event_function (pay->sinkpad, gst_pinos_pay_sink_event);
|
||||
gst_pad_set_query_function (pay->sinkpad, gst_pinos_pay_query);
|
||||
gst_element_add_pad (GST_ELEMENT (pay), pay->sinkpad);
|
||||
|
||||
pay->allocator = gst_tmpfile_allocator_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pinos_pay_class_init (GstPinosPayClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&gst_pinos_pay_src_template));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&gst_pinos_pay_sink_template));
|
||||
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"Pinos Payloader", "Generic",
|
||||
"Pinos Payloader for zero-copy IPC with Pinos",
|
||||
"Wim Taymans <wim.taymans@gmail.com>");
|
||||
|
||||
gobject_class->finalize = gst_pinos_pay_finalize;
|
||||
}
|
||||
57
src/gst/gstpinospay.h
Normal file
57
src/gst/gstpinospay.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2014 William Manley <will@williammanley.net>
|
||||
* (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GST_PINOS_PAY_H_
|
||||
#define _GST_PINOS_PAY_H_
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_PINOS_PAY (gst_pinos_pay_get_type())
|
||||
#define GST_PINOS_PAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_PAY,GstPinosPay))
|
||||
#define GST_PINOS_PAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_PAY,GstPinosPayClass))
|
||||
#define GST_IS_PINOS_PAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_PAY))
|
||||
#define GST_IS_PINOS_PAY_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_PAY))
|
||||
|
||||
typedef struct _GstPinosPay GstPinosPay;
|
||||
typedef struct _GstPinosPayClass GstPinosPayClass;
|
||||
|
||||
struct _GstPinosPay
|
||||
{
|
||||
GstElement parent;
|
||||
|
||||
gboolean negotiated;
|
||||
GstPad *srcpad, *sinkpad;
|
||||
|
||||
GstAllocator *allocator;
|
||||
|
||||
};
|
||||
|
||||
struct _GstPinosPayClass
|
||||
{
|
||||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_pinos_pay_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -126,7 +126,7 @@ setup_pipeline (PinosGstSource *source, GError **error)
|
|||
gst_bin_add (GST_BIN (priv->pipeline), priv->filter);
|
||||
gst_element_link (priv->element, priv->filter);
|
||||
|
||||
elem = gst_element_factory_make ("pinosfdpay", NULL);
|
||||
elem = gst_element_factory_make ("pinospay", NULL);
|
||||
gst_bin_add (GST_BIN (priv->pipeline), elem);
|
||||
gst_element_link (priv->filter, elem);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ on_socket_notify (GObject *gobject,
|
|||
GstCaps *caps;
|
||||
GError *error = NULL;
|
||||
|
||||
pipeline = gst_parse_launch ("socketsrc name=src ! pinosfddepay ! capsfilter name=filter ! videoconvert ! xvimagesink", &error);
|
||||
pipeline = gst_parse_launch ("socketsrc name=src ! pinosdepay ! capsfilter name=filter ! videoconvert ! xvimagesink", &error);
|
||||
if (error != NULL) {
|
||||
g_warning ("error creating pipeline: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue