1
mirror of https://code.videolan.org/videolan/vlc synced 2024-07-25 09:41:30 +02:00

video_filter: add formatcrop filter

This filter crops the input pictures by adjusting the format (offsets
and size), without any copy (contrary to croppadd).

This is especially useful to receive pictures with arbitrary visible
area (smaller than the full size), to debug vouts or filters.
This commit is contained in:
Romain Vimont 2021-10-14 15:56:13 +02:00 committed by Hugo Beauzée-Luyssen
parent 03e6957832
commit 22775b884b
4 changed files with 198 additions and 0 deletions

1
NEWS
View File

@ -2073,6 +2073,7 @@ Video Filters:
* Improvements on the transform filter, to support 10bits and RGB formats
* Revival of the openCV and openCV example filters
* ARM NEON acceleration of chroma filters
* New crop filter without picture copy
Stream Output:
* Extended support for recording, notably for MKV and AVI

View File

@ -34,6 +34,7 @@ libhqdn3d_plugin_la_SOURCES = video_filter/hqdn3d.c video_filter/hqdn3d.h
libhqdn3d_plugin_la_LIBADD = $(LIBM)
libinvert_plugin_la_SOURCES = video_filter/invert.c
libmagnify_plugin_la_SOURCES = video_filter/magnify.c
libformatcrop_plugin_la_SOURCES = video_filter/formatcrop.c
libmirror_plugin_la_SOURCES = video_filter/mirror.c
libmotionblur_plugin_la_SOURCES = video_filter/motionblur.c
libmotiondetect_plugin_la_SOURCES = video_filter/motiondetect.c
@ -86,6 +87,7 @@ video_filter_LTLIBRARIES = \
libgaussianblur_plugin.la \
libinvert_plugin.la \
libmagnify_plugin.la \
libformatcrop_plugin.la \
libmirror_plugin.la \
libmotionblur_plugin.la \
libmotiondetect_plugin.la \

View File

@ -0,0 +1,194 @@
/*****************************************************************************
* formatcrop.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 <limits.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_filter.h>
#include <vlc_picture.h>
/**
* This filter crops the input pictures by adjusting the format (offsets and
* size) without any copy (contrary to croppadd).
*/
#define CFG_PREFIX "formatcrop-"
static const char *const filter_options[] = {
"top", "bottom", "left", "right", NULL,
};
#define CROPTOP_TEXT N_("Pixels to crop from top")
#define CROPTOP_LONGTEXT \
N_("Number of pixels to crop from the top of the image.")
#define CROPBOTTOM_TEXT N_("Pixels to crop from bottom")
#define CROPBOTTOM_LONGTEXT \
N_("Number of pixels to crop from the bottom of the image.")
#define CROPLEFT_TEXT N_("Pixels to crop from left")
#define CROPLEFT_LONGTEXT \
N_("Number of pixels to crop from the left of the image.")
#define CROPRIGHT_TEXT N_("Pixels to crop from right")
#define CROPRIGHT_LONGTEXT \
N_("Number of pixels to crop from the right of the image.")
struct sys {
unsigned x;
unsigned y;
unsigned width;
unsigned height;
};
#define IDX_TOP 0
#define IDX_LEFT 1
#define IDX_BOTTOM 2
#define IDX_RIGHT 3
struct transform {
unsigned idx_top;
unsigned idx_left;
/* idx_bottom is idx_top XOR 2
idx_right is idx_left XOR 2 */
};
static const struct transform transforms[8] = {
[ORIENT_TOP_LEFT] = { IDX_TOP, IDX_LEFT },
[ORIENT_TOP_RIGHT] = { IDX_TOP, IDX_RIGHT },
[ORIENT_BOTTOM_LEFT] = { IDX_BOTTOM, IDX_LEFT },
[ORIENT_BOTTOM_RIGHT] = { IDX_BOTTOM, IDX_RIGHT },
[ORIENT_LEFT_TOP] = { IDX_LEFT, IDX_TOP },
[ORIENT_LEFT_BOTTOM] = { IDX_LEFT, IDX_BOTTOM },
[ORIENT_RIGHT_TOP] = { IDX_RIGHT, IDX_TOP },
[ORIENT_RIGHT_BOTTOM] = { IDX_RIGHT, IDX_BOTTOM },
};
static picture_t *
Filter(filter_t *filter, picture_t *pic)
{
struct sys *sys = filter->p_sys;
if (!pic)
return NULL;
picture_t *out = picture_Clone(pic);
if (!out)
return NULL;
picture_CopyProperties(out, pic);
picture_Release(pic);
video_format_t *fmt = &out->format;
fmt->i_x_offset = sys->x;
fmt->i_y_offset = sys->y;
fmt->i_visible_width = sys->width;
fmt->i_visible_height = sys->height;
return out;
}
static void
Close(filter_t *filter)
{
struct sys *sys = filter->p_sys;
free(sys);
}
static int
Open(filter_t *filter)
{
config_ChainParse(filter, CFG_PREFIX, filter_options, filter->p_cfg);
unsigned top = var_InheritInteger(filter, CFG_PREFIX "top");
unsigned bottom = var_InheritInteger(filter, CFG_PREFIX "bottom");
unsigned left = var_InheritInteger(filter, CFG_PREFIX "left");
unsigned right = var_InheritInteger(filter, CFG_PREFIX "right");
video_format_t *fmt = &filter->fmt_in.video;
video_orientation_t orientation = fmt->orientation;
/* In the same order as IDX_ constants values */
unsigned crop[] = { top, left, bottom, right };
/* Transform from picture crop to physical crop (with orientation) */
const struct transform *tx = &transforms[orientation];
unsigned crop_top = crop[tx->idx_top];
unsigned crop_left = crop[tx->idx_left];
unsigned crop_bottom = crop[tx->idx_top ^ 2];
unsigned crop_right = crop[tx->idx_left ^ 2];
if (crop_top + crop_bottom >= fmt->i_visible_height)
{
msg_Err(filter, "Vertical crop (top=%u, bottom=%u) "
"greater than the picture height (%u)\n",
crop_top, crop_bottom, fmt->i_visible_height);
return VLC_EGENERIC;
}
if (crop_left + crop_right >= fmt->i_visible_width)
{
msg_Err(filter, "Horizontal crop (left=%u, right=%u) "
"greater than the picture width (%u)\n",
crop_left, crop_right, fmt->i_visible_width);
return VLC_EGENERIC;
}
struct sys *sys = malloc(sizeof(*sys));
if (!sys)
return VLC_EGENERIC;
filter->p_sys = sys;
sys->x = fmt->i_x_offset + crop_left;
sys->y = fmt->i_y_offset + crop_top;
sys->width = fmt->i_visible_width - crop_left - crop_right;
sys->height = fmt->i_visible_height - crop_top - crop_bottom;
static const struct vlc_filter_operations filter_ops =
{
.filter_video = Filter,
.close = Close,
};
filter->ops = &filter_ops;
return VLC_SUCCESS;
}
vlc_module_begin()
set_shortname("formatcrop")
set_description(N_("Video cropping filter"))
set_callback_video_filter(Open)
set_category(CAT_VIDEO)
set_subcategory(SUBCAT_VIDEO_VFILTER);
add_integer_with_range(CFG_PREFIX "top", 0, 0, INT_MAX,
CROPTOP_TEXT, CROPTOP_LONGTEXT)
add_integer_with_range(CFG_PREFIX "bottom", 0, 0, INT_MAX,
CROPBOTTOM_TEXT, CROPTOP_LONGTEXT)
add_integer_with_range(CFG_PREFIX "left", 0, 0, INT_MAX,
CROPLEFT_TEXT, CROPTOP_LONGTEXT)
add_integer_with_range(CFG_PREFIX "right", 0, 0, INT_MAX,
CROPRIGHT_TEXT, CROPTOP_LONGTEXT)
vlc_module_end()

View File

@ -1301,6 +1301,7 @@ modules/video_filter/edgedetection.c
modules/video_filter/erase.c
modules/video_filter/extract.c
modules/video_filter/fps.c
modules/video_filter/formatcrop.c
modules/video_filter/freeze.c
modules/video_filter/gaussianblur.c
modules/video_filter/gradfun.c