summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2012-01-27 17:43:33 +0200
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2012-01-27 17:43:33 +0200
commit9f06be71a28ef85f146d1ef3b7fbbba3ee16b651 (patch)
treeddf3d0626b4d1f1d06125b9a177ba7026f915fab
parent4b45a8565f9881a73dd6458d28862f5ef20b1ddf (diff)
qtvideosink: Make a separate qtglvideosink element that has GL capabilities.
This is to make it more clear to the user when GL is used and when it is not, as well as prevent situations where the user would like to use GL but initializes the glcontext property at a wrong time and gets software rendering instead. So, this new qtglvideosink element supports the GLSL/ArbFp backends and fails to become READY if none of them can be initialized, while the qtvideosink element now supports only the raster backend, since there is no way to set a glcontext to it. This also has the advantage that the supported caps no longer depend on when you will set the glcontext property and the to-be-added ColorBalance interface will only exist in qtglvideosink, since it is not supported on the raster backend.
-rw-r--r--elements/gstqtvideosink/CMakeLists.txt11
-rw-r--r--elements/gstqtvideosink/autotest.cpp6
-rw-r--r--elements/gstqtvideosink/gstqtglvideosink.cpp143
-rw-r--r--elements/gstqtvideosink/gstqtglvideosink.h72
-rw-r--r--elements/gstqtvideosink/gstqtglvideosinkbase.cpp129
-rw-r--r--elements/gstqtvideosink/gstqtglvideosinkbase.h62
-rw-r--r--elements/gstqtvideosink/gstqtvideosink.cpp84
-rw-r--r--elements/gstqtvideosink/gstqtvideosink.h18
-rw-r--r--elements/gstqtvideosink/gstqtvideosinkbase.cpp49
-rw-r--r--elements/gstqtvideosink/gstqtvideosinkplugin.cpp16
-rw-r--r--elements/gstqtvideosink/gstqtvideosinkplugin.h36
-rw-r--r--elements/gstqtvideosink/gstqwidgetvideosink.cpp39
-rw-r--r--elements/gstqtvideosink/gstqwidgetvideosink.h6
-rw-r--r--elements/gstqtvideosink/qtvideosinkdelegate.cpp25
-rw-r--r--elements/gstqtvideosink/qtvideosinkdelegate.h4
15 files changed, 504 insertions, 196 deletions
diff --git a/elements/gstqtvideosink/CMakeLists.txt b/elements/gstqtvideosink/CMakeLists.txt
index 2f51298..e8f4fb3 100644
--- a/elements/gstqtvideosink/CMakeLists.txt
+++ b/elements/gstqtvideosink/CMakeLists.txt
@@ -22,7 +22,14 @@ set(GstQtVideoSink_SRCS
)
if (QT_QTOPENGL_FOUND AND OPENGL_FOUND)
- set(GstQtVideoSink_GL_SRCS openglsurfacepainter.cpp)
+ set(GstQtVideoSink_GL_SRCS
+ openglsurfacepainter.cpp
+ gstqtglvideosinkbase.cpp
+ gstqtglvideosink.cpp
+ )
+ set(GstQtVideoSink_test_GL_SRCS
+ openglsurfacepainter.cpp
+ )
set(GstQtVideoSink_GL_LIBS ${OPENGL_gl_LIBRARY} ${QT_QTOPENGL_LIBRARY})
include_directories(${OPENGL_INCLUDE_DIR} ${QT_QTOPENGL_INCLUDE_DIR})
else()
@@ -48,7 +55,7 @@ if (QTGSTREAMER_TESTS)
utils.cpp
bufferformat.cpp
genericsurfacepainter.cpp
- ${GstQtVideoSink_GL_SRCS}
+ ${GstQtVideoSink_test_GL_SRCS}
)
target_link_libraries(qtvideosink_autotest
${QT_QTTEST_LIBRARY}
diff --git a/elements/gstqtvideosink/autotest.cpp b/elements/gstqtvideosink/autotest.cpp
index 4086164..5d7e96d 100644
--- a/elements/gstqtvideosink/autotest.cpp
+++ b/elements/gstqtvideosink/autotest.cpp
@@ -738,7 +738,7 @@ GstPipeline *QtVideoSinkTest::constructPipeline(GstCaps *caps,
MAKE_ELEMENT(tee, "tee");
MAKE_ELEMENT(queue, "queue");
- MAKE_ELEMENT(qtvideosink, "qtvideosink");
+ MAKE_ELEMENT(qtvideosink, context ? "qtglvideosink" : "qtvideosink");
MAKE_ELEMENT(queue2, "queue");
MAKE_ELEMENT(colorspace, "ffmpegcolorspace");
@@ -751,7 +751,9 @@ GstPipeline *QtVideoSinkTest::constructPipeline(GstCaps *caps,
g_object_set(capsfilter2, "caps", fakesinkCaps, NULL);
g_object_set(fakesink, "enable-last-buffer", TRUE, NULL);
- g_object_set(qtvideosink, "glcontext", context, NULL);
+ if (context) {
+ g_object_set(qtvideosink, "glcontext", context, NULL);
+ }
g_object_set(qtvideosink, "force-aspect-ratio", (gboolean) forceAspectRatio, NULL);
g_object_set(videoscale, "add-borders", (gboolean) forceAspectRatio, NULL);
diff --git a/elements/gstqtvideosink/gstqtglvideosink.cpp b/elements/gstqtvideosink/gstqtglvideosink.cpp
new file mode 100644
index 0000000..2c02cb2
--- /dev/null
+++ b/elements/gstqtvideosink/gstqtglvideosink.cpp
@@ -0,0 +1,143 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
+ Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1
+ as published by the Free Software Foundation.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "gstqtglvideosink.h"
+#include "gstqtvideosinkmarshal.h"
+#include "qtvideosinkdelegate.h"
+
+
+guint GstQtGLVideoSink::s_signals[];
+
+DEFINE_TYPE(GstQtGLVideoSink, GST_TYPE_QT_GL_VIDEO_SINK_BASE)
+
+//------------------------------
+
+void GstQtGLVideoSink::emit_update(gpointer sink)
+{
+ g_signal_emit(sink, GstQtGLVideoSink::s_signals[UPDATE_SIGNAL], 0);
+}
+
+//------------------------------
+
+void GstQtGLVideoSink::base_init(gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
+
+ gst_element_class_set_details_simple(element_class, "Qt GL video sink", "Sink/Video",
+ "A video sink that can draw on any Qt GL surface",
+ "George Kiagiadakis <george.kiagiadakis@collabora.com>");
+}
+
+void GstQtGLVideoSink::class_init(gpointer g_class, gpointer class_data)
+{
+ Q_UNUSED(class_data);
+
+ GObjectClass *object_class = G_OBJECT_CLASS(g_class);
+ object_class->set_property = GstQtGLVideoSink::set_property;
+
+ GstQtGLVideoSinkClass *qt_video_sink_class = reinterpret_cast<GstQtGLVideoSinkClass*>(g_class);
+ qt_video_sink_class->paint = GstQtGLVideoSink::paint;
+
+ /**
+ * GstQtGLVideoSink::paint
+ * @painter: A valid QPainter pointer that will be used to paint the video
+ * @x: The x coordinate of the target area rectangle
+ * @y: The y coordinate of the target area rectangle
+ * @width: The width of the target area rectangle
+ * @height: The height of the target area rectangle
+ *
+ * This is an action signal that you can call from your Qt surface class inside
+ * its paint function to render the video. It takes a QPainter* and the target
+ * area rectangle as arguments. You should schedule to call this function to
+ * repaint the surface whenever the ::update signal is emited.
+ *
+ * Note that the x,y,width and height arguments are actually qreal. This means
+ * that on architectures like arm they will be float instead of double. You should
+ * cast the arguments to qreal if they are not already when emitting this signal.
+ */
+ s_signals[PAINT_SIGNAL] =
+ g_signal_new("paint", G_TYPE_FROM_CLASS(g_class),
+ static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
+ G_STRUCT_OFFSET(GstQtGLVideoSinkClass, paint),
+ NULL, NULL,
+ qRealIsDouble() ?
+ g_cclosure_user_marshal_VOID__POINTER_DOUBLE_DOUBLE_DOUBLE_DOUBLE :
+ g_cclosure_user_marshal_VOID__POINTER_FLOAT_FLOAT_FLOAT_FLOAT,
+ G_TYPE_NONE, 5,
+ G_TYPE_POINTER, G_TYPE_QREAL, G_TYPE_QREAL, G_TYPE_QREAL, G_TYPE_QREAL);
+
+ /**
+ * GstQtGLVideoSink::update
+ *
+ * This signal is emited when the surface should be repainted. It should
+ * be connected to QWidget::update() or QGraphicsItem::update() or any
+ * other similar function in your surface.
+ */
+ s_signals[UPDATE_SIGNAL] =
+ g_signal_new("update", G_TYPE_FROM_CLASS(g_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+
+ /**
+ * GstQtGLVideoSink::glcontext
+ *
+ * This property holds a pointer to the QGLContext that will be used to render
+ * the video using OpenGL acceleration. You must set this to a valid QGLContext
+ * pointer before the element changes state to READY, or else the state change will fail.
+ **/
+ g_object_class_install_property(object_class, PROP_GLCONTEXT,
+ g_param_spec_pointer("glcontext", "GL context",
+ "The QGLContext that will be used to do OpenGL-accelerated rendering",
+ static_cast<GParamFlags>(G_PARAM_WRITABLE)));
+}
+
+void GstQtGLVideoSink::init(GTypeInstance *instance, gpointer g_class)
+{
+ Q_UNUSED(g_class);
+
+ GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(instance);
+ sinkBase->delegate = new QtVideoSinkDelegate(sinkBase);
+}
+
+//------------------------------
+
+void GstQtGLVideoSink::set_property(GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(object);
+
+ switch (prop_id) {
+ case PROP_GLCONTEXT:
+ sinkBase->delegate->setGLContext(static_cast<QGLContext*>(g_value_get_pointer(value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+//------------------------------
+
+void GstQtGLVideoSink::paint(GstQtGLVideoSink *sink, gpointer painter,
+ qreal x, qreal y, qreal width, qreal height)
+{
+ GST_QT_VIDEO_SINK_BASE(sink)->delegate->paint(static_cast<QPainter*>(painter),
+ QRectF(x, y, width, height));
+}
diff --git a/elements/gstqtvideosink/gstqtglvideosink.h b/elements/gstqtvideosink/gstqtglvideosink.h
new file mode 100644
index 0000000..ad9f09f
--- /dev/null
+++ b/elements/gstqtvideosink/gstqtglvideosink.h
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
+ Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1
+ as published by the Free Software Foundation.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef GST_QT_GL_VIDEO_SINK_H
+#define GST_QT_GL_VIDEO_SINK_H
+
+#include "gstqtglvideosinkbase.h"
+
+#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
+
+#define GST_TYPE_QT_GL_VIDEO_SINK \
+ (GstQtGLVideoSink::get_type())
+
+struct GstQtGLVideoSink
+{
+public:
+ GstQtGLVideoSinkBase parent;
+
+ static GType get_type();
+ static void emit_update(gpointer sink);
+
+private:
+ enum {
+ PROP_0,
+ PROP_GLCONTEXT
+ };
+
+ enum {
+ PAINT_SIGNAL,
+ UPDATE_SIGNAL,
+ LAST_SIGNAL
+ };
+
+ static void base_init(gpointer g_class);
+ static void class_init(gpointer g_class, gpointer class_data);
+ static void init(GTypeInstance *instance, gpointer g_class);
+
+ static void set_property(GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+
+ static void paint(GstQtGLVideoSink *sink, gpointer painter,
+ qreal x, qreal y, qreal width, qreal height);
+
+ static guint s_signals[LAST_SIGNAL];
+};
+
+
+struct GstQtGLVideoSinkClass
+{
+ GstQtGLVideoSinkBaseClass parent_class;
+
+ /* paint action signal */
+ void (*paint) (GstQtGLVideoSink *sink, gpointer painter,
+ qreal x, qreal y, qreal width, qreal height);
+};
+
+#endif // GST_QT_VIDEO_SINK_NO_OPENGL
+#endif // GST_QT_GL_VIDEO_SINK_H
diff --git a/elements/gstqtvideosink/gstqtglvideosinkbase.cpp b/elements/gstqtvideosink/gstqtglvideosinkbase.cpp
new file mode 100644
index 0000000..cbce129
--- /dev/null
+++ b/elements/gstqtvideosink/gstqtglvideosinkbase.cpp
@@ -0,0 +1,129 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
+ Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1
+ as published by the Free Software Foundation.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "gstqtglvideosinkbase.h"
+#include "openglsurfacepainter.h"
+#include "qtvideosinkdelegate.h"
+
+DEFINE_TYPE_FULL(GstQtGLVideoSinkBase, GST_TYPE_QT_VIDEO_SINK_BASE, init_interfaces)
+
+//------------------------------
+
+void GstQtGLVideoSinkBase::base_init(gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
+ element_class->padtemplates = NULL; //get rid of the pad template of the base class
+
+ static GstStaticPadTemplate sink_pad_template =
+ GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ GST_STATIC_CAPS(
+ "video/x-raw-rgb, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ]"
+ "; "
+ "video/x-raw-yuv, "
+ "framerate = (fraction) [ 0, MAX ], "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ]"
+ "; "
+ )
+ );
+
+ gst_element_class_add_pad_template(
+ element_class, gst_static_pad_template_get(&sink_pad_template));
+}
+
+void GstQtGLVideoSinkBase::class_init(gpointer g_class, gpointer class_data)
+{
+ Q_UNUSED(class_data);
+
+ GObjectClass *object_class = G_OBJECT_CLASS(g_class);
+ object_class->set_property = GstQtGLVideoSinkBase::set_property;
+ object_class->get_property = GstQtGLVideoSinkBase::get_property;
+
+ GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS(g_class);
+ base_sink_class->start = GstQtGLVideoSinkBase::start;
+ base_sink_class->get_caps = GstQtGLVideoSinkBase::get_caps;
+
+ //TODO colorbalance properties
+}
+
+void GstQtGLVideoSinkBase::init(GTypeInstance *instance, gpointer g_class)
+{
+ Q_UNUSED(instance);
+ Q_UNUSED(g_class);
+}
+
+void GstQtGLVideoSinkBase::init_interfaces(GType type)
+{
+ //TODO colorbalance interface
+}
+
+//------------------------------
+
+void GstQtGLVideoSinkBase::set_property(GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+void GstQtGLVideoSinkBase::get_property(GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(object);
+
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+//------------------------------
+
+gboolean GstQtGLVideoSinkBase::start(GstBaseSink *base)
+{
+ GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(base);
+
+ //fail on purpose if the user hasn't set a context
+ if (sink->delegate->supportedPainterTypes() == QtVideoSinkDelegate::Generic) {
+ GST_WARNING_OBJECT(sink, "Neither GLSL nor ARB Fragment Program are supported "
+ "for painting. Did you forget to set a gl context?");
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+GstCaps *GstQtGLVideoSinkBase::get_caps(GstBaseSink *base)
+{
+ GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(base);
+ GstCaps *caps = gst_caps_new_empty();
+
+ Q_FOREACH(GstVideoFormat format, OpenGLSurfacePainter::supportedPixelFormats()) {
+ gst_caps_append(caps, BufferFormat::newTemplateCaps(format));
+ }
+
+ return caps;
+}
diff --git a/elements/gstqtvideosink/gstqtglvideosinkbase.h b/elements/gstqtvideosink/gstqtglvideosinkbase.h
new file mode 100644
index 0000000..b8be078
--- /dev/null
+++ b/elements/gstqtvideosink/gstqtglvideosinkbase.h
@@ -0,0 +1,62 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). <qt-info@nokia.com>
+ Copyright (C) 2011-2012 Collabora Ltd. <info@collabora.com>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1
+ as published by the Free Software Foundation.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef GST_QT_GL_VIDEO_SINK_BASE_H
+#define GST_QT_GL_VIDEO_SINK_BASE_H
+
+#include "gstqtvideosinkbase.h"
+
+#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
+
+#define GST_TYPE_QT_GL_VIDEO_SINK_BASE \
+ (GstQtGLVideoSinkBase::get_type())
+
+struct GstQtGLVideoSinkBase
+{
+public:
+ GstQtVideoSinkBase parent;
+
+ static GType get_type();
+
+private:
+ enum {
+ PROP_0,
+ };
+
+ static void base_init(gpointer g_class);
+ static void class_init(gpointer g_class, gpointer class_data);
+
+ static void init(GTypeInstance *instance, gpointer g_class);
+ static void init_interfaces(GType type);
+
+ static void set_property(GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+ static void get_property(GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+ static gboolean start(GstBaseSink *sink);
+ static GstCaps *get_caps(GstBaseSink *sink);
+};
+
+
+struct GstQtGLVideoSinkBaseClass
+{
+ GstQtVideoSinkBaseClass parent_class;
+};
+
+#endif // GST_QT_VIDEO_SINK_NO_OPENGL
+#endif // GST_QT_GL_VIDEO_SINK_BASE_H
diff --git a/elements/gstqtvideosink/gstqtvideosink.cpp b/elements/gstqtvideosink/gstqtvideosink.cpp
index 67a4808..693f58b 100644
--- a/elements/gstqtvideosink/gstqtvideosink.cpp
+++ b/elements/gstqtvideosink/gstqtvideosink.cpp
@@ -27,48 +27,16 @@
#include "gstqtvideosinkmarshal.h"
#include "qtvideosinkdelegate.h"
-//------------------------------
-
-inline bool qRealIsDouble() { return sizeof(qreal) == sizeof(double); }
-#define G_TYPE_QREAL qRealIsDouble() ? G_TYPE_DOUBLE : G_TYPE_FLOAT
-
-//------------------------------
guint GstQtVideoSink::s_signals[];
-GstQtVideoSinkBaseClass *GstQtVideoSink::s_parent_class = NULL;
-GType GstQtVideoSink::get_type()
-{
- /* The typedef for GType may be gulong or gsize, depending on the
- * system and whether the compiler is c++ or not. The g_once_init_*
- * functions always take a gsize * though ... */
- static volatile gsize gonce_data = 0;
- if (g_once_init_enter(&gonce_data)) {
- GType type;
- type = gst_type_register_static_full(
- GST_TYPE_QT_VIDEO_SINK_BASE,
- g_intern_static_string("GstQtVideoSink"),
- sizeof(GstQtVideoSinkClass),
- &GstQtVideoSink::base_init,
- NULL, /* base_finalize */
- &GstQtVideoSink::class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(GstQtVideoSink),
- 0, /* n_preallocs */
- &GstQtVideoSink::init,
- NULL,
- (GTypeFlags) 0);
- g_once_init_leave(&gonce_data, (gsize) type);
- }
- return (GType) gonce_data;
-}
+DEFINE_TYPE(GstQtVideoSink, GST_TYPE_QT_VIDEO_SINK_BASE)
//------------------------------
-void GstQtVideoSink::emit_update(GstQtVideoSink *sink)
+void GstQtVideoSink::emit_update(gpointer sink)
{
- g_signal_emit(sink, GstQtVideoSink::s_signals[GstQtVideoSink::UPDATE_SIGNAL], 0);
+ g_signal_emit(sink, GstQtVideoSink::s_signals[UPDATE_SIGNAL], 0);
}
//------------------------------
@@ -78,7 +46,7 @@ void GstQtVideoSink::base_init(gpointer g_class)
GstElementClass *element_class = GST_ELEMENT_CLASS(g_class);
gst_element_class_set_details_simple(element_class, "Qt video sink", "Sink/Video",
- "A video sink that can draw on any Qt surface (QPaintDevice/QWidget/QGraphicsItem/QML)",
+ "A video sink that can draw on any Qt surface",
"George Kiagiadakis <george.kiagiadakis@collabora.com>");
}
@@ -86,27 +54,9 @@ void GstQtVideoSink::class_init(gpointer g_class, gpointer class_data)
{
Q_UNUSED(class_data);
- s_parent_class = reinterpret_cast<GstQtVideoSinkBaseClass*>(g_type_class_peek_parent(g_class));
-
- GObjectClass *object_class = G_OBJECT_CLASS(g_class);
- object_class->set_property = GstQtVideoSink::set_property;
-
- GstQtVideoSinkClass *qt_video_sink_class = GST_QT_VIDEO_SINK_CLASS(g_class);
+ GstQtVideoSinkClass *qt_video_sink_class = reinterpret_cast<GstQtVideoSinkClass*>(g_class);
qt_video_sink_class->paint = GstQtVideoSink::paint;
-
- /**
- * GstQtVideoSink::glcontext
- *
- * This property holds a pointer to the QGLContext that will be used to render
- * the video using OpenGL acceleration. You must set this to a valid QGLContext
- * pointer before linking this element, or else OpenGL acceleration will be disabled.
- **/
- g_object_class_install_property(object_class, PROP_GLCONTEXT,
- g_param_spec_pointer("glcontext", "GL context",
- "The QGLContext that will be used to do OpenGL-accelerated rendering",
- static_cast<GParamFlags>(G_PARAM_WRITABLE)));
-
/**
* GstQtVideoSink::paint
* @painter: A valid QPainter pointer that will be used to paint the video
@@ -119,6 +69,10 @@ void GstQtVideoSink::class_init(gpointer g_class, gpointer class_data)
* its paint function to render the video. It takes a QPainter* and the target
* area rectangle as arguments. You should schedule to call this function to
* repaint the surface whenever the ::update signal is emited.
+ *
+ * Note that the x,y,width and height arguments are actually qreal. This means
+ * that on architectures like arm they will be float instead of double. You should
+ * cast the arguments to qreal if they are not already when emitting this signal.
*/
s_signals[PAINT_SIGNAL] =
g_signal_new("paint", G_TYPE_FROM_CLASS(g_class),
@@ -154,25 +108,7 @@ void GstQtVideoSink::init(GTypeInstance *instance, gpointer g_class)
sinkBase->delegate = new QtVideoSinkDelegate(sinkBase);
}
-void GstQtVideoSink::set_property(GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- GstQtVideoSinkBase *sinkBase = GST_QT_VIDEO_SINK_BASE(object);
-
- switch (prop_id) {
- case PROP_GLCONTEXT:
-#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
- sinkBase->delegate->setGLContext(static_cast<QGLContext*>(g_value_get_pointer(value)));
-#else
- GST_WARNING_OBJECT(sinkBase, "Attempted to write on the glcontext property, "
- "but qtvideosink has been compiled without OpenGL support");
-#endif
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
+//------------------------------
void GstQtVideoSink::paint(GstQtVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height)
diff --git a/elements/gstqtvideosink/gstqtvideosink.h b/elements/gstqtvideosink/gstqtvideosink.h
index a6fe1b8..8544f82 100644
--- a/elements/gstqtvideosink/gstqtvideosink.h
+++ b/elements/gstqtvideosink/gstqtvideosink.h
@@ -19,15 +19,9 @@
#define GST_QT_VIDEO_SINK_H
#include "gstqtvideosinkbase.h"
-#include <QtCore/QtGlobal>
#define GST_TYPE_QT_VIDEO_SINK \
(GstQtVideoSink::get_type())
-#define GST_QT_VIDEO_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QT_VIDEO_SINK, GstQtVideoSink))
-#define GST_QT_VIDEO_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QT_VIDEO_SINK, GstQtVideoSinkClass))
-
struct GstQtVideoSink
{
@@ -35,15 +29,10 @@ public:
GstQtVideoSinkBase parent;
static GType get_type();
- static void emit_update(GstQtVideoSink *sink);
+ static void emit_update(gpointer sink);
private:
enum {
- PROP_0,
- PROP_GLCONTEXT
- };
-
- enum {
PAINT_SIGNAL,
UPDATE_SIGNAL,
LAST_SIGNAL
@@ -53,15 +42,10 @@ private:
static void class_init(gpointer g_class, gpointer class_data);
static void init(GTypeInstance *instance, gpointer g_class);
- static void set_property(GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec);
-
static void paint(GstQtVideoSink *sink, gpointer painter,
qreal x, qreal y, qreal width, qreal height);
-
static guint s_signals[LAST_SIGNAL];
- static GstQtVideoSinkBaseClass *s_parent_class;
};
diff --git a/elements/gstqtvideosink/gstqtvideosinkbase.cpp b/elements/gstqtvideosink/gstqtvideosinkbase.cpp
index 9452235..552f71f 100644
--- a/elements/gstqtvideosink/gstqtvideosinkbase.cpp
+++ b/elements/gstqtvideosink/gstqtvideosinkbase.cpp
@@ -17,39 +17,13 @@
#include "gstqtvideosinkbase.h"
#include "qtvideosinkdelegate.h"
+#include "genericsurfacepainter.h"
#include <QtCore/QCoreApplication>
GstVideoSinkClass *GstQtVideoSinkBase::s_parent_class = NULL;
-//------------------------------
-
-GType GstQtVideoSinkBase::get_type()
-{
- /* The typedef for GType may be gulong or gsize, depending on the
- * system and whether the compiler is c++ or not. The g_once_init_*
- * functions always take a gsize * though ... */
- static volatile gsize gonce_data = 0;
- if (g_once_init_enter(&gonce_data)) {
- GType type;
- type = gst_type_register_static_full(
- GST_TYPE_VIDEO_SINK,
- g_intern_static_string("GstQtVideoSinkBase"),
- sizeof(GstQtVideoSinkBaseClass),
- &GstQtVideoSinkBase::base_init,
- NULL, /* base_finalize */
- &GstQtVideoSinkBase::class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(GstQtVideoSinkBase),
- 0, /* n_preallocs */
- &GstQtVideoSinkBase::init,
- NULL,
- (GTypeFlags) 0);
- g_once_init_leave(&gonce_data, (gsize) type);
- }
- return (GType) gonce_data;
-}
+DEFINE_TYPE(GstQtVideoSinkBase, GST_TYPE_VIDEO_SINK)
//------------------------------
@@ -65,11 +39,6 @@ void GstQtVideoSinkBase::base_init(gpointer g_class)
"width = (int) [ 1, MAX ], "
"height = (int) [ 1, MAX ]"
"; "
- "video/x-raw-yuv, "
- "framerate = (fraction) [ 0, MAX ], "
- "width = (int) [ 1, MAX ], "
- "height = (int) [ 1, MAX ]"
- "; "
)
);
@@ -129,8 +98,10 @@ void GstQtVideoSinkBase::finalize(GObject *object)
sink->delegate = 0;
}
+//------------------------------
+
void GstQtVideoSinkBase::set_property(GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
+ const GValue *value, GParamSpec *pspec)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(object);
@@ -145,7 +116,7 @@ void GstQtVideoSinkBase::set_property(GObject *object, guint prop_id,
}
void GstQtVideoSinkBase::get_property(GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
+ GValue *value, GParamSpec *pspec)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(object);
@@ -159,6 +130,8 @@ void GstQtVideoSinkBase::get_property(GObject *object, guint prop_id,
}
}
+//------------------------------
+
GstStateChangeReturn GstQtVideoSinkBase::change_state(GstElement *element, GstStateChange transition)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(element);
@@ -177,12 +150,14 @@ GstStateChangeReturn GstQtVideoSinkBase::change_state(GstElement *element, GstSt
return GST_ELEMENT_CLASS(s_parent_class)->change_state(element, transition);
}
+//------------------------------
+
GstCaps *GstQtVideoSinkBase::get_caps(GstBaseSink *base)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(base);
GstCaps *caps = gst_caps_new_empty();
- Q_FOREACH(GstVideoFormat format, sink->delegate->supportedPixelFormats()) {
+ Q_FOREACH(GstVideoFormat format, GenericSurfacePainter::supportedPixelFormats()) {
gst_caps_append(caps, BufferFormat::newTemplateCaps(format));
}
@@ -198,6 +173,8 @@ gboolean GstQtVideoSinkBase::set_caps(GstBaseSink *base, GstCaps *caps)
return TRUE;
}
+//------------------------------
+
GstFlowReturn GstQtVideoSinkBase::show_frame(GstVideoSink *video_sink, GstBuffer *buffer)
{
GstQtVideoSinkBase *sink = GST_QT_VIDEO_SINK_BASE(video_sink);
diff --git a/elements/gstqtvideosink/gstqtvideosinkplugin.cpp b/elements/gstqtvideosink/gstqtvideosinkplugin.cpp
index eec7691..62c9cff 100644
--- a/elements/gstqtvideosink/gstqtvideosinkplugin.cpp
+++ b/elements/gstqtvideosink/gstqtvideosinkplugin.cpp
@@ -17,6 +17,7 @@
#include "gstqtvideosinkplugin.h"
#include "gstqtvideosink.h"
+#include "gstqtglvideosink.h"
#include "gstqwidgetvideosink.h"
GST_DEBUG_CATEGORY(gst_qt_video_sink_debug);
@@ -27,11 +28,16 @@ static gboolean plugin_init(GstPlugin *plugin)
GST_DEBUG_CATEGORY_INIT(gst_qt_video_sink_debug, "qtvideosink", 0,
"Debug category for GstQtVideoSink");
- gboolean r1 = gst_element_register(plugin, "qtvideosink",
- GST_RANK_NONE, GST_TYPE_QT_VIDEO_SINK);
- gboolean r2 = gst_element_register(plugin, "qwidgetvideosink",
- GST_RANK_NONE, GST_TYPE_QWIDGET_VIDEO_SINK);
- return r1 && r2;
+ gst_element_register(plugin, "qtvideosink",
+ GST_RANK_NONE, GST_TYPE_QT_VIDEO_SINK);
+#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
+ gst_element_register(plugin, "qtglvideosink",
+ GST_RANK_NONE, GST_TYPE_QT_GL_VIDEO_SINK);
+#endif
+ gst_element_register(plugin, "qwidgetvideosink",
+ GST_RANK_NONE, GST_TYPE_QWIDGET_VIDEO_SINK);
+
+ return TRUE;
}
GST_PLUGIN_DEFINE (
diff --git a/elements/gstqtvideosink/gstqtvideosinkplugin.h b/elements/gstqtvideosink/gstqtvideosinkplugin.h
index 3869ad6..2fddd34 100644
--- a/elements/gstqtvideosink/gstqtvideosinkplugin.h
+++ b/elements/gstqtvideosink/gstqtvideosinkplugin.h
@@ -18,8 +18,44 @@
#define GST_QT_VIDEO_SINK_PLUGIN_H
#include <gst/gst.h>
+#include <QtCore/QtGlobal>
GST_DEBUG_CATEGORY_EXTERN(gst_qt_video_sink_debug);
#define GST_CAT_DEFAULT gst_qt_video_sink_debug
+
+#define DEFINE_TYPE_FULL(cpp_type, parent_type, additional_initializations) \
+ GType cpp_type::get_type() \
+ { \
+ static volatile gsize gonce_data = 0; \
+ if (g_once_init_enter(&gonce_data)) { \
+ GType type; \
+ type = gst_type_register_static_full( \
+ parent_type, \
+ g_intern_static_string(#cpp_type), \
+ sizeof(cpp_type##Class), \
+ &cpp_type::base_init, \
+ NULL, /* base_finalize */ \
+ &cpp_type::class_init, \
+ NULL, /* class_finalize */ \
+ NULL, /* class_data */ \
+ sizeof(cpp_type), \
+ 0, /* n_preallocs */ \
+ &cpp_type::init, \
+ NULL, \
+ (GTypeFlags) 0); \
+ additional_initializations(type); \
+ g_once_init_leave(&gonce_data, (gsize) type); \
+ } \
+ return (GType) gonce_data; \
+ }
+
+#define DEFINE_TYPE(cpp_type, parent_type) \
+ DEFINE_TYPE_FULL(cpp_type, parent_type, Q_UNUSED)
+
+
+inline bool qRealIsDouble() { return sizeof(qreal) == sizeof(double); }
+#define G_TYPE_QREAL qRealIsDouble() ? G_TYPE_DOUBLE : G_TYPE_FLOAT
+
+
#endif
diff --git a/elements/gstqtvideosink/gstqwidgetvideosink.cpp b/elements/gstqtvideosink/gstqwidgetvideosink.cpp
index 4f2dc1e..7f5d458 100644
--- a/elements/gstqtvideosink/gstqwidgetvideosink.cpp
+++ b/elements/gstqtvideosink/gstqwidgetvideosink.cpp
@@ -25,10 +25,10 @@
*
* This is useful for cases where you cannot or you do not want to use one of the
* sinks that implement the GstXOverlay interface, for example for rendering video
- * inside a QGraphicsView or for rendering video on the QWS (Qt/Embedded) platform.
- * This sink is guaranteed to work on all platforms supported by Qt, however it
- * is not recommended to use it if you have another choice. For example, on X11 it
- * is recommended to use "xvimagesink" instead, which uses hardware acceleration.
+ * on the QWS (Qt/Embedded) platform. This sink is guaranteed to work on all platforms
+ * supported by Qt, however it is not recommended to use it if you have another choice.
+ * For example, on X11 it is recommended to use "xvimagesink" instead, which uses
+ * hardware acceleration.
*
* There are certain rules for using qwidgetvideosink with threads. It must be
* created in the main thread, it must be destructed in the main thread and the
@@ -39,34 +39,7 @@
#include "gstqwidgetvideosink.h"
#include "qwidgetvideosinkdelegate.h"
-GstQtVideoSinkBaseClass *GstQWidgetVideoSink::s_parent_class = NULL;
-
-GType GstQWidgetVideoSink::get_type()
-{
- /* The typedef for GType may be gulong or gsize, depending on the
- * system and whether the compiler is c++ or not. The g_once_init_*
- * functions always take a gsize * though ... */
- static volatile gsize gonce_data = 0;
- if (g_once_init_enter(&gonce_data)) {
- GType type;
- type = gst_type_register_static_full(
- GST_TYPE_QT_VIDEO_SINK_BASE,
- g_intern_static_string("GstQWidgetVideoSink"),
- sizeof(GstQWidgetVideoSinkClass),
- &GstQWidgetVideoSink::base_init,
- NULL, /* base_finalize */
- &GstQWidgetVideoSink::class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof(GstQWidgetVideoSink),
- 0, /* n_preallocs */
- &GstQWidgetVideoSink::init,
- NULL,
- (GTypeFlags) 0);
- g_once_init_leave(&gonce_data, (gsize) type);
- }
- return (GType) gonce_data;
-}
+DEFINE_TYPE(GstQWidgetVideoSink, GST_TYPE_QT_VIDEO_SINK_BASE)
//------------------------------
@@ -83,8 +56,6 @@ void GstQWidgetVideoSink::class_init(gpointer g_class, gpointer class_data)
{
Q_UNUSED(class_data);
- s_parent_class = GST_QT_VIDEO_SINK_BASE_CLASS(g_type_class_peek_parent(g_class));
-
GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
gobject_class->set_property = GstQWidgetVideoSink::set_property;
gobject_class->get_property = GstQWidgetVideoSink::get_property;
diff --git a/elements/gstqtvideosink/gstqwidgetvideosink.h b/elements/gstqtvideosink/gstqwidgetvideosink.h
index 62a6800..883d340 100644
--- a/elements/gstqtvideosink/gstqwidgetvideosink.h
+++ b/elements/gstqtvideosink/gstqwidgetvideosink.h
@@ -23,10 +23,6 @@
#define GST_TYPE_QWIDGET_VIDEO_SINK \
(GstQWidgetVideoSink::get_type())
-#define GST_QWIDGET_VIDEO_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_QWIDGET_VIDEO_SINK, GstQWidgetVideoSink))
-#define GST_QWIDGETVIDEOSINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_QWIDGET_VIDEO_SINK, GstQWidgetVideoSinkClass))
struct GstQWidgetVideoSink
{
@@ -49,8 +45,6 @@ private:
const GValue *value, GParamSpec *pspec);
static void get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
-
- static GstQtVideoSinkBaseClass *s_parent_class;
};
struct GstQWidgetVideoSinkClass
diff --git a/elements/gstqtvideosink/qtvideosinkdelegate.cpp b/elements/gstqtvideosink/qtvideosinkdelegate.cpp
index cda4dc6..e8b7bf4 100644
--- a/elements/gstqtvideosink/qtvideosinkdelegate.cpp
+++ b/elements/gstqtvideosink/qtvideosinkdelegate.cpp
@@ -19,6 +19,7 @@
#include "genericsurfacepainter.h"
#include "openglsurfacepainter.h"
#include "gstqtvideosink.h"
+#include "gstqtglvideosink.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QStack>
@@ -61,19 +62,6 @@ QtVideoSinkDelegate::~QtVideoSinkDelegate()
//-------------------------------------
-QSet<GstVideoFormat> QtVideoSinkDelegate::supportedPixelFormats() const
-{
- QSet<GstVideoFormat> result;
-#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
- if (m_supportedPainters & Glsl || m_supportedPainters & ArbFp)
- result = OpenGLSurfacePainter::supportedPixelFormats();
- else
-#endif
- result = GenericSurfacePainter::supportedPixelFormats();
-
- return result;
-}
-
bool QtVideoSinkDelegate::isActive() const
{
QReadLocker l(&m_isActiveLock);
@@ -260,9 +248,6 @@ QGLContext *QtVideoSinkDelegate::glContext() const
void QtVideoSinkDelegate::setGLContext(QGLContext *context)
{
- GST_LOG_OBJECT(m_sink, "Setting GL context. context=%p m_glContext=%p m_painter=%p",
- context, m_glContext, m_painter);
-
if (m_glContext == context)
return;
@@ -285,7 +270,6 @@ void QtVideoSinkDelegate::setGLContext(QGLContext *context)
&& extensions.contains("ARB_shader_objects"))
#endif
m_supportedPainters |= Glsl;
-
}
GST_LOG_OBJECT(m_sink, "Done setting GL context. m_supportedPainters=%x", (int) m_supportedPainters);
@@ -422,5 +406,10 @@ bool QtVideoSinkDelegate::event(QEvent *event)
void QtVideoSinkDelegate::update()
{
- GstQtVideoSink::emit_update(GST_QT_VIDEO_SINK(m_sink));
+#ifndef GST_QT_VIDEO_SINK_NO_OPENGL
+ if (G_TYPE_CHECK_INSTANCE_TYPE(m_sink, GST_TYPE_QT_GL_VIDEO_SINK)) {
+ GstQtGLVideoSink::emit_update(m_sink);
+ } else
+#endif
+ GstQtVideoSink::emit_update(m_sink);
}
diff --git a/elements/gstqtvideosink/qtvideosinkdelegate.h b/elements/gstqtvideosink/qtvideosinkdelegate.h
index 3a22e06..b3e157d 100644
--- a/elements/gstqtvideosink/qtvideosinkdelegate.h
+++ b/elements/gstqtvideosink/qtvideosinkdelegate.h
@@ -78,11 +78,11 @@ public:
// API for GstQtVideoSinkBase
- QSet<GstVideoFormat> supportedPixelFormats() const;
-
bool isActive() const;
void setActive(bool playing);
+ PainterTypes supportedPainterTypes() const { return m_supportedPainters; }
+
// GstColorBalance interface
int brightness() const;