diff options
author | Benjamin Otte <otte@gnome.org> | 2009-10-05 15:56:39 +0200 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2009-10-05 15:56:39 +0200 |
commit | 24b2c59eb0e1aa8ea51041159b664f0d84983474 (patch) | |
tree | 6b35f5d50225ba5812fb75ab9f89bb89fd79f12c | |
parent | e17b1f1d10d52dcd7f2c74ba2b25fef423e6f692 (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.am | 2 | ||||
-rw-r--r-- | ext/xlib/gstcairoxconvert.c | 203 | ||||
-rw-r--r-- | ext/xlib/gstcairoxconvert.h | 63 | ||||
-rw-r--r-- | ext/xlib/gstcairoxlib.c | 5 |
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, |