[vlc-commits] [Git][videolan/vlc][master] 4 commits: video_chroma: chain: refactor filter creation

François Cartegnie (@fcartegnie) gitlab at videolan.org
Sat Jan 21 13:32:48 UTC 2023



François Cartegnie pushed to branch master at VideoLAN / VLC


Commits:
422ea417 by Alexandre Janniaux at 2023-01-21T13:13:11+00:00
video_chroma: chain: refactor filter creation

- - - - -
cb07a077 by Alexandre Janniaux at 2023-01-21T13:13:11+00:00
video_chroma: chain: remove useless braces

- - - - -
352cc4c8 by Alexandre Janniaux at 2023-01-21T13:13:11+00:00
video_chroma: cvpx: forward the host filter to buffer new

Allocate a new picture by forwarding the host filter whenever the last
filter of the cvpx chain asked a new video buffer.

The host filter and last CVPX buffer are supposed to have the same
format, but the host filter might play a different role in its parent
filter chain than the requesting filter. In particular, filter chain
will try to detect the last filter, which can only work for filters
belonging to the chain.

Fix a crash when plugging a chain NV12->RV32 which creates first a
converter (cvpx) CVPX_NV12 -> CVPX_I420 -> I420 and then another
converter I420 -> RV32 filter, leading to the cvpx filter allocating
the wrong type of output frame.

Fixes #27721

- - - - -
782bf9ad by Alexandre Janniaux at 2023-01-21T13:13:11+00:00
test: add non-regression test for CVPX snapshot

Add a CVPX_NV12 -> png conversion test to ensure it doesn't crash.

Refs #27721

- - - - -


4 changed files:

- modules/video_chroma/chain.c
- modules/video_chroma/cvpx.c
- test/Makefile.am
- + test/src/misc/image_cvpx.c


Changes:

=====================================
modules/video_chroma/chain.c
=====================================
@@ -374,6 +374,7 @@ static int ChainMouse( filter_t *p_filter, vlc_mouse_t *p_mouse,
 static int BuildFilterChain( filter_t *p_filter )
 {
     es_format_t fmt_mid;
+    es_format_Init(&fmt_mid, p_filter->fmt_in.i_cat, p_filter->fmt_in.i_codec);
     int i_ret = VLC_EGENERIC;
 
     filter_sys_t *p_sys = p_filter->p_sys;
@@ -392,6 +393,7 @@ static int BuildFilterChain( filter_t *p_filter )
         msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man",
                  (char*)&i_chroma );
 
+        es_format_Clean( &fmt_mid );
         es_format_Copy( &fmt_mid, &p_filter->fmt_in );
         fmt_mid.i_codec        =
         fmt_mid.video.i_chroma = i_chroma;
@@ -401,26 +403,27 @@ static int BuildFilterChain( filter_t *p_filter )
         video_format_FixRgb(&fmt_mid.video);
 
         if( filter_chain_AppendConverter( p_sys->p_chain,
-                                          &fmt_mid ) == VLC_SUCCESS )
-        {
-            p_sys->p_video_filter =
-                filter_chain_AppendFilter( p_sys->p_chain,
-                                           p_filter->psz_name, p_filter->p_cfg,
-                                           &fmt_mid );
-            if( p_sys->p_video_filter )
-            {
-                filter_AddProxyCallbacks( p_filter,
-                                          p_sys->p_video_filter,
-                                          RestartFilterCallback );
-
-                es_format_Clean( &fmt_mid );
-                i_ret = VLC_SUCCESS;
-                p_filter->vctx_out = filter_chain_GetVideoCtxOut( p_sys->p_chain );
-                break;
-            }
-        }
-        es_format_Clean( &fmt_mid );
+                                          &fmt_mid ) != VLC_SUCCESS )
+            continue;
+        
+        p_sys->p_video_filter =
+            filter_chain_AppendFilter( p_sys->p_chain,
+                                       p_filter->psz_name, p_filter->p_cfg,
+                                       &fmt_mid );
+        if( p_sys->p_video_filter == NULL)
+            continue;
+
+        filter_AddProxyCallbacks( p_filter,
+                                  p_sys->p_video_filter,
+                                  RestartFilterCallback );
+
+        i_ret = VLC_SUCCESS;
+        p_filter->vctx_out = filter_chain_GetVideoCtxOut( p_sys->p_chain );
+        break;
     }
+
+    es_format_Clean( &fmt_mid );
+
     if( i_ret != VLC_SUCCESS )
         filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, p_filter->vctx_in, &p_filter->fmt_out );
 
@@ -435,15 +438,12 @@ static int CreateChain( filter_t *p_filter, const es_format_t *p_fmt_mid )
     filter_sys_t *p_sys = p_filter->p_sys;
     filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, p_filter->vctx_in, &p_filter->fmt_out );
 
-    {
-        if( filter_chain_AppendConverter( p_sys->p_chain, p_fmt_mid ) )
-            return VLC_EGENERIC;
-    }
+    if( filter_chain_AppendConverter( p_sys->p_chain, p_fmt_mid ) )
+        return VLC_EGENERIC;
+
+    if( filter_chain_AppendConverter( p_sys->p_chain, &p_filter->fmt_out ) )
+        goto error;
 
-    {
-        if( filter_chain_AppendConverter( p_sys->p_chain, &p_filter->fmt_out ) )
-            goto error;
-    }
     p_filter->vctx_out = filter_chain_GetVideoCtxOut( p_sys->p_chain );
     return VLC_SUCCESS;
 error:


=====================================
modules/video_chroma/cvpx.c
=====================================
@@ -560,6 +560,18 @@ static const struct vlc_filter_operations chain_CVPX_ops = {
     .close = Close_chain_CVPX,
 };
 
+static picture_t *VideoBufferNew(filter_t *filter)
+{
+    filter_t *cvpx_chain = filter->owner.sys;
+    return filter_NewPicture(cvpx_chain);
+}
+
+static struct vlc_decoder_device *VideoHoldDevice(vlc_object_t *obj, void *sys)
+{
+    filter_t *cvpx_chain = sys;
+    return filter_HoldDecoderDevice(cvpx_chain);
+}
+
 static int
 Open_chain_CVPX(filter_t *filter)
 {
@@ -624,9 +636,21 @@ Open_chain_CVPX(filter_t *filter)
              (const char *)&input_chroma,
              (const char *)&output_chroma);
 
+    static const struct filter_video_callbacks owner_cbs =
+    {
+        .buffer_new = VideoBufferNew,
+        .hold_device = VideoHoldDevice,
+    };
+
+    const struct filter_owner_t owner =
+    {
+        .sys = filter,
+        .video = &owner_cbs,
+    };
+
     /* We create a filter chain to encapsulate the two converters. */
     filter_chain_t *chain =
-        filter_chain_NewVideo(filter, false, &filter->owner);
+        filter_chain_NewVideo(filter, false, &owner);
     if (chain == NULL)
         return VLC_ENOMEM;
 


=====================================
test/Makefile.am
=====================================
@@ -50,6 +50,10 @@ check_PROGRAMS = \
 	test_modules_playlist_m3u \
 	$(NULL)
 
+if HAVE_DARWIN
+check_PROGRAMS += test_src_misc_image_cvpx
+endif
+
 if ENABLE_SOUT
 check_PROGRAMS += test_modules_tls \
 	test_modules_stream_out_transcode \
@@ -136,6 +140,9 @@ test_src_misc_epg_SOURCES = src/misc/epg.c
 test_src_misc_epg_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_src_misc_keystore_SOURCES = src/misc/keystore.c
 test_src_misc_keystore_LDADD = $(LIBVLCCORE) $(LIBVLC)
+test_src_misc_image_cvpx_SOURCES = src/misc/image_cvpx.c
+test_src_misc_image_cvpx_LDADD = $(LIBVLCCORE) $(LIBVLC) ../modules/libvlc_vtutils.la
+test_src_misc_image_cvpx_LDFLAGS = $(AM_LDFLAGS) -Wl,-framework,CoreVideo
 test_src_interface_dialog_SOURCES = src/interface/dialog.c
 test_src_interface_dialog_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_src_media_source_LDADD = $(LIBVLCCORE) $(LIBVLC)


=====================================
test/src/misc/image_cvpx.c
=====================================
@@ -0,0 +1,123 @@
+/*****************************************************************************
+ * image_cvpx.c: export test for image_handler with cvpx sources
+ *****************************************************************************
+ * Copyright (C) 2023 Videolabs
+ *
+ * Authors: Alexandre Janniaux <ajanni at 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
+
+/* Define a builtin module for mocked parts */
+#define MODULE_NAME test_misc_image_cvpx
+#define MODULE_STRING "test_misc_image_cvpx"
+#undef __PLUGIN__
+const char vlc_module_name[] = MODULE_STRING;
+
+#include "../../libvlc/test.h"
+#include "../../../modules/codec/vt_utils.h"
+
+#include <vlc/vlc.h>
+
+#include <vlc_common.h>
+#include <vlc_image.h>
+#include <vlc_picture.h>
+#include <vlc_plugin.h>
+#include <vlc_block.h>
+
+#include <limits.h>
+
+static int OpenIntf(vlc_object_t *root)
+{
+    image_handler_t *ih = image_HandlerCreate(root);
+    assert(ih != NULL);
+
+    video_format_t fmt_in;
+    video_format_Init(&fmt_in, VLC_CODEC_CVPX_NV12);
+    fmt_in.i_width = fmt_in.i_visible_width = 800;
+    fmt_in.i_height = fmt_in.i_visible_height = 600;
+
+    CVPixelBufferPoolRef pool = cvpxpool_create(&fmt_in, 1);
+    assert(pool != NULL);
+
+    CVPixelBufferRef buffer = cvpxpool_new_cvpx(pool);
+    assert(buffer != NULL);
+
+    picture_t *picture = picture_NewFromFormat(&fmt_in);
+    assert(picture != NULL);
+
+    struct vlc_decoder_device *device = NULL;
+    static const struct vlc_video_context_operations ops = {
+        NULL
+    };
+
+    struct vlc_video_context *vctx =vlc_video_context_CreateCVPX(
+      device, CVPX_VIDEO_CONTEXT_DEFAULT, 0, &ops);
+    int ret = cvpxpic_attach(picture, buffer, vctx,
+                             NULL /* TODO: check everything is released */);
+    assert(ret == VLC_SUCCESS);
+
+    video_format_t fmt_out;
+    video_format_Init(&fmt_out, VLC_CODEC_PNG);
+    fmt_out.i_width = fmt_out.i_visible_width = 800;
+    fmt_out.i_height = fmt_out.i_visible_height = 600;
+
+    block_t *block;
+
+    block = image_Write(ih, picture, &fmt_in, &fmt_out);
+    assert(block != NULL);
+    block_Release(block);
+    image_HandlerDelete(ih);
+
+    return VLC_SUCCESS;
+}
+
+/** Inject the mocked modules as a static plugin: **/
+vlc_module_begin()
+    set_callback(OpenIntf)
+    set_capability("interface", 0)
+vlc_module_end()
+
+/* Helper typedef for vlc_static_modules */
+typedef int (*vlc_plugin_cb)(vlc_set_cb, void*);
+
+VLC_EXPORT const vlc_plugin_cb vlc_static_modules[] = {
+    VLC_SYMBOL(vlc_entry),
+    NULL
+};
+
+
+int main()
+{
+    test_init();
+
+    const char * const args[] = {
+        "-vvv", "--vout=dummy", "--aout=dummy", "--text-renderer=dummy",
+        "--no-auto-preparse",
+    };
+
+    libvlc_instance_t *vlc = libvlc_new(ARRAY_SIZE(args), args);
+
+    libvlc_add_intf(vlc, MODULE_STRING);
+    libvlc_playlist_play(vlc);
+
+    libvlc_release(vlc);
+
+}
+



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/bd2be7d8294c2eef92eb6b3cf1a026509fb45e4b...782bf9ad5aff54c987ae15caf6bd6dd371230920

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