mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
263255137e
gstgl doesn't undo/overwrite what GL state the examples are changing anymore. As such, the examples need to reset the GL state themselves to be able to play nice with libgstgl
285 lines
7.6 KiB
C++
285 lines
7.6 KiB
C++
/*
|
|
* GStreamer
|
|
* Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
|
|
* Copyright (C) 2009 Andrey Nechypurenko <andreynech@gmail.com>
|
|
* Copyright (C) 2010 Nuno Santos <nunosantos@imaginando.net>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <QGLWidget>
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QCloseEvent>
|
|
|
|
#include <GL/glx.h>
|
|
|
|
#include <gst/video/video.h>
|
|
#include <gst/gl/gl.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"
|
|
|
|
#if defined(Q_WS_MAC)
|
|
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)
|
|
{
|
|
move (20, 10);
|
|
resize (640, 480);
|
|
}
|
|
|
|
QGLRenderer::~QGLRenderer ()
|
|
{
|
|
}
|
|
|
|
void
|
|
QGLRenderer::initializeGL ()
|
|
{
|
|
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 */
|
|
#if GST_GL_HAVE_PLATFORM_WGL
|
|
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);
|
|
#elif GST_GL_HAVE_PLATFORM_GLX
|
|
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 (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)
|
|
{
|
|
// Reset The Current Viewport And Perspective Transformation
|
|
glViewport (0, 0, width, height);
|
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
glLoadIdentity ();
|
|
|
|
glMatrixMode (GL_MODELVIEW);
|
|
}
|
|
|
|
void
|
|
QGLRenderer::newFrame ()
|
|
{
|
|
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->mem.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 ();
|
|
|
|
glScalef (0.5f, 0.5f, 0.5f);
|
|
|
|
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;
|
|
|
|
glLoadIdentity();
|
|
glDisable(GL_DEPTH_TEST);
|
|
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 ();
|
|
}
|
|
}
|