From a458b6af6b88534edadd8bd218b368fbf173a273 Mon Sep 17 00:00:00 2001 From: Antoine Cellerier Date: Sun, 22 Jun 2008 16:15:49 +0200 Subject: [PATCH] New canvas video filter. --- configure.ac | 1 + modules/video_filter/Modules.am | 1 + modules/video_filter/canvas.c | 224 ++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) create mode 100644 modules/video_filter/canvas.c diff --git a/configure.ac b/configure.ac index 7094471f82..0ee5d8535e 100644 --- a/configure.ac +++ b/configure.ac @@ -1133,6 +1133,7 @@ VLC_ADD_PLUGIN([extract]) VLC_ADD_PLUGIN([sharpen]) VLC_ADD_PLUGIN([seamcarving]) VLC_ADD_PLUGIN([croppadd]) +VLC_ADD_PLUGIN([canvas]) VLC_ADD_PLUGIN([blendbench]) VLC_ADD_PLUGIN([blend]) VLC_ADD_PLUGIN([scale]) diff --git a/modules/video_filter/Modules.am b/modules/video_filter/Modules.am index 1b2909504b..2268d9a84e 100644 --- a/modules/video_filter/Modules.am +++ b/modules/video_filter/Modules.am @@ -38,6 +38,7 @@ SOURCES_gaussianblur = gaussianblur.c SOURCES_grain = grain.c SOURCES_seamcarving = seamcarving.c SOURCES_croppadd = croppadd.c +SOURCES_canvas = canvas.c SOURCES_blendbench = blendbench.c SOURCES_chain = chain.c SOURCES_postproc = postproc.c diff --git a/modules/video_filter/canvas.c b/modules/video_filter/canvas.c new file mode 100644 index 0000000000..fe46726b48 --- /dev/null +++ b/modules/video_filter/canvas.c @@ -0,0 +1,224 @@ +/***************************************************************************** + * canvas.c : automatically resize and padd a video to fit in canvas + ***************************************************************************** + * Copyright (C) 2008 the VideoLAN team + * $Id$ + * + * Authors: Antoine Cellerier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU 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. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include +#include + +/***************************************************************************** + * Local and extern prototypes. + *****************************************************************************/ +static int Activate( vlc_object_t * ); +static void Destroy( vlc_object_t * ); +static picture_t *Filter( filter_t *, picture_t * ); +static int alloc_init( filter_t *, void * ); + +#define WIDTH_TEXT N_( "Image width" ) +#define WIDTH_LONGTEXT N_( \ + "Image width" ) +#define HEIGHT_TEXT N_( "Image height" ) +#define HEIGHT_LONGTEXT N_( \ + "Image height" ) + +#define CFG_PREFIX "canvas-" + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +vlc_module_begin(); + set_description( N_("Automatically resize and padd a video") ); + set_capability( "video filter2", 0 ); + set_callbacks( Activate, Destroy ); + + add_integer_with_range( CFG_PREFIX "width", 0, 0, INT_MAX, NULL, + WIDTH_TEXT, WIDTH_LONGTEXT, false ); + add_integer_with_range( CFG_PREFIX "height", 0, 0, INT_MAX, NULL, + HEIGHT_TEXT, HEIGHT_LONGTEXT, false ); +vlc_module_end(); + +static const char *const ppsz_filter_options[] = { + "width", "height", NULL +}; + +struct filter_sys_t +{ + filter_chain_t *p_chain; +}; + +/***************************************************************************** + * + *****************************************************************************/ +static int Activate( vlc_object_t *p_this ) +{ + filter_t *p_filter = (filter_t *)p_this; + unsigned int i_width, i_height; + es_format_t fmt; + char psz_croppadd[100]; + int i_padd; + + if( !p_filter->b_allow_fmt_out_change ) + { + msg_Err( p_filter, "Picture format change isn't allowed" ); + return VLC_EGENERIC; + } + + if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma ) + { + msg_Err( p_filter, "Input and output chromas don't match" ); + return VLC_EGENERIC; + } + + config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options, + p_filter->p_cfg ); + + i_width = var_CreateGetInteger( p_filter, CFG_PREFIX "width" ); + i_height = var_CreateGetInteger( p_filter, CFG_PREFIX "height" ); + + if( i_width == 0 || i_height == 0 ) + { + msg_Err( p_filter, "Width and height options must be set" ); + return VLC_EGENERIC; + } + + if( i_width & 1 || i_height & 1 ) + { + msg_Err( p_filter, "Width and height options must be even integers" ); + return VLC_EGENERIC; + } + + filter_sys_t *p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) ); + if( !p_sys ) + return VLC_ENOMEM; + p_filter->p_sys = p_sys; + + p_sys->p_chain = filter_chain_New( p_filter, "video filter2", true, + alloc_init, NULL, p_filter ); + if( !p_sys->p_chain ) + { + msg_Err( p_filter, "Could not allocate filter chain" ); + free( p_sys ); + return VLC_EGENERIC; + } + + es_format_Copy( &fmt, &p_filter->fmt_in ); + + fmt.video.i_width = i_width; + fmt.video.i_height = ( p_filter->fmt_in.video.i_height * i_width ) + / p_filter->fmt_in.video.i_width; + if( fmt.video.i_height > i_height ) + { + fmt.video.i_height = i_height; + fmt.video.i_width = ( p_filter->fmt_in.video.i_width * i_height ) + / p_filter->fmt_in.video.i_height; + if( fmt.video.i_width & 1 ) fmt.video.i_width -= 1; + i_padd = i_width - fmt.video.i_width; + /* Gruik */ + snprintf( psz_croppadd, 100, "croppadd{paddleft=%d,paddright=%d}", + i_padd/2, (i_padd+1)/2 ); + } + else + { + if( fmt.video.i_height & 1 ) fmt.video.i_height -= 1; + i_padd = i_height - fmt.video.i_height; + /* Gruik */ + snprintf( psz_croppadd, 100, "croppadd{paddtop=%d,paddbottom=%d}", + i_padd/2, (i_padd+1)/2 ); + } + + fmt.video.i_visible_width = fmt.video.i_width; + fmt.video.i_visible_height = fmt.video.i_height; + + filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &fmt ); + /* Append scaling module */ + filter_chain_AppendFilter( p_sys->p_chain, NULL, NULL, NULL, NULL ); + /* Append padding module */ + filter_chain_AppendFromString( p_sys->p_chain, psz_croppadd ); + + fmt = *filter_chain_GetFmtOut( p_sys->p_chain ); + es_format_Copy( &p_filter->fmt_out, &fmt ); + + if( p_filter->fmt_out.video.i_width != i_width + || p_filter->fmt_out.video.i_height != i_height ) + { + msg_Warn( p_filter, "Looks like something went wrong. " + "Output size is %dx%d while we asked for %dx%d", + p_filter->fmt_out.video.i_width, + p_filter->fmt_out.video.i_height, + i_width, i_height ); + } + + p_filter->pf_video_filter = Filter; + + return VLC_SUCCESS; +} + +/***************************************************************************** + * + *****************************************************************************/ +static void Destroy( vlc_object_t *p_this ) +{ + filter_t *p_filter = (filter_t *)p_this; + filter_chain_Delete( p_filter->p_sys->p_chain ); + free( p_filter->p_sys ); +} + +/***************************************************************************** + * + *****************************************************************************/ +static picture_t *Filter( filter_t *p_filter, picture_t *p_pic ) +{ + return filter_chain_VideoFilter( p_filter->p_sys->p_chain, p_pic ); +} + +/***************************************************************************** + * + *****************************************************************************/ +static picture_t *video_new( filter_t *p_filter ) +{ + return ((filter_t*)p_filter->p_owner)->pf_vout_buffer_new( (filter_t*)p_filter->p_owner ); +} + +static void video_del( filter_t *p_filter, picture_t *p_pic ) +{ + if( ((filter_t*)p_filter->p_owner)->pf_vout_buffer_del ) + ((filter_t*)p_filter->p_owner)->pf_vout_buffer_del( (filter_t*)p_filter->p_owner, p_pic ); +} + +static int alloc_init( filter_t *p_filter, void *p_data ) +{ + p_filter->p_owner = p_data; + p_filter->pf_vout_buffer_new = video_new; + p_filter->pf_vout_buffer_del = video_del; + return VLC_SUCCESS; +} -- 2.39.5