• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/imgutils.h"
22 #include "libavutil/opt.h"
23 #include "libavutil/pixdesc.h"
24 #include "libavutil/qsort.h"
25 #include "avfilter.h"
26 
27 #define FF_BUFQUEUE_SIZE 129
28 #include "bufferqueue.h"
29 
30 #include "formats.h"
31 #include "internal.h"
32 #include "video.h"
33 
34 #define SIZE FF_BUFQUEUE_SIZE
35 
36 enum smooth_mode {
37     ARITHMETIC_MEAN,
38     GEOMETRIC_MEAN,
39     HARMONIC_MEAN,
40     QUADRATIC_MEAN,
41     CUBIC_MEAN,
42     POWER_MEAN,
43     MEDIAN,
44     NB_SMOOTH_MODE,
45 };
46 
47 typedef struct DeflickerContext {
48     const AVClass *class;
49 
50     int size;
51     int mode;
52     int bypass;
53 
54     int eof;
55     int depth;
56     int nb_planes;
57     int planewidth[4];
58     int planeheight[4];
59 
60     uint64_t *histogram;
61     float luminance[SIZE];
62     float sorted[SIZE];
63 
64     struct FFBufQueue q;
65     int available;
66 
67     void (*get_factor)(AVFilterContext *ctx, float *f);
68     float (*calc_avgy)(AVFilterContext *ctx, AVFrame *in);
69     int (*deflicker)(AVFilterContext *ctx, const uint8_t *src, ptrdiff_t src_linesize,
70                      uint8_t *dst, ptrdiff_t dst_linesize, int w, int h, float f);
71 } DeflickerContext;
72 
73 #define OFFSET(x) offsetof(DeflickerContext, x)
74 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
75 
76 static const AVOption deflicker_options[] = {
77     { "size",  "set how many frames to use",  OFFSET(size), AV_OPT_TYPE_INT, {.i64=5}, 2, SIZE, FLAGS },
78     { "s",     "set how many frames to use",  OFFSET(size), AV_OPT_TYPE_INT, {.i64=5}, 2, SIZE, FLAGS },
79     { "mode",  "set how to smooth luminance", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SMOOTH_MODE-1, FLAGS, "mode" },
80     { "m",     "set how to smooth luminance", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SMOOTH_MODE-1, FLAGS, "mode" },
81         { "am",      "arithmetic mean", 0, AV_OPT_TYPE_CONST, {.i64=ARITHMETIC_MEAN},  0, 0, FLAGS, "mode" },
82         { "gm",      "geometric mean",  0, AV_OPT_TYPE_CONST, {.i64=GEOMETRIC_MEAN},   0, 0, FLAGS, "mode" },
83         { "hm",      "harmonic mean",   0, AV_OPT_TYPE_CONST, {.i64=HARMONIC_MEAN},    0, 0, FLAGS, "mode" },
84         { "qm",      "quadratic mean",  0, AV_OPT_TYPE_CONST, {.i64=QUADRATIC_MEAN},   0, 0, FLAGS, "mode" },
85         { "cm",      "cubic mean",      0, AV_OPT_TYPE_CONST, {.i64=CUBIC_MEAN},       0, 0, FLAGS, "mode" },
86         { "pm",      "power mean",      0, AV_OPT_TYPE_CONST, {.i64=POWER_MEAN},       0, 0, FLAGS, "mode" },
87         { "median",  "median",          0, AV_OPT_TYPE_CONST, {.i64=MEDIAN},           0, 0, FLAGS, "mode" },
88     { "bypass", "leave frames unchanged",  OFFSET(bypass), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
89     { NULL }
90 };
91 
92 AVFILTER_DEFINE_CLASS(deflicker);
93 
94 static const enum AVPixelFormat pixel_fmts[] = {
95     AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10,
96     AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16,
97     AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,
98     AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
99     AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
100     AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P,
101     AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P,
102     AV_PIX_FMT_YUVJ411P,
103     AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9,
104     AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
105     AV_PIX_FMT_YUV440P10,
106     AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12,
107     AV_PIX_FMT_YUV440P12,
108     AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14,
109     AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16,
110     AV_PIX_FMT_YUVA420P,  AV_PIX_FMT_YUVA422P,   AV_PIX_FMT_YUVA444P,
111     AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16,
112     AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16,
113     AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16,
114     AV_PIX_FMT_NONE
115 };
116 
deflicker8(AVFilterContext * ctx,const uint8_t * src,ptrdiff_t src_linesize,uint8_t * dst,ptrdiff_t dst_linesize,int w,int h,float f)117 static int deflicker8(AVFilterContext *ctx,
118                       const uint8_t *src, ptrdiff_t src_linesize,
119                       uint8_t *dst, ptrdiff_t dst_linesize,
120                       int w, int h, float f)
121 {
122     int x, y;
123 
124     for (y = 0; y < h; y++) {
125         for (x = 0; x < w; x++) {
126             dst[x] = av_clip_uint8(src[x] * f);
127         }
128 
129         dst += dst_linesize;
130         src += src_linesize;
131     }
132 
133     return 0;
134 }
135 
deflicker16(AVFilterContext * ctx,const uint8_t * ssrc,ptrdiff_t src_linesize,uint8_t * ddst,ptrdiff_t dst_linesize,int w,int h,float f)136 static int deflicker16(AVFilterContext *ctx,
137                        const uint8_t *ssrc, ptrdiff_t src_linesize,
138                        uint8_t *ddst, ptrdiff_t dst_linesize,
139                        int w, int h, float f)
140 {
141     DeflickerContext *s = ctx->priv;
142     const uint16_t *src = (const uint16_t *)ssrc;
143     uint16_t *dst = (uint16_t *)ddst;
144     const int max = (1 << s->depth) - 1;
145     int x, y;
146 
147     for (y = 0; y < h; y++) {
148         for (x = 0; x < w; x++) {
149             dst[x] = av_clip(src[x] * f, 0, max);
150         }
151 
152         dst += dst_linesize / 2;
153         src += src_linesize / 2;
154     }
155 
156     return 0;
157 }
158 
calc_avgy8(AVFilterContext * ctx,AVFrame * in)159 static float calc_avgy8(AVFilterContext *ctx, AVFrame *in)
160 {
161     DeflickerContext *s = ctx->priv;
162     const uint8_t *src = in->data[0];
163     int64_t sum = 0;
164     int y, x;
165 
166     memset(s->histogram, 0, (1 << s->depth) * sizeof(*s->histogram));
167 
168     for (y = 0; y < s->planeheight[0]; y++) {
169         for (x = 0; x < s->planewidth[0]; x++) {
170             s->histogram[src[x]]++;
171         }
172         src += in->linesize[0];
173     }
174 
175     for (y = 0; y < 1 << s->depth; y++) {
176         sum += s->histogram[y] * y;
177     }
178 
179     return 1.0f * sum / (s->planeheight[0] * s->planewidth[0]);
180 }
181 
calc_avgy16(AVFilterContext * ctx,AVFrame * in)182 static float calc_avgy16(AVFilterContext *ctx, AVFrame *in)
183 {
184     DeflickerContext *s = ctx->priv;
185     const uint16_t *src = (const uint16_t *)in->data[0];
186     int64_t sum = 0;
187     int y, x;
188 
189     memset(s->histogram, 0, (1 << s->depth) * sizeof(*s->histogram));
190 
191     for (y = 0; y < s->planeheight[0]; y++) {
192         for (x = 0; x < s->planewidth[0]; x++) {
193             s->histogram[src[x]]++;
194         }
195         src += in->linesize[0] / 2;
196     }
197 
198     for (y = 0; y < 1 << s->depth; y++) {
199         sum += s->histogram[y] * y;
200     }
201 
202     return 1.0f * sum / (s->planeheight[0] * s->planewidth[0]);
203 }
204 
get_am_factor(AVFilterContext * ctx,float * f)205 static void get_am_factor(AVFilterContext *ctx, float *f)
206 {
207     DeflickerContext *s = ctx->priv;
208     int y;
209 
210     *f = 0.0f;
211 
212     for (y = 0; y < s->size; y++) {
213         *f += s->luminance[y];
214     }
215 
216     *f /= s->size;
217     *f /= s->luminance[0];
218 }
219 
get_gm_factor(AVFilterContext * ctx,float * f)220 static void get_gm_factor(AVFilterContext *ctx, float *f)
221 {
222     DeflickerContext *s = ctx->priv;
223     int y;
224 
225     *f = 1;
226 
227     for (y = 0; y < s->size; y++) {
228         *f *= s->luminance[y];
229     }
230 
231     *f = pow(*f, 1.0f / s->size);
232     *f /= s->luminance[0];
233 }
234 
get_hm_factor(AVFilterContext * ctx,float * f)235 static void get_hm_factor(AVFilterContext *ctx, float *f)
236 {
237     DeflickerContext *s = ctx->priv;
238     int y;
239 
240     *f = 0.0f;
241 
242     for (y = 0; y < s->size; y++) {
243         *f += 1.0f / s->luminance[y];
244     }
245 
246     *f = s->size / *f;
247     *f /= s->luminance[0];
248 }
249 
get_qm_factor(AVFilterContext * ctx,float * f)250 static void get_qm_factor(AVFilterContext *ctx, float *f)
251 {
252     DeflickerContext *s = ctx->priv;
253     int y;
254 
255     *f = 0.0f;
256 
257     for (y = 0; y < s->size; y++) {
258         *f += s->luminance[y] * s->luminance[y];
259     }
260 
261     *f /= s->size;
262     *f  = sqrtf(*f);
263     *f /= s->luminance[0];
264 }
265 
get_cm_factor(AVFilterContext * ctx,float * f)266 static void get_cm_factor(AVFilterContext *ctx, float *f)
267 {
268     DeflickerContext *s = ctx->priv;
269     int y;
270 
271     *f = 0.0f;
272 
273     for (y = 0; y < s->size; y++) {
274         *f += s->luminance[y] * s->luminance[y] * s->luminance[y];
275     }
276 
277     *f /= s->size;
278     *f  = cbrtf(*f);
279     *f /= s->luminance[0];
280 }
281 
get_pm_factor(AVFilterContext * ctx,float * f)282 static void get_pm_factor(AVFilterContext *ctx, float *f)
283 {
284     DeflickerContext *s = ctx->priv;
285     int y;
286 
287     *f = 0.0f;
288 
289     for (y = 0; y < s->size; y++) {
290         *f += powf(s->luminance[y], s->size);
291     }
292 
293     *f /= s->size;
294     *f  = powf(*f, 1.0f / s->size);
295     *f /= s->luminance[0];
296 }
297 
comparef(const void * a,const void * b)298 static int comparef(const void *a, const void *b)
299 {
300     const float *aa = a, *bb = b;
301     return round(aa - bb);
302 }
303 
get_median_factor(AVFilterContext * ctx,float * f)304 static void get_median_factor(AVFilterContext *ctx, float *f)
305 {
306     DeflickerContext *s = ctx->priv;
307 
308     memcpy(s->sorted, s->luminance, sizeof(s->sorted));
309     AV_QSORT(s->sorted, s->size, float, comparef);
310 
311     *f = s->sorted[s->size >> 1] / s->luminance[0];
312 }
313 
config_input(AVFilterLink * inlink)314 static int config_input(AVFilterLink *inlink)
315 {
316     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
317     AVFilterContext *ctx = inlink->dst;
318     DeflickerContext *s = ctx->priv;
319 
320     s->nb_planes = desc->nb_components;
321 
322     s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
323     s->planeheight[0] = s->planeheight[3] = inlink->h;
324     s->planewidth[1]  = s->planewidth[2]  = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
325     s->planewidth[0]  = s->planewidth[3]  = inlink->w;
326 
327     s->depth = desc->comp[0].depth;
328     if (s->depth == 8) {
329         s->deflicker = deflicker8;
330         s->calc_avgy = calc_avgy8;
331     } else {
332         s->deflicker = deflicker16;
333         s->calc_avgy = calc_avgy16;
334     }
335 
336     s->histogram = av_calloc(1 << s->depth, sizeof(*s->histogram));
337     if (!s->histogram)
338         return AVERROR(ENOMEM);
339 
340     switch (s->mode) {
341     case MEDIAN:          s->get_factor = get_median_factor; break;
342     case ARITHMETIC_MEAN: s->get_factor = get_am_factor;     break;
343     case GEOMETRIC_MEAN:  s->get_factor = get_gm_factor;     break;
344     case HARMONIC_MEAN:   s->get_factor = get_hm_factor;     break;
345     case QUADRATIC_MEAN:  s->get_factor = get_qm_factor;     break;
346     case CUBIC_MEAN:      s->get_factor = get_cm_factor;     break;
347     case POWER_MEAN:      s->get_factor = get_pm_factor;     break;
348     }
349 
350     return 0;
351 }
352 
filter_frame(AVFilterLink * inlink,AVFrame * buf)353 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
354 {
355     AVFilterContext *ctx = inlink->dst;
356     AVFilterLink *outlink = ctx->outputs[0];
357     DeflickerContext *s = ctx->priv;
358     AVDictionary **metadata;
359     AVFrame *out, *in;
360     float f;
361     int y;
362 
363     if (s->q.available < s->size && !s->eof) {
364         s->luminance[s->available] = s->calc_avgy(ctx, buf);
365         ff_bufqueue_add(ctx, &s->q, buf);
366         s->available++;
367         return 0;
368     }
369 
370     in = ff_bufqueue_peek(&s->q, 0);
371 
372     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
373     if (!out) {
374         av_frame_free(&buf);
375         return AVERROR(ENOMEM);
376     }
377 
378     s->get_factor(ctx, &f);
379     if (!s->bypass)
380         s->deflicker(ctx, in->data[0], in->linesize[0], out->data[0], out->linesize[0],
381                      outlink->w, outlink->h, f);
382     for (y = 1 - s->bypass; y < s->nb_planes; y++) {
383         av_image_copy_plane(out->data[y], out->linesize[y],
384                             in->data[y], in->linesize[y],
385                             s->planewidth[y] * (1 + (s->depth > 8)), s->planeheight[y]);
386     }
387 
388     av_frame_copy_props(out, in);
389     metadata = &out->metadata;
390     if (metadata) {
391         uint8_t value[128];
392 
393         snprintf(value, sizeof(value), "%f", s->luminance[0]);
394         av_dict_set(metadata, "lavfi.deflicker.luminance", value, 0);
395 
396         snprintf(value, sizeof(value), "%f", s->luminance[0] * f);
397         av_dict_set(metadata, "lavfi.deflicker.new_luminance", value, 0);
398 
399         snprintf(value, sizeof(value), "%f", f - 1.0f);
400         av_dict_set(metadata, "lavfi.deflicker.relative_change", value, 0);
401     }
402 
403     in = ff_bufqueue_get(&s->q);
404     av_frame_free(&in);
405     memmove(&s->luminance[0], &s->luminance[1], sizeof(*s->luminance) * (s->size - 1));
406     s->luminance[s->available - 1] = s->calc_avgy(ctx, buf);
407     ff_bufqueue_add(ctx, &s->q, buf);
408 
409     return ff_filter_frame(outlink, out);
410 }
411 
request_frame(AVFilterLink * outlink)412 static int request_frame(AVFilterLink *outlink)
413 {
414     AVFilterContext *ctx = outlink->src;
415     DeflickerContext *s = ctx->priv;
416     int ret;
417 
418     ret = ff_request_frame(ctx->inputs[0]);
419     if (ret == AVERROR_EOF && s->available > 0) {
420         AVFrame *buf = ff_bufqueue_peek(&s->q, s->available - 1);
421         if (!buf)
422             return AVERROR(ENOMEM);
423         buf = av_frame_clone(buf);
424         if (!buf)
425             return AVERROR(ENOMEM);
426 
427         s->eof = 1;
428         ret = filter_frame(ctx->inputs[0], buf);
429         s->available--;
430     }
431 
432     return ret;
433 }
434 
uninit(AVFilterContext * ctx)435 static av_cold void uninit(AVFilterContext *ctx)
436 {
437     DeflickerContext *s = ctx->priv;
438 
439     ff_bufqueue_discard_all(&s->q);
440     av_freep(&s->histogram);
441 }
442 
443 static const AVFilterPad inputs[] = {
444     {
445         .name         = "default",
446         .type         = AVMEDIA_TYPE_VIDEO,
447         .filter_frame = filter_frame,
448         .config_props = config_input,
449     },
450 };
451 
452 static const AVFilterPad outputs[] = {
453     {
454         .name          = "default",
455         .type          = AVMEDIA_TYPE_VIDEO,
456         .request_frame = request_frame,
457     },
458 };
459 
460 const AVFilter ff_vf_deflicker = {
461     .name          = "deflicker",
462     .description   = NULL_IF_CONFIG_SMALL("Remove temporal frame luminance variations."),
463     .priv_size     = sizeof(DeflickerContext),
464     .priv_class    = &deflicker_class,
465     .uninit        = uninit,
466     FILTER_INPUTS(inputs),
467     FILTER_OUTPUTS(outputs),
468     FILTER_PIXFMTS_ARRAY(pixel_fmts),
469 };
470