FFmpeg
Loading...
Searching...
No Matches
vf_boxblur.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2011 Stefano Sabatini
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22/**
23 * @file
24 * Apply a boxblur filter to the input video.
25 * Ported from MPlayer libmpcodecs/vf_boxblur.c.
26 */
27
28#include "libavutil/avassert.h"
29#include "libavutil/common.h"
30#include "libavutil/mem.h"
31#include "libavutil/opt.h"
32#include "avfilter.h"
33#include "filters.h"
34#include "formats.h"
35#include "video.h"
36#include "boxblur.h"
37
38
39typedef struct BoxBlurContext {
40 const AVClass *class;
44
45 int hsub, vsub;
46 int radius[4];
47 int power[4];
48 uint8_t *temp[2]; ///< temporary buffer used in blur_power()
50
52{
53 BoxBlurContext *s = ctx->priv;
54
55 av_freep(&s->temp[0]);
56 av_freep(&s->temp[1]);
57}
58
60 AVFilterFormatsConfig **cfg_in,
61 AVFilterFormatsConfig **cfg_out)
62{
64 int fmt, ret;
65
66 for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
69 desc->comp[0].depth <= 16 &&
70 (desc->flags & AV_PIX_FMT_FLAG_PLANAR || desc->nb_components == 1) &&
71 (!(desc->flags & AV_PIX_FMT_FLAG_BE) == !HAVE_BIGENDIAN || desc->comp[0].depth == 8) &&
72 (ret = ff_add_format(&formats, fmt)) < 0)
73 return ret;
74 }
75
76 return ff_set_common_formats2(ctx, cfg_in, cfg_out, formats);
77}
78
79static int config_input(AVFilterLink *inlink)
80{
82 AVFilterContext *ctx = inlink->dst;
83 BoxBlurContext *s = ctx->priv;
84 int w = inlink->w, h = inlink->h;
85 int ret;
86
87 if (!(s->temp[0] = av_malloc(2*FFMAX(w, h))) ||
88 !(s->temp[1] = av_malloc(2*FFMAX(w, h))))
89 return AVERROR(ENOMEM);
90
91 s->hsub = desc->log2_chroma_w;
92 s->vsub = desc->log2_chroma_h;
93
95 &s->luma_param,
96 &s->chroma_param,
97 &s->alpha_param);
98
99 if (ret != 0) {
100 av_log(ctx, AV_LOG_ERROR, "Failed to evaluate "
101 "filter params: %d.\n", ret);
102 return ret;
103 }
104
105 s->radius[Y] = s->luma_param.radius;
106 s->radius[U] = s->radius[V] = s->chroma_param.radius;
107 s->radius[A] = s->alpha_param.radius;
108
109 s->power[Y] = s->luma_param.power;
110 s->power[U] = s->power[V] = s->chroma_param.power;
111 s->power[A] = s->alpha_param.power;
112
113 return 0;
114}
115
116/* Naive boxblur would sum source pixels from x-radius .. x+radius
117 * for destination pixel x. That would be O(radius*width).
118 * If you now look at what source pixels represent 2 consecutive
119 * output pixels, then you see they are almost identical and only
120 * differ by 2 pixels, like:
121 * src0 111111111
122 * dst0 1
123 * src1 111111111
124 * dst1 1
125 * src0-src1 1 -1
126 * so when you know one output pixel you can find the next by just adding
127 * and subtracting 1 input pixel.
128 * The following code adopts this faster variant.
129 */
130#define BLUR(type, depth) \
131static inline void blur ## depth(type *dst, int dst_step, const type *src, \
132 int src_step, int len, int radius) \
133{ \
134 const int length = radius*2 + 1; \
135 const int inv = ((1<<16) + length/2)/length; \
136 int x, sum = src[radius*src_step]; \
137 \
138 for (x = 0; x < radius; x++) \
139 sum += src[x*src_step]<<1; \
140 \
141 sum = sum*inv + (1<<15); \
142 \
143 for (x = 0; x <= radius; x++) { \
144 sum += (src[(radius+x)*src_step] - src[(radius-x)*src_step])*inv; \
145 dst[x*dst_step] = sum>>16; \
146 } \
147 \
148 for (; x < len-radius; x++) { \
149 sum += (src[(radius+x)*src_step] - src[(x-radius-1)*src_step])*inv; \
150 dst[x*dst_step] = sum >>16; \
151 } \
152 \
153 for (; x < len; x++) { \
154 sum += (src[(2*len-radius-x-1)*src_step] - src[(x-radius-1)*src_step])*inv; \
155 dst[x*dst_step] = sum>>16; \
156 } \
157}
158
159BLUR(uint8_t, 8)
160BLUR(uint16_t, 16)
161
162#undef BLUR
163
164static inline void blur(uint8_t *dst, int dst_step, const uint8_t *src, int src_step,
165 int len, int radius, int pixsize)
166{
167 if (pixsize == 1) blur8 (dst, dst_step , src, src_step , len, radius);
168 else if (pixsize == 2)
169 blur16((uint16_t*)dst, dst_step>>1, (const uint16_t*)src, src_step>>1, len, radius);
170 else
171 av_assert0(0);
172}
173
174static inline void blur_power(uint8_t *dst, int dst_step, const uint8_t *src, int src_step,
175 int len, int radius, int power, uint8_t *temp[2], int pixsize)
176{
177 uint8_t *a = temp[0], *b = temp[1];
178
179 if (radius && power) {
180 blur(a, pixsize, src, src_step, len, radius, pixsize);
181 for (; power > 2; power--) {
182 uint8_t *c;
183 blur(b, pixsize, a, pixsize, len, radius, pixsize);
184 c = a; a = b; b = c;
185 }
186 if (power > 1) {
187 blur(dst, dst_step, a, pixsize, len, radius, pixsize);
188 } else {
189 int i;
190 if (pixsize == 1) {
191 for (i = 0; i < len; i++)
192 dst[i*dst_step] = a[i];
193 } else
194 for (i = 0; i < len; i++)
195 *(uint16_t*)(dst + i*dst_step) = ((uint16_t*)a)[i];
196 }
197 } else {
198 int i;
199 if (pixsize == 1) {
200 for (i = 0; i < len; i++)
201 dst[i*dst_step] = src[i*src_step];
202 } else
203 for (i = 0; i < len; i++)
204 *(uint16_t*)(dst + i*dst_step) = *(uint16_t*)(src + i*src_step);
205 }
206}
207
208static void hblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize,
209 int w, int h, int radius, int power, uint8_t *temp[2], int pixsize)
210{
211 int y;
212
213 if (radius == 0 && dst == src)
214 return;
215
216 for (y = 0; y < h; y++)
217 blur_power(dst + y*dst_linesize, pixsize, src + y*src_linesize, pixsize,
218 w, radius, power, temp, pixsize);
219}
220
221static void vblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize,
222 int w, int h, int radius, int power, uint8_t *temp[2], int pixsize)
223{
224 int x;
225
226 if (radius == 0 && dst == src)
227 return;
228
229 for (x = 0; x < w; x++)
230 blur_power(dst + x*pixsize, dst_linesize, src + x*pixsize, src_linesize,
231 h, radius, power, temp, pixsize);
232}
233
234static int filter_frame(AVFilterLink *inlink, AVFrame *in)
235{
236 AVFilterContext *ctx = inlink->dst;
237 BoxBlurContext *s = ctx->priv;
238 AVFilterLink *outlink = inlink->dst->outputs[0];
239 AVFrame *out;
240 int plane;
241 int cw = AV_CEIL_RSHIFT(inlink->w, s->hsub), ch = AV_CEIL_RSHIFT(in->height, s->vsub);
242 int w[4] = { inlink->w, cw, cw, inlink->w };
243 int h[4] = { in->height, ch, ch, in->height };
245 const int depth = desc->comp[0].depth;
246 const int pixsize = (depth+7)/8;
247
248 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
249 if (!out) {
250 av_frame_free(&in);
251 return AVERROR(ENOMEM);
252 }
254
255 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++)
256 hblur(out->data[plane], out->linesize[plane],
257 in ->data[plane], in ->linesize[plane],
258 w[plane], h[plane], s->radius[plane], s->power[plane],
259 s->temp, pixsize);
260
261 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++)
262 vblur(out->data[plane], out->linesize[plane],
263 out->data[plane], out->linesize[plane],
264 w[plane], h[plane], s->radius[plane], s->power[plane],
265 s->temp, pixsize);
266
267 av_frame_free(&in);
268
269 return ff_filter_frame(outlink, out);
270}
271
272#define OFFSET(x) offsetof(BoxBlurContext, x)
273#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
274
275static const AVOption boxblur_options[] = {
276 { "luma_radius", "Radius of the luma blurring box", OFFSET(luma_param.radius_expr), AV_OPT_TYPE_STRING, {.str="2"}, .flags = FLAGS },
277 { "lr", "Radius of the luma blurring box", OFFSET(luma_param.radius_expr), AV_OPT_TYPE_STRING, {.str="2"}, .flags = FLAGS },
278 { "luma_power", "How many times should the boxblur be applied to luma", OFFSET(luma_param.power), AV_OPT_TYPE_INT, {.i64=2}, 0, INT_MAX, .flags = FLAGS },
279 { "lp", "How many times should the boxblur be applied to luma", OFFSET(luma_param.power), AV_OPT_TYPE_INT, {.i64=2}, 0, INT_MAX, .flags = FLAGS },
280
281 { "chroma_radius", "Radius of the chroma blurring box", OFFSET(chroma_param.radius_expr), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
282 { "cr", "Radius of the chroma blurring box", OFFSET(chroma_param.radius_expr), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
283 { "chroma_power", "How many times should the boxblur be applied to chroma", OFFSET(chroma_param.power), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
284 { "cp", "How many times should the boxblur be applied to chroma", OFFSET(chroma_param.power), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
285
286 { "alpha_radius", "Radius of the alpha blurring box", OFFSET(alpha_param.radius_expr), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
287 { "ar", "Radius of the alpha blurring box", OFFSET(alpha_param.radius_expr), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
288 { "alpha_power", "How many times should the boxblur be applied to alpha", OFFSET(alpha_param.power), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
289 { "ap", "How many times should the boxblur be applied to alpha", OFFSET(alpha_param.power), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, .flags = FLAGS },
290
291 { NULL }
292};
293
295
297 {
298 .name = "default",
299 .type = AVMEDIA_TYPE_VIDEO,
300 .config_props = config_input,
301 .filter_frame = filter_frame,
302 },
303};
304
306 .p.name = "boxblur",
307 .p.description = NULL_IF_CONFIG_SMALL("Blur the input."),
308 .p.priv_class = &boxblur_class,
310 .priv_size = sizeof(BoxBlurContext),
311 .uninit = uninit,
315};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition aeval.c:246
static int config_input(AVFilterLink *inlink)
const FFFilter ff_vf_boxblur
Definition vf_boxblur.c:305
#define U(x)
Definition vpx_arith.h:37
#define A(x)
Definition vpx_arith.h:28
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define V
Definition avdct.c:32
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
Main libavfilter public API header.
int ff_boxblur_eval_filter_params(AVFilterLink *inlink, FilterParam *luma_param, FilterParam *chroma_param, FilterParam *alpha_param)
Definition boxblur.c:47
#define Y
Definition boxblur.h:37
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
common internal and external API header
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define NULL
Definition coverity.c:32
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
int ff_set_common_formats2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, AVFilterFormats *formats)
Definition formats.c:1137
int ff_add_format(AVFilterFormats **avff, int64_t fmt)
Add fmt to the list of media formats contained in *avff.
Definition formats.c:571
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition avfilter.h:196
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int a
#define b
Definition input.c:43
static av_cold void uninit(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
const char * desc
Definition libsvtav1.c:83
uint8_t w
Definition llvidencdsp.c:39
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_BITSTREAM
All values of a component are bit-wise packed end to end.
Definition pixdesc.h:124
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition pixdesc.h:128
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition pixdesc.h:132
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition pixdesc.h:116
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition pixdesc.h:120
static float power(float r, float g, float b, float max)
formats
Definition signature.h:47
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
AVFilterLink ** outputs
array of pointers to output links
Definition avfilter.h:285
Lists of formats / etc.
Definition avfilter.h:120
A list of supported formats for one end of a filter link.
Definition formats.h:64
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int height
Definition frame.h:544
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
FilterParam luma_param
Definition vf_boxblur.c:41
uint8_t * temp[2]
temporary buffer used in blur_power()
Definition vf_boxblur.c:48
FilterParam chroma_param
Definition vf_boxblur.c:42
FilterParam alpha_param
Definition vf_boxblur.c:43
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
static void vblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int w, int h, int radius, int power, uint8_t *temp[2], int pixsize)
Definition vf_boxblur.c:221
static const AVFilterPad avfilter_vf_boxblur_inputs[]
Definition vf_boxblur.c:296
#define BLUR(type, depth)
Definition vf_boxblur.c:130
static int config_input(AVFilterLink *inlink)
Definition vf_boxblur.c:79
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition vf_boxblur.c:234
static const AVOption boxblur_options[]
Definition vf_boxblur.c:275
static void blur_power(uint8_t *dst, int dst_step, const uint8_t *src, int src_step, int len, int radius, int power, uint8_t *temp[2], int pixsize)
Definition vf_boxblur.c:174
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition vf_boxblur.c:59
static av_cold void uninit(AVFilterContext *ctx)
Definition vf_boxblur.c:51
static void hblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int w, int h, int radius, int power, uint8_t *temp[2], int pixsize)
Definition vf_boxblur.c:208
#define OFFSET(x)
Definition vf_boxblur.c:272
static void blur(uint8_t *dst, int dst_step, const uint8_t *src, int src_step, int len, int radius, int pixsize)
Definition vf_boxblur.c:164
else temp
Definition vf_mcdeint.c:275
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
Definition video.c:37
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89
int len
static double c[64]