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.
_______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits