From 6b96a87003adf0204cbe1517b3ca588d571170ce Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 29 Sep 2014 00:23:57 +1000 Subject: [PATCH] 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 --- tests/examples/gl/qt/qglwtextureshare/README | 3 + .../examples/gl/qt/qglwtextureshare/gstthread.cpp | 6 +- tests/examples/gl/qt/qglwtextureshare/gstthread.h | 4 +- tests/examples/gl/qt/qglwtextureshare/pipeline.cpp | 318 ++++++++--------- tests/examples/gl/qt/qglwtextureshare/pipeline.h | 4 +- .../gl/qt/qglwtextureshare/qglrenderer.cpp | 376 ++++++++++++--------- .../gl/qt/qglwtextureshare/qglwtextureshare.pro | 1 + 7 files changed, 386 insertions(+), 326 deletions(-) diff --git a/tests/examples/gl/qt/qglwtextureshare/README b/tests/examples/gl/qt/qglwtextureshare/README index 305847c..9a97c56 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 2a1ff69..25d1890 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 d18218c..bd34dd5 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 942e1a7..6de2a39 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 c2a1c9d..e517a12 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 200c3e4..3eeac47 100644 --- a/tests/examples/gl/qt/qglwtextureshare/qglrenderer.cpp +++ b/tests/examples/gl/qt/qglwtextureshare/qglrenderer.cpp @@ -25,220 +25,260 @@ #include #include +#include + #include #include +#if GST_GL_HAVE_PLATFORM_GLX +#include +#include +#endif + #include "gstthread.h" #include "qglrenderer.h" #include "pipeline.h" -#include - #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 c3d3f3a..81dc333 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 -- 2.7.4