Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
  3.  * Copyright (c) 2013 Paul B Mahol
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (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 GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. /**
  23.  * @file
  24.  * noise generator
  25.  */
  26.  
  27. #include "libavutil/opt.h"
  28. #include "libavutil/imgutils.h"
  29. #include "libavutil/lfg.h"
  30. #include "libavutil/parseutils.h"
  31. #include "libavutil/pixdesc.h"
  32. #include "avfilter.h"
  33. #include "formats.h"
  34. #include "internal.h"
  35. #include "vf_noise.h"
  36. #include "video.h"
  37.  
  38. typedef struct ThreadData {
  39.     AVFrame *in, *out;
  40. } ThreadData;
  41.  
  42. #define OFFSET(x) offsetof(NoiseContext, x)
  43. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  44.  
  45. #define NOISE_PARAMS(name, x, param)                                                                                             \
  46.     {#name"_seed", "set component #"#x" noise seed", OFFSET(param.seed), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, FLAGS},        \
  47.     {#name"_strength", "set component #"#x" strength", OFFSET(param.strength), AV_OPT_TYPE_INT, {.i64=0}, 0, 100, FLAGS},        \
  48.     {#name"s",         "set component #"#x" strength", OFFSET(param.strength), AV_OPT_TYPE_INT, {.i64=0}, 0, 100, FLAGS},        \
  49.     {#name"_flags", "set component #"#x" flags", OFFSET(param.flags), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, 31, FLAGS, #name"_flags"}, \
  50.     {#name"f", "set component #"#x" flags", OFFSET(param.flags), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, 31, FLAGS, #name"_flags"},      \
  51.     {"a", "averaged noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_AVERAGED}, 0, 0, FLAGS, #name"_flags"},                            \
  52.     {"p", "(semi)regular pattern", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_PATTERN},  0, 0, FLAGS, #name"_flags"},                     \
  53.     {"t", "temporal noise", 0, AV_OPT_TYPE_CONST, {.i64=NOISE_TEMPORAL}, 0, 0, FLAGS, #name"_flags"},                            \
  54.     {"u", "uniform noise",  0, AV_OPT_TYPE_CONST, {.i64=NOISE_UNIFORM},  0, 0, FLAGS, #name"_flags"},
  55.  
  56. static const AVOption noise_options[] = {
  57.     NOISE_PARAMS(all, 0, all)
  58.     NOISE_PARAMS(c0,  0, param[0])
  59.     NOISE_PARAMS(c1,  1, param[1])
  60.     NOISE_PARAMS(c2,  2, param[2])
  61.     NOISE_PARAMS(c3,  3, param[3])
  62.     {NULL}
  63. };
  64.  
  65. AVFILTER_DEFINE_CLASS(noise);
  66.  
  67. static const int8_t patt[4] = { -1, 0, 1, 0 };
  68.  
  69. #define RAND_N(range) ((int) ((double) range * av_lfg_get(lfg) / (UINT_MAX + 1.0)))
  70. static av_cold int init_noise(NoiseContext *n, int comp)
  71. {
  72.     int8_t *noise = av_malloc(MAX_NOISE * sizeof(int8_t));
  73.     FilterParams *fp = &n->param[comp];
  74.     AVLFG *lfg = &n->param[comp].lfg;
  75.     int strength = fp->strength;
  76.     int flags = fp->flags;
  77.     int i, j;
  78.  
  79.     if (!noise)
  80.         return AVERROR(ENOMEM);
  81.  
  82.     av_lfg_init(&fp->lfg, fp->seed + comp*31415U);
  83.  
  84.     for (i = 0, j = 0; i < MAX_NOISE; i++, j++) {
  85.         if (flags & NOISE_UNIFORM) {
  86.             if (flags & NOISE_AVERAGED) {
  87.                 if (flags & NOISE_PATTERN) {
  88.                     noise[i] = (RAND_N(strength) - strength / 2) / 6
  89.                         + patt[j % 4] * strength * 0.25 / 3;
  90.                 } else {
  91.                     noise[i] = (RAND_N(strength) - strength / 2) / 3;
  92.                 }
  93.             } else {
  94.                 if (flags & NOISE_PATTERN) {
  95.                     noise[i] = (RAND_N(strength) - strength / 2) / 2
  96.                         + patt[j % 4] * strength * 0.25;
  97.                 } else {
  98.                     noise[i] = RAND_N(strength) - strength / 2;
  99.                 }
  100.             }
  101.         } else {
  102.             double x1, x2, w, y1;
  103.             do {
  104.                 x1 = 2.0 * av_lfg_get(lfg) / (float)UINT_MAX - 1.0;
  105.                 x2 = 2.0 * av_lfg_get(lfg) / (float)UINT_MAX - 1.0;
  106.                 w = x1 * x1 + x2 * x2;
  107.             } while (w >= 1.0);
  108.  
  109.             w   = sqrt((-2.0 * log(w)) / w);
  110.             y1  = x1 * w;
  111.             y1 *= strength / sqrt(3.0);
  112.             if (flags & NOISE_PATTERN) {
  113.                 y1 /= 2;
  114.                 y1 += patt[j % 4] * strength * 0.35;
  115.             }
  116.             y1 = av_clipf(y1, -128, 127);
  117.             if (flags & NOISE_AVERAGED)
  118.                 y1 /= 3.0;
  119.             noise[i] = (int)y1;
  120.         }
  121.         if (RAND_N(6) == 0)
  122.             j--;
  123.     }
  124.  
  125.     for (i = 0; i < MAX_RES; i++)
  126.         for (j = 0; j < 3; j++)
  127.             fp->prev_shift[i][j] = noise + (av_lfg_get(lfg) & (MAX_SHIFT - 1));
  128.  
  129.     fp->noise = noise;
  130.     return 0;
  131. }
  132.  
  133. static int query_formats(AVFilterContext *ctx)
  134. {
  135.     AVFilterFormats *formats = NULL;
  136.     int fmt;
  137.  
  138.     for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
  139.         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
  140.         if (desc->flags & AV_PIX_FMT_FLAG_PLANAR && !((desc->comp[0].depth_minus1 + 1) & 7))
  141.             ff_add_format(&formats, fmt);
  142.     }
  143.  
  144.     return ff_set_common_formats(ctx, formats);
  145. }
  146.  
  147. static int config_input(AVFilterLink *inlink)
  148. {
  149.     NoiseContext *n = inlink->dst->priv;
  150.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
  151.     int ret;
  152.  
  153.     n->nb_planes = av_pix_fmt_count_planes(inlink->format);
  154.  
  155.     if ((ret = av_image_fill_linesizes(n->bytewidth, inlink->format, inlink->w)) < 0)
  156.         return ret;
  157.  
  158.     n->height[1] = n->height[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
  159.     n->height[0] = n->height[3] = inlink->h;
  160.  
  161.     return 0;
  162. }
  163.  
  164. void ff_line_noise_c(uint8_t *dst, const uint8_t *src, const int8_t *noise,
  165.                      int len, int shift)
  166. {
  167.     int i;
  168.  
  169.     noise += shift;
  170.     for (i = 0; i < len; i++) {
  171.         int v = src[i] + noise[i];
  172.  
  173.         dst[i] = av_clip_uint8(v);
  174.     }
  175. }
  176.  
  177. void ff_line_noise_avg_c(uint8_t *dst, const uint8_t *src,
  178.                          int len, const int8_t * const *shift)
  179. {
  180.     int i;
  181.     const int8_t *src2 = (const int8_t*)src;
  182.  
  183.     for (i = 0; i < len; i++) {
  184.         const int n = shift[0][i] + shift[1][i] + shift[2][i];
  185.         dst[i] = src2[i] + ((n * src2[i]) >> 7);
  186.     }
  187. }
  188.  
  189. static void noise(uint8_t *dst, const uint8_t *src,
  190.                   int dst_linesize, int src_linesize,
  191.                   int width, int start, int end, NoiseContext *n, int comp)
  192. {
  193.     FilterParams *p = &n->param[comp];
  194.     int8_t *noise = p->noise;
  195.     const int flags = p->flags;
  196.     int y;
  197.  
  198.     if (!noise) {
  199.         if (dst != src)
  200.             av_image_copy_plane(dst, dst_linesize, src, src_linesize, width, end - start);
  201.         return;
  202.     }
  203.  
  204.     for (y = start; y < end; y++) {
  205.         const int ix = y & (MAX_RES - 1);
  206.         int x;
  207.         for (x=0; x < width; x+= MAX_RES) {
  208.             int w = FFMIN(width - x, MAX_RES);
  209.             int shift = p->rand_shift[ix];
  210.  
  211.             if (flags & NOISE_AVERAGED) {
  212.                 n->line_noise_avg(dst + x, src + x, w, (const int8_t**)p->prev_shift[ix]);
  213.                 p->prev_shift[ix][shift & 3] = noise + shift;
  214.             } else {
  215.                 n->line_noise(dst + x, src + x, noise, w, shift);
  216.             }
  217.         }
  218.         dst += dst_linesize;
  219.         src += src_linesize;
  220.     }
  221. }
  222.  
  223. static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
  224. {
  225.     NoiseContext *s = ctx->priv;
  226.     ThreadData *td = arg;
  227.     int plane;
  228.  
  229.     for (plane = 0; plane < s->nb_planes; plane++) {
  230.         const int height = s->height[plane];
  231.         const int start  = (height *  jobnr   ) / nb_jobs;
  232.         const int end    = (height * (jobnr+1)) / nb_jobs;
  233.         noise(td->out->data[plane] + start * td->out->linesize[plane],
  234.               td->in->data[plane]  + start * td->in->linesize[plane],
  235.               td->out->linesize[plane], td->in->linesize[plane],
  236.               s->bytewidth[plane], start, end, s, plane);
  237.     }
  238.     return 0;
  239. }
  240.  
  241. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  242. {
  243.     AVFilterContext *ctx = inlink->dst;
  244.     AVFilterLink *outlink = ctx->outputs[0];
  245.     NoiseContext *n = ctx->priv;
  246.     ThreadData td;
  247.     AVFrame *out;
  248.     int comp, i;
  249.  
  250.     if (av_frame_is_writable(inpicref)) {
  251.         out = inpicref;
  252.     } else {
  253.         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  254.         if (!out) {
  255.             av_frame_free(&inpicref);
  256.             return AVERROR(ENOMEM);
  257.         }
  258.         av_frame_copy_props(out, inpicref);
  259.     }
  260.  
  261.     for (comp = 0; comp < 4; comp++) {
  262.         FilterParams *fp = &n->param[comp];
  263.  
  264.         if ((!fp->rand_shift_init || (fp->flags & NOISE_TEMPORAL)) && fp->strength) {
  265.  
  266.             for (i = 0; i < MAX_RES; i++) {
  267.                 fp->rand_shift[i] = av_lfg_get(&fp->lfg) & (MAX_SHIFT - 1);
  268.             }
  269.             fp->rand_shift_init = 1;
  270.         }
  271.     }
  272.  
  273.     td.in = inpicref; td.out = out;
  274.     ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(n->height[0], ctx->graph->nb_threads));
  275.     emms_c();
  276.  
  277.     if (inpicref != out)
  278.         av_frame_free(&inpicref);
  279.     return ff_filter_frame(outlink, out);
  280. }
  281.  
  282. static av_cold int init(AVFilterContext *ctx)
  283. {
  284.     NoiseContext *n = ctx->priv;
  285.     int ret, i;
  286.  
  287.     for (i = 0; i < 4; i++) {
  288.         if (n->all.seed >= 0)
  289.             n->param[i].seed = n->all.seed;
  290.         else
  291.             n->param[i].seed = 123457;
  292.         if (n->all.strength)
  293.             n->param[i].strength = n->all.strength;
  294.         if (n->all.flags)
  295.             n->param[i].flags = n->all.flags;
  296.     }
  297.  
  298.     for (i = 0; i < 4; i++) {
  299.         if (n->param[i].strength && ((ret = init_noise(n, i)) < 0))
  300.             return ret;
  301.     }
  302.  
  303.     n->line_noise     = ff_line_noise_c;
  304.     n->line_noise_avg = ff_line_noise_avg_c;
  305.  
  306.     if (ARCH_X86)
  307.         ff_noise_init_x86(n);
  308.  
  309.     return 0;
  310. }
  311.  
  312. static av_cold void uninit(AVFilterContext *ctx)
  313. {
  314.     NoiseContext *n = ctx->priv;
  315.     int i;
  316.  
  317.     for (i = 0; i < 4; i++)
  318.         av_freep(&n->param[i].noise);
  319. }
  320.  
  321. static const AVFilterPad noise_inputs[] = {
  322.     {
  323.         .name         = "default",
  324.         .type         = AVMEDIA_TYPE_VIDEO,
  325.         .filter_frame = filter_frame,
  326.         .config_props = config_input,
  327.     },
  328.     { NULL }
  329. };
  330.  
  331. static const AVFilterPad noise_outputs[] = {
  332.     {
  333.         .name = "default",
  334.         .type = AVMEDIA_TYPE_VIDEO,
  335.     },
  336.     { NULL }
  337. };
  338.  
  339. AVFilter ff_vf_noise = {
  340.     .name          = "noise",
  341.     .description   = NULL_IF_CONFIG_SMALL("Add noise."),
  342.     .priv_size     = sizeof(NoiseContext),
  343.     .init          = init,
  344.     .uninit        = uninit,
  345.     .query_formats = query_formats,
  346.     .inputs        = noise_inputs,
  347.     .outputs       = noise_outputs,
  348.     .priv_class    = &noise_class,
  349.     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
  350. };
  351.