diff --git a/tests/examples/gl/qt/qglwtextureshare/README b/tests/examples/gl/qt/qglwtextureshare/README index 305847cb42..9a97c56e90 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 2a1ff69795..25d1890bd9 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 d18218c5c2..bd34dd5513 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 942e1a76e9..6de2a39973 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); - } + 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_object_unref(m_bus); + 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); + /* 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; - } + 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); + // 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!"); + 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; + /* 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) + 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); + /* 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(); + 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); - } + /* 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); - } + 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); + gst_object_unref (m_pipeline); } -gboolean -Pipeline::bus_call(GstBus *bus, GstMessage *msg, Pipeline* p) +gboolean Pipeline::bus_call (GstBus * bus, GstMessage * msg, Pipeline * p) { - Q_UNUSED(bus) + Q_UNUSED (bus) - switch(GST_MESSAGE_TYPE(msg)) + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS: + qDebug ("End-of-stream received. Stopping."); + p->stop (); + break; + + case GST_MESSAGE_ERROR: { - 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; + 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; } - return TRUE; + default: + break; + } + + return TRUE; +} + +gboolean Pipeline::sync_bus_call (GstBus * bus, GstMessage * msg, Pipeline * p) +{ + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_NEED_CONTEXT: + { + 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; + } + default: + break; + } + return FALSE; } diff --git a/tests/examples/gl/qt/qglwtextureshare/pipeline.h b/tests/examples/gl/qt/qglwtextureshare/pipeline.h index c2a1c9daab..e517a12d7a 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 200c3e4b60..3eeac475e0 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; + GstGLContext *context; + GstGLDisplay *display; - display = gst_gl_display_new (); +#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); + 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(); + // 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); + 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 + 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(); + 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) + Pipeline *pipeline = this->gst_thread->getPipeline (); + if (!pipeline) + return; + + /* frame is initialized as null */ + if (this->frame) + pipeline->queue_output_buf.put (this->frame); + + this->frame = pipeline->queue_input_buf.get (); + + /* direct call to paintGL (no queued) */ + this->updateGL (); +} + +static void +flushGstreamerGL (GstGLContext * context, void *data G_GNUC_UNUSED) +{ + context->gl_vtable->Flush (); +} + +void +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; + } - /* frame is initialized as null */ - if (this->frame) - pipeline->queue_output_buf.put(this->frame); + 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); - this->frame = pipeline->queue_input_buf.get(); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); - /* direct call to paintGL (no queued) */ - this->updateGL(); -} + glTranslatef (0.0f, 0.0f, -5.0f); -static void flushGstreamerGL(GstGLContext* context,void *data){ - context->gl_vtable->Flush(); + 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::paintGL() +QGLRenderer::closeEvent (QCloseEvent * event) { - 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) -{ - 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 c3d3f3a2fc..81dc333650 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