[vlc-commits] [Git][videolan/vlc][master] 3 commits: deinterlace: fail on unknown mode

Romain Vimont gitlab at videolan.org
Tue Jun 8 15:00:41 UTC 2021



Romain Vimont pushed to branch master at VideoLAN / VLC


Commits:
a5b4903d by Romain Vimont at 2021-06-08T14:36:51+00:00
deinterlace: fail on unknown mode

This will allow to try an alternate deinterlace filter (for example
an OpenGL filter).

- - - - -
4de0b416 by Romain Vimont at 2021-06-08T14:36:51+00:00
deinterlace: add --deinterlace-filter option

The option --deinterlace-mode selects the deinterlace algorithm to use,
but the same algorithm might be implemented by several modules, for
example a CPU version and an OpenGL version.

For that purpose, add a separate option to select the module(s) to use.
The default value is "deinterlace".

To select the blend deinterlace algorithm:

    --deinterlace-mode=blend

or equivalently ("deinterlace" is the default filter):

    --deinterlace-filter=deinterlace --deinterlace-mode=blend

To run the OpenGL version (the mode is "auto"):

    --deinterlace-filter=glblend

The module glblend only implements the "blend" algorithm, it can be
passed explicitly:

    --deinterlace-filter=glblend --deinterlace-mode=blend

To pass a list a modules, executed in order until one works:

    --deinterlace-filter=glblend,deinterlace --deinterlace-mode=blend

- - - - -
8ef60b3b by Romain Vimont at 2021-06-08T14:36:51+00:00
opengl: add blend deinterlace filter

- - - - -


6 changed files:

- modules/video_filter/Makefile.am
- modules/video_filter/deinterlace/deinterlace.c
- + modules/video_filter/deinterlace/glblend.c
- src/libvlc-module.c
- src/video_output/interlacing.c
- src/video_output/video_output.c


Changes:

=====================================
modules/video_filter/Makefile.am
=====================================
@@ -188,6 +188,25 @@ endif
 libdeinterlace_plugin_la_LIBADD = libdeinterlace_common.la
 video_filter_LTLIBRARIES += libdeinterlace_plugin.la
 
+libglblend_plugin_la_SOURCES = video_filter/deinterlace/glblend.c
+libglblend_plugin_la_CFLAGS = $(AM_CFLAGS)
+if HAVE_GL
+libglblend_plugin_la_LIBADD = libvlc_opengl.la
+video_filter_LTLIBRARIES += libglblend_plugin.la
+endif
+
+if HAVE_IOS
+libglblend_plugin_la_LIBADD = libvlc_opengles.la
+libglblend_plugin_la_CFLAGS += -DUSE_OPENGL_ES2=1
+video_filter_LTLIBRARIES += libglblend_plugin.la
+endif
+
+if HAVE_ANDROID
+libglblend_plugin_la_LIBADD = libvlc_opengles.la
+libglblend_plugin_la_CFLAGS += -DUSE_OPENGL_ES2=1
+video_filter_LTLIBRARIES += libglblend_plugin.la
+endif
+
 libopencv_wrapper_plugin_la_SOURCES = video_filter/opencv_wrapper.c
 libopencv_wrapper_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(OPENCV_CFLAGS)
 libopencv_wrapper_plugin_la_LIBADD = $(OPENCV_LIBS)


=====================================
modules/video_filter/deinterlace/deinterlace.c
=====================================
@@ -373,7 +373,7 @@ static struct filter_mode_t filter_mode [] = {
  * @param mode Desired method. See mode_list for available choices.
  * @see mode_list
  */
-static void SetFilterMethod( filter_t *p_filter, const char *mode, bool pack )
+static int SetFilterMethod( filter_t *p_filter, const char *mode, bool pack )
 {
     filter_sys_t *p_sys = p_filter->p_sys;
 
@@ -388,25 +388,23 @@ static void SetFilterMethod( filter_t *p_filter, const char *mode, bool pack )
             {
                 msg_Err( p_filter, "unknown or incompatible deinterlace mode \"%s\""
                         " for packed format", mode );
-                SetFilterMethod( p_filter, "blend", pack );
-                return;
+                return SetFilterMethod( p_filter, "blend", pack );
             }
             if( p_sys->chroma->pixel_size > 1 && !filter_mode[i].b_high_bit_depth )
             {
                 msg_Err( p_filter, "unknown or incompatible deinterlace mode \"%s\""
                         " for high depth format", mode );
-                SetFilterMethod( p_filter, "blend", pack );
-                return;
+                return SetFilterMethod( p_filter, "blend", pack );
             }
 
             msg_Dbg( p_filter, "using %s deinterlace method", mode );
             p_sys->context.settings = filter_mode[i].settings;
             p_sys->context.pf_render_ordered = filter_mode[i].pf_render_ordered;
-            return;
+            return VLC_SUCCESS;
         }
     }
 
-    msg_Err( p_filter, "unknown deinterlace mode \"%s\"", mode );
+    return VLC_EGENERIC;
 }
 
 /**
@@ -541,7 +539,13 @@ notsupp:
     config_ChainParse( p_filter, FILTER_CFG_PREFIX, ppsz_filter_options,
                        p_filter->p_cfg );
     char *psz_mode = var_InheritString( p_filter, FILTER_CFG_PREFIX "mode" );
-    SetFilterMethod( p_filter, psz_mode, packed );
+    int ret = SetFilterMethod( p_filter, psz_mode, packed );
+    if (ret != VLC_SUCCESS)
+    {
+        free(psz_mode);
+        free(p_sys);
+        return ret;
+    }
 
     IVTCClearState( p_filter );
 


=====================================
modules/video_filter/deinterlace/glblend.c
=====================================
@@ -0,0 +1,238 @@
+/*****************************************************************************
+ * glblend.c
+ *****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * 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
+
+#include <vlc_common.h>
+#include <vlc_picture.h>
+#include <vlc_plugin.h>
+#include <vlc_modules.h>
+#include <vlc_opengl.h>
+#include <vlc_filter.h>
+
+#include "video_output/opengl/filter.h"
+#include "video_output/opengl/gl_api.h"
+#include "video_output/opengl/gl_common.h"
+#include "video_output/opengl/gl_util.h"
+
+struct sys {
+    GLuint program_id;
+
+    GLuint vbo;
+
+    struct {
+        GLint vertex_pos;
+        GLint height;
+    } loc;
+};
+
+static int
+Draw(struct vlc_gl_filter *filter, const struct vlc_gl_input_meta *meta)
+{
+    struct sys *sys = filter->sys;
+
+    const opengl_vtable_t *vt = &filter->api->vt;
+
+    vt->UseProgram(sys->program_id);
+
+    struct vlc_gl_sampler *sampler = vlc_gl_filter_GetSampler(filter);
+    vlc_gl_sampler_Load(sampler);
+
+    vt->BindBuffer(GL_ARRAY_BUFFER, sys->vbo);
+    vt->EnableVertexAttribArray(sys->loc.vertex_pos);
+    vt->VertexAttribPointer(sys->loc.vertex_pos, 2, GL_FLOAT, GL_FALSE, 0,
+                            (const void *) 0);
+
+    GLsizei height = sampler->tex_heights[meta->plane];
+    vt->Uniform1f(sys->loc.height, height);
+
+    vt->Clear(GL_COLOR_BUFFER_BIT);
+    vt->DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+    return VLC_SUCCESS;
+}
+
+static void
+Close(struct vlc_gl_filter *filter)
+{
+    struct sys *sys = filter->sys;
+
+    const opengl_vtable_t *vt = &filter->api->vt;
+    vt->DeleteProgram(sys->program_id);
+    vt->DeleteBuffers(1, &sys->vbo);
+
+    free(sys);
+}
+
+static int
+Open(struct vlc_gl_filter *filter, const config_chain_t *config,
+     struct vlc_gl_tex_size *size_out)
+{
+    (void) config;
+    (void) size_out;
+
+    struct sys *sys = filter->sys = malloc(sizeof(*sys));
+    if (!sys)
+        return VLC_EGENERIC;
+
+    static const struct vlc_gl_filter_ops ops = {
+        .draw = Draw,
+        .close = Close,
+    };
+    filter->ops = &ops;
+    filter->config.filter_planes = true;
+
+    struct vlc_gl_sampler *sampler = vlc_gl_filter_GetSampler(filter);
+
+    static const char *const VERTEX_SHADER =
+        "attribute vec2 vertex_pos;\n"
+        "varying vec2 tex_coords;\n"
+        "varying vec2 tex_coords_up;\n"
+        "uniform float height;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(vertex_pos, 0.0, 1.0);\n"
+        "  tex_coords = vec2((vertex_pos.x + 1.0) / 2.0,\n"
+        "                    (vertex_pos.y + 1.0) / 2.0);\n"
+        "  tex_coords_up = vec2(tex_coords.x,\n"
+        "                       tex_coords.y + 1.0 / height);\n"
+        "}\n";
+
+    static const char *const FRAGMENT_SHADER =
+        "varying vec2 tex_coords;\n"
+        "varying vec2 tex_coords_up;\n"
+        "void main() {\n"
+        "  vec4 pix = vlc_texture(tex_coords);\n"
+        "  vec4 pix_up = vlc_texture(tex_coords_up);\n"
+        "  gl_FragColor = (pix + pix_up) / 2.0;\n"
+        "}\n";
+
+    const char *shader_version;
+    const char *shader_precision;
+    if (filter->api->is_gles)
+    {
+        shader_version = "#version 100\n";
+        shader_precision = "precision highp float;\n";
+    }
+    else
+    {
+        shader_version = "#version 120\n";
+        shader_precision = "";
+    }
+
+    const char *extensions = sampler->shader.extensions
+                           ? sampler->shader.extensions : "";
+
+    const opengl_vtable_t *vt = &filter->api->vt;
+
+    const char *vertex_shader[] = { shader_version, VERTEX_SHADER };
+    const char *fragment_shader[] = {
+        shader_version,
+        extensions,
+        shader_precision,
+        sampler->shader.body,
+        FRAGMENT_SHADER,
+    };
+
+    GLuint program_id =
+        vlc_gl_BuildProgram(VLC_OBJECT(filter), vt,
+                            ARRAY_SIZE(vertex_shader), vertex_shader,
+                            ARRAY_SIZE(fragment_shader), fragment_shader);
+
+    if (!program_id)
+        goto error;
+
+    vlc_gl_sampler_FetchLocations(sampler, program_id);
+
+    sys->program_id = program_id;
+
+    sys->loc.vertex_pos = vt->GetAttribLocation(program_id, "vertex_pos");
+    assert(sys->loc.vertex_pos != -1);
+
+    sys->loc.height = vt->GetUniformLocation(program_id, "height");
+    assert(sys->loc.height != -1);
+
+    vt->GenBuffers(1, &sys->vbo);
+
+    static const GLfloat vertex_pos[] = {
+        -1,  1,
+        -1, -1,
+         1,  1,
+         1, -1,
+    };
+
+    vt->BindBuffer(GL_ARRAY_BUFFER, sys->vbo);
+    vt->BufferData(GL_ARRAY_BUFFER, sizeof(vertex_pos), vertex_pos,
+                   GL_STATIC_DRAW);
+
+    vt->BindBuffer(GL_ARRAY_BUFFER, 0);
+
+    return VLC_SUCCESS;
+
+error:
+    free(sys);
+    return VLC_EGENERIC;
+}
+
+static int OpenVideoFilter(vlc_object_t *obj)
+{
+    filter_t *filter = (filter_t*)obj;
+
+    char *mode = var_InheritString(obj, "deinterlace-mode");
+    bool is_supported = !mode
+        || !strcmp(mode, "auto")
+        || !strcmp(mode, "blend");
+    free(mode);
+
+    if (!is_supported)
+        return VLC_EGENERIC;
+
+    const config_chain_t *prev_chain = filter->p_cfg;
+    var_Create(filter, "opengl-filter", VLC_VAR_STRING);
+    var_SetString(filter, "opengl-filter", "glblend");
+
+    filter->p_cfg = NULL;
+    module_t *module = module_need(obj, "video filter", "opengl", true);
+    filter->p_cfg = prev_chain;
+
+    var_Destroy(filter, "opengl-filter");
+
+    if (module == NULL)
+        return VLC_EGENERIC;
+
+    return VLC_SUCCESS;
+}
+
+vlc_module_begin()
+    set_shortname("blend")
+    set_description("OpenGL blend deinterlace filter")
+    set_category(CAT_VIDEO)
+    set_subcategory(SUBCAT_VIDEO_VFILTER)
+
+    set_capability("video filter", 0)
+    set_callback(OpenVideoFilter)
+    add_shortcut("glblend")
+
+    add_submodule()
+        set_capability("opengl filter", 0)
+        set_callback(Open)
+        add_shortcut("glblend")
+vlc_module_end()


=====================================
src/libvlc-module.c
=====================================
@@ -373,6 +373,9 @@ static const char * const ppsz_deinterlace_mode_text[] = {
     N_("Film NTSC (IVTC)")
 };
 
+#define DEINTERLACE_FILTER_TEXT N_("Deinterlace filter")
+#define DEINTERLACE_FILTER_LONGTEXT N_("Deinterlace module to use.")
+
 static const int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
 static const char *const ppsz_pos_descriptions[] =
 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
@@ -1715,6 +1718,9 @@ vlc_module_begin ()
                 DEINTERLACE_MODE_TEXT, DEINTERLACE_MODE_LONGTEXT )
         change_string_list( ppsz_deinterlace_mode, ppsz_deinterlace_mode_text )
         change_safe()
+    add_string( "deinterlace-filter", "deinterlace",
+                DEINTERLACE_FILTER_TEXT, DEINTERLACE_FILTER_LONGTEXT )
+        change_safe()
 
     set_subcategory( SUBCAT_VIDEO_VOUT )
     add_module("vout", "vout display", NULL, VOUT_TEXT, VOUT_LONGTEXT)


=====================================
src/video_output/interlacing.c
=====================================
@@ -73,6 +73,7 @@ static int DeinterlaceCallback(vlc_object_t *object, char const *cmd,
     const bool is_needed         = var_GetBool(vout,    "deinterlace-needed");
     if (!mode || !DeinterlaceIsModeValid(mode))
     {
+        msg_Err(vout, "unknown deinterlace mode %s", mode);
         free(mode);
         return VLC_EGENERIC;
     }


=====================================
src/video_output/video_output.c
=====================================
@@ -859,7 +859,9 @@ static void ThreadChangeFilters(vout_thread_sys_t *vout)
 
         if (likely(e))
         {
-            free(config_ChainCreate(&e->name, &e->cfg, "deinterlace"));
+            char *filter = var_InheritString(&vout->obj, "deinterlace-filter");
+            free(config_ChainCreate(&e->name, &e->cfg, filter));
+            free(filter);
             vlc_array_append_or_abort(&array_static, e);
         }
     }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/62bf14a8563855aeb77441083e38824cddedaf30...8ef60b3b62adc5bd7cb2281e9d676dd938d66663

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/62bf14a8563855aeb77441083e38824cddedaf30...8ef60b3b62adc5bd7cb2281e9d676dd938d66663
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list