[vlc-commits] [Git][videolan/vlc][master] 3 commits: opengl: use 3x3 matrix for orientation

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sat Oct 2 09:23:55 UTC 2021



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
b7db3881 by Romain Vimont at 2021-10-02T09:01:13+00:00
opengl: use 3x3 matrix for orientation

The orientation matrix applies a 2D affine transform, so a 3x3 matrix is
sufficient.

- - - - -
9d00bf29 by Romain Vimont at 2021-10-02T09:01:13+00:00
opengl: use 3x3 matrix for Android transform

The transform matrix provided by Android is 4x4:
<https://developer.android.com/reference/android/graphics/SurfaceTexture#getTransformMatrix(float%5B%5D)>

However, the third column is never used, since the input vector is in
the form (s, t, 0, 1). Similarly, the third row is never used either,
since only the two first coordinates of the output vector are kept.

Using a 3x3 matrix simplifies the product with other 3x3 matrices.

Note: in theory, a 3x2 matrix would be sufficient, but use a square
matrix for wider compatibility with all OpenGL versions.

- - - - -
fd8a4fd8 by Romain Vimont at 2021-10-02T09:01:13+00:00
opengl: fix transform order

The TransformMatrix is provided by Android to apply its internal
coordinates transformations to sample the texture at the correct
location, so it must be applied last, after the orientation/crop from
the picture_t.

The fact that their internal transform is exposed as an explicit matrix
is an arbitrary design choice from Android. Instead they could have
exposed a GLSL function "android_texture2D(vec2 coords)":

    vec2 tex_coords = TexCoordsMap * OrientationMatrix * pic_coords;
    vec4 texel = android_texture2D(tex_coords);

In that case, it is obvious that their transform would be applied last.

Refs <https://developer.android.com/reference/android/graphics/SurfaceTexture#getTransformMatrix(float%5B%5D)>

- - - - -


3 changed files:

- modules/video_output/opengl/interop.h
- modules/video_output/opengl/interop_android.c
- modules/video_output/opengl/sampler.c


Changes:

=====================================
modules/video_output/opengl/interop.h
=====================================
@@ -76,11 +76,11 @@ struct vlc_gl_interop_ops {
      *
      * This function pointer can be NULL. If it is set, it may return NULL.
      *
-     * Otherwise, it must return a 4x4 matrix, as an array of 16 floats in
+     * Otherwise, it must return a 3x3 matrix, as an array of 9 floats in
      * column-major order.
      *
      * This transform matrix maps 2D homogeneous texture coordinates of the
-     * form (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the
+     * form (s, t, 1) with s and t in the inclusive range [0, 1] to the
      * texture coordinate that should be used to sample that location from the
      * texture.
      *
@@ -88,7 +88,7 @@ struct vlc_gl_interop_ops {
      * freed before the module is closed.
      *
      * \param interop the OpenGL interop
-     * \return a 4x4 transformatoin matrix (possibly NULL)
+     * \return a 3x3 transformation matrix (possibly NULL)
      */
     const float *
     (*get_transform_matrix)(const struct vlc_gl_interop *interop);


=====================================
modules/video_output/opengl/interop_android.c
=====================================
@@ -34,12 +34,48 @@
 
 struct priv
 {
+    float mtx_3x3[3*3];
     const float *transform_mtx;
+
     bool stex_attached;
     struct vlc_asurfacetexture *previous_texture;
     picture_t *current_picture;
 };
 
+static void
+ReductMatrix(float *mtx_3x3, const float *mtx_4x4)
+{
+    /*
+     * The transform matrix provided by Android is 4x4:
+     * <https://developer.android.com/reference/android/graphics/SurfaceTexture#getTransformMatrix(float%5B%5D)>
+     *
+     * However, the third column is never used, since the input vector is in
+     * the form (s, t, 0, 1). Similarly, the third row is never used either,
+     * since only the two first coordinates of the output vector are kept.
+     *
+     *       mat_4x4        mat_3x3
+     *
+     *     / a b . c \     / a b c \
+     *     | d e . f | --> | d e f |
+     *     | . . . . |     \ g h i /
+     *     \ g h . i /
+     */
+
+#define MTX4(COL,ROW) mtx_4x4[(COL)*4 + (ROW)]
+#define MTX3(COL,ROW) mtx_3x3[(COL)*3 + (ROW)]
+    MTX3(0,0) = MTX4(0,0); // a
+    MTX3(1,0) = MTX4(1,0); // b
+    MTX3(2,0) = MTX4(3,0); // c
+    MTX3(0,1) = MTX4(0,1); // d
+    MTX3(1,1) = MTX4(1,1); // e
+    MTX3(2,1) = MTX4(3,1); // f
+    MTX3(0,2) = MTX4(0,3); // g
+    MTX3(1,2) = MTX4(1,3); // h
+    MTX3(2,2) = MTX4(3,3); // i
+#undef MTX4
+#undef MTX3
+}
+
 static int
 tc_anop_allocate_textures(const struct vlc_gl_interop *interop, GLuint *textures,
                           const GLsizei *tex_width, const GLsizei *tex_height)
@@ -103,13 +139,17 @@ tc_anop_update(struct vlc_gl_interop *interop, GLuint *textures,
     if (previous_texture && previous_texture != texture)
         SurfaceTexture_releaseTexImage(previous_texture);
 
-    if (SurfaceTexture_updateTexImage(texture, &priv->transform_mtx)
+    const float *mtx_4x4;
+    if (SurfaceTexture_updateTexImage(texture, &mtx_4x4)
         != VLC_SUCCESS)
     {
         priv->transform_mtx = NULL;
         goto error;
     }
 
+    ReductMatrix(priv->mtx_3x3, mtx_4x4);
+    priv->transform_mtx = priv->mtx_3x3;
+
     interop->vt->ActiveTexture(GL_TEXTURE0);
     interop->vt->BindTexture(interop->tex_target, textures[0]);
 


=====================================
modules/video_output/opengl/sampler.c
=====================================
@@ -47,7 +47,7 @@ struct vlc_gl_sampler_priv {
     const opengl_vtable_t *vt; /* for convenience, same as &api->vt */
 
     struct {
-        GLfloat OrientationMatrix[4*4];
+        GLfloat OrientationMatrix[3*3];
         GLfloat TexCoordsMap[3*3];
     } var;
     struct {
@@ -332,7 +332,7 @@ GetTransformMatrix(const struct vlc_gl_interop *interop)
     if (interop && interop->ops && interop->ops->get_transform_matrix)
         tm = interop->ops->get_transform_matrix(interop);
     if (!tm)
-        tm = MATRIX4_IDENTITY;
+        tm = MATRIX3_IDENTITY;
     return tm;
 }
 
@@ -362,9 +362,9 @@ sampler_base_load(struct vlc_gl_sampler *sampler)
 
     /* Return the expected transform matrix if interop == NULL */
     const GLfloat *tm = GetTransformMatrix(priv->interop);
-    vt->UniformMatrix4fv(priv->uloc.TransformMatrix, 1, GL_FALSE, tm);
+    vt->UniformMatrix3fv(priv->uloc.TransformMatrix, 1, GL_FALSE, tm);
 
-    vt->UniformMatrix4fv(priv->uloc.OrientationMatrix, 1, GL_FALSE,
+    vt->UniformMatrix3fv(priv->uloc.OrientationMatrix, 1, GL_FALSE,
                          priv->var.OrientationMatrix);
 
     if (priv->tex_target == GL_TEXTURE_RECTANGLE)
@@ -446,9 +446,9 @@ sampler_xyz12_load(struct vlc_gl_sampler *sampler)
 
     /* Return the expected transform matrix if interop == NULL */
     const GLfloat *tm = GetTransformMatrix(priv->interop);
-    vt->UniformMatrix4fv(priv->uloc.TransformMatrix, 1, GL_FALSE, tm);
+    vt->UniformMatrix3fv(priv->uloc.TransformMatrix, 1, GL_FALSE, tm);
 
-    vt->UniformMatrix4fv(priv->uloc.OrientationMatrix, 1, GL_FALSE,
+    vt->UniformMatrix3fv(priv->uloc.OrientationMatrix, 1, GL_FALSE,
                          priv->var.OrientationMatrix);
 }
 
@@ -479,13 +479,13 @@ xyz12_shader_init(struct vlc_gl_sampler *sampler)
         "    0.0,      0.0,         0.0,        1.0 "
         " );"
 
-        "uniform mat4 TransformMatrix;\n"
-        "uniform mat4 OrientationMatrix;\n"
+        "uniform mat3 TransformMatrix;\n"
+        "uniform mat3 OrientationMatrix;\n"
         "uniform mat3 TexCoordsMap;\n"
         "vec4 vlc_texture(vec2 pic_coords)\n"
         "{ "
         " vec4 v_in, v_out;"
-        " vec2 tex_coords = (TexCoordsMap * vec3((TransformMatrix * OrientationMatrix * vec4(pic_coords, 0.0, 1.0)).xy, 1.0)).xy;\n"
+        " vec2 tex_coords = (TransformMatrix * TexCoordsMap * OrientationMatrix * vec3(pic_coords, 1.0)).xy;\n"
         " v_in  = texture2D(Textures[0], tex_coords);\n"
         " v_in = pow(v_in, xyz_gamma);"
         " v_out = matrix_xyz_rgb * v_in ;"
@@ -563,30 +563,26 @@ opengl_init_swizzle(struct vlc_gl_sampler *sampler,
 }
 
 static void
-InitOrientationMatrix(GLfloat matrix[static 4*4],
+InitOrientationMatrix(GLfloat matrix[static 3*3],
                       video_orientation_t orientation)
 {
-    memcpy(matrix, MATRIX4_IDENTITY, sizeof(MATRIX4_IDENTITY));
+    memcpy(matrix, MATRIX3_IDENTITY, sizeof(MATRIX3_IDENTITY));
 
 /**
- * / C0R0  C1R0     0  C3R0 \
- * | C0R1  C1R1     0  C3R1 |
- * |    0     0     1     0 |  <-- keep the z coordinate unchanged
- * \    0     0     0     1 /
- *                  ^
- *                  |
- *                  z never impacts the orientation
+ * / C0R0  C1R0  C3R0 \
+ * | C0R1  C1R1  C3R1 |
+ * \    0     0     1 /
  *
  * (note that in memory, the matrix is stored in column-major order)
  */
 #define MATRIX_SET(C0R0, C1R0, C3R0, \
                    C0R1, C1R1, C3R1) \
-    matrix[0*4 + 0] = C0R0; \
-    matrix[1*4 + 0] = C1R0; \
-    matrix[3*4 + 0] = C3R0; \
-    matrix[0*4 + 1] = C0R1; \
-    matrix[1*4 + 1] = C1R1; \
-    matrix[3*4 + 1] = C3R1;
+    matrix[0*3 + 0] = C0R0; \
+    matrix[1*3 + 0] = C1R0; \
+    matrix[2*3 + 0] = C3R0; \
+    matrix[0*3 + 1] = C0R1; \
+    matrix[1*3 + 1] = C1R1; \
+    matrix[2*3 + 1] = C3R1;
 
     /**
      * The following schemas show how the video picture is oriented in the
@@ -804,9 +800,9 @@ sampler_planes_load(struct vlc_gl_sampler *sampler)
 
     /* Return the expected transform matrix if interop == NULL */
     const GLfloat *tm = GetTransformMatrix(priv->interop);
-    vt->UniformMatrix4fv(priv->uloc.TransformMatrix, 1, GL_FALSE, tm);
+    vt->UniformMatrix3fv(priv->uloc.TransformMatrix, 1, GL_FALSE, tm);
 
-    vt->UniformMatrix4fv(priv->uloc.OrientationMatrix, 1, GL_FALSE,
+    vt->UniformMatrix3fv(priv->uloc.OrientationMatrix, 1, GL_FALSE,
                          priv->var.OrientationMatrix);
 
     if (priv->tex_target == GL_TEXTURE_RECTANGLE)
@@ -835,14 +831,14 @@ sampler_planes_init(struct vlc_gl_sampler *sampler)
 
     ADDF("uniform %s Texture;\n", sampler_type);
     ADD("uniform mat3 TexCoordsMap;\n"
-        "uniform mat4 TransformMatrix;\n"
-        "uniform mat4 OrientationMatrix;\n");
+        "uniform mat3 TransformMatrix;\n"
+        "uniform mat3 OrientationMatrix;\n");
 
     if (tex_target == GL_TEXTURE_RECTANGLE)
         ADD("uniform vec2 TexSize;\n");
 
     ADD("vec4 vlc_texture(vec2 pic_coords) {\n"
-        " vec2 tex_coords = (TexCoordsMap * vec3((TransformMatrix * OrientationMatrix * vec4(pic_coords, 0.0, 1.0)).xy, 1.0)).xy;\n");
+        " vec2 tex_coords = (TransformMatrix * TexCoordsMap * OrientationMatrix * vec3(pic_coords, 1.0)).xy;\n");
 
     if (tex_target == GL_TEXTURE_RECTANGLE)
     {
@@ -929,8 +925,8 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, GLenum tex_target,
 #define ADD(x) vlc_memstream_puts(&ms, x)
 #define ADDF(x, ...) vlc_memstream_printf(&ms, x, ##__VA_ARGS__)
 
-    ADD("uniform mat4 TransformMatrix;\n"
-        "uniform mat4 OrientationMatrix;\n");
+    ADD("uniform mat3 TransformMatrix;\n"
+        "uniform mat3 OrientationMatrix;\n");
     ADDF("uniform %s Textures[%u];\n", glsl_sampler, tex_count);
     ADD("uniform mat3 TexCoordsMap;\n");
 
@@ -1022,7 +1018,7 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, GLenum tex_target,
         ADD("uniform mat4 ConvMatrix;\n");
 
     ADD("vec4 vlc_texture(vec2 pic_coords) {\n"
-        " vec2 tex_coords = (TexCoordsMap * vec3((TransformMatrix * OrientationMatrix * vec4(pic_coords, 0.0, 1.0)).xy, 1.0)).xy;\n");
+        " vec2 tex_coords = (TransformMatrix * TexCoordsMap * OrientationMatrix * vec3(pic_coords, 1.0)).xy;\n");
 
     unsigned color_count;
     if (is_yuv) {



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/176241cf2cadc32f9fd74dff3015e6b2f84367a7...fd8a4fd89fd1428f659fce3ce2090d02352ea52c

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/176241cf2cadc32f9fd74dff3015e6b2f84367a7...fd8a4fd89fd1428f659fce3ce2090d02352ea52c
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list