mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05: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,8 +30,20 @@
 | 
			
		|||
 | 
			
		||||
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,
 | 
			
		||||
pinos_buffer_init_data (PinosBuffer       *buffer,
 | 
			
		||||
                        gpointer           data,
 | 
			
		||||
                        gsize              size,
 | 
			
		||||
                        GSocketControlMessage *message)
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +53,7 @@ pinos_buffer_init_take_data (PinosBuffer       *buffer,
 | 
			
		|||
  sb->magic = PSB_MAGIC;
 | 
			
		||||
  sb->data = data;
 | 
			
		||||
  sb->size = size;
 | 
			
		||||
  sb->allocated_size = size;
 | 
			
		||||
  sb->allocated_size = 0;
 | 
			
		||||
  sb->message = message;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +64,8 @@ pinos_buffer_clear (PinosBuffer *buffer)
 | 
			
		|||
 | 
			
		||||
  g_return_val_if_fail (is_valid_buffer (buffer), -1);
 | 
			
		||||
 | 
			
		||||
  sb->magic = 0;
 | 
			
		||||
  if (sb->allocated_size)
 | 
			
		||||
    g_free (sb->data);
 | 
			
		||||
  sb->size = 0;
 | 
			
		||||
  sb->allocated_size = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -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