Merge lp:~jhodapp/qtvideo-node/rotate-camera-video into lp:qtvideo-node

Proposed by Jim Hodapp
Status: Merged
Approved by: Ricardo Salveti
Approved revision: no longer in the source branch.
Merged at revision: 51
Proposed branch: lp:~jhodapp/qtvideo-node/rotate-camera-video
Merge into: lp:qtvideo-node
Diff against target: 274 lines (+142/-11)
5 files modified
src/shadervideomaterial.cpp (+124/-4)
src/shadervideomaterial.h (+15/-4)
src/shadervideoshader.cpp (+1/-1)
src/src.pro (+1/-1)
unittests/shadervideonode/shadervideonode.pro (+1/-1)
To merge this branch: bzr merge lp:~jhodapp/qtvideo-node/rotate-camera-video
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+238356@code.launchpad.net

Commit message

Rotate the video 90 degrees and do an orthographic projection when necessary, otherwise render same as always.

Description of the change

* Rotate the video 90 degrees and do an orthographic projection when necessary, otherwise render same as always.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
54. By Jim Hodapp

Do a manual tranpose of the matrix before uploading to the GPU since OpenGLES 2.0 doesn't support doing this in hardware.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
55. By Jim Hodapp

Properly rotate the matrix 90 degrees if necessary and undo the Android Y flip (which becomes an X flip after height/width flip and 90 degree rotation).

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

LGTM, but this only fixes the orientation in one case. Recording at 180 and 270 degrees were still wrong for me.

Revision history for this message
Ricardo Salveti (rsalveti) wrote :

From IRC:
<jhodapp> rsalveti: go ahead and approve that qtvideo-node branch, and I'll do a separate MR for the 180/270 cases

So the extra use cases will be covered by another MR.

review: Approve
56. By Jim Hodapp

Add 180 and 270 degree rotation/flipping of video playback.

57. By Jim Hodapp

Merged with trunk.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/shadervideomaterial.cpp'
2--- src/shadervideomaterial.cpp 2014-04-03 15:46:09 +0000
3+++ src/shadervideomaterial.cpp 2014-10-21 14:29:15 +0000
4@@ -22,6 +22,8 @@
5 #endif
6
7 #include <QGLShaderProgram>
8+#include <QtOpenGL>
9+#include <QTransform>
10
11 #include <QtCore/qdebug.h>
12
13@@ -29,6 +31,7 @@
14 #include "shadervideoshader.h"
15
16 #include <camera_compatibility_layer.h>
17+#include <qtubuntu_media_signals.h>
18 #include <surface_texture_client_hybris.h>
19
20 ShaderVideoShader *ShaderVideoMaterial::m_videoShader = 0;
21@@ -39,8 +42,11 @@
22 m_textureId(0),
23 m_surfaceTextureClient(0),
24 m_glConsumer(0),
25- m_readyToRender(false)
26+ m_readyToRender(false),
27+ m_orientation(SharedSignal::Orientation::rotate0)
28 {
29+ connect(SharedSignal::instance(), SIGNAL(setOrientation(const SharedSignal::Orientation&, const QSize&)),
30+ this, SLOT(onSetOrientation(const SharedSignal::Orientation&, const QSize&)));
31 }
32
33 QSGMaterialShader *ShaderVideoMaterial::createShader() const
34@@ -109,8 +115,19 @@
35 textureDirty = true;
36 }
37
38- undoAndroidYFlip(m_textureMatrix);
39- glUniformMatrix4fv(m_videoShader->m_tex_matrix, 1, GL_FALSE, m_textureMatrix);
40+ // See if the video needs rotation
41+ if (m_orientation == SharedSignal::Orientation::rotate90 ||
42+ m_orientation == SharedSignal::Orientation::rotate180 ||
43+ m_orientation == SharedSignal::Orientation::rotate270)
44+ {
45+ QMatrix4x4 qRotated = rotateAndFlip(m_textureMatrix, m_orientation);
46+ glUniformMatrix4fv(m_videoShader->m_tex_matrix, 1, GL_FALSE, qRotated.data());
47+ }
48+ else
49+ {
50+ undoAndroidYFlip(m_textureMatrix);
51+ glUniformMatrix4fv(m_videoShader->m_tex_matrix, 1, GL_FALSE, m_textureMatrix);
52+ }
53
54 glTexParameteri(TEXTURE_TARGET, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
55 glTexParameteri(TEXTURE_TARGET, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
56@@ -120,6 +137,97 @@
57 return textureDirty;
58 }
59
60+void ShaderVideoMaterial::onSetOrientation(const SharedSignal::Orientation& orientation,
61+ const QSize &size)
62+{
63+ m_orientation = orientation;
64+ m_frameSize = size;
65+ qDebug() << "orientation: " << orientation;
66+ qDebug() << "frameSize: " << size;
67+}
68+
69+// Takes a GLfloat texture matrix and desired orientation, and outputs a rotated and
70+// horizontally flipped matrix
71+QMatrix4x4 ShaderVideoMaterial::rotateAndFlip(GLfloat *m, const SharedSignal::Orientation &orientation)
72+{
73+ QMatrix4x4 ret;
74+
75+ if (m == NULL)
76+ return ret;
77+
78+ /* TODO: Because of the column-to-row major format change, horizontal flips
79+ * are really vertical flips, and vice versa. An improvement that needs to happen
80+ * to more generically handle any container transformation matrix is to not convert
81+ * to row-major format.
82+ */
83+ QMatrix4x4 qRowMajorTextureMatrix(m[0], m[4], m[8], m[12],
84+ m[1], m[5], m[9], m[13],
85+ m[2], m[6], m[10], m[14],
86+ m[3], m[7], m[11], m[15]);
87+ const QMatrix4x4 qFlipH (-1, 0, 0, 1,
88+ 0, 1, 0, 0,
89+ 0, 0, 1, 0,
90+ 0, 0, 0, 1);
91+ const QMatrix4x4 qFlipV ( 1, 0, 0, 0,
92+ 0, -1, 0, 1,
93+ 0, 0, 1, 0,
94+ 0, 0, 0, 1);
95+
96+ switch (orientation)
97+ {
98+ case SharedSignal::Orientation::rotate90:
99+ {
100+ // FIXME: This matrix comes from the file container, but could not
101+ // get this actual matrix up from GStreamer to here, so hardcoded
102+ // for now.
103+ const QMatrix4x4 qRotate90 (0, 1, 0, 0,
104+ -1, 0, 0, 0,
105+ 0, 0, 1, 0,
106+ 0, 0, 0, 1);
107+
108+ ret = qRowMajorTextureMatrix * qRotate90;
109+ // This must be done manually since OpenGLES 2.0 does not support doing the transpose
110+ // when uploading the matrix to the GPU. OpenGLES 3.0 supports this.
111+ ret = ret.transposed();
112+ // Undo the Android mirroring. Since we already flipped height/width and rotated,
113+ // do this about the vertical axis.
114+ ret = ret * qFlipH;
115+ }
116+ break;
117+ case SharedSignal::Orientation::rotate180:
118+ {
119+ ret = qRowMajorTextureMatrix * qFlipH;
120+ }
121+ break;
122+ case SharedSignal::Orientation::rotate270:
123+ {
124+ // FIXME: This matrix comes from the file container, but could not
125+ // get this actual matrix up from GStreamer to here, so hardcoded
126+ // for now.
127+ const QMatrix4x4 qRotate270( 0, 1, 0, 0,
128+ -1, 0, 0, 0,
129+ 0, 0, 1, 0,
130+ 0, 0, 0, 1);
131+
132+ ret = qRowMajorTextureMatrix * qRotate270;
133+ // This must be done manually since OpenGLES 2.0 does not support doing the transpose
134+ // when uploading the matrix to the GPU. OpenGLES 3.0 supports this.
135+ ret = ret.transposed();
136+ // Undo the Android mirroring. Since we already flipped height/width and rotated,
137+ // do this about the horizontal axis.
138+ ret = ret * qFlipV;
139+ }
140+ break;
141+ case SharedSignal::Orientation::rotate0:
142+ // No-op, no rotation needed
143+ default:
144+ qDebug() << "Not rotating";
145+ break;
146+ }
147+
148+ return ret;
149+}
150+
151 void ShaderVideoMaterial::undoAndroidYFlip(GLfloat matrix[])
152 {
153 // The android matrix flips the y coordinate
154@@ -133,7 +241,7 @@
155
156 /*!
157 * \brief ShaderVideoMaterial::printGLMaxtrix
158- * Prints a OpenGL matrix (GLfloat m[16]) to std out.
159+ * Prints an EGL matrix (GLfloat m[16]) to stdout.
160 * This function stays here for convenience in case some more debugging is necessary for the android
161 * transformation matrix.
162 * \param matrix Matrix to be printed to std out
163@@ -145,3 +253,15 @@
164 qDebug() << matrix[2] << matrix[6] << matrix[10] << matrix[14];
165 qDebug() << matrix[3] << matrix[7] << matrix[11] << matrix[15];
166 }
167+
168+/*!
169+ * \brief Prints a row-major matrix to stdout.
170+ * \param matrix Matrix to be printed to std out
171+ */
172+void ShaderVideoMaterial::printMaxtrix(float matrix[])
173+{
174+ qDebug() << matrix[0] << matrix[1] << matrix[2] << matrix[3];
175+ qDebug() << matrix[4] << matrix[5] << matrix[6] << matrix[7];
176+ qDebug() << matrix[8] << matrix[9] << matrix[10] << matrix[11];
177+ qDebug() << matrix[12] << matrix[13] << matrix[14] << matrix[15];
178+}
179
180=== modified file 'src/shadervideomaterial.h'
181--- src/shadervideomaterial.h 2014-04-03 15:46:09 +0000
182+++ src/shadervideomaterial.h 2014-10-21 14:29:15 +0000
183@@ -1,5 +1,5 @@
184 /*
185- * Copyright (C) 2013 Canonical, Ltd.
186+ * Copyright (C) 2013-2014 Canonical, Ltd.
187 *
188 * This program is free software; you can redistribute it and/or modify
189 * it under the terms of the GNU Lesser General Public License as published by
190@@ -23,15 +23,19 @@
191 #else
192 #include <QtQuick/QSGMaterial>
193 #endif
194+#include <qgl.h>
195+#include <QMatrix4x4>
196+#include <QObject>
197 #include <QVideoSurfaceFormat>
198-#include <qgl.h>
199+#include <qtubuntu_media_signals.h>
200
201 struct CameraControl;
202 struct MediaPlayerWrapper;
203 class ShaderVideoShader;
204
205-class ShaderVideoMaterial : public QSGMaterial
206+class ShaderVideoMaterial : public QObject, public QSGMaterial
207 {
208+ Q_OBJECT
209 public:
210 typedef void* SurfaceTextureClientHybris;
211 typedef void* GLConsumerWrapperHybris;
212@@ -54,11 +58,16 @@
213
214 bool updateTexture();
215
216- GLfloat m_textureMatrix[16];
217+ GLfloat m_textureMatrix[16] {};
218+
219+private Q_SLOTS:
220+ void onSetOrientation(const SharedSignal::Orientation& orientation, const QSize &size);
221
222 private:
223+ QMatrix4x4 rotateAndFlip(GLfloat *m, const SharedSignal::Orientation &orientation);
224 void undoAndroidYFlip(GLfloat matrix[]);
225 void printGLMaxtrix(GLfloat matrix[]);
226+ void printMaxtrix(float matrix[]);
227
228 QVideoSurfaceFormat m_format;
229 CameraControl *m_camControl;
230@@ -67,6 +76,8 @@
231 GLConsumerWrapperHybris m_glConsumer;
232 bool m_readyToRender;
233 static ShaderVideoShader *m_videoShader; // the shader is cached in the Qt scene graph
234+ SharedSignal::Orientation m_orientation;
235+ QSize m_frameSize;
236 };
237
238 #endif // SHADERVIDEOMATERIAL_H
239
240=== modified file 'src/shadervideoshader.cpp'
241--- src/shadervideoshader.cpp 2014-04-01 19:31:38 +0000
242+++ src/shadervideoshader.cpp 2014-10-21 14:29:15 +0000
243@@ -75,7 +75,7 @@
244 "varying highp vec2 qt_TexCoord; \n"
245 "void main() \n"
246 "{ \n"
247- " gl_FragColor = texture2D( sTexture, qt_TexCoord );\n"
248+ " gl_FragColor = texture2D( sTexture, qt_TexCoord ) * vec4(opacity);\n"
249 "} \n";
250 return shader;
251 }
252
253=== modified file 'src/src.pro'
254--- src/src.pro 2014-06-06 14:54:20 +0000
255+++ src/src.pro 2014-10-21 14:29:15 +0000
256@@ -1,6 +1,6 @@
257 TARGET = shadervideonode
258 TEMPLATE = lib
259-CONFIG += plugin
260+CONFIG += plugin c++11
261 QT += multimedia opengl quick-private quick
262
263 include(../coverage.pri)
264
265=== modified file 'unittests/shadervideonode/shadervideonode.pro'
266--- unittests/shadervideonode/shadervideonode.pro 2014-04-03 15:46:09 +0000
267+++ unittests/shadervideonode/shadervideonode.pro 2014-10-21 14:29:15 +0000
268@@ -1,5 +1,5 @@
269 CONFIG += testcase
270-CONFIG += no_private_qt_headers_warning
271+CONFIG += no_private_qt_headers_warning c++11
272 TARGET = tst_shadervideonode
273
274 # We don't want to install unit tests anywhere as it doesn't make sense

Subscribers

People subscribed via source and target branches