diff --git a/Changelog b/Changelog index 59905a650c..ec83ad8f2b 100644 --- a/Changelog +++ b/Changelog @@ -48,6 +48,7 @@ version : - apad filter - adaptive frame-level multithreading for H.264 - documentation split into per-component manuals +- pp (postproc) filter ported from MPlayer version 1.0: diff --git a/LICENSE b/LICENSE index a1204f4adb..d083e56777 100644 --- a/LICENSE +++ b/LICENSE @@ -34,6 +34,7 @@ Specifically, the GPL parts of FFmpeg are - vf_hqdn3d.c - vf_hue.c - vf_mp.c + - vf_pp.c - vf_smartblur.c - vf_super2xsai.c - vf_tinterlace.c diff --git a/configure b/configure index b90ae6ed08..0c59aa87cc 100755 --- a/configure +++ b/configure @@ -1991,6 +1991,7 @@ negate_filter_deps="lut_filter" resample_filter_deps="avresample" ocv_filter_deps="libopencv" pan_filter_deps="swresample" +pp_filter_deps="gpl postproc" removelogo_filter_deps="avcodec avformat swscale" scale_filter_deps="swscale" smartblur_filter_deps="gpl swscale" diff --git a/doc/filters.texi b/doc/filters.texi index f456d03617..3e37b5302d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3423,6 +3423,174 @@ format=monow, pixdesctest can be used to test the monowhite pixel format descriptor definition. +@section pp + +Enable the specified chain of postprocessing subfilters using libpostproc. This +library should be automatically selected with a GPL build (@code{--enable-gpl}). +Subfilters must be separated by '/' and can be disabled by prepending a '-'. +Each subfilter and some options have a short and a long name that can be used +interchangeably, i.e. dr/dering are the same. + +All subfilters share common options to determine their scope: + +@table @option +@item a/autoq +Honor the quality commands for this subfilter. + +@item c/chrom +Do chrominance filtering, too (default). + +@item y/nochrom +Do luminance filtering only (no chrominance). + +@item n/noluma +Do chrominance filtering only (no luminance). +@end table + +These options can be appended after the subfilter name, separated by a ':'. + +Available subfilters are: + +@table @option +@item hb/hdeblock[:difference[:flatness]] +Horizontal deblocking filter +@table @option +@item difference +Difference factor where higher values mean more deblocking (default: @code{32}). +@item flatness +Flatness threshold where lower values mean more deblocking (default: @code{39}). +@end table + +@item vb/vdeblock[:difference[:flatness]] +Vertical deblocking filter +@table @option +@item difference +Difference factor where higher values mean more deblocking (default: @code{32}). +@item flatness +Flatness threshold where lower values mean more deblocking (default: @code{39}). +@end table + +@item ha/hadeblock[:difference[:flatness]] +Accurate horizontal deblocking filter +@table @option +@item difference +Difference factor where higher values mean more deblocking (default: @code{32}). +@item flatness +Flatness threshold where lower values mean more deblocking (default: @code{39}). +@end table + +@item va/vadeblock[:difference[:flatness]] +Accurate vertical deblocking filter +@table @option +@item difference +Difference factor where higher values mean more deblocking (default: @code{32}). +@item flatness +Flatness threshold where lower values mean more deblocking (default: @code{39}). +@end table +@end table + +The horizontal and vertical deblocking filters share the difference and +flatness values so you cannot set different horizontal and vertical +thresholds. + +@table @option +@item h1/x1hdeblock +Experimental horizontal deblocking filter + +@item v1/x1vdeblock +Experimental vertical deblocking filter + +@item dr/dering +Deringing filter + +@item tn/tmpnoise[:threshold1[:threshold2[:threshold3]]], temporal noise reducer +@table @option +@item threshold1 +larger -> stronger filtering +@item threshold2 +larger -> stronger filtering +@item threshold3 +larger -> stronger filtering +@end table + +@item al/autolevels[:f/fullyrange], automatic brightness / contrast correction +@table @option +@item f/fullyrange +Stretch luminance to @code{0-255}. +@end table + +@item lb/linblenddeint +Linear blend deinterlacing filter that deinterlaces the given block by +filtering all lines with a @code{(1 2 1)} filter. + +@item li/linipoldeint +Linear interpolating deinterlacing filter that deinterlaces the given block by +linearly interpolating every second line. + +@item ci/cubicipoldeint +Cubic interpolating deinterlacing filter deinterlaces the given block by +cubically interpolating every second line. + +@item md/mediandeint +Median deinterlacing filter that deinterlaces the given block by applying a +median filter to every second line. + +@item fd/ffmpegdeint +FFmpeg deinterlacing filter that deinterlaces the given block by filtering every +second line with a @code{(-1 4 2 4 -1)} filter. + +@item l5/lowpass5 +Vertically applied FIR lowpass deinterlacing filter that deinterlaces the given +block by filtering all lines with a @code{(-1 2 6 2 -1)} filter. + +@item fq/forceQuant[:quantizer] +Overrides the quantizer table from the input with the constant quantizer you +specify. +@table @option +@item quantizer +Quantizer to use +@end table + +@item de/default +Default pp filter combination (@code{hb:a,vb:a,dr:a}) + +@item fa/fast +Fast pp filter combination (@code{h1:a,v1:a,dr:a}) + +@item ac +High quality pp filter combination (@code{ha:a:128:7,va:a,dr:a}) +@end table + +@subsection Examples + +@itemize +@item +Apply horizontal and vertical deblocking, deringing and automatic +brightness/contrast: +@example +pp=hb/vb/dr/al +@end example + +@item +Apply default filters without brightness/contrast correction: +@example +pp=de/-al +@end example + +@item +Apply default filters and temporal denoiser: +@example +pp=default/tmpnoise:1:2:3 +@end example + +@item +Apply deblocking on luminance only, and switch vertical deblocking on or off +automatically depending on available CPU time: +@example +pp=hb:y/vb:a +@end example +@end itemize + @section removelogo Suppress a TV station logo, using an image file to determine which diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 1061444b1c..0e7fa1f13b 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -123,6 +123,7 @@ OBJS-$(CONFIG_OCV_FILTER) += vf_libopencv.o OBJS-$(CONFIG_OVERLAY_FILTER) += vf_overlay.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o +OBJS-$(CONFIG_PP_FILTER) += vf_pp.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_SCALE_FILTER) += vf_scale.o OBJS-$(CONFIG_SELECT_FILTER) += f_select.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index fc96809cab..b842add1ee 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -116,6 +116,7 @@ void avfilter_register_all(void) REGISTER_FILTER (OVERLAY, overlay, vf); REGISTER_FILTER (PAD, pad, vf); REGISTER_FILTER (PIXDESCTEST, pixdesctest, vf); + REGISTER_FILTER (PP, pp, vf); REGISTER_FILTER (REMOVELOGO, removelogo, vf); REGISTER_FILTER (SCALE, scale, vf); REGISTER_FILTER (SELECT, select, vf); diff --git a/libavfilter/version.h b/libavfilter/version.h index 08e28f1511..a83ddb48ce 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,8 +29,8 @@ #include "libavutil/avutil.h" #define LIBAVFILTER_VERSION_MAJOR 3 -#define LIBAVFILTER_VERSION_MINOR 29 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MINOR 30 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_pp.c b/libavfilter/vf_pp.c new file mode 100644 index 0000000000..bde5ebf3ce --- /dev/null +++ b/libavfilter/vf_pp.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2002 A'rpi + * Copyright (C) 2012 Clément Bœsch + * + * This file is part of FFmpeg. + * + * FFmpeg 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. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * @file + * libpostproc filter, ported from MPlayer. + */ + +#include "libavutil/avassert.h" +#include "libavutil/opt.h" +#include "internal.h" + +#include "libpostproc/postprocess.h" + +typedef struct { + int mode_id; + pp_mode *modes[PP_QUALITY_MAX + 1]; + void *pp_ctx; +} PPFilterContext; + +static av_cold int pp_init(AVFilterContext *ctx, const char *args) +{ + int i; + PPFilterContext *pp = ctx->priv; + + if (!args || !*args) + args = "de"; + + for (i = 0; i <= PP_QUALITY_MAX; i++) { + pp->modes[i] = pp_get_mode_by_name_and_quality(args, i); + if (!pp->modes[i]) + return AVERROR_EXTERNAL; + } + pp->mode_id = PP_QUALITY_MAX; + return 0; +} + +static int pp_process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + PPFilterContext *pp = ctx->priv; + + if (!strcmp(cmd, "quality")) { + pp->mode_id = av_clip(strtol(args, NULL, 10), 0, PP_QUALITY_MAX); + return 0; + } + return AVERROR(ENOSYS); +} + +static int pp_query_formats(AVFilterContext *ctx) +{ + static const enum PixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_NONE + }; + ff_set_common_formats(ctx, ff_make_format_list(pix_fmts)); + return 0; +} + +static int pp_config_props(AVFilterLink *inlink) +{ + int flags = PP_CPU_CAPS_AUTO; + PPFilterContext *pp = inlink->dst->priv; + + switch (inlink->format) { + case AV_PIX_FMT_YUVJ420P: + case AV_PIX_FMT_YUV420P: flags |= PP_FORMAT_420; break; + case AV_PIX_FMT_YUVJ422P: + case AV_PIX_FMT_YUV422P: flags |= PP_FORMAT_422; break; + case AV_PIX_FMT_YUV411P: flags |= PP_FORMAT_411; break; + case AV_PIX_FMT_YUVJ444P: + case AV_PIX_FMT_YUV444P: flags |= PP_FORMAT_444; break; + default: av_assert0(0); + } + + pp->pp_ctx = pp_get_context(inlink->w, inlink->h, flags); + if (!pp->pp_ctx) + return AVERROR(ENOMEM); + return 0; +} + +static int pp_filter_frame(AVFilterLink *inlink, AVFilterBufferRef *inbuf) +{ + AVFilterContext *ctx = inlink->dst; + PPFilterContext *pp = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + const int aligned_w = FFALIGN(outlink->w, 8); + const int aligned_h = FFALIGN(outlink->h, 8); + AVFilterBufferRef *outbuf; + + outbuf = ff_get_video_buffer(outlink, AV_PERM_WRITE, aligned_w, aligned_h); + if (!outbuf) { + avfilter_unref_buffer(inbuf); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(outbuf, inbuf); + + pp_postprocess((const uint8_t **)inbuf->data, inbuf->linesize, + outbuf->data, outbuf->linesize, + aligned_w, outlink->h, + outbuf->video->qp_table, + outbuf->video->qp_table_linesize, + pp->modes[pp->mode_id], + pp->pp_ctx, + outbuf->video->pict_type); + + avfilter_unref_buffer(inbuf); + return ff_filter_frame(outlink, outbuf); +} + +static av_cold void pp_uninit(AVFilterContext *ctx) +{ + int i; + PPFilterContext *pp = ctx->priv; + + for (i = 0; i <= PP_QUALITY_MAX; i++) + pp_free_mode(pp->modes[i]); + if (pp->pp_ctx) + pp_free_context(pp->pp_ctx); +} + +static const AVFilterPad pp_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = pp_config_props, + .filter_frame = pp_filter_frame, + .min_perms = AV_PERM_READ, + }, + { NULL } +}; + +static const AVFilterPad pp_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { NULL } +}; + +AVFilter avfilter_vf_pp = { + .name = "pp", + .description = NULL_IF_CONFIG_SMALL("Filter video using libpostproc."), + .priv_size = sizeof(PPFilterContext), + .init = pp_init, + .uninit = pp_uninit, + .query_formats = pp_query_formats, + .inputs = pp_inputs, + .outputs = pp_outputs, + .process_command = pp_process_command, +}; diff --git a/tests/lavfi-regression.sh b/tests/lavfi-regression.sh index 6899799afe..6278f0a36a 100755 --- a/tests/lavfi-regression.sh +++ b/tests/lavfi-regression.sh @@ -49,12 +49,12 @@ do_lavfi "idet" "idet" do_lavfi "null" "null" do_lavfi "overlay" "split[m],scale=88:72,pad=96:80:4:4[o2];[m]fifo[o1],[o1][o2]overlay=240:16" do_lavfi "pad" "pad=iw*1.5:ih*1.5:iw*0.3:ih*0.2" -do_lavfi "pp" "mp=pp=be/hb/vb/tn/l5/al" -do_lavfi "pp2" "mp=pp=be/fq:16/h1/v1/lb" -do_lavfi "pp3" "mp=pp=be/fq:8/ha:128:7/va/li" -do_lavfi "pp4" "mp=pp=be/ci" -do_lavfi "pp5" "mp=pp=md" -do_lavfi "pp6" "mp=pp=be/fd" +do_lavfi "pp" "pp=be/hb/vb/tn/l5/al" +do_lavfi "pp2" "pp=be/fq:16/h1/v1/lb" +do_lavfi "pp3" "pp=be/fq:8/ha:128:7/va/li" +do_lavfi "pp4" "pp=be/ci" +do_lavfi "pp5" "pp=md" +do_lavfi "pp6" "pp=be/fd" do_lavfi "scale200" "scale=200:200" do_lavfi "scale500" "scale=500:500" do_lavfi "select" "select=not(eq(mod(n\,2)\,0)+eq(mod(n\,3)\,0))"