From 73973e8013949a36bf95fad43edaf973471ea7c7 Mon Sep 17 00:00:00 2001
From: Vittorio Giovara <vittorio.giovara@gmail.com>
Date: Tue, 26 Feb 2019 18:37:48 -0500
Subject: [PATCH 1/6] demux/libmp4: Apply flip operations from the display
 matrix

---
 modules/demux/mp4/essetup.c | 15 ++++++++++++++-
 modules/demux/mp4/libmp4.c  | 10 ++++++++++
 modules/demux/mp4/libmp4.h  |  1 +
 modules/demux/mp4/mp4.c     |  1 +
 modules/demux/mp4/mp4.h     |  1 +
 5 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/modules/demux/mp4/essetup.c b/modules/demux/mp4/essetup.c
index 19b5ff16fc64..da14800c95d0 100644
--- a/modules/demux/mp4/essetup.c
+++ b/modules/demux/mp4/essetup.c
@@ -280,13 +280,26 @@ int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
             p_track->fmt.video.orientation = ORIENT_ROTATED_90;
             break;
         case 180:
-            p_track->fmt.video.orientation = ORIENT_ROTATED_180;
+            if (p_track->i_flip == 1) {
+                p_track->fmt.video.orientation = ORIENT_VFLIPPED;
+            } else {
+                p_track->fmt.video.orientation = ORIENT_ROTATED_180;
+            }
             break;
         case 270:
             p_track->fmt.video.orientation = ORIENT_ROTATED_270;
             break;
     }
 
+    /* Flip, unless already flipped */
+    if (p_track->i_flip == 1 && (int)p_track->f_rotation != 180) {
+    fprintf(stderr, "p_track->f_rotation %f flip %d\n", p_track->f_rotation, p_track->i_flip);
+        video_transform_t transform = (video_transform_t)p_track->fmt.video.orientation;
+        /* Flip first then rotate */
+        p_track->fmt.video.orientation = ORIENT_HFLIPPED;
+        video_format_TransformBy(&p_track->fmt.video, transform);
+    }
+
     /* Set 360 video mode */
     p_track->fmt.video.projection_mode = PROJECTION_MODE_RECTANGULAR;
     const MP4_Box_t *p_uuid = MP4_BoxGet( p_track->p_track, "uuid" );
diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index cf9eeadf42fd..b76e46493ca8 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -1227,6 +1227,16 @@ static int MP4_ReadBox_tkhd(  stream_t *p_stream, MP4_Box_t *p_box )
     double scale[2];    // scale factor; sx = scale[0] , sy = scale[1]
     int32_t *matrix = p_box->data.p_tkhd->i_matrix;
 
+    int32_t fmatrix[9];
+    int64_t det = (int64_t)matrix[0] * matrix[4] - (int64_t)matrix[1] * matrix[3];
+    if (det < 0) {
+        /* If determinant is negative copy the matrix and flip it horizontally. */
+        const int flip[] = { -1, 1, 1 };
+        for (int j = 0; j < 9; j++)
+            matrix[j] *= flip[j % 3];
+        p_box->data.p_tkhd->i_flip = 1;
+    }
+
     scale[0] = sqrt(conv_fx(matrix[0]) * conv_fx(matrix[0]) +
                     conv_fx(matrix[3]) * conv_fx(matrix[3]));
     scale[1] = sqrt(conv_fx(matrix[1]) * conv_fx(matrix[1]) +
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index bfab16515f70..dd3082d66ae1 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -509,6 +509,7 @@ typedef struct MP4_Box_data_tkhd_s
     int32_t  i_width;
     int32_t  i_height;
     float    f_rotation;
+    int      i_flip;
 
 } MP4_Box_data_tkhd_t;
 
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index a5178d860f2d..908890183bf9 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -3367,6 +3367,7 @@ static void MP4_TrackSetup( demux_t *p_demux, mp4_track_t *p_track,
     p_track->i_width = BOXDATA(p_tkhd)->i_width / BLOCK16x16;
     p_track->i_height = BOXDATA(p_tkhd)->i_height / BLOCK16x16;
     p_track->f_rotation = BOXDATA(p_tkhd)->f_rotation;
+    p_track->i_flip = BOXDATA(p_tkhd)->i_flip;
 
     /* FIXME: unhandled box: tref */
 
diff --git a/modules/demux/mp4/mp4.h b/modules/demux/mp4/mp4.h
index b7c6cdf3d718..d2855246a324 100644
--- a/modules/demux/mp4/mp4.h
+++ b/modules/demux/mp4/mp4.h
@@ -99,6 +99,7 @@ typedef struct
     int i_width;
     int i_height;
     float f_rotation;
+    int i_flip;
 
     /* more internal data */
     uint32_t        i_timescale;    /* time scale for this track only */
-- 
GitLab


From 3588386593e7d808e2a1305790989debec5d9930 Mon Sep 17 00:00:00 2001
From: Francois Cartegnie <fcvlcdev@free.fr>
Date: Fri, 3 May 2019 12:58:31 +0200
Subject: [PATCH 2/6] demux: mp4: remove junk debug

---
 modules/demux/mp4/essetup.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/modules/demux/mp4/essetup.c b/modules/demux/mp4/essetup.c
index da14800c95d0..a1be66f55614 100644
--- a/modules/demux/mp4/essetup.c
+++ b/modules/demux/mp4/essetup.c
@@ -293,7 +293,6 @@ int SetupVideoES( demux_t *p_demux, mp4_track_t *p_track, MP4_Box_t *p_sample )
 
     /* Flip, unless already flipped */
     if (p_track->i_flip == 1 && (int)p_track->f_rotation != 180) {
-    fprintf(stderr, "p_track->f_rotation %f flip %d\n", p_track->f_rotation, p_track->i_flip);
         video_transform_t transform = (video_transform_t)p_track->fmt.video.orientation;
         /* Flip first then rotate */
         p_track->fmt.video.orientation = ORIENT_HFLIPPED;
-- 
GitLab


From 6ce6acef9c881adeb8f42b1126ba79e4d082e815 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= <remi@remlab.net>
Date: Sat, 2 Mar 2019 21:29:43 +0200
Subject: [PATCH 3/6] mp4: remove unused variable

---
 modules/demux/mp4/libmp4.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index b76e46493ca8..0f5e91fd40c3 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -1227,7 +1227,6 @@ static int MP4_ReadBox_tkhd(  stream_t *p_stream, MP4_Box_t *p_box )
     double scale[2];    // scale factor; sx = scale[0] , sy = scale[1]
     int32_t *matrix = p_box->data.p_tkhd->i_matrix;
 
-    int32_t fmatrix[9];
     int64_t det = (int64_t)matrix[0] * matrix[4] - (int64_t)matrix[1] * matrix[3];
     if (det < 0) {
         /* If determinant is negative copy the matrix and flip it horizontally. */
-- 
GitLab


From 36ffb136bdc861ba648ee54afe031bfdf9db9a2d Mon Sep 17 00:00:00 2001
From: Alexandre Janniaux <ajanni@videolabs.io>
Date: Mon, 19 Jun 2023 08:47:04 +0200
Subject: [PATCH 4/6] misc: es_format: set orientation during setup

During video_format_Setup(), the size, visible size and source aspect
ratio is defined for the given video_format_t instance, but those values
only make sense for a given orientation. Transforming the picture would
mean transform the coordinates, as seen in video_format_TransformBy().

To ensure the correct behaviour is found when transforming after the
setup, initialize the orientation to ORIENT_NORMAL as well.
---
 src/misc/es_format.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/misc/es_format.c b/src/misc/es_format.c
index c2a09132d1b3..63f5584ef02d 100644
--- a/src/misc/es_format.c
+++ b/src/misc/es_format.c
@@ -142,6 +142,7 @@ void video_format_Setup( video_format_t *p_fmt, vlc_fourcc_t i_chroma,
     p_fmt->i_visible_height = i_visible_height;
     p_fmt->i_x_offset       =
     p_fmt->i_y_offset       = 0;
+    p_fmt->orientation      = ORIENT_NORMAL;
     vlc_ureduce( &p_fmt->i_sar_num, &p_fmt->i_sar_den,
                  i_sar_num, i_sar_den, 0 );
 
-- 
GitLab


From a005050c3c8dca263bbdcf8076788b95213fbe3b Mon Sep 17 00:00:00 2001
From: Alexandre Janniaux <ajanni@videolabs.io>
Date: Fri, 16 Jun 2023 18:07:35 +0200
Subject: [PATCH 5/6] test: opengl: add test for filters

This test is able to use any offscreen opengl implementation available
to run the opengl filters engine on both GL Core and GL ES, and will
skip the test for one of those targets if no implementations are
available.

It currently mainly smoke-test the filters engine, while checking that
orientation handling is correct, and uses glReadPixels to check the
resulting rendered picture in a multi-platform way.
---
 test/Makefile.am                           |  75 ++++++
 test/modules/video_output/opengl/filters.c | 300 +++++++++++++++++++++
 2 files changed, 375 insertions(+)
 create mode 100644 test/modules/video_output/opengl/filters.c

diff --git a/test/Makefile.am b/test/Makefile.am
index c2b0d082c9b0..c9eaa59d2b6d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -36,6 +36,15 @@ check_PROGRAMS = \
 if ENABLE_SOUT
 check_PROGRAMS += test_modules_tls
 endif
+
+if HAVE_GL
+check_PROGRAMS += test_modules_video_output_opengl_filters
+endif
+
+if HAVE_GLES2
+check_PROGRAMS += test_modules_video_output_opengl_es2_filters
+endif
+
 if UPDATE_CHECK
 check_PROGRAMS += test_src_crypto_update
 endif
@@ -130,6 +139,72 @@ test_modules_keystore_SOURCES = modules/keystore/test.c
 test_modules_keystore_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_modules_tls_SOURCES = modules/misc/tls.c
 test_modules_tls_LDADD = $(LIBVLCCORE) $(LIBVLC)
+<<<<<<< HEAD
+=======
+test_modules_demux_timestamps_filter_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_modules_demux_timestamps_filter_SOURCES = modules/demux/timestamps_filter.c
+test_modules_demux_ts_pes_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_modules_demux_ts_pes_SOURCES = modules/demux/ts_pes.c \
+				../modules/demux/mpeg/ts_pes.c \
+				../modules/demux/mpeg/ts_pes.h
+test_modules_playlist_m3u_SOURCES = modules/demux/playlist/m3u.c
+test_modules_playlist_m3u_LDADD = $(LIBVLCCORE) $(LIBVLC)
+
+test_modules_codec_hxxx_helper_SOURCES = modules/codec/hxxx_helper.c \
+                                      ../modules/codec/hxxx_helper.c \
+                                      ../modules/packetizer/hxxx_nal.c \
+                                      ../modules/packetizer/h264_slice.c \
+                                      ../modules/packetizer/h264_nal.c \
+                                      ../modules/packetizer/hevc_nal.c
+test_modules_codec_hxxx_helper_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_modules_video_output_opengl_filters_SOURCES = \
+	modules/video_output/opengl/filters.c \
+	../modules/video_output/opengl/filters.c \
+	../modules/video_output/opengl/filters.h \
+	../modules/video_output/opengl/filter.c \
+	../modules/video_output/opengl/gl_api.c \
+	../modules/video_output/opengl/gl_api.h \
+	../modules/video_output/opengl/interop.c \
+	../modules/video_output/opengl/interop.h \
+	../modules/video_output/opengl/importer.c \
+	../modules/video_output/opengl/importer.h
+test_modules_video_output_opengl_filters_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_modules_video_output_opengl_filters_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_TEST_OPENGL_API=VLC_OPENGL
+test_modules_video_output_opengl_es2_filters_SOURCES = $(test_modules_video_output_opengl_filters_SOURCES)
+test_modules_video_output_opengl_es2_filters_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_modules_video_output_opengl_es2_filters_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_TEST_OPENGL_API=VLC_OPENGL_ES2
+
+
+test_src_video_output_SOURCES = \
+	src/video_output/video_output.c \
+	src/video_output/video_output.h \
+	src/video_output/video_output_scenarios.c
+test_src_video_output_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_src_video_output_opengl_SOURCES = src/video_output/opengl.c
+test_src_video_output_opengl_LDADD = $(LIBVLCCORE) $(LIBVLC)
+
+test_modules_stream_out_transcode_SOURCES = \
+	modules/stream_out/transcode.c \
+	modules/stream_out/transcode.h \
+	modules/stream_out/transcode_scenarios.c
+test_modules_stream_out_transcode_LDADD = $(LIBVLCCORE) $(LIBVLC)
+
+test_modules_stream_out_pcr_sync_SOURCES = modules/stream_out/pcr_sync.c \
+	../modules/stream_out/transcode/pcr_sync.c \
+	../modules/stream_out/transcode/pcr_sync.h \
+	../modules/stream_out/transcode/pcr_helper.h \
+	../modules/stream_out/transcode/pcr_helper.c
+test_modules_stream_out_pcr_sync_LDADD = $(LIBVLCCORE)
+
+test_src_input_decoder_SOURCES = \
+	src/input/decoder/input_decoder.c \
+	src/input/decoder/input_decoder.h \
+	src/input/decoder/input_decoder_scenarios.c
+test_src_input_decoder_LDADD = $(LIBVLCCORE) $(LIBVLC)
+
+test_src_misc_image_SOURCES = src/misc/image.c
+test_src_misc_image_LDADD = $(LIBVLCCORE) $(LIBVLC)
+>>>>>>> 8ae846de79 (test: opengl: add test for filters)
 
 checkall:
 	$(MAKE) check_PROGRAMS="$(check_PROGRAMS) $(EXTRA_PROGRAMS)" check
diff --git a/test/modules/video_output/opengl/filters.c b/test/modules/video_output/opengl/filters.c
new file mode 100644
index 000000000000..f8647fd5a8b1
--- /dev/null
+++ b/test/modules/video_output/opengl/filters.c
@@ -0,0 +1,300 @@
+/*****************************************************************************
+ * opengl.c: test for the OpenGL client code
+ *****************************************************************************
+ * Copyright (C) 2023 VideoLabs
+ *
+ * Authors: Alexandre Janniaux <ajanni@videolabs.io>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef VLC_TEST_OPENGL_API
+# error "Define VLC_TEST_OPENGL_API to the VLC_OPENGL API to use"
+#endif
+
+/* Define a builtin module for mocked parts */
+#define MODULE_NAME test_opengl
+#undef VLC_DYNAMIC_PLUGIN
+
+#include "../../../libvlc/test.h"
+#include "../../../lib/libvlc_internal.h"
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_opengl.h>
+#include <vlc_filter.h>
+#include <vlc_modules.h>
+#include <vlc_vout_display.h>
+
+#include "../../../modules/video_output/opengl/filters.h"
+#include "../../../modules/video_output/opengl/gl_api.h"
+
+static_assert(
+    VLC_TEST_OPENGL_API == VLC_OPENGL ||
+    VLC_TEST_OPENGL_API == VLC_OPENGL_ES2);
+
+const char vlc_module_name[] = MODULE_STRING;
+static const uint8_t green[] = { 0x0, 0xff, 0x00, 0xff };
+static const uint8_t red[] = { 0xff, 0x0, 0x0, 0xff };
+static const uint8_t blue[] = { 0x00, 0x0, 0xff, 0xff };
+
+struct test_point
+{
+    int x, y;
+    const uint8_t *color;
+};
+
+static void test_opengl_offscreen(
+        vlc_object_t *root,
+        video_orientation_t orientation,
+        struct test_point *points,
+        size_t points_count
+){
+    struct vlc_decoder_device *device =
+        vlc_decoder_device_Create(root, NULL);
+    vlc_gl_t *gl = vlc_gl_CreateOffscreen(
+            root, device, 3, 3, VLC_TEST_OPENGL_API, NULL, NULL);
+    assert(gl != NULL);
+    if (device != NULL)
+        vlc_decoder_device_Release(device);
+
+    int ret = vlc_gl_MakeCurrent(gl);
+    assert(ret == VLC_SUCCESS);
+
+    struct vlc_gl_api api;
+    ret = vlc_gl_api_Init(&api, gl);
+    assert(ret == VLC_SUCCESS);
+
+    GLuint out_tex;
+    api.vt.GenTextures(1, &out_tex);
+    api.vt.BindTexture(GL_TEXTURE_2D, out_tex);
+    api.vt.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    api.vt.BindTexture(GL_TEXTURE_2D, 0);
+
+    GLuint out_fb;
+    api.vt.GenFramebuffers(1, &out_fb);
+    api.vt.BindFramebuffer(GL_FRAMEBUFFER, out_fb);
+    api.vt.BindFramebuffer(GL_READ_FRAMEBUFFER, out_fb);
+    api.vt.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                GL_TEXTURE_2D, out_tex, 0);
+
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    video_format_t fmt;
+    video_format_Setup(&fmt, VLC_CODEC_RGBA, 3, 3, 3, 3, 1, 1);
+    fmt.primaries = COLOR_PRIMARIES_SRGB;
+    fmt.space = COLOR_SPACE_SRGB;
+    fmt.transfer = TRANSFER_FUNC_SRGB;
+    fmt.projection_mode = PROJECTION_MODE_RECTANGULAR;
+
+    struct vlc_gl_interop *interop =
+        vlc_gl_interop_New(gl, NULL, &fmt);
+    assert(interop != NULL);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    GLint fbo_binding;
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+
+    struct vlc_gl_filters *filters =
+        vlc_gl_filters_New(gl, &api, interop, orientation);
+    assert(filters != NULL);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+
+    struct vlc_gl_filter *filter =
+        vlc_gl_filters_Append(filters, "renderer", NULL);
+    assert(filter != NULL);
+    GL_ASSERT_NOERROR(&api.vt);
+    assert((GLuint)fbo_binding == out_fb);
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+    (void)filter;
+
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+
+    ret = vlc_gl_filters_InitFramebuffers(filters);
+    assert(ret == VLC_SUCCESS);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+
+    vlc_gl_filters_SetViewport(filters, 0, 0, 3, 3);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    vlc_gl_filters_SetOutputSize(filters, 3, 3);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    picture_t *picture = picture_NewFromFormat(&fmt);
+    assert(picture != NULL);
+
+    size_t size = picture->p[0].i_lines * picture->p[0].i_pitch / picture->p[0].i_pixel_pitch;
+    for (size_t i=0; i < size; ++i)
+        memcpy(&picture->p[0].p_pixels[i * 4], green, sizeof(green));
+
+    memcpy(&picture->p[0].p_pixels[0 * 4], red, sizeof(red));
+    memcpy(&picture->p[0].p_pixels[2 * 4], blue, sizeof(blue));
+
+    ret = vlc_gl_filters_UpdatePicture(filters, picture);
+    assert(ret == VLC_SUCCESS);
+    GL_ASSERT_NOERROR(&api.vt);
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+
+    ret = vlc_gl_filters_Draw(filters);
+    assert(ret == VLC_SUCCESS);
+    GL_ASSERT_NOERROR(&api.vt);
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+
+    api.vt.Finish();
+    GL_ASSERT_NOERROR(&api.vt);
+
+    /* Disable pixel packing to use glReadPixels. */
+    api.vt.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    uint8_t pixel[4];
+
+    fprintf(stderr, "Results (vertically flipped):\n");
+    for (size_t i = 0; i < 3; ++i)
+    {
+        for (size_t j = 0; j < 3; ++j)
+        {
+            api.vt.ReadPixels(j, i, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+            fprintf(stderr, "    %u:%u:%u:%u", pixel[0], pixel[1], pixel[2], pixel[3]);
+        }
+        fprintf(stderr, "\n");
+    }
+
+    for (size_t i = 0; i < points_count; ++i)
+    {
+        api.vt.ReadPixels(points[i].x, points[i].y, 1, 1, GL_RGBA,
+                          GL_UNSIGNED_BYTE, &pixel);
+        GL_ASSERT_NOERROR(&api.vt);
+        assert(memcmp(pixel, points[i].color, sizeof(pixel)) == 0);
+    }
+
+    vlc_gl_filters_Delete(filters);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    vlc_gl_interop_Delete(interop);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    vlc_gl_ReleaseCurrent(gl);
+    vlc_gl_Delete(gl);
+}
+
+int main( int argc, char **argv )
+{
+    (void)argc; (void)argv;
+    test_init();
+
+    const char * const vlc_argv[] = {
+        "-vvv", "--aout=dummy", "--text-renderer=dummy",
+    };
+
+    libvlc_instance_t *vlc = libvlc_new(ARRAY_SIZE(vlc_argv), vlc_argv);
+    vlc_object_t *root = &vlc->p_libvlc_int->obj;
+
+    const char *cap =
+        (VLC_TEST_OPENGL_API == VLC_OPENGL)     ? "opengl offscreen" :
+        (VLC_TEST_OPENGL_API == VLC_OPENGL_ES2) ? "opengl es2 offscreen" :
+        NULL;
+    assert(cap != NULL);
+
+    fprintf(stderr, "Looking for cap %s\n", cap);
+
+    module_t **providers;
+    size_t strict_matches;
+    ssize_t provider_available = vlc_module_match(
+            cap, NULL, false, &providers, &strict_matches);
+    (void)strict_matches;
+    free(providers);
+
+    if (provider_available <= 0)
+    {
+        libvlc_release(vlc);
+        return 77;
+    }
+
+    struct vlc_decoder_device *device =
+        vlc_decoder_device_Create(root, NULL);
+    vlc_gl_t *gl = vlc_gl_CreateOffscreen(
+            root, device, 3, 3, VLC_TEST_OPENGL_API, NULL, NULL);
+    if (device != NULL)
+        vlc_decoder_device_Release(device);
+
+    if (gl == NULL)
+    {
+        libvlc_release(vlc);
+        return 77;
+    }
+    vlc_gl_Delete(gl);
+
+    struct test_point points_normal[] = {
+        { 1, 1, green },
+        { 0, 2, red },
+        { 2, 2, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_NORMAL,
+                          points_normal, ARRAY_SIZE(points_normal));
+
+    struct test_point points_rotated_90[] = {
+        { 1, 1, green },
+        { 0, 0, red },
+        { 0, 2, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_ROTATED_90,
+                          points_rotated_90, ARRAY_SIZE(points_rotated_90));
+
+    struct test_point points_rotated_180[] = {
+        { 1, 1, green },
+        { 2, 0, red },
+        { 0, 0, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_ROTATED_180,
+                          points_rotated_180, ARRAY_SIZE(points_rotated_180));
+
+    struct test_point points_rotated_270[] = {
+        { 1, 1, green },
+        { 2, 2, red },
+        { 2, 0, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_ROTATED_270,
+                          points_rotated_270, ARRAY_SIZE(points_rotated_270));
+
+
+    libvlc_release(vlc);
+    return 0;
+}
-- 
GitLab


From 7e05d83dce93371c1a26ac33a5955a1bb98f88f2 Mon Sep 17 00:00:00 2001
From: Alexandre Janniaux <ajanni@videolabs.io>
Date: Tue, 20 Jun 2023 22:54:57 +0200
Subject: [PATCH 6/6] opengl: test mirrored orientation

Test the different missing orientation:

 - ORIENT_TRANSPOSED is ORIENT_ROTATED_270 + HFLIP
 - ORIENT_ANTITRANSPOSED is ORIENT_ROTATED_90 + HFLIP
 - ORIENT_HFLIP is ORIENT_NORMAL + HFLIP
 - ORIENT_VFLIP is ORIENT_ROTATED_180 + HFLIP
---
 test/modules/video_output/opengl/filters.c | 33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/test/modules/video_output/opengl/filters.c b/test/modules/video_output/opengl/filters.c
index f8647fd5a8b1..4cf04cbd0ac5 100644
--- a/test/modules/video_output/opengl/filters.c
+++ b/test/modules/video_output/opengl/filters.c
@@ -294,6 +294,39 @@ int main( int argc, char **argv )
     test_opengl_offscreen(root, ORIENT_ROTATED_270,
                           points_rotated_270, ARRAY_SIZE(points_rotated_270));
 
+    struct test_point points_hflip[] = {
+        { 1, 1, green },
+        { 2, 2, red },
+        { 0, 2, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_HFLIPPED,
+                          points_hflip, ARRAY_SIZE(points_hflip));
+
+    struct test_point points_vflip[] = {
+        { 1, 1, green },
+        { 0, 0, red },
+        { 2, 0, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_VFLIPPED,
+                          points_vflip, ARRAY_SIZE(points_vflip));
+
+    struct test_point points_transposed[] = {
+        { 1, 1, green },
+        { 2, 0, red },
+        { 2, 2, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_TRANSPOSED,
+                          points_transposed, ARRAY_SIZE(points_transposed));
+
+    struct test_point points_antitransposed[] = {
+        { 1, 1, green },
+        { 0, 2, red },
+        { 0, 0, blue },
+    };
+    test_opengl_offscreen(root, ORIENT_ANTI_TRANSPOSED,
+                          points_antitransposed, ARRAY_SIZE(points_antitransposed));
+
+
 
     libvlc_release(vlc);
     return 0;
-- 
GitLab