diff options
author | Jan Schmidt <jan@centricular.com> | 2014-09-29 00:23:57 +1000 |
---|---|---|
committer | Jan Schmidt <jan@centricular.com> | 2014-09-29 00:39:07 +1000 |
commit | 37c70c8efa90b2bcedb5445ec350c9cd81453458 (patch) | |
tree | 329e0ea4df438e2028f1b4fceef621fc1a5b2671 /tests/examples/gl | |
parent | 0fd0683996bb97ddb50e76818ded50eef8cf90ea (diff) | |
download | gstreamer-plugins-bad-37c70c8efa90b2bcedb5445ec350c9cd81453458.tar.gz |
examples: Fix Qt/GL qglwtextureshare example for X11
We need to pass the X11 display to GstGL or else it will
use its own X11 Display pointer, and the GL Context won't get shared
correctly on newer X servers
Diffstat (limited to 'tests/examples/gl')
7 files changed, 386 insertions, 326 deletions
diff --git a/tests/examples/gl/qt/qglwtextureshare/README b/tests/examples/gl/qt/qglwtextureshare/README index 305847cb4..9a97c56e9 100644 --- a/tests/examples/gl/qt/qglwtextureshare/README +++ b/tests/examples/gl/qt/qglwtextureshare/README @@ -1,3 +1,6 @@ +Requires: >= Qt 5.1 for the x11extras module (or else you need to +get x11extras from gitorious yourself) + This example illustrates how to integrate Gstreamer GL plugin with Qt. In particular it uses glupload with fakesink elements to create texture with decoded video frame. This texture is shared with diff --git a/tests/examples/gl/qt/qglwtextureshare/gstthread.cpp b/tests/examples/gl/qt/qglwtextureshare/gstthread.cpp index 2a1ff6979..25d1890bd 100644 --- a/tests/examples/gl/qt/qglwtextureshare/gstthread.cpp +++ b/tests/examples/gl/qt/qglwtextureshare/gstthread.cpp @@ -23,15 +23,15 @@ #include "gstthread.h" -GstThread::GstThread(GstGLContext *context, +GstThread::GstThread(GstGLDisplay *display, + GstGLContext *context, const QString &videoLocation, const char *renderer_slot, QObject *parent): QThread(parent), m_videoLocation(videoLocation) { - this->context = context; - m_pipeline = new Pipeline(this->context, m_videoLocation, this); + m_pipeline = new Pipeline(display, context, m_videoLocation, this); QObject::connect(m_pipeline, SIGNAL(newFrameReady()), this->parent(), renderer_slot, Qt::QueuedConnection); } diff --git a/tests/examples/gl/qt/qglwtextureshare/gstthread.h b/tests/examples/gl/qt/qglwtextureshare/gstthread.h index d18218c5c..bd34dd551 100644 --- a/tests/examples/gl/qt/qglwtextureshare/gstthread.h +++ b/tests/examples/gl/qt/qglwtextureshare/gstthread.h @@ -34,7 +34,8 @@ class GstThread : public QThread Q_OBJECT public: - GstThread(GstGLContext *context, + GstThread(GstGLDisplay *display, + GstGLContext *context, const QString &videoLocation, const char *renderer_slot, QObject *parent = 0); @@ -50,7 +51,6 @@ protected: void run(); private: - GstGLContext *context; const QString m_videoLocation; Pipeline* m_pipeline; }; diff --git a/tests/examples/gl/qt/qglwtextureshare/pipeline.cpp b/tests/examples/gl/qt/qglwtextureshare/pipeline.cpp index 942e1a76e..6de2a3997 100644 --- a/tests/examples/gl/qt/qglwtextureshare/pipeline.cpp +++ b/tests/examples/gl/qt/qglwtextureshare/pipeline.cpp @@ -22,200 +22,214 @@ #include "pipeline.h" -Pipeline::Pipeline(GstGLContext *context, - const QString &videoLocation, - QObject *parent) - : QObject(parent), - m_videoLocation(videoLocation), - m_loop(NULL), - m_bus(NULL), - m_pipeline(NULL) +Pipeline::Pipeline (GstGLDisplay *display, + GstGLContext * context, const QString & videoLocation, QObject * parent) + : +QObject (parent), +m_videoLocation (videoLocation), +m_loop (NULL), +m_bus (NULL), +m_pipeline (NULL) { - this->context = context; - this->configure(); + this->display = display; + this->context = context; + this->configure (); } -Pipeline::~Pipeline() +Pipeline::~Pipeline () { } void -Pipeline::configure() +Pipeline::configure () { #ifdef Q_WS_WIN - m_loop = g_main_loop_new (NULL, FALSE); + m_loop = g_main_loop_new (NULL, FALSE); #endif - if(m_videoLocation.isEmpty()) - { - qDebug("No video file specified. Using video test source."); - m_pipeline = - GST_PIPELINE (gst_parse_launch - ("videotestsrc ! " - "video/x-raw, width=640, height=480, " - "framerate=(fraction)30/1 ! " - "gleffects effect=5 ! fakesink sync=1", - NULL)); - } - else - { - QByteArray ba = m_videoLocation.toLocal8Bit(); - qDebug("Loading video: %s", ba.data()); - gchar *pipeline = g_strdup_printf ("filesrc location='%s' ! " - "decodebin ! gleffects effect=5 ! " - "fakesink sync=1", ba.data()); - m_pipeline = GST_PIPELINE (gst_parse_launch (pipeline, NULL)); - g_free (pipeline); - } - - m_bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline)); - gst_bus_add_watch(m_bus, (GstBusFunc) bus_call, this); - gst_object_unref(m_bus); - - /* Retrieve the last gl element */ - GstElement *gl_element = gst_bin_get_by_name(GST_BIN(m_pipeline), "gleffects0"); - if(!gl_element) - { - qDebug ("gl element could not be found"); - return; - } - g_object_set(G_OBJECT (gl_element), "other-context", - this->context, NULL); - gst_object_unref(gl_element); - - gst_element_set_state(GST_ELEMENT(this->m_pipeline), GST_STATE_PAUSED); - GstState state = GST_STATE_PAUSED; - if(gst_element_get_state(GST_ELEMENT(this->m_pipeline), - &state, NULL, GST_CLOCK_TIME_NONE) - != GST_STATE_CHANGE_SUCCESS) - { - qDebug("failed to pause pipeline"); - return; - } + if (m_videoLocation.isEmpty ()) { + qDebug ("No video file specified. Using video test source."); + m_pipeline = + GST_PIPELINE (gst_parse_launch + ("videotestsrc ! " + "video/x-raw, width=640, height=480, " + "framerate=(fraction)30/1 ! " + "gleffects effect=5 ! fakesink sync=1", NULL)); + } else { + QByteArray ba = m_videoLocation.toLocal8Bit (); + qDebug ("Loading video: %s", ba.data ()); + gchar *pipeline = g_strdup_printf ("filesrc name=f ! " + "decodebin ! gleffects effect=5 ! " "fakesink sync=1"); + m_pipeline = GST_PIPELINE (gst_parse_launch (pipeline, NULL)); + GstElement *f = gst_bin_get_by_name (GST_BIN (m_pipeline), "f"); + g_object_set (G_OBJECT (f), "location", ba.data (), NULL); + gst_object_unref (GST_OBJECT (f)); + g_free (pipeline); + } + + m_bus = gst_pipeline_get_bus (GST_PIPELINE (m_pipeline)); + gst_bus_add_watch (m_bus, (GstBusFunc) bus_call, this); + gst_bus_enable_sync_message_emission (m_bus); + g_signal_connect (m_bus, "sync-message", G_CALLBACK (sync_bus_call), this); + gst_object_unref (m_bus); + + /* Retrieve the last gl element */ + GstElement *gl_element = + gst_bin_get_by_name (GST_BIN (m_pipeline), "gleffects0"); + if (!gl_element) { + qDebug ("gl element could not be found"); + return; + } + g_object_set (G_OBJECT (gl_element), "other-context", this->context, NULL); + gst_object_unref (gl_element); + + gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_PAUSED); + GstState state = GST_STATE_PAUSED; + if (gst_element_get_state (GST_ELEMENT (this->m_pipeline), + &state, NULL, GST_CLOCK_TIME_NONE) + != GST_STATE_CHANGE_SUCCESS) { + qDebug ("failed to pause pipeline"); + return; + } } void -Pipeline::start() +Pipeline::start () { - // set a callback to retrieve the gst gl textures - GstElement *fakesink = gst_bin_get_by_name(GST_BIN(this->m_pipeline), - "fakesink0"); - g_object_set(G_OBJECT (fakesink), "signal-handoffs", TRUE, NULL); - g_signal_connect(fakesink, "handoff", G_CALLBACK (on_gst_buffer), this); - gst_object_unref(fakesink); - - GstStateChangeReturn ret = - gst_element_set_state(GST_ELEMENT(this->m_pipeline), GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) - { - qDebug("Failed to start up pipeline!"); - - /* check if there is an error message with details on the bus */ - GstMessage* msg = gst_bus_poll(this->m_bus, GST_MESSAGE_ERROR, 0); - if (msg) - { - GError *err = NULL; - gst_message_parse_error (msg, &err, NULL); - qDebug ("ERROR: %s", err->message); - g_error_free (err); - gst_message_unref (msg); - } - return; + // set a callback to retrieve the gst gl textures + GstElement *fakesink = gst_bin_get_by_name (GST_BIN (this->m_pipeline), + "fakesink0"); + g_object_set (G_OBJECT (fakesink), "signal-handoffs", TRUE, NULL); + g_signal_connect (fakesink, "handoff", G_CALLBACK (on_gst_buffer), this); + gst_object_unref (fakesink); + + GstStateChangeReturn ret = + gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + qDebug ("Failed to start up pipeline!"); + + /* check if there is an error message with details on the bus */ + GstMessage *msg = gst_bus_poll (this->m_bus, GST_MESSAGE_ERROR, 0); + if (msg) { + GError *err = NULL; + gst_message_parse_error (msg, &err, NULL); + qDebug ("ERROR: %s", err->message); + g_error_free (err); + gst_message_unref (msg); } - + return; + } #ifdef Q_WS_WIN - g_main_loop_run(m_loop); + g_main_loop_run (m_loop); #endif } /* fakesink handoff callback */ void -Pipeline::on_gst_buffer(GstElement * element, - GstBuffer * buf, - GstPad * pad, - Pipeline* p) +Pipeline::on_gst_buffer (GstElement * element, + GstBuffer * buf, GstPad * pad, Pipeline * p) { - Q_UNUSED(pad) - Q_UNUSED(element) - - /* ref then push buffer to use it in qt */ - gst_buffer_ref(buf); - p->queue_input_buf.put(buf); - - if (p->queue_input_buf.size() > 3) - p->notifyNewFrame(); - - /* pop then unref buffer we have finished to use in qt */ - if (p->queue_output_buf.size() > 3) - { - GstBuffer *buf_old = (p->queue_output_buf.get()); - if (buf_old) - gst_buffer_unref(buf_old); - } + Q_UNUSED (pad) + Q_UNUSED (element) + + /* ref then push buffer to use it in qt */ + gst_buffer_ref (buf); + p->queue_input_buf.put (buf); + + if (p->queue_input_buf.size () > 3) + p->notifyNewFrame (); + + /* pop then unref buffer we have finished to use in qt */ + if (p->queue_output_buf.size () > 3) { + GstBuffer *buf_old = (p->queue_output_buf.get ()); + if (buf_old) + gst_buffer_unref (buf_old); + } } void -Pipeline::stop() +Pipeline::stop () { #ifdef Q_WS_WIN - g_main_loop_quit(m_loop); + g_main_loop_quit (m_loop); #else - emit stopRequested(); + emit stopRequested (); #endif } void -Pipeline::unconfigure() +Pipeline::unconfigure () { - gst_element_set_state(GST_ELEMENT(this->m_pipeline), GST_STATE_NULL); + gst_element_set_state (GST_ELEMENT (this->m_pipeline), GST_STATE_NULL); + + GstBuffer *buf; + while (this->queue_input_buf.size ()) { + buf = (GstBuffer *) (this->queue_input_buf.get ()); + gst_buffer_unref (buf); + } + while (this->queue_output_buf.size ()) { + buf = (GstBuffer *) (this->queue_output_buf.get ()); + gst_buffer_unref (buf); + } + + gst_object_unref (m_pipeline); +} - GstBuffer *buf; - while(this->queue_input_buf.size()) - { - buf = (GstBuffer*)(this->queue_input_buf.get()); - gst_buffer_unref(buf); - } - while(this->queue_output_buf.size()) +gboolean Pipeline::bus_call (GstBus * bus, GstMessage * msg, Pipeline * p) +{ + Q_UNUSED (bus) + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS: + qDebug ("End-of-stream received. Stopping."); + p->stop (); + break; + + case GST_MESSAGE_ERROR: { - buf = (GstBuffer*)(this->queue_output_buf.get()); - gst_buffer_unref(buf); + gchar * + debug = NULL; + GError * + err = NULL; + gst_message_parse_error (msg, &err, &debug); + qDebug ("Error: %s", err->message); + g_error_free (err); + if (debug) { + qDebug ("Debug deails: %s", debug); + g_free (debug); + } + p->stop (); + break; } - gst_object_unref(m_pipeline); + default: + break; + } + + return TRUE; } -gboolean -Pipeline::bus_call(GstBus *bus, GstMessage *msg, Pipeline* p) +gboolean Pipeline::sync_bus_call (GstBus * bus, GstMessage * msg, Pipeline * p) { - Q_UNUSED(bus) - - switch(GST_MESSAGE_TYPE(msg)) + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_NEED_CONTEXT: { - case GST_MESSAGE_EOS: - qDebug("End-of-stream received. Stopping."); - p->stop(); - break; - - case GST_MESSAGE_ERROR: - { - gchar *debug = NULL; - GError *err = NULL; - gst_message_parse_error(msg, &err, &debug); - qDebug("Error: %s", err->message); - g_error_free (err); - if(debug) - { - qDebug("Debug deails: %s", debug); - g_free(debug); - } - p->stop(); - break; - } - - default: - break; + const gchar * + context_type; + + gst_message_parse_context_type (msg, &context_type); + g_print ("got need context %s\n", context_type); + + if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) { + GstContext *display_context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE); + gst_context_set_gl_display (display_context, p->display); + gst_element_set_context (GST_ELEMENT (msg->src), display_context); + } + break; } - - return TRUE; + default: + break; + } + return FALSE; } diff --git a/tests/examples/gl/qt/qglwtextureshare/pipeline.h b/tests/examples/gl/qt/qglwtextureshare/pipeline.h index c2a1c9daa..e517a12d7 100644 --- a/tests/examples/gl/qt/qglwtextureshare/pipeline.h +++ b/tests/examples/gl/qt/qglwtextureshare/pipeline.h @@ -34,7 +34,7 @@ class Pipeline : public QObject Q_OBJECT public: - Pipeline(GstGLContext *context, + Pipeline(GstGLDisplay *display, GstGLContext *context, const QString &videoLocation, QObject *parent); ~Pipeline(); @@ -53,6 +53,7 @@ Q_SIGNALS: void stopRequested(); private: + GstGLDisplay *display; GstGLContext *context; const QString m_videoLocation; GMainLoop* m_loop; @@ -64,6 +65,7 @@ private: static void on_gst_buffer(GstElement * element, GstBuffer * buf, GstPad * pad, Pipeline* p); static gboolean bus_call (GstBus *bus, GstMessage *msg, Pipeline* p); + static gboolean sync_bus_call (GstBus *bus, GstMessage *msg, Pipeline* p); }; #endif diff --git a/tests/examples/gl/qt/qglwtextureshare/qglrenderer.cpp b/tests/examples/gl/qt/qglwtextureshare/qglrenderer.cpp index 200c3e4b6..3eeac475e 100644 --- a/tests/examples/gl/qt/qglwtextureshare/qglrenderer.cpp +++ b/tests/examples/gl/qt/qglwtextureshare/qglrenderer.cpp @@ -25,220 +25,260 @@ #include <QDebug> #include <QCloseEvent> +#include <GL/glx.h> + #include <gst/video/video.h> #include <gst/gl/gstglmemory.h> +#if GST_GL_HAVE_PLATFORM_GLX +#include <QX11Info> +#include <gst/gl/x11/gstgldisplay_x11.h> +#endif + #include "gstthread.h" #include "qglrenderer.h" #include "pipeline.h" -#include <GL/glx.h> - #if defined(Q_WS_MAC) -extern void *qt_current_nsopengl_context(); +extern void *qt_current_nsopengl_context (); #endif -QGLRenderer::QGLRenderer(const QString &videoLocation, - QWidget *parent) - : QGLWidget(parent), - videoLoc(videoLocation), - gst_thread(NULL), - closing(false), - frame(NULL) +QGLRenderer::QGLRenderer (const QString & videoLocation, QWidget * parent) + : +QGLWidget (parent), +videoLoc (videoLocation), +gst_thread (NULL), +closing (false), +frame (NULL) { - move(20, 10); - resize(640, 480); + move (20, 10); + resize (640, 480); } -QGLRenderer::~QGLRenderer() +QGLRenderer::~QGLRenderer () { } void -QGLRenderer::initializeGL() +QGLRenderer::initializeGL () { - GstGLContext *context; - GstGLDisplay *display; - - display = gst_gl_display_new (); + GstGLContext *context; + GstGLDisplay *display; + +#if GST_GL_HAVE_PLATFORM_GLX + display = + (GstGLDisplay *) gst_gl_display_x11_new_with_display (QX11Info:: + display ()); +#else + display = gst_gl_display_new (); +#endif - /* FIXME: Allow the choice at runtime */ + /* FIXME: Allow the choice at runtime */ #if GST_GL_HAVE_PLATFORM_WGL - context = gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (), GST_GL_PLATFORM_WGL, GST_GL_API_OPENGL); + context = + gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (), + GST_GL_PLATFORM_WGL, GST_GL_API_OPENGL); #elif GST_GL_HAVE_PLATFORM_CGL - context = gst_gl_context_new_wrapped (display, (guintptr) qt_current_nsopengl_context(), GST_GL_PLATFORM_CGL, GST_GL_API_OPENGL); + context = + gst_gl_context_new_wrapped (display, + (guintptr) qt_current_nsopengl_context (), GST_GL_PLATFORM_CGL, + GST_GL_API_OPENGL); #elif GST_GL_HAVE_PLATFORM_GLX - context = gst_gl_context_new_wrapped (display, (guintptr) glXGetCurrentContext (), GST_GL_PLATFORM_GLX, GST_GL_API_OPENGL); + context = + gst_gl_context_new_wrapped (display, (guintptr) glXGetCurrentContext (), + GST_GL_PLATFORM_GLX, GST_GL_API_OPENGL); #endif - gst_object_unref (display); - - // We need to unset Qt context before initializing gst-gl plugin. - // Otherwise the attempt to share gst-gl context with Qt will fail. - this->doneCurrent(); - this->gst_thread = - new GstThread(context, this->videoLoc, SLOT(newFrame()), this); - this->makeCurrent(); - - QObject::connect(this->gst_thread, SIGNAL(finished()), - this, SLOT(close())); - QObject::connect(this, SIGNAL(closeRequested()), - this->gst_thread, SLOT(stop()), Qt::QueuedConnection); - - qglClearColor(QApplication::palette().color(QPalette::Active, - QPalette::Window)); - //glShadeModel(GL_FLAT); - //glEnable(GL_DEPTH_TEST); - //glEnable(GL_CULL_FACE); - glEnable(GL_TEXTURE_2D); // Enable Texture Mapping - - this->gst_thread->start(); + gst_object_unref (display); + + // We need to unset Qt context before initializing gst-gl plugin. + // Otherwise the attempt to share gst-gl context with Qt will fail. + this->doneCurrent (); + this->gst_thread = + new GstThread (display, context, this->videoLoc, + SLOT (newFrame ()), this); + this->makeCurrent (); + + QObject::connect (this->gst_thread, SIGNAL (finished ()), + this, SLOT (close ())); + QObject::connect (this, SIGNAL (closeRequested ()), + this->gst_thread, SLOT (stop ()), Qt::QueuedConnection); + + qglClearColor (QApplication::palette ().color (QPalette::Active, + QPalette::Window)); + //glShadeModel(GL_FLAT); + //glEnable(GL_DEPTH_TEST); + //glEnable(GL_CULL_FACE); + glEnable (GL_TEXTURE_2D); // Enable Texture Mapping + + this->gst_thread->start (); } void -QGLRenderer::resizeGL(int width, int height) +QGLRenderer::resizeGL (int width, int height) { // Reset The Current Viewport And Perspective Transformation - glViewport(0, 0, width, height); + glViewport (0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); - gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f); - glMatrixMode(GL_MODELVIEW); + gluPerspective (45.0f, (GLfloat) width / (GLfloat) height, 0.1f, 100.0f); + glMatrixMode (GL_MODELVIEW); } void -QGLRenderer::newFrame() +QGLRenderer::newFrame () { - Pipeline *pipeline = this->gst_thread->getPipeline(); - if(!pipeline) - return; + Pipeline *pipeline = this->gst_thread->getPipeline (); + if (!pipeline) + return; - /* frame is initialized as null */ - if (this->frame) - pipeline->queue_output_buf.put(this->frame); + /* frame is initialized as null */ + if (this->frame) + pipeline->queue_output_buf.put (this->frame); - this->frame = pipeline->queue_input_buf.get(); + this->frame = pipeline->queue_input_buf.get (); - /* direct call to paintGL (no queued) */ - this->updateGL(); + /* direct call to paintGL (no queued) */ + this->updateGL (); } -static void flushGstreamerGL(GstGLContext* context,void *data){ - context->gl_vtable->Flush(); +static void +flushGstreamerGL (GstGLContext * context, void *data G_GNUC_UNUSED) +{ + context->gl_vtable->Flush (); } void -QGLRenderer::paintGL() +QGLRenderer::paintGL () { - static GLfloat xrot = 0; - static GLfloat yrot = 0; - static GLfloat zrot = 0; - - if (this->frame) - { - guint tex_id; - GstMemory *mem; - GstVideoInfo v_info; - GstVideoFrame v_frame; - GstVideoMeta *v_meta; - - mem = gst_buffer_peek_memory (this->frame, 0); - v_meta = gst_buffer_get_video_meta (this->frame); - - Q_ASSERT(gst_is_gl_memory (mem)); - - GstGLMemory *gl_memory=(GstGLMemory*)mem; - - gst_gl_context_thread_add(gl_memory->context,flushGstreamerGL,NULL); - - gst_video_info_set_format (&v_info, v_meta->format, v_meta->width, - v_meta->height); - - gst_video_frame_map (&v_frame, &v_info, this->frame, - (GstMapFlags) (GST_MAP_READ | GST_MAP_GL)); - - tex_id = *(guint *) v_frame.data[0]; - - glEnable(GL_DEPTH_TEST); - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, tex_id); - if(glGetError () != GL_NO_ERROR) - { - qDebug ("failed to bind texture that comes from gst-gl"); - emit closeRequested(); - return; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glTranslatef(0.0f,0.0f,-5.0f); - - glRotatef(xrot,1.0f,0.0f,0.0f); - glRotatef(yrot,0.0f,1.0f,0.0f); - glRotatef(zrot,0.0f,0.0f,1.0f); - - glBegin(GL_QUADS); - // Front Face - glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); - glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); - glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); - // Back Face - glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); - glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); - glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); - // Top Face - glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); - glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); - glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); - // Bottom Face - glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); - glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 1.0f); - glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); - // Right face - glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); - glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); - glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); - // Left Face - glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); - glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); - glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); - glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); - glEnd(); - - xrot+=0.3f; - yrot+=0.2f; - zrot+=0.4f; - - glBindTexture(GL_TEXTURE_2D, 0); - - gst_video_frame_unmap(&v_frame); + static GLfloat xrot = 0; + static GLfloat yrot = 0; + static GLfloat zrot = 0; + + if (this->frame) { + guint tex_id; + GstMemory *mem; + GstVideoInfo v_info; + GstVideoFrame v_frame; + GstVideoMeta *v_meta; + + mem = gst_buffer_peek_memory (this->frame, 0); + v_meta = gst_buffer_get_video_meta (this->frame); + + Q_ASSERT (gst_is_gl_memory (mem)); + + GstGLMemory *gl_memory = (GstGLMemory *) mem; + + gst_gl_context_thread_add (gl_memory->context, flushGstreamerGL, NULL); + + gst_video_info_set_format (&v_info, v_meta->format, v_meta->width, + v_meta->height); + + gst_video_frame_map (&v_frame, &v_info, this->frame, + (GstMapFlags) (GST_MAP_READ | GST_MAP_GL)); + + tex_id = *(guint *) v_frame.data[0]; + + glEnable (GL_DEPTH_TEST); + + glEnable (GL_TEXTURE_2D); + glBindTexture (GL_TEXTURE_2D, tex_id); + if (glGetError () != GL_NO_ERROR) { + qDebug ("failed to bind texture that comes from gst-gl"); + emit closeRequested (); + return; } + + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + glTranslatef (0.0f, 0.0f, -5.0f); + + glRotatef (xrot, 1.0f, 0.0f, 0.0f); + glRotatef (yrot, 0.0f, 1.0f, 0.0f); + glRotatef (zrot, 0.0f, 0.0f, 1.0f); + + glBegin (GL_QUADS); + // Front Face + glTexCoord2f (1.0f, 0.0f); + glVertex3f (-1.0f, -1.0f, 1.0f); + glTexCoord2f (0.0f, 0.0f); + glVertex3f (1.0f, -1.0f, 1.0f); + glTexCoord2f (0.0f, 1.0f); + glVertex3f (1.0f, 1.0f, 1.0f); + glTexCoord2f (1.0f, 1.0f); + glVertex3f (-1.0f, 1.0f, 1.0f); + // Back Face + glTexCoord2f (0.0f, 0.0f); + glVertex3f (-1.0f, -1.0f, -1.0f); + glTexCoord2f (0.0f, 1.0f); + glVertex3f (-1.0f, 1.0f, -1.0f); + glTexCoord2f (1.0f, 1.0f); + glVertex3f (1.0f, 1.0f, -1.0f); + glTexCoord2f (1.0f, 0.0f); + glVertex3f (1.0f, -1.0f, -1.0f); + // Top Face + glTexCoord2f (1.0f, 1.0f); + glVertex3f (-1.0f, 1.0f, -1.0f); + glTexCoord2f (1.0f, 0.0f); + glVertex3f (-1.0f, 1.0f, 1.0f); + glTexCoord2f (0.0f, 0.0f); + glVertex3f (1.0f, 1.0f, 1.0f); + glTexCoord2f (0.0f, 1.0f); + glVertex3f (1.0f, 1.0f, -1.0f); + // Bottom Face + glTexCoord2f (1.0f, 0.0f); + glVertex3f (-1.0f, -1.0f, -1.0f); + glTexCoord2f (0.0f, 0.0f); + glVertex3f (1.0f, -1.0f, -1.0f); + glTexCoord2f (0.0f, 1.0f); + glVertex3f (1.0f, -1.0f, 1.0f); + glTexCoord2f (1.0f, 1.0f); + glVertex3f (-1.0f, -1.0f, 1.0f); + // Right face + glTexCoord2f (0.0f, 0.0f); + glVertex3f (1.0f, -1.0f, -1.0f); + glTexCoord2f (0.0f, 1.0f); + glVertex3f (1.0f, 1.0f, -1.0f); + glTexCoord2f (1.0f, 1.0f); + glVertex3f (1.0f, 1.0f, 1.0f); + glTexCoord2f (1.0f, 0.0f); + glVertex3f (1.0f, -1.0f, 1.0f); + // Left Face + glTexCoord2f (1.0f, 0.0f); + glVertex3f (-1.0f, -1.0f, -1.0f); + glTexCoord2f (0.0f, 0.0f); + glVertex3f (-1.0f, -1.0f, 1.0f); + glTexCoord2f (0.0f, 1.0f); + glVertex3f (-1.0f, 1.0f, 1.0f); + glTexCoord2f (1.0f, 1.0f); + glVertex3f (-1.0f, 1.0f, -1.0f); + glEnd (); + + xrot += 0.3f; + yrot += 0.2f; + zrot += 0.4f; + + glBindTexture (GL_TEXTURE_2D, 0); + + gst_video_frame_unmap (&v_frame); + } } void -QGLRenderer::closeEvent(QCloseEvent* event) +QGLRenderer::closeEvent (QCloseEvent * event) { - if(this->closing == false) - { - this->closing = true; - emit closeRequested(); - event->ignore(); - } + if (this->closing == false) { + this->closing = true; + emit closeRequested (); + event->ignore (); + } } diff --git a/tests/examples/gl/qt/qglwtextureshare/qglwtextureshare.pro b/tests/examples/gl/qt/qglwtextureshare/qglwtextureshare.pro index c3d3f3a2f..81dc33365 100644 --- a/tests/examples/gl/qt/qglwtextureshare/qglwtextureshare.pro +++ b/tests/examples/gl/qt/qglwtextureshare/qglwtextureshare.pro @@ -37,6 +37,7 @@ unix:!mac { -lgstgl-1.0 \ -lGLU \ -lGL + QT += x11extras } mac { DEFINES += MACOSX |