[vlc-commits] [Git][videolan/vlc][master] 4 commits: opengl: interop: hold video context

Steve Lhomme (@robUx4) gitlab at videolan.org
Tue Feb 14 11:57:53 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
0095945c by Romain Vimont at 2023-02-14T11:36:04+00:00
opengl: interop: hold video context

The video context must not be destroyed while the interop is alive.

- - - - -
e831af37 by Romain Vimont at 2023-02-14T11:36:04+00:00
vout: update format after filters

The vout is created first, based on the input format. Then filters
(filter_t) could be added, possibly producing pictures in a different
format.

      input ---> filters --->    MISMATCH    [I420] vout
            I420         RGBA

To avoid a mismatch between the output of the last filter and the
expected format of the vout input, a converter was added when necessary
to compensate:

      input ---> filters ---> converter ---> [I420] vout
            I420         RGBA           I420

But this was often a waste, and it caused problems for opaque formats.

Instead, request the vout to adapt itself to the actual format produced
by the last filter. If it can, we can avoid an additional converter.

      input ---> filters --->    MISMATCH    [I420] vout
            I420         RGBA

      input ---> filters ------------------> [RGBA] vout
            I420         RGBA

If the vout does not support the new format (or does not accept to
update its format), a converter is still added like before.

Co-authored-by: Alexandre Janniaux <ajanni at videolabs.io>

- - - - -
4da11af9 by Romain Vimont at 2023-02-14T11:36:04+00:00
vout: update format only if chroma changed alone

The core is not ready to support size changes via the "update format"
mechanism.

Attempt to update the vout format only when the only difference between
the old and new format is the chroma.

Refs #1021

- - - - -
adcec0ed by Romain Vimont at 2023-02-14T11:36:04+00:00
opengl: accept vout format change

If the core requests to change the vout format (because it added filters
having a different format), recreate the interop and the filters to
accept the new format without an additional converter.

- - - - -


10 changed files:

- include/vlc_vout_display.h
- modules/video_output/caopengllayer.m
- modules/video_output/macosx.m
- modules/video_output/opengl/display.c
- modules/video_output/opengl/interop.c
- modules/video_output/opengl/vout_helper.c
- modules/video_output/opengl/vout_helper.h
- src/video_output/display.c
- src/video_output/video_output.c
- src/video_output/vout_wrapper.h


Changes:

=====================================
include/vlc_vout_display.h
=====================================
@@ -320,6 +320,18 @@ struct vlc_display_operations
      * \param prof new ICC profile associated with display, or NULL for none
      */
     void       (*set_icc_profile)(vout_display_t *, const vlc_icc_profile_t *prof);
+
+    /**
+     * Notifies a change in the input format.
+     *
+     * The format size is not expected to change.
+     *
+     * \param fmt the requested input format
+     * \param ctx the video context
+     * \return VLC_SUCCESS on success, another value on error
+     */
+    int (*update_format)(vout_display_t *, const video_format_t *fmt,
+                         vlc_video_context *ctx);
 };
 
 struct vout_display_t {


=====================================
modules/video_output/caopengllayer.m
=====================================
@@ -180,7 +180,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *vp)
 }
 
 static const struct vlc_display_operations ops = {
-    Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint,
+    Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint, NULL,
 };
 
 /**


=====================================
modules/video_output/macosx.m
=====================================
@@ -135,7 +135,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *vp)
 }
 
 static const struct vlc_display_operations ops = {
-    Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint,
+    Close, PictureRender, PictureDisplay, Control, NULL, SetViewpoint, NULL,
 };
 
 static int Open (vout_display_t *vd,


=====================================
modules/video_output/opengl/display.c
=====================================
@@ -82,6 +82,7 @@ typedef struct vout_display_sys_t
     struct {
         PFNGLFLUSHPROC Flush;
     } vt;
+    vlc_viewpoint_t viewpoint;
 } vout_display_sys_t;
 
 /* Display callbacks */
@@ -92,7 +93,38 @@ static int Control (vout_display_t *, int);
 static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *vp)
 {
     vout_display_sys_t *sys = vd->sys;
-    return vout_display_opengl_SetViewpoint (sys->vgl, vp);
+    int ret = vout_display_opengl_SetViewpoint(sys->vgl, vp);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    sys->viewpoint = *vp;
+    return VLC_SUCCESS;
+}
+
+static int
+UpdateFormat(vout_display_t *vd, const video_format_t *fmt,
+             vlc_video_context *vctx)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    int ret = vlc_gl_MakeCurrent(sys->gl);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    ret = vout_display_opengl_UpdateFormat(sys->vgl, fmt, vctx);
+
+    /* Force to recompute the viewport on next picture */
+    sys->place_changed = true;
+
+    /* Restore viewpoint */
+    int vp_ret = vout_display_opengl_SetViewpoint(sys->vgl, &sys->viewpoint);
+    /* The viewpoint previously applied is necessarily valid */
+    assert(vp_ret == VLC_SUCCESS);
+    (void) vp_ret;
+
+    vlc_gl_ReleaseCurrent(sys->gl);
+
+    return ret;
 }
 
 static const struct vlc_display_operations ops = {
@@ -101,6 +133,7 @@ static const struct vlc_display_operations ops = {
     .display = PictureDisplay,
     .control = Control,
     .set_viewpoint = SetViewpoint,
+    .update_format = UpdateFormat,
 };
 
 static void
@@ -184,6 +217,8 @@ static int Open(vout_display_t *vd,
     if (sys->vgl == NULL)
         goto error;
 
+    vlc_viewpoint_init(&sys->viewpoint);
+
     vd->sys = sys;
     vd->info.subpicture_chromas = spu_chromas;
     vd->ops = &ops;


=====================================
modules/video_output/opengl/interop.c
=====================================
@@ -180,11 +180,13 @@ vlc_gl_interop_New(struct vlc_gl_t *gl, vlc_video_context *context,
     if (desc->plane_count == 0)
     {
         /* Opaque chroma: load a module to handle it */
-        interop->vctx = context;
+        assert(context);
+        interop->vctx = vlc_video_context_Hold(context);
         interop->module = module_need_var(interop, "glinterop", "glinterop");
     }
     else
     {
+        interop->vctx = NULL;
         interop->module = module_need(interop, "opengl sw interop", NULL, false);
     }
 
@@ -233,6 +235,8 @@ vlc_gl_interop_Delete(struct vlc_gl_interop *interop)
 {
     if (interop->ops && interop->ops->close)
         interop->ops->close(interop);
+    if (interop->vctx)
+        vlc_video_context_Release(interop->vctx);
     if (interop->module)
         module_unneed(interop, interop->module);
     vlc_object_delete(interop);


=====================================
modules/video_output/opengl/vout_helper.c
=====================================
@@ -275,6 +275,55 @@ free_vgl:
     return NULL;
 }
 
+int vout_display_opengl_UpdateFormat(vout_display_opengl_t *vgl,
+                                     const video_format_t *fmt,
+                                     vlc_video_context *vctx)
+{
+    /* If the format can't be changed, the state must remain valid to accept the
+     * initial format. */
+
+    vlc_gl_t *gl = vgl->gl;
+    const struct vlc_gl_api *api = &vgl->api;
+
+    assert(!fmt->p_palette);
+    video_format_t in_fmt = *fmt;
+
+    struct vlc_gl_interop *interop = vlc_gl_interop_New(gl, vctx, &in_fmt);
+    if (!interop)
+    {
+        msg_Err(gl, "Could not create interop");
+        return VLC_EGENERIC;
+    }
+
+    if (in_fmt.i_chroma != fmt->i_chroma)
+    {
+        msg_Warn(gl, "Could not update format, the interop changed the "
+                     "requested chroma from %4.4s to %4.4s\n",
+                     (char *) &fmt->i_chroma, (char *) &in_fmt.i_chroma);
+        vlc_gl_interop_Delete(interop);
+        return VLC_EGENERIC;
+    }
+
+    struct vlc_gl_renderer *renderer;
+    struct vlc_gl_filters *filters = CreateFilters(gl, api, interop, &renderer);
+    if (!filters)
+    {
+        vlc_gl_interop_Delete(interop);
+        return VLC_EGENERIC;
+    }
+
+    /* We created everything necessary, it worked, now the old ones could be
+     * replaced. */
+    vlc_gl_filters_Delete(vgl->filters);
+    vlc_gl_interop_Delete(vgl->interop);
+
+    vgl->interop = interop;
+    vgl->filters = filters;
+    vgl->renderer = renderer;
+
+    return VLC_SUCCESS;
+}
+
 void vout_display_opengl_Delete(vout_display_opengl_t *vgl)
 {
     const opengl_vtable_t *vt = &vgl->api.vt;


=====================================
modules/video_output/opengl/vout_helper.h
=====================================
@@ -82,4 +82,8 @@ int vout_display_opengl_Prepare(vout_display_opengl_t *vgl,
                                 picture_t *picture, subpicture_t *subpicture);
 int vout_display_opengl_Display(vout_display_opengl_t *vgl);
 
+int vout_display_opengl_UpdateFormat(vout_display_opengl_t *vgl,
+                                     const video_format_t *fmt,
+                                     vlc_video_context *vctx);
+
 #endif


=====================================
src/video_output/display.c
=====================================
@@ -639,6 +639,35 @@ void vout_SetDisplayIccProfile(vout_display_t *vd,
         vd->ops->set_icc_profile(vd, profile);
 }
 
+int vout_SetDisplayFormat(vout_display_t *vd, const video_format_t *fmt,
+                          vlc_video_context *vctx)
+{
+    if (!vd->ops->update_format)
+        return VLC_EGENERIC;
+
+    int ret = vd->ops->update_format(vd, fmt, vctx);
+    if (ret != VLC_SUCCESS)
+        return ret;
+
+    vout_display_priv_t *osys = container_of(vd, vout_display_priv_t, display);
+
+    /* Update source format */
+    assert(!fmt->p_palette);
+    video_format_Clean(&osys->source);
+    osys->source = *fmt;
+    if (vctx)
+        vlc_video_context_Hold(vctx);
+    if (osys->src_vctx)
+        vlc_video_context_Release(osys->src_vctx);
+    osys->src_vctx = vctx;
+
+    /* On update_format success, the vout display accepts the target format, so
+     * no display converters are needed. */
+    filter_chain_Clear(osys->converters);
+
+    return VLC_SUCCESS;
+}
+
 vout_display_t *vout_display_New(vlc_object_t *parent,
                                  const video_format_t *source,
                                  vlc_video_context *vctx,


=====================================
src/video_output/video_output.c
=====================================
@@ -869,13 +869,37 @@ static void ChangeFilters(vout_thread_sys_t *vout)
     }
 
     if (!es_format_IsSimilar(p_fmt_current, &fmt_target)) {
-        msg_Dbg(&vout->obj, "Adding a filter to compensate for format changes");
-        if (filter_chain_AppendConverter(sys->filter.chain_interactive,
-                                         &fmt_target) != 0) {
-            msg_Err(&vout->obj, "Failed to compensate for the format changes, removing all filters");
-            DelAllFilterCallbacks(vout);
-            filter_chain_Reset(sys->filter.chain_static,      &fmt_target, vctx_target, &fmt_target);
-            filter_chain_Reset(sys->filter.chain_interactive, &fmt_target, vctx_target, &fmt_target);
+        /* Shallow local copy */
+        es_format_t tmp = *p_fmt_current;
+        /* Assign the same chroma to compare everything except the chroma */
+        tmp.i_codec = fmt_target.i_codec;
+        tmp.video.i_chroma = fmt_target.video.i_chroma;
+
+        int ret = VLC_EGENERIC;
+
+        bool only_chroma_changed = es_format_IsSimilar(&tmp, &fmt_target);
+        if (only_chroma_changed)
+        {
+            msg_Dbg(&vout->obj, "Changing vout format to %4.4s",
+                                (const char *) &p_fmt_current->video.i_chroma);
+            /* Only the chroma changed, request the vout to update the format */
+            ret = vout_SetDisplayFormat(sys->display, &p_fmt_current->video,
+                                        vctx_current);
+            if (ret != VLC_SUCCESS)
+                msg_Dbg(&vout->obj, "Changing vout format to %4.4s failed",
+                        (const char *) &p_fmt_current->video.i_chroma);
+        }
+
+        if (ret != VLC_SUCCESS)
+        {
+            msg_Dbg(&vout->obj, "Adding a filter to compensate for format changes");
+            if (filter_chain_AppendConverter(sys->filter.chain_interactive,
+                                             &fmt_target) != 0) {
+                msg_Err(&vout->obj, "Failed to compensate for the format changes, removing all filters");
+                DelAllFilterCallbacks(vout);
+                filter_chain_Reset(sys->filter.chain_static,      &fmt_target, vctx_target, &fmt_target);
+                filter_chain_Reset(sys->filter.chain_interactive, &fmt_target, vctx_target, &fmt_target);
+            }
         }
     }
 


=====================================
src/video_output/vout_wrapper.h
=====================================
@@ -39,6 +39,8 @@ void vout_SetDisplayZoom(vout_display_t *, unsigned num, unsigned den);
 void vout_SetDisplayAspect(vout_display_t *, unsigned num, unsigned den);
 void vout_SetDisplayCrop(vout_display_t *, const struct vout_crop *);
 void vout_SetDisplayViewpoint(vout_display_t *, const vlc_viewpoint_t *);
+int vout_SetDisplayFormat(vout_display_t *, const video_format_t *fmt,
+                          vlc_video_context *vctx);
 
 /* The owner/caller is responsible for managing the lifetime of this ICC
  * profile and always updating the display state to a consistent value */



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b3ffbdb67d0f185f2995795527d24bb0f2bc3ba9...adcec0edcc143ede51b883fc6e931483f7f50033

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b3ffbdb67d0f185f2995795527d24bb0f2bc3ba9...adcec0edcc143ede51b883fc6e931483f7f50033
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