[vlc-devel] [PATCH 1/5] Make opengl.c handle movie rotations.

Matthias Keiser matthias at tristan-inc.com
Tue Mar 18 22:53:27 CET 2014


Am 17.03.2014 um 18:05 schrieb Rémi Denis-Courmont <remi at remlab.net>:

> Le dimanche 16 mars 2014, 22:16:16 Matthias Keiser a écrit :
>> Am 15.03.2014 um 09:33 schrieb Rémi Denis-Courmont <remi at remlab.net>:
>>> Le vendredi 14 mars 2014, 01:00:07 Matthias Keiser a écrit :
>>>> ---
>>>> modules/video_output/opengl.c | 102
>>>> ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98
>>>> insertions(+), 4 deletions(-)
>>> 
>>> Trying with 90 degrees rotation...
>>> 
>>> With the NVIDIA driver, I still get an immediate segmentation fault. With
>>> the Mesa R300 driver, the picture is corrupted, partly rotated, partly
>>> not.
>> Ok, this is awkward because I can't reproduce it myself, but if we are lucky
>> this fixes it:
> 
> This yields the exact same crash as before in glDrawArrays(). In fact, it also 
> crashes for straight videos, now that I checked it.
> 
> According to the internets, this is a common problem with programs to clear 
> dangling state. I don't know OpenGL though.


Upon further review I noticed the matrix was declared as floats instead as GLfloats, which is clearly wrong. However it is unlikely that this is the root of this issue. Corrected patch posted nevertheless for reference:

---
 modules/video_output/opengl.c | 103 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 98 insertions(+), 5 deletions(-)

diff --git a/modules/video_output/opengl.c b/modules/video_output/opengl.c
index 33db19d..8d89a35 100644
--- a/modules/video_output/opengl.c
+++ b/modules/video_output/opengl.c
@@ -49,6 +49,7 @@
 #   define PFNGLGETATTRIBLOCATIONPROC        typeof(glGetAttribLocation)*
 #   define PFNGLVERTEXATTRIBPOINTERPROC      typeof(glVertexAttribPointer)*
 #   define PFNGLENABLEVERTEXATTRIBARRAYPROC  typeof(glEnableVertexAttribArray)*
+#   define PFNGLUNIFORMMATRIX4FVPROC         typeof(glUniformMatrix4fv)*
 #   define PFNGLUNIFORM4FVPROC               typeof(glUniform4fv)*
 #   define PFNGLUNIFORM4FPROC                typeof(glUniform4f)*
 #   define PFNGLUNIFORM1IPROC                typeof(glUniform1i)*
@@ -146,9 +147,10 @@ struct vout_display_opengl_t {
     PFNGLVERTEXATTRIBPOINTERPROC     VertexAttribPointer;
     PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
 
-    PFNGLUNIFORM4FVPROC   Uniform4fv;
-    PFNGLUNIFORM4FPROC    Uniform4f;
-    PFNGLUNIFORM1IPROC    Uniform1i;
+    PFNGLUNIFORMMATRIX4FVPROC   UniformMatrix4fv;
+    PFNGLUNIFORM4FVPROC         Uniform4fv;
+    PFNGLUNIFORM4FPROC          Uniform4f;
+    PFNGLUNIFORM1IPROC          Uniform1i;
 
     /* Shader command */
     PFNGLCREATESHADERPROC CreateShader;
@@ -221,12 +223,13 @@ static void BuildVertexShader(vout_display_opengl_t *vgl,
         PRECISION
         "varying vec4 TexCoord0,TexCoord1, TexCoord2;"
         "attribute vec4 MultiTexCoord0,MultiTexCoord1,MultiTexCoord2;"
-        "attribute vec4 VertexPosition;"
+        "attribute vec2 VertexPosition;"
+        "uniform mat4 RotationMatrix;"
         "void main() {"
         " TexCoord0 = MultiTexCoord0;"
         " TexCoord1 = MultiTexCoord1;"
         " TexCoord2 = MultiTexCoord2;"
-        " gl_Position = VertexPosition;"
+        " gl_Position = RotationMatrix * vec4(VertexPosition, 0.0, 1.0);"
         "}";
 
     *shader = vgl->CreateShader(GL_VERTEX_SHADER);
@@ -432,6 +435,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     vgl->GetAttribLocation  = glGetAttribLocation;
     vgl->VertexAttribPointer= glVertexAttribPointer;
     vgl->EnableVertexAttribArray = glEnableVertexAttribArray;
+    vgl->UniformMatrix4fv = glUniformMatrix4fv;
     vgl->Uniform4fv    = glUniform4fv;
     vgl->Uniform4f     = glUniform4f;
     vgl->Uniform1i     = glUniform1i;
@@ -458,6 +462,7 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
     vgl->GetAttribLocation  = (PFNGLGETATTRIBLOCATIONPROC)vlc_gl_GetProcAddress(vgl->gl, "glGetAttribLocation");
     vgl->VertexAttribPointer= (PFNGLVERTEXATTRIBPOINTERPROC)vlc_gl_GetProcAddress(vgl->gl, "glVertexAttribPointer");
     vgl->EnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)vlc_gl_GetProcAddress(vgl->gl, "glEnableVertexAttribArray");
+    vgl->UniformMatrix4fv   = (PFNGLUNIFORMMATRIX4FVPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniformMatrix4fv");
     vgl->Uniform4fv    = (PFNGLUNIFORM4FVPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniform4fv");
     vgl->Uniform4f     = (PFNGLUNIFORM4FPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniform4f");
     vgl->Uniform1i     = (PFNGLUNIFORM1IPROC)vlc_gl_GetProcAddress(vgl->gl,"glUniform1i");
@@ -947,6 +952,76 @@ int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
     return VLC_SUCCESS;
 }
 
+static const GLfloat identity[] = {
+    1.0f, 0.0f, 0.0f, 0.0f,
+    0.0f, 1.0f, 0.0f, 0.0f,
+    0.0f, 0.0f, 1.0f, 0.0f,
+    0.0f, 0.0f, 0.0f, 1.0f
+};
+
+static void orientationTransformMatrix(GLfloat matrix[static 16], video_orientation_t orientation) {
+
+    memcpy(matrix, identity, sizeof(identity));
+
+    const int k_cos_pi = -1;
+    const int k_cos_pi_2 = 0;
+    const int k_cos_n_pi_2 = 0;
+
+    const int k_sin_pi = 0;
+    const int k_sin_pi_2 = 1;
+    const int k_sin_n_pi_2 = -1;
+
+    bool rotate = false;
+    int cos = 0, sin = 0;
+
+    switch (orientation) {
+
+        case ORIENT_ROTATED_90:
+            cos = k_cos_pi_2;
+            sin = k_sin_pi_2;
+            rotate = true;
+            break;
+        case ORIENT_ROTATED_180:
+            cos = k_cos_pi;
+            sin = k_sin_pi;
+            rotate = true;
+            break;
+        case ORIENT_ROTATED_270:
+            cos = k_cos_n_pi_2;
+            sin = k_sin_n_pi_2;
+            rotate = true;
+            break;
+        case ORIENT_HFLIPPED:
+            matrix[0 * 4 + 0] = -1;
+            break;
+        case ORIENT_VFLIPPED:
+            matrix[1 * 4 + 1] = -1;
+            break;
+        case ORIENT_TRANSPOSED:
+            matrix[0 * 4 + 0] = 0;
+            matrix[0 * 4 + 1] = -1;
+            matrix[1 * 4 + 0] = -1;
+            matrix[1 * 4 + 1] = 0;
+            break;
+        case ORIENT_ANTI_TRANSPOSED:
+            matrix[0 * 4 + 0] = 0;
+            matrix[0 * 4 + 1] = 1;
+            matrix[1 * 4 + 0] = 1;
+            matrix[1 * 4 + 1] = 0;
+            break;
+        default:
+            break;
+    }
+
+    if(rotate) {
+
+        matrix[0 * 4 + 0] = cos;
+        matrix[0 * 4 + 1] = -sin;
+        matrix[1 * 4 + 0] = sin;
+        matrix[1 * 4 + 1] = cos;
+    }
+}
+
 #ifdef SUPPORTS_FIXED_PIPELINE
 static void DrawWithoutShaders(vout_display_opengl_t *vgl,
                                float *left, float *top, float *right, float *bottom)
@@ -965,6 +1040,13 @@ static void DrawWithoutShaders(vout_display_opengl_t *vgl,
         right[0], top[0]
     };
 
+    GLfloat transformMatrix[16];
+    orientationTransformMatrix(transformMatrix, vgl->fmt.orientation);
+
+    glPushMatrix();
+    glMatrixMode(GL_MODELVIEW);
+    glLoadMatrixf(transformMatrix);
+
     glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
     glEnable(vgl->tex_target);
     glActiveTexture(GL_TEXTURE0 + 0);
@@ -983,6 +1065,9 @@ static void DrawWithoutShaders(vout_display_opengl_t *vgl,
     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     glDisableClientState(GL_VERTEX_ARRAY);
     glDisable(vgl->tex_target);
+
+    glPopMatrix();
+
 }
 #endif
 
@@ -1035,6 +1120,11 @@ static void DrawWithShaders(vout_display_opengl_t *vgl,
     vgl->EnableVertexAttribArray(vgl->GetAttribLocation(vgl->program[program], "VertexPosition"));
     vgl->VertexAttribPointer(vgl->GetAttribLocation(vgl->program[program], "VertexPosition"), 2, GL_FLOAT, 0, 0, vertexCoord);
 
+    GLfloat transformMatrix[16];
+    orientationTransformMatrix(transformMatrix, vgl->fmt.orientation);
+    vgl->EnableVertexAttribArray(vgl->GetUniformLocation(vgl->program[program], "RotationMatrix"));
+    vgl->UniformMatrix4fv(vgl->GetUniformLocation(vgl->program[program], "RotationMatrix"), 1, GL_FALSE, transformMatrix);
+
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 }
 #endif
@@ -1138,6 +1228,9 @@ int vout_display_opengl_Display(vout_display_opengl_t *vgl,
             vgl->VertexAttribPointer(vgl->GetAttribLocation(vgl->program[1], "MultiTexCoord0"), 2, GL_FLOAT, 0, 0, textureCoord);
             vgl->EnableVertexAttribArray(vgl->GetAttribLocation(vgl->program[1], "VertexPosition"));
             vgl->VertexAttribPointer(vgl->GetAttribLocation(vgl->program[1], "VertexPosition"), 2, GL_FLOAT, 0, 0, vertexCoord);
+            //Subpictures have the correct orientation:
+            vgl->EnableVertexAttribArray(vgl->GetUniformLocation(vgl->program[1], "RotationMatrix"));
+            vgl->UniformMatrix4fv(vgl->GetUniformLocation(vgl->program[1], "RotationMatrix"), 1, GL_FALSE, identity);
 #endif
         } else {
 #ifdef SUPPORTS_FIXED_PIPELINE
-- 
1.8.3.4 (Apple Git-47)





More information about the vlc-devel mailing list