summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2009-10-05 15:56:39 +0200
committerBenjamin Otte <otte@gnome.org>2009-10-05 15:56:39 +0200
commit24b2c59eb0e1aa8ea51041159b664f0d84983474 (patch)
tree6b35f5d50225ba5812fb75ab9f89bb89fd79f12c
parente17b1f1d10d52dcd7f2c74ba2b25fef423e6f692 (diff)
Add cairoxconvert element
This is a simple colorspace conversion that uses an X connection to supply hardware-accelerated buffers. So you can use source ! cairoscale ! cairoxconvert ! sink to get support for hardware-accelerated scaling. I'm not sure about this element yet, I'd prefer gst-cairo being able to determine the fastest format on its own and use that. But for now it's a simple solution that works. It also reduces the encoding time for the video I posted on http://blogs.gnome.org/otte/2009/10/05/cairo-is-slow/ from 17 to 5 minutes.
-rw-r--r--ext/xlib/Makefile.am2
-rw-r--r--ext/xlib/gstcairoxconvert.c203
-rw-r--r--ext/xlib/gstcairoxconvert.h63
-rw-r--r--ext/xlib/gstcairoxlib.c5
4 files changed, 272 insertions, 1 deletions
diff --git a/ext/xlib/Makefile.am b/ext/xlib/Makefile.am
index 34c6381..bdaa257 100644
--- a/ext/xlib/Makefile.am
+++ b/ext/xlib/Makefile.am
@@ -6,12 +6,14 @@ AM_LIBS = $(GST_BASE_LIBS) $(CAIRO_LIBS) $(XLIB_LIBS)
noinst_HEADERS = \
gstcairoxbuffer.h \
+ gstcairoxconvert.h \
gstcairoxdisplay.h \
gstcairoxsink.h \
gstcairoxsource.h
libgstcairoxlib_la_SOURCES = \
gstcairoxbuffer.c \
+ gstcairoxconvert.c \
gstcairoxdisplay.c \
gstcairoxlib.c \
gstcairoxsink.c \
diff --git a/ext/xlib/gstcairoxconvert.c b/ext/xlib/gstcairoxconvert.c
new file mode 100644
index 0000000..5eda206
--- /dev/null
+++ b/ext/xlib/gstcairoxconvert.c
@@ -0,0 +1,203 @@
+/* GStreamer
+ * Copyright (C) 2009 Benjamin Otte <otte@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-cairo_x_convert
+ *
+ * Convert video frames between a great variety of x_convert formats.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v videotestsrc ! video/x-raw-yuv,format=\(fourcc\)YUY2 ! cairo_x_convert ! ximagesink
+ * ]|
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "gstcairoxconvert.h"
+
+#include <X11/Xlib.h>
+
+#include "gstcairoxbuffer.h"
+
+GST_BOILERPLATE (GstCairoXConvert, gst_cairo_x_convert, GstElement,
+ GST_TYPE_BASE_TRANSFORM);
+
+static GstCaps *
+gst_cairo_x_convert_transform_caps (GstBaseTransform * btrans,
+ GstPadDirection direction, GstCaps * caps)
+{
+ GstCaps *cairo, *expand, *result;
+
+ cairo = gst_caps_from_string ("video/x-cairo");
+ expand = gst_cairo_caps_expand (caps, GST_CAIRO_FORMAT_FORMAT);
+ result = gst_caps_intersect (cairo, expand);
+ /* must exist, we just expanded to make sure */
+ g_assert (result);
+ gst_caps_unref (cairo);
+ gst_caps_append (result, expand);
+
+ return result;
+}
+
+static gboolean
+gst_cairo_x_convert_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
+ GstCaps * outcaps)
+{
+ GstCairoXConvert *convert = GST_CAIRO_X_CONVERT (btrans);
+
+ gst_cairo_format_free (convert->in_format);
+ convert->in_format = gst_cairo_format_new (incaps);
+ gst_cairo_format_free (convert->out_format);
+ convert->out_format = gst_cairo_format_new (outcaps);
+
+ return gst_cairo_format_equal (convert->in_format, convert->out_format,
+ GST_CAIRO_FORMAT_FORMAT);
+}
+
+static gboolean
+gst_cairo_x_convert_start (GstBaseTransform * btrans)
+{
+ GstCairoXConvert *convert = GST_CAIRO_X_CONVERT (btrans);
+
+ convert->display = gst_cairo_x_display_new (NULL);
+ if (convert->display == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_cairo_x_convert_stop (GstBaseTransform * btrans)
+{
+ GstCairoXConvert *convert = GST_CAIRO_X_CONVERT (btrans);
+
+ gst_cairo_format_free (convert->in_format);
+ convert->in_format = NULL;
+ gst_cairo_format_free (convert->out_format);
+ convert->out_format = NULL;
+ gst_cairo_x_display_free (convert->display);
+ convert->display = NULL;
+
+ return TRUE;
+}
+
+static gboolean
+gst_cairo_x_convert_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
+ guint * size)
+{
+ GstCairoFormat *format;
+
+ format = gst_cairo_format_new (caps);
+ *size = gst_cairo_format_get_buffer_size (format);
+ gst_cairo_format_free (format);
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_cairo_x_convert_transform (GstBaseTransform * btrans, GstBuffer * inbuf,
+ GstBuffer * outbuf)
+{
+ GstCairoXConvert *convert = GST_CAIRO_X_CONVERT (btrans);
+ cairo_surface_t *in, *out;
+ cairo_t *cr;
+
+ in = gst_cairo_create_surface (inbuf, convert->in_format);
+ out = gst_cairo_create_surface (outbuf, convert->out_format);
+
+ cr = cairo_create (out);
+
+ cairo_set_source_surface (cr, in, 0, 0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+
+ cairo_surface_destroy (in);
+ cairo_surface_destroy (out);
+
+ return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_cairo_x_convert_buffer_alloc (GstPad * pad, guint64 offset,
+ guint size, GstCaps * caps, GstBuffer ** buf)
+{
+ GstCairoXConvert *convert = GST_CAIRO_X_CONVERT (gst_pad_get_parent (pad));
+ GstCairoFormat *format;
+
+ format = gst_cairo_format_new (caps);
+
+ if (gst_cairo_format_is_native (format))
+ *buf = gst_cairo_x_buffer_new (convert->display,
+ DefaultRootWindow (gst_cairo_x_display_get_display (convert->display)),
+ format);
+
+ gst_cairo_format_free (format);
+ gst_object_unref (convert);
+
+ return GST_FLOW_OK;
+}
+
+static void
+gst_cairo_x_convert_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_cairo_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS));
+ gst_element_class_add_pad_template (element_class,
+ gst_cairo_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS));
+ gst_element_class_set_details_simple (element_class,
+ "Cairo X converter",
+ "Filter/Converter/Video",
+ "Allows video to be accelerated by the X server",
+ "Benjamin Otte <otte@gnome.org>");
+}
+
+static void
+gst_cairo_x_convert_class_init (GstCairoXConvertClass * klass)
+{
+ GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ basetransform_class->transform_caps = gst_cairo_x_convert_transform_caps;
+ basetransform_class->set_caps = gst_cairo_x_convert_set_caps;
+ basetransform_class->get_unit_size = gst_cairo_x_convert_get_unit_size;
+ basetransform_class->transform = gst_cairo_x_convert_transform;
+ basetransform_class->start = gst_cairo_x_convert_start;
+ basetransform_class->stop = gst_cairo_x_convert_stop;
+
+ basetransform_class->passthrough_on_same_caps = TRUE;
+}
+
+static void
+gst_cairo_x_convert_init (GstCairoXConvert * convert,
+ GstCairoXConvertClass * klass)
+{
+ gst_base_transform_set_qos_enabled (GST_BASE_TRANSFORM (convert), TRUE);
+
+ gst_pad_set_bufferalloc_function (GST_BASE_TRANSFORM_SINK_PAD (convert),
+ gst_cairo_x_convert_buffer_alloc);
+}
diff --git a/ext/xlib/gstcairoxconvert.h b/ext/xlib/gstcairoxconvert.h
new file mode 100644
index 0000000..b904708
--- /dev/null
+++ b/ext/xlib/gstcairoxconvert.h
@@ -0,0 +1,63 @@
+/* GStreamer
+ * Copyright (C) 2009 Benjamin Otte <otte@gnome.org>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_CAIRO_X_CONVERT_H__
+#define __GST_CAIRO_X_CONVERT_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/cairo/gstcairo.h>
+
+#include "gstcairoxdisplay.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_CAIRO_X_CONVERT (gst_cairo_x_convert_get_type())
+#define GST_CAIRO_X_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAIRO_X_CONVERT,GstCairoXConvert))
+#define GST_CAIRO_X_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAIRO_X_CONVERT,GstCairoXConvertClass))
+#define GST_IS_CAIRO_X_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAIRO_X_CONVERT))
+#define GST_IS_CAIRO_X_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAIRO_X_CONVERT))
+
+typedef struct _GstCairoXConvert GstCairoXConvert;
+typedef struct _GstCairoXConvertClass GstCairoXConvertClass;
+
+/**
+ * GstCairoXConvert:
+ *
+ * Opaque object data structure.
+ */
+struct _GstCairoXConvert {
+ GstBaseTransform element;
+
+ GstCairoFormat * in_format; /* negotiated format on the sink side */
+ GstCairoFormat * out_format; /* negotiated format on the source side */
+
+ GstCairoXDisplay * display; /* connection to X server */
+};
+
+struct _GstCairoXConvertClass
+{
+ GstBaseTransformClass parent_class;
+};
+
+GType gst_cairo_x_convert_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_CAIRO_X_CONVERT_H__ */
diff --git a/ext/xlib/gstcairoxlib.c b/ext/xlib/gstcairoxlib.c
index 039e3a3..7d37c6e 100644
--- a/ext/xlib/gstcairoxlib.c
+++ b/ext/xlib/gstcairoxlib.c
@@ -27,6 +27,7 @@
#include <gst/gst.h>
+#include "gstcairoxconvert.h"
#include "gstcairoxsink.h"
static gboolean
@@ -35,7 +36,9 @@ plugin_init (GstPlugin * plugin)
XInitThreads ();
return gst_element_register (plugin, "cairoxsink",
- GST_RANK_NONE, GST_TYPE_CAIRO_X_SINK);
+ GST_RANK_NONE, GST_TYPE_CAIRO_X_SINK) &&
+ gst_element_register (plugin, "cairoxconvert",
+ GST_RANK_NONE, GST_TYPE_CAIRO_X_CONVERT);
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,