• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer
3  * Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
4  * Copyright (C) 2009 Andrey Nechypurenko <andreynech@gmail.com>
5  * Copyright (C) 2010 Nuno Santos <nunosantos@imaginando.net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include <QGLWidget>
24 #include <QApplication>
25 #include <QDebug>
26 #include <QCloseEvent>
27 
28 #include <gst/video/video.h>
29 #include <gst/gl/gl.h>
30 #include <gst/gl/gstglfuncs.h>
31 
32 #if GST_GL_HAVE_PLATFORM_GLX
33 #include <GL/glx.h>
34 #include <QX11Info>
35 #include <gst/gl/x11/gstgldisplay_x11.h>
36 #endif
37 
38 #include "gstthread.h"
39 #include "qglrenderer.h"
40 #include "pipeline.h"
41 
42 #if defined(Q_WS_MAC)
43 extern void *qt_current_nsopengl_context ();
44 #endif
45 
QGLRenderer(const QString & videoLocation,QWidget * parent)46 QGLRenderer::QGLRenderer (const QString & videoLocation, QWidget * parent)
47     :
48 QGLWidget (parent),
49 videoLoc (videoLocation),
50 gst_thread (NULL),
51 closing (false),
52 frame (NULL)
53 {
54   move (20, 10);
55   resize (640, 480);
56 }
57 
~QGLRenderer()58 QGLRenderer::~QGLRenderer ()
59 {
60 }
61 
62 void
initializeGL()63 QGLRenderer::initializeGL ()
64 {
65   GstGLContext *context;
66   GstGLDisplay *display;
67 
68 #if GST_GL_HAVE_PLATFORM_GLX
69   display =
70       (GstGLDisplay *) gst_gl_display_x11_new_with_display (QX11Info::
71       display ());
72 #else
73   display = gst_gl_display_new ();
74 #endif
75 
76   /* FIXME: Allow the choice at runtime */
77 #if GST_GL_HAVE_PLATFORM_WGL
78   context =
79       gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (),
80       GST_GL_PLATFORM_WGL, GST_GL_API_OPENGL);
81 #elif GST_GL_HAVE_PLATFORM_CGL
82   context =
83       gst_gl_context_new_wrapped (display,
84       (guintptr) qt_current_nsopengl_context (), GST_GL_PLATFORM_CGL,
85       GST_GL_API_OPENGL);
86 #elif GST_GL_HAVE_PLATFORM_GLX
87   context =
88       gst_gl_context_new_wrapped (display, (guintptr) glXGetCurrentContext (),
89       GST_GL_PLATFORM_GLX, GST_GL_API_OPENGL);
90 #endif
91   gst_object_unref (display);
92 
93   // We need to unset Qt context before initializing gst-gl plugin.
94   // Otherwise the attempt to share gst-gl context with Qt will fail.
95   this->doneCurrent ();
96   this->gst_thread =
97       new GstThread (display, context, this->videoLoc,
98       SLOT (newFrame ()), this);
99   this->makeCurrent ();
100 
101   QObject::connect (this->gst_thread, SIGNAL (finished ()),
102       this, SLOT (close ()));
103   QObject::connect (this, SIGNAL (closeRequested ()),
104       this->gst_thread, SLOT (stop ()), Qt::QueuedConnection);
105 
106   qglClearColor (QApplication::palette ().color (QPalette::Active,
107           QPalette::Window));
108   //glShadeModel(GL_FLAT);
109   //glEnable(GL_DEPTH_TEST);
110   //glEnable(GL_CULL_FACE);
111   glEnable (GL_TEXTURE_2D);     // Enable Texture Mapping
112 
113   this->gst_thread->start ();
114 }
115 
116 void
resizeGL(int width,int height)117 QGLRenderer::resizeGL (int width, int height)
118 {
119   // Reset The Current Viewport And Perspective Transformation
120   glViewport (0, 0, width, height);
121 
122   glMatrixMode (GL_PROJECTION);
123   glLoadIdentity ();
124 
125   glMatrixMode (GL_MODELVIEW);
126 }
127 
128 void
newFrame()129 QGLRenderer::newFrame ()
130 {
131   Pipeline *pipeline = this->gst_thread->getPipeline ();
132   if (!pipeline)
133     return;
134 
135   /* frame is initialized as null */
136   if (this->frame)
137     pipeline->queue_output_buf.put (this->frame);
138 
139   this->frame = pipeline->queue_input_buf.get ();
140 
141   /* direct call to paintGL (no queued) */
142   this->updateGL ();
143 }
144 
145 static void
flushGstreamerGL(GstGLContext * context,void * data G_GNUC_UNUSED)146 flushGstreamerGL (GstGLContext * context, void *data G_GNUC_UNUSED)
147 {
148   context->gl_vtable->Flush ();
149 }
150 
151 void
paintGL()152 QGLRenderer::paintGL ()
153 {
154   static GLfloat xrot = 0;
155   static GLfloat yrot = 0;
156   static GLfloat zrot = 0;
157 
158   if (this->frame) {
159     guint tex_id;
160     GstMemory *mem;
161     GstVideoInfo v_info;
162     GstVideoFrame v_frame;
163     GstVideoMeta *v_meta;
164 
165     mem = gst_buffer_peek_memory (this->frame, 0);
166     v_meta = gst_buffer_get_video_meta (this->frame);
167 
168     Q_ASSERT (gst_is_gl_memory (mem));
169 
170     GstGLMemory *gl_memory = (GstGLMemory *) mem;
171 
172     gst_gl_context_thread_add (gl_memory->mem.context, flushGstreamerGL, NULL);
173 
174     gst_video_info_set_format (&v_info, v_meta->format, v_meta->width,
175         v_meta->height);
176 
177     gst_video_frame_map (&v_frame, &v_info, this->frame,
178         (GstMapFlags) (GST_MAP_READ | GST_MAP_GL));
179 
180     tex_id = *(guint *) v_frame.data[0];
181 
182     glEnable (GL_DEPTH_TEST);
183 
184     glEnable (GL_TEXTURE_2D);
185     glBindTexture (GL_TEXTURE_2D, tex_id);
186     if (glGetError () != GL_NO_ERROR) {
187       qDebug ("failed to bind texture that comes from gst-gl");
188       emit closeRequested ();
189       return;
190     }
191 
192     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
193     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
194     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
195     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
196     glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
197 
198     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
199     glMatrixMode (GL_MODELVIEW);
200     glLoadIdentity ();
201 
202     glScalef (0.5f, 0.5f, 0.5f);
203 
204     glRotatef (xrot, 1.0f, 0.0f, 0.0f);
205     glRotatef (yrot, 0.0f, 1.0f, 0.0f);
206     glRotatef (zrot, 0.0f, 0.0f, 1.0f);
207 
208     glBegin (GL_QUADS);
209     // Front Face
210     glTexCoord2f (1.0f, 0.0f);
211     glVertex3f (-1.0f, -1.0f, 1.0f);
212     glTexCoord2f (0.0f, 0.0f);
213     glVertex3f (1.0f, -1.0f, 1.0f);
214     glTexCoord2f (0.0f, 1.0f);
215     glVertex3f (1.0f, 1.0f, 1.0f);
216     glTexCoord2f (1.0f, 1.0f);
217     glVertex3f (-1.0f, 1.0f, 1.0f);
218     // Back Face
219     glTexCoord2f (0.0f, 0.0f);
220     glVertex3f (-1.0f, -1.0f, -1.0f);
221     glTexCoord2f (0.0f, 1.0f);
222     glVertex3f (-1.0f, 1.0f, -1.0f);
223     glTexCoord2f (1.0f, 1.0f);
224     glVertex3f (1.0f, 1.0f, -1.0f);
225     glTexCoord2f (1.0f, 0.0f);
226     glVertex3f (1.0f, -1.0f, -1.0f);
227     // Top Face
228     glTexCoord2f (1.0f, 1.0f);
229     glVertex3f (-1.0f, 1.0f, -1.0f);
230     glTexCoord2f (1.0f, 0.0f);
231     glVertex3f (-1.0f, 1.0f, 1.0f);
232     glTexCoord2f (0.0f, 0.0f);
233     glVertex3f (1.0f, 1.0f, 1.0f);
234     glTexCoord2f (0.0f, 1.0f);
235     glVertex3f (1.0f, 1.0f, -1.0f);
236     // Bottom Face
237     glTexCoord2f (1.0f, 0.0f);
238     glVertex3f (-1.0f, -1.0f, -1.0f);
239     glTexCoord2f (0.0f, 0.0f);
240     glVertex3f (1.0f, -1.0f, -1.0f);
241     glTexCoord2f (0.0f, 1.0f);
242     glVertex3f (1.0f, -1.0f, 1.0f);
243     glTexCoord2f (1.0f, 1.0f);
244     glVertex3f (-1.0f, -1.0f, 1.0f);
245     // Right face
246     glTexCoord2f (0.0f, 0.0f);
247     glVertex3f (1.0f, -1.0f, -1.0f);
248     glTexCoord2f (0.0f, 1.0f);
249     glVertex3f (1.0f, 1.0f, -1.0f);
250     glTexCoord2f (1.0f, 1.0f);
251     glVertex3f (1.0f, 1.0f, 1.0f);
252     glTexCoord2f (1.0f, 0.0f);
253     glVertex3f (1.0f, -1.0f, 1.0f);
254     // Left Face
255     glTexCoord2f (1.0f, 0.0f);
256     glVertex3f (-1.0f, -1.0f, -1.0f);
257     glTexCoord2f (0.0f, 0.0f);
258     glVertex3f (-1.0f, -1.0f, 1.0f);
259     glTexCoord2f (0.0f, 1.0f);
260     glVertex3f (-1.0f, 1.0f, 1.0f);
261     glTexCoord2f (1.0f, 1.0f);
262     glVertex3f (-1.0f, 1.0f, -1.0f);
263     glEnd ();
264 
265     xrot += 0.3f;
266     yrot += 0.2f;
267     zrot += 0.4f;
268 
269     glLoadIdentity();
270     glDisable(GL_DEPTH_TEST);
271     glBindTexture (GL_TEXTURE_2D, 0);
272 
273     gst_video_frame_unmap (&v_frame);
274   }
275 }
276 
277 void
closeEvent(QCloseEvent * event)278 QGLRenderer::closeEvent (QCloseEvent * event)
279 {
280   if (this->closing == false) {
281     this->closing = true;
282     emit closeRequested ();
283     event->ignore ();
284   }
285 }
286