[vlc-commits] [Git][videolan/vlc][master] 7 commits: vlc_vout: add a MAX value for stereoscopic enum

Alexandre Janniaux (@alexandre-janniaux) gitlab at videolan.org
Wed Mar 26 10:47:08 UTC 2025



Alexandre Janniaux pushed to branch master at VideoLAN / VLC


Commits:
aed3d7bb by Alexandre Janniaux at 2025-03-26T10:32:14+00:00
vlc_vout: add a MAX value for stereoscopic enum

The MAX value allows checking whether the provided stereoscopic value is
valid or not.

- - - - -
93092b6c by Alexandre Janniaux at 2025-03-26T10:32:14+00:00
opengl: renderer: add support for video-stereo-mode

The video-stereo-mode is setup the same way I did the projection mode.
The client needs to restart the renderer to re-compile the shaders and
re-setup the variables for the mode, avoiding the need for a specific
API. This is justified by changing video-stereo-mode not happening at
each frame.

Note that projection_mode is temporarily enforced to
PROJECTION_MODE_RECTANGULAR whenever the multiview_mode is enforced to
another value than the source, to avoid trying to change the projection
from a texture containing the two eyes, leading to weird behaviour. This
happens when setting the SIDE_BY_SIDE stereoscopic mode which is made
for showing the two frames, but also in the STEREO stereoscopic mode
which is not yet supported in the module (need vlc-vr work).

- - - - -
0db936f2 by Alexandre Janniaux at 2025-03-26T10:32:14+00:00
opengl: vout helper: factor renderer restarting code

Create a dedicated function to restart the renderer given a set of
parameters. The function will also be used to change the
video-stereo-mode value in the renderer.

- - - - -
fb7d451d by Alexandre Janniaux at 2025-03-26T10:32:14+00:00
opengl: vout helper: store first projection state

The first projection state will be needed when changing the stereo-mode
in future commits.

- - - - -
37e222f6 by Alexandre Janniaux at 2025-03-26T10:32:14+00:00
opengl: vout helper: add support for changing video-stereo-mode

- - - - -
0902aed2 by Alexandre Janniaux at 2025-03-26T10:32:14+00:00
opengl: display: add support for set_stereo callback

Just like it's done for projection_mode, setup a state so that changing
the stereo mode can be asynchronously done when the rendering loop is
ready to provide the OpenGL context.

- - - - -
013a7c33 by Alexandre Janniaux at 2025-03-26T10:32:14+00:00
opengl: renderer: remove vout_helper.h include

- - - - -


6 changed files:

- include/vlc_vout.h
- modules/video_output/opengl/display.c
- modules/video_output/opengl/renderer.c
- modules/video_output/opengl/renderer.h
- modules/video_output/opengl/vout_helper.c
- modules/video_output/opengl/vout_helper.h


Changes:

=====================================
include/vlc_vout.h
=====================================
@@ -94,6 +94,7 @@ typedef enum vlc_stereoscopic_mode_t
     VIDEO_STEREO_OUTPUT_LEFT_ONLY,
     VIDEO_STEREO_OUTPUT_RIGHT_ONLY,
     VIDEO_STEREO_OUTPUT_SIDE_BY_SIDE,
+#define VIDEO_STEREO_OUTPUT_MAX VIDEO_STEREO_OUTPUT_SIDE_BY_SIDE
 } vlc_stereoscopic_mode_t;
 
 /*****************************************************************************


=====================================
modules/video_output/opengl/display.c
=====================================
@@ -80,6 +80,11 @@ typedef struct vout_display_sys_t
     bool is_dirty;
     bool restart_renderer;
 
+    struct {
+        vlc_stereoscopic_mode_t mode;
+        bool changed;
+    } stereo;
+
     struct {
         PFNGLFLUSHPROC Flush;
     } vt;
@@ -174,6 +179,15 @@ static int ChangeSourceProjection(vout_display_t *vd, video_projection_mode_t pr
     return VLC_SUCCESS;
 }
 
+static int SetStereoMode(vout_display_t *vd, vlc_stereoscopic_mode_t mode)
+{
+    vout_display_sys_t *sys = vd->sys;
+    UpdateConfig(vd);
+    sys->stereo.mode = mode;
+    sys->stereo.changed = true;
+    return VLC_SUCCESS;
+}
+
 static const struct vlc_display_operations ops = {
     .close = Close,
     .prepare = PictureRender,
@@ -182,6 +196,7 @@ static const struct vlc_display_operations ops = {
     .set_viewpoint = SetViewpoint,
     .update_format = UpdateFormat,
     .change_source_projection = ChangeSourceProjection,
+    .set_stereo = SetStereoMode,
 };
 
 /**
@@ -237,6 +252,7 @@ static int Open(vout_display_t *vd,
     struct vout_display_placement dp = vd->cfg->display;
     PlacePicture(vd, &sys->place, dp);
     sys->place_changed = true;
+    sys->stereo.changed = false;
     vlc_gl_Resize (sys->gl, vd->cfg->display.width, vd->cfg->display.height);
 
     /* Initialize video display */
@@ -298,6 +314,12 @@ static void PictureRender (vout_display_t *vd, picture_t *pic,
 
     if (vlc_gl_MakeCurrent (sys->gl) == VLC_SUCCESS)
     {
+        if (sys->stereo.changed)
+        {
+            vout_display_opengl_ChangeStereoMode(sys->vgl, sys->stereo.mode);
+            sys->stereo.changed = false;
+        }
+
         if (sys->restart_renderer)
         {
             vout_display_opengl_ChangeProjection(sys->vgl, vd->cfg->projection);


=====================================
modules/video_output/opengl/renderer.c
=====================================
@@ -41,7 +41,6 @@
 #include <vlc_configuration.h>
 
 #include "gl_util.h"
-#include "vout_helper.h"
 #include "sampler.h"
 #include "picture.h"
 
@@ -80,8 +79,9 @@ static void getProjectionMatrix(float sar, float fovy, GLfloat matrix[static 16]
 static void getViewpointMatrixes(struct vlc_gl_renderer *renderer,
                                  video_projection_mode_t projection_mode)
 {
-    if (projection_mode == PROJECTION_MODE_EQUIRECTANGULAR
+    if ((projection_mode == PROJECTION_MODE_EQUIRECTANGULAR
         || projection_mode == PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD)
+        && renderer->multiview_mode == renderer->sampler->glfmt.fmt.multiview_mode)
     {
         getProjectionMatrix(renderer->f_sar, renderer->f_fovy,
                             renderer->var.ProjectionMatrix);
@@ -104,6 +104,7 @@ static void getViewpointMatrixes(struct vlc_gl_renderer *renderer,
 
 static void
 InitStereoMatrix(GLfloat matrix_out[static 3*3],
+                 vlc_stereoscopic_mode_t stereo_mode,
                  video_multiview_mode_t multiview_mode)
 {
     /*
@@ -112,10 +113,6 @@ InitStereoMatrix(GLfloat matrix_out[static 3*3],
      *
      * This 2D transformation is affine, so the matrix is 3x3 and applies to 3D
      * vectors in the form (x, y, 1).
-     *
-     * Note that since for now, we always crop the left eye, in practice the
-     * offset is always 0, so the transform is actually linear (a 2x2 matrix
-     * would be sufficient).
      */
 
     memcpy(matrix_out, MATRIX3_IDENTITY, sizeof(MATRIX3_IDENTITY));
@@ -123,6 +120,11 @@ InitStereoMatrix(GLfloat matrix_out[static 3*3],
 #define COL(x) (x*3)
 #define ROW(x) (x)
 
+    if (stereo_mode == VIDEO_STEREO_OUTPUT_SIDE_BY_SIDE)
+        return;
+    assert(stereo_mode == VIDEO_STEREO_OUTPUT_LEFT_ONLY ||
+           stereo_mode == VIDEO_STEREO_OUTPUT_RIGHT_ONLY);
+
     switch (multiview_mode)
     {
         case MULTIVIEW_STEREO_SBS:
@@ -142,6 +144,8 @@ InitStereoMatrix(GLfloat matrix_out[static 3*3],
              *            \ 0    0    1 /
              */
             matrix_out[COL(0) + ROW(0)] = 0.5;
+            if (stereo_mode == VIDEO_STEREO_OUTPUT_RIGHT_ONLY)
+                matrix_out[COL(2) + ROW(0)] = 0.5;
             break;
         case MULTIVIEW_STEREO_TB:
             /*
@@ -165,6 +169,8 @@ InitStereoMatrix(GLfloat matrix_out[static 3*3],
              *            \ 0    0    1 /
              */
             matrix_out[COL(1) + ROW(1)] = 0.5;
+            if (stereo_mode == VIDEO_STEREO_OUTPUT_RIGHT_ONLY)
+                matrix_out[COL(2) + ROW(1)] = 0.5;
             break;
         default:
             break;
@@ -673,8 +679,12 @@ static int SetupCoords(struct vlc_gl_renderer *renderer,
     GLushort *indices;
     unsigned nbVertices, nbIndices;
 
+    video_projection_mode_t projection_mode = renderer->projection_mode;
+    if (renderer->multiview_mode != renderer->sampler->glfmt.fmt.multiview_mode)
+        projection_mode = PROJECTION_MODE_RECTANGULAR;
+
     int i_ret;
-    switch (renderer->projection_mode)
+    switch (projection_mode)
     {
     case PROJECTION_MODE_RECTANGULAR:
         i_ret = BuildRectangle(&vertexCoord, &textureCoord, &nbVertices,
@@ -798,7 +808,7 @@ vlc_gl_renderer_Open(struct vlc_gl_filter *filter,
 {
     (void) size_out;
 
-    const char * const options[] = { "projection-mode", NULL };
+    const char * const options[] = { "projection-mode", "video-stereo-mode", NULL };
     config_ChainParse(filter, "", options, config);
 
     const opengl_vtable_t *vt = &filter->api->vt;
@@ -844,6 +854,33 @@ vlc_gl_renderer_Open(struct vlc_gl_filter *filter,
             break;
     }
 
+    int stereo_mode = var_InheritInteger(filter, "video-stereo-mode");
+    if (stereo_mode > VIDEO_STEREO_OUTPUT_AUTO && stereo_mode <= VIDEO_STEREO_OUTPUT_MAX)
+        renderer->stereo_mode = stereo_mode;
+
+    if (sampler->glfmt.fmt.multiview_mode == MULTIVIEW_2D)
+    {
+        renderer->stereo_mode = VIDEO_STEREO_OUTPUT_SIDE_BY_SIDE;
+        renderer->multiview_mode = MULTIVIEW_2D;
+    }
+    else switch (stereo_mode)
+    {
+        case VIDEO_STEREO_OUTPUT_LEFT_ONLY:
+        case VIDEO_STEREO_OUTPUT_RIGHT_ONLY:
+        case VIDEO_STEREO_OUTPUT_AUTO:
+            /* multiview_mode != MULTIVIEW_2D */
+            renderer->multiview_mode = sampler->glfmt.fmt.multiview_mode;
+            if (stereo_mode == VIDEO_STEREO_OUTPUT_AUTO)
+                renderer->stereo_mode = VIDEO_STEREO_OUTPUT_LEFT_ONLY;
+            break;
+        case VIDEO_STEREO_OUTPUT_SIDE_BY_SIDE:
+        case VIDEO_STEREO_OUTPUT_STEREO: /* stereo mode is not supported yet */
+        default:
+            renderer->multiview_mode = MULTIVIEW_2D; /* Enforce the planar view */
+            renderer->stereo_mode = VIDEO_STEREO_OUTPUT_SIDE_BY_SIDE;
+            break;
+    }
+
     int ret = opengl_link_program(filter);
     if (ret != VLC_SUCCESS)
     {
@@ -852,10 +889,9 @@ vlc_gl_renderer_Open(struct vlc_gl_filter *filter,
         return ret;
     }
 
-    const video_format_t *fmt = &sampler->glfmt.fmt;
-    InitStereoMatrix(renderer->var.StereoMatrix, fmt->multiview_mode);
+    InitStereoMatrix(renderer->var.StereoMatrix, renderer->stereo_mode, renderer->multiview_mode);
 
-    getViewpointMatrixes(renderer, fmt->projection_mode);
+    getViewpointMatrixes(renderer, renderer->projection_mode);
 
     vt->GenBuffers(1, &renderer->vertex_buffer_object);
     vt->GenBuffers(1, &renderer->index_buffer_object);


=====================================
modules/video_output/opengl/renderer.h
=====================================
@@ -104,6 +104,8 @@ struct vlc_gl_renderer
 
     /* Projection mode for the input data */
     video_projection_mode_t projection_mode;
+    vlc_stereoscopic_mode_t stereo_mode;
+    video_multiview_mode_t multiview_mode;
 };
 
 vlc_gl_filter_open_fn vlc_gl_renderer_Open;


=====================================
modules/video_output/opengl/vout_helper.c
=====================================
@@ -65,6 +65,7 @@ struct vout_display_opengl_t {
 
     vlc_viewpoint_t viewpoint;
     video_projection_mode_t projection;
+    vlc_stereoscopic_mode_t stereo_mode;
 };
 
 static const vlc_fourcc_t gl_subpicture_chromas[] = {
@@ -180,22 +181,46 @@ error:
     return NULL;
 }
 
-int vout_display_opengl_ChangeProjection(vout_display_opengl_t *vgl,
-                                         video_projection_mode_t projection)
+struct renderer_config
+{
+    video_projection_mode_t projection;
+    vlc_stereoscopic_mode_t stereo_mode;
+};
+
+static int RestartRenderer(vout_display_opengl_t *vgl,
+                           const struct renderer_config *config)
 {
-    const config_chain_t chain = {
+    config_chain_t chain_projection = {
         .psz_name = strdup("projection-mode"),
-        .psz_value = strdup(projection == PROJECTION_MODE_RECTANGULAR ? "0" : "-1"),
+        .psz_value = strdup(config->projection == PROJECTION_MODE_RECTANGULAR ? "0" : "-1"),
+    };
+
+    config_chain_t chain_stereo = {
+        .psz_name = strdup("video-stereo-mode"),
+        .p_next = &chain_projection,
     };
+    if (chain_projection.psz_name == NULL ||
+        chain_projection.psz_value == NULL ||
+        chain_stereo.psz_name == NULL ||
+        asprintf(&chain_stereo.psz_value, "%d", (int)config->stereo_mode) == -1)
+    {
+        free(chain_projection.psz_name);
+        free(chain_projection.psz_value);
+        free(chain_stereo.psz_name);
+        free(chain_stereo.psz_value);
+        return VLC_ENOMEM;
+    }
 
     struct vlc_gl_filter *new_renderer =
-        vlc_gl_filters_Replace(vgl->filters, vgl->renderer_filter, "renderer", &chain);
-    free(chain.psz_name);
-    free(chain.psz_value);
+        vlc_gl_filters_Replace(vgl->filters, vgl->renderer_filter, "renderer", &chain_stereo);
+    free(chain_projection.psz_name);
+    free(chain_projection.psz_value);
+    free(chain_stereo.psz_name);
+    free(chain_stereo.psz_value);
     if (new_renderer == NULL)
     {
-        msg_Err(vgl->gl, "Could not re-create renderer filter for projection mode %d",
-                (int)projection);
+        msg_Err(vgl->gl, "Could not re-create renderer filter for projection=%d stereo_mode=%d",
+                (int)config->projection, (int)config->stereo_mode);
         return VLC_EGENERIC;
     }
 
@@ -210,11 +235,41 @@ int vout_display_opengl_ChangeProjection(vout_display_opengl_t *vgl,
     vgl->renderer = new_renderer->sys;
 
     vlc_gl_renderer_SetViewpoint(vgl->renderer, &vgl->viewpoint);
+    return VLC_SUCCESS;
+}
 
+int vout_display_opengl_ChangeProjection(vout_display_opengl_t *vgl,
+                                         video_projection_mode_t projection)
+{
+    struct renderer_config config = {
+        .projection = projection,
+        .stereo_mode = vgl->stereo_mode,
+    };
+    int ret = RestartRenderer(vgl, &config);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    vgl->projection = projection;
     msg_Dbg(vgl->gl, "Changed to projection mode %d", projection);
     return VLC_SUCCESS;
 }
 
+int vout_display_opengl_ChangeStereoMode(vout_display_opengl_t *vgl,
+                                         vlc_stereoscopic_mode_t stereo_mode)
+{
+    struct renderer_config config = {
+        .projection = vgl->projection,
+        .stereo_mode = stereo_mode,
+    };
+    int ret = RestartRenderer(vgl, &config);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    vgl->stereo_mode = stereo_mode;
+    msg_Dbg(vgl->gl, "Changed to stereo mode %d", stereo_mode);
+    return VLC_SUCCESS;
+}
+
 vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
                                                const vlc_fourcc_t **subpicture_chromas,
                                                vlc_gl_t *gl,
@@ -293,6 +348,20 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
      && vout_display_opengl_SetViewpoint(vgl, viewpoint) != VLC_SUCCESS)
         msg_Err(gl, "Could not set viewpoint");
 
+    int projection_mode = var_InheritInteger(gl, "projection-mode");
+    if (projection_mode == PROJECTION_MODE_RECTANGULAR ||
+        projection_mode == PROJECTION_MODE_EQUIRECTANGULAR ||
+        projection_mode == PROJECTION_MODE_CUBEMAP_LAYOUT_STANDARD)
+        vgl->projection = projection_mode;
+    else
+        vgl->projection = fmt->projection_mode;
+
+    int stereo_mode = var_InheritInteger(gl, "video-stereo-mode");
+    if (stereo_mode > 0 && stereo_mode <= VIDEO_STEREO_OUTPUT_MAX)
+        vgl->stereo_mode = stereo_mode;
+    else
+        vgl->stereo_mode = VIDEO_STEREO_OUTPUT_AUTO;
+
     /* Forward to the core the changes to the input format requested by the
      * interop */
     video_format_Clean(fmt);


=====================================
modules/video_output/opengl/vout_helper.h
=====================================
@@ -90,4 +90,7 @@ int vout_display_opengl_UpdateFormat(vout_display_opengl_t *vgl,
 int vout_display_opengl_ChangeProjection(vout_display_opengl_t *vgl,
                                          video_projection_mode_t projection);
 
+int vout_display_opengl_ChangeStereoMode(vout_display_opengl_t *vgl,
+                                         vlc_stereoscopic_mode_t projection);
+
 #endif



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9cff68f0c37e42820b91b33d33f47827830c9b15...013a7c33605bc13aa269e182d81afe2ebe79e661

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9cff68f0c37e42820b91b33d33f47827830c9b15...013a7c33605bc13aa269e182d81afe2ebe79e661
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list