History

lavfi: add Perlin noise generator

Stefano Sabatini committed 2 years ago

Commit 3764b8e1 parent c9151ea7 files · +597 −0Browse files

Unified · Split

7 files
  1. Changelog +1 −0
  2. doc/filters.texi +100 −0
  3. libavfilter/Makefile +1 −0
  4. libavfilter/allfilters.c +1 −0
  5. libavfilter/perlin.c +224 −0
  6. libavfilter/perlin.h +101 −0
  7. libavfilter/vsrc_perlin.c +169 −0
Changelog+1−0
@@ -14,6 +14,7 @@ version <next>: · 13 unmodified lines
14- xHE-AAC decoder14- xHE-AAC decoder
15- removed DEC Alpha DSP and support code15- removed DEC Alpha DSP and support code
16- VVC encoding support via libvvenc16- VVC encoding support via libvvenc
17- perlin video source
17 18
18 19
19version 7.0:20version 7.0:
doc/filters.texi+100−0
@@ -17290,6 +17290,9 @@ The command accepts the same syntax of the corresponding option. · 17289 unmodified lines
17290If the specified expression is not valid, it is kept at its current17290If the specified expression is not valid, it is kept at its current
17291value.17291value.
17292 17292
17293@anchor{lutrgb}
17294@anchor{lutyuv}
17295@anchor{lut}
17293@section lut, lutrgb, lutyuv17296@section lut, lutrgb, lutyuv
17294 17297
17295Compute a look-up table for binding each pixel component input value17298Compute a look-up table for binding each pixel component input value
@@ -29281,6 +29284,103 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c · 11985 unmodified lines
29281@end example29284@end example
29282@end itemize29285@end itemize
29283 29286
29287@section perlin
29288Generate Perlin noise.
29289
29290Perlin noise is a kind of noise with local continuity in space. This
29291can be used to generate patterns with continuity in space and time,
29292e.g. to simulate smoke, fluids, or terrain.
29293
29294In case more than one octave is specified through the @option{octaves}
29295option, Perlin noise is generated as a sum of components, each one
29296with doubled frequency. In this case the @option{persistence} option
29297specify the ratio of the amplitude with respect to the previous
29298component. More octave components enable to specify more high
29299frequency details in the generated noise (e.g. small size variations
29300due to boulders in a generated terrain).
29301
29302@subsection Options
29303@table @option
29304
29305@item size, s
29306Specify the size (width and height) of the buffered video frames. For the
29307syntax of this option, check the
29308@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}.
29309
29310@item rate, r
29311Specify the frame rate expected for the video stream, expressed as a
29312number of frames per second.
29313
29314@item octaves
29315Specify the total number of components making up the noise, each one
29316with doubled frequency.
29317
29318@item persistence
29319Set the ratio used to compute the amplitude of the next octave
29320component with respect to the previous component amplitude.
29321
29322@item xscale
29323@item yscale
29324Define a scale factor used to multiple the x, y coordinates. This can
29325be useful to define an effect with a pattern stretched along the x or
29326y axis.
29327
29328@item tscale
29329Define a scale factor used to multiple the time coordinate. This can
29330be useful to change the time variation speed.
29331
29332@item random_mode
29333Set random mode used to compute initial pattern.
29334
29335Supported values are:
29336@table @option
29337@item random
29338Compute and use random seed.
29339
29340@item ken
29341Use the predefined initial pattern defined by Ken Perlin in the
29342original article, can be useful to compare the output with other
29343sources.
29344
29345@item seed
29346Use the value specified by @option{random_seed} option.
29347@end table
29348
29349@item random_seed, seed
29350When @option{random_mode} is set to @var{random_seed}, use this value
29351to compute the initial pattern.
29352@end table
29353
29354@subsection Examples
29355@itemize
29356@item
29357Generate single component:
29358@example
29359perlin
29360@end example
29361
29362@item
29363Use Perlin noise with 7 components, each one with a halved contribution
29364to total amplitude:
29365@example
29366perlin=octaves=7:persistence=0.5
29367@end example
29368
29369@item
29370Chain Perlin noise with the @ref{lutyuv} to generate a black&white
29371effect:
29372@example
29373perlin=octaves=3:tscale=0.3,lutyuv=y='if(lt(val\,128)\,255\,0)'
29374@end example
29375
29376@item
29377Stretch noise along the y axis, and convert gray level to red-only
29378signal:
29379@example
29380perlin=octaves=7:tscale=0.4:yscale=0.3,lutrgb=r=val:b=0:g=0
29381@end example
29382@end itemize
29383
29284@section qrencodesrc29384@section qrencodesrc
29285 29385
29286Generate a QR code using the libqrencode library (see29386Generate a QR code using the libqrencode library (see
libavfilter/Makefile+1−0
@@ -603,6 +603,7 @@ OBJS-$(CONFIG_NULLSRC_FILTER) += vsrc_testsrc.o · 602 unmodified lines
603OBJS-$(CONFIG_OPENCLSRC_FILTER) += vf_program_opencl.o opencl.o603OBJS-$(CONFIG_OPENCLSRC_FILTER) += vf_program_opencl.o opencl.o
604OBJS-$(CONFIG_PAL75BARS_FILTER) += vsrc_testsrc.o604OBJS-$(CONFIG_PAL75BARS_FILTER) += vsrc_testsrc.o
605OBJS-$(CONFIG_PAL100BARS_FILTER) += vsrc_testsrc.o605OBJS-$(CONFIG_PAL100BARS_FILTER) += vsrc_testsrc.o
606OBJS-$(CONFIG_PERLIN_FILTER) += vsrc_perlin.o perlin.o
606OBJS-$(CONFIG_QRENCODE_FILTER) += qrencode.o textutils.o607OBJS-$(CONFIG_QRENCODE_FILTER) += qrencode.o textutils.o
607OBJS-$(CONFIG_QRENCODESRC_FILTER) += qrencode.o textutils.o608OBJS-$(CONFIG_QRENCODESRC_FILTER) += qrencode.o textutils.o
608OBJS-$(CONFIG_RGBTESTSRC_FILTER) += vsrc_testsrc.o609OBJS-$(CONFIG_RGBTESTSRC_FILTER) += vsrc_testsrc.o
libavfilter/allfilters.c+1−0
@@ -569,6 +569,7 @@ extern const AVFilter ff_vsrc_openclsrc; · 568 unmodified lines
569extern const AVFilter ff_vsrc_qrencodesrc;569extern const AVFilter ff_vsrc_qrencodesrc;
570extern const AVFilter ff_vsrc_pal75bars;570extern const AVFilter ff_vsrc_pal75bars;
571extern const AVFilter ff_vsrc_pal100bars;571extern const AVFilter ff_vsrc_pal100bars;
572extern const AVFilter ff_vsrc_perlin;
572extern const AVFilter ff_vsrc_rgbtestsrc;573extern const AVFilter ff_vsrc_rgbtestsrc;
573extern const AVFilter ff_vsrc_sierpinski;574extern const AVFilter ff_vsrc_sierpinski;
574extern const AVFilter ff_vsrc_smptebars;575extern const AVFilter ff_vsrc_smptebars;
libavfilter/perlin.c+224−0
@@ -0,0 +1,224 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19/**
20 * @file
21 * Perlin Noise generator, based on code from:
22 * https://adrianb.io/2014/08/09/perlinnoise.html
23 *
24 * Original article from Ken Perlin:
25 * http://mrl.nyu.edu/~perlin/paper445.pdf
26 */
27
28#include <math.h>
29
30#include "libavutil/lfg.h"
31#include "libavutil/random_seed.h"
32#include "perlin.h"
33
34static inline int inc(int num, int period)
35{
36 num++;
37 if (period > 0)
38 num %= period;
39 return num;
40}
41
42static inline double grad(int hash, double x, double y, double z)
43{
44 // Take the hashed value and take the first 4 bits of it (15 == 0b1111)
45 int h = hash & 15;
46 // If the most significant bit (MSB) of the hash is 0 then set u = x. Otherwise y.
47 double u = h < 8 /* 0b1000 */ ? x : y;
48 double v;
49
50 // In Ken Perlin's original implementation this was another
51 // conditional operator (?:), then expanded for readability.
52 if (h < 4 /* 0b0100 */)
53 // If the first and second significant bits are 0 set v = y
54 v = y;
55 // If the first and second significant bits are 1 set v = x
56 else if (h == 12 /* 0b1100 */ || h == 14 /* 0b1110 */)
57 v = x;
58 else
59 // If the first and second significant bits are not equal (0/1, 1/0) set v = z
60 v = z;
61
62 // Use the last 2 bits to decide if u and v are positive or negative. Then return their addition.
63 return ((h&1) == 0 ? u : -u)+((h&2) == 0 ? v : -v);
64}
65
66static inline double fade(double t)
67{
68 // Fade function as defined by Ken Perlin. This eases coordinate values
69 // so that they will "ease" towards integral values. This ends up smoothing
70 // the final output.
71 // use Horner method to compute: 6t^5 - 15t^4 + 10t^3
72 return t * t * t * (t * (t * 6 - 15) + 10);
73}
74
75static double lerp(double a, double b, double x)
76{
77 return a + x * (b - a);
78}
79
80// Hash lookup table as defined by Ken Perlin. This is a randomly
81// arranged array of all numbers from 0-255 inclusive.
82static uint8_t ken_permutations[] = {
83 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
84 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
85 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
86 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
87 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
88 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
89 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
90 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
91 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
92 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
93 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
94 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
95 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
96 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
97 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
98 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
99};
100
101int ff_perlin_init(FFPerlin *perlin, double period, int octaves, double persistence,
102 enum FFPerlinRandomMode random_mode, unsigned int random_seed)
103{
104 int i;
105
106 perlin->period = period;
107 perlin->octaves = octaves;
108 perlin->persistence = persistence;
109 perlin->random_mode = random_mode;
110 perlin->random_seed = random_seed;
111
112 if (perlin->random_mode == FF_PERLIN_RANDOM_MODE_KEN) {
113 for (i = 0; i < 512; i++) {
114 perlin->permutations[i] = ken_permutations[i % 256];
115 }
116 } else {
117 AVLFG lfg;
118 uint8_t random_permutations[256];
119
120 if (perlin->random_mode == FF_PERLIN_RANDOM_MODE_RANDOM)
121 perlin->random_seed = av_get_random_seed();
122
123 av_lfg_init(&lfg, perlin->random_seed);
124
125 for (i = 0; i < 256; i++) {
126 random_permutations[i] = i;
127 }
128
129 for (i = 0; i < 256; i++) {
130 unsigned int random_idx = av_lfg_get(&lfg) % (256-i);
131 uint8_t random_val = random_permutations[random_idx];
132 random_permutations[random_idx] = random_permutations[256-i];
133
134 perlin->permutations[i] = perlin->permutations[i+256] = random_val;
135 }
136 }
137
138 return 0;
139}
140
141static double perlin_get(FFPerlin *perlin, double x, double y, double z)
142{
143 int xi, yi, zi;
144 double xf, yf, zf;
145 double u, v, w;
146 const uint8_t *p = perlin->permutations;
147 double period = perlin->period;
148 int aaa, aba, aab, abb, baa, bba, bab, bbb;
149 double x1, x2, y1, y2;
150
151 if (perlin->period > 0) {
152 // If we have any period on, change the coordinates to their "local" repetitions
153 x = fmod(x, perlin->period);
154 y = fmod(y, perlin->period);
155 z = fmod(z, perlin->period);
156 }
157
158 // Calculate the "unit cube" that the point asked will be located in
159 // The left bound is ( |_x_|,|_y_|,|_z_| ) and the right bound is that
160 // plus 1. Next we calculate the location (from 0.0 to 1.0) in that cube.
161 xi = (int)x & 255;
162 yi = (int)y & 255;
163 zi = (int)z & 255;
164
165 xf = x - (int)x;
166 yf = y - (int)y;
167 zf = z - (int)z;
168
169 // We also fade the location to smooth the result.
170 u = fade(xf);
171 v = fade(yf);
172 w = fade(zf);
173
174 aaa = p[p[p[ xi ] + yi ] + zi ];
175 aba = p[p[p[ xi ] + inc(yi, period)] + zi ];
176 aab = p[p[p[ xi ] + yi ] + inc(zi, period)];
177 abb = p[p[p[ xi ] + inc(yi, period)] + inc(zi, period)];
178 baa = p[p[p[inc(xi, period)] + yi ] + zi ];
179 bba = p[p[p[inc(xi, period)] + inc(yi, period)] + zi ];
180 bab = p[p[p[inc(xi, period)] + yi ] + inc(zi, period)];
181 bbb = p[p[p[inc(xi, period)] + inc(yi, period)] + inc(zi, period)];
182
183 // The gradient function calculates the dot product between a pseudorandom
184 // gradient vector and the vector from the input coordinate to the 8
185 // surrounding points in its unit cube.
186 // This is all then lerped together as a sort of weighted average based on the faded (u,v,w)
187 // values we made earlier.
188 x1 = lerp(grad(aaa, xf , yf , zf),
189 grad(baa, xf-1, yf , zf),
190 u);
191 x2 = lerp(grad(aba, xf , yf-1, zf),
192 grad(bba, xf-1, yf-1, zf),
193 u);
194 y1 = lerp(x1, x2, v);
195
196 x1 = lerp(grad(aab, xf , yf , zf-1),
197 grad(bab, xf-1, yf , zf-1),
198 u);
199 x2 = lerp(grad(abb, xf , yf-1, zf-1),
200 grad(bbb, xf-1, yf-1, zf-1),
201 u);
202 y2 = lerp(x1, x2, v);
203
204 // For convenience we bound it to 0 - 1 (theoretical min/max before is -1 - 1)
205 return (lerp(y1, y2, w) + 1) / 2;
206}
207
208double ff_perlin_get(FFPerlin *perlin, double x, double y, double z)
209{
210 double total = 0;
211 double frequency = 1;
212 double amplitude = 1;
213 double max_value = 0; // Used for normalizing result to 0.0 - 1.0
214
215 for (int i = 0; i < perlin->octaves; i++) {
216 total += perlin_get(perlin, x * frequency, y * frequency, z * frequency) * amplitude;
217 max_value += amplitude;
218 amplitude *= perlin->persistence;
219 frequency *= 2;
220 }
221
222 return total / max_value;
223}
224
libavfilter/perlin.h+101−0
@@ -0,0 +1,101 @@
1/*
2 * Perlin noise generator
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/**
22 * @file
23 * Perlin Noise generator
24 */
25
26#ifndef AVFILTER_PERLIN_H
27#define AVFILTER_PERLIN_H
28
29#include <stdint.h>
30
31enum FFPerlinRandomMode {
32 FF_PERLIN_RANDOM_MODE_RANDOM,
33 FF_PERLIN_RANDOM_MODE_KEN,
34 FF_PERLIN_RANDOM_MODE_SEED,
35 FF_PERLIN_RANDOM_MODE_NB
36};
37
38/**
39 * Perlin generator context. This needs to be initialized with the
40 * parameters used to generate the Perlin noise.
41 */
42typedef struct FFPerlin {
43 /**
44 * spatial repeat period, if negative it is ignored
45 */
46 double period;
47
48 /**
49 * total number of components making up the noise, each one with
50 * doubled frequency
51 */
52 int octaves;
53
54 /**
55 * ratio used to compute the amplitude of the next octave
56 * component with respect to the previous component
57 */
58 double persistence;
59
60 /**
61 * permutations array used to compute the Perlin noise hash
62 */
63 uint8_t permutations[512];
64
65 /**
66 * define how to compute the permutations array
67 */
68 enum FFPerlinRandomMode random_mode;
69
70 /**
71 * when random_mode is set FF_PERLIN_RANDOM_MODE_RANDOM, set random
72 * seed used to compute the permutations array
73 */
74 unsigned int random_seed;
75} FFPerlin;
76
77/**
78 * Initialize the Perlin noise generator with parameters.
79 *
80 * @param perlin Perlin noise generator context
81 * @param period spatial repeat period, if negative it is ignored
82 * @param octaves total number of components making up the noise, each one with doubled frequency
83 * @param persistence define ratio used to compute the amplitude of the next octave
84 * component with respect to the previous component
85 * @param random_mode define how to compute the permutations array
86 * @param random_seed when random_mode is set to FF_PERLIN_RANDOM_MODE_RANDOM, set random
87 * seed used to compute the permutations array
88 * @return a negative AVERROR code in case of error, a non negative value otherwise
89 */
90int ff_perlin_init(FFPerlin *perlin, double period, int octaves, double persistence,
91 enum FFPerlinRandomMode random_mode, unsigned int random_seed);
92
93/**
94 * Compute Perlin noise given the x, y, z coordinates.
95 *
96 * @param perlin Perlin noise generator context
97 * @return normalized value for the perlin noise, in the range [0, 1]
98 */
99double ff_perlin_get(FFPerlin *perlin, double x, double y, double z);
100
101#endif /* AVFILTER_PERLIN_H */
libavfilter/vsrc_perlin.c+169−0
@@ -0,0 +1,169 @@
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19/**
20 * @file
21 * Perlin noise generator
22 */
23
24#include <float.h>
25
26#include "perlin.h"
27#include "libavutil/lfg.h"
28#include "libavutil/opt.h"
29#include "avfilter.h"
30#include "internal.h"
31#include "formats.h"
32#include "video.h"
33
34typedef struct PerlinContext {
35 const AVClass *class;
36
37 int w, h;
38 AVRational frame_rate;
39
40 FFPerlin perlin;
41 int octaves;
42 double persistence;
43 unsigned int random_seed;
44 enum FFPerlinRandomMode random_mode;
45
46 double xscale, yscale, tscale;
47 uint64_t pts;
48} PerlinContext;
49
50#define OFFSET(x) offsetof(PerlinContext, x)
51#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
52
53static const AVOption perlin_options[] = {
54 { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="320x240"}, 0, 0, FLAGS },
55 { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="320x240"}, 0, 0, FLAGS },
56 { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
57 { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
58 { "octaves", "set the number of components to use to generate the noise", OFFSET(octaves), AV_OPT_TYPE_INT, {.i64=1}, 1, INT_MAX, FLAGS },
59 { "persistence", "set the octaves persistence", OFFSET(persistence), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0, DBL_MAX, FLAGS },
60
61 { "xscale", "set x-scale factor", OFFSET(xscale), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0, DBL_MAX, FLAGS },
62 { "yscale", "set y-scale factor", OFFSET(yscale), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0, DBL_MAX, FLAGS },
63 { "tscale", "set t-scale factor", OFFSET(tscale), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.0, DBL_MAX, FLAGS },
64
65 { "random_mode", "set random mode used to compute initial pattern", OFFSET(random_mode), AV_OPT_TYPE_INT, {.i64=FF_PERLIN_RANDOM_MODE_RANDOM}, 0, FF_PERLIN_RANDOM_MODE_NB-1, FLAGS, .unit = "random_mode" },
66 { "random", "compute and use random seed", 0, AV_OPT_TYPE_CONST, {.i64=FF_PERLIN_RANDOM_MODE_RANDOM}, 0, 0, FLAGS, .unit = "random_mode" },
67 { "ken", "use the predefined initial pattern defined by Ken Perlin in the original article", 0, AV_OPT_TYPE_CONST, {.i64=FF_PERLIN_RANDOM_MODE_KEN}, 0, 0, FLAGS, .unit = "random_mode" },
68 { "seed", "use the value specified by random_seed", 0, AV_OPT_TYPE_CONST, {.i64=FF_PERLIN_RANDOM_MODE_SEED}, 0, 0, FLAGS, .unit="random_mode" },
69
70 { "random_seed", "set the seed for filling the initial pattern", OFFSET(random_seed), AV_OPT_TYPE_UINT, {.i64=0}, 0, UINT_MAX, FLAGS },
71 { "seed", "set the seed for filling the initial pattern", OFFSET(random_seed), AV_OPT_TYPE_UINT, {.i64=0}, 0, UINT_MAX, FLAGS },
72 { NULL }
73};
74
75AVFILTER_DEFINE_CLASS(perlin);
76
77static av_cold int init(AVFilterContext *ctx)
78{
79 PerlinContext *perlin = ctx->priv;
80 int ret;
81
82 if (ret = ff_perlin_init(&perlin->perlin, -1, perlin->octaves, perlin->persistence,
83 perlin->random_mode, perlin->random_seed)) {
84 return ret;
85 }
86
87 av_log(ctx, AV_LOG_VERBOSE,
88 "s:%dx%d r:%d/%d octaves:%d persistence:%f xscale:%f yscale:%f tscale:%f\n",
89 perlin->w, perlin->h, perlin->frame_rate.num, perlin->frame_rate.den,
90 perlin->octaves, perlin->persistence,
91 perlin->xscale, perlin->yscale, perlin->tscale);
92 return 0;
93}
94
95static int config_props(AVFilterLink *outlink)
96{
97 PerlinContext *perlin = outlink->src->priv;
98
99 outlink->w = perlin->w;
100 outlink->h = perlin->h;
101 outlink->time_base = av_inv_q(perlin->frame_rate);
102 outlink->frame_rate = perlin->frame_rate;
103
104 return 0;
105}
106
107static int request_frame(AVFilterLink *outlink)
108{
109 AVFilterContext *ctx = outlink->src;
110 PerlinContext *perlin = ctx->priv;
111 AVFrame *picref = ff_get_video_buffer(outlink, perlin->w, perlin->h);
112 int i, j;
113 uint8_t *data0, *data;
114 double x, y, t;
115
116 if (!picref)
117 return AVERROR(ENOMEM);
118
119 picref->sample_aspect_ratio = (AVRational) {1, 1};
120 picref->pts = perlin->pts++;
121 picref->duration = 1;
122
123 t = perlin->tscale * (perlin->pts * av_q2d(outlink->time_base));
124 data0 = picref->data[0];
125
126 for (i = 0; i < perlin->h; i++) {
127 y = perlin->yscale * (double)i / perlin->h;
128
129 data = data0;
130
131 for (j = 0; j < perlin->w; j++) {
132 double res;
133 x = perlin->xscale * (double)j / perlin->w;
134 res = ff_perlin_get(&perlin->perlin, x, y, t);
135 av_log(ctx, AV_LOG_DEBUG, "x:%f y:%f t:%f => %f\n", x, y, t, res);
136 *data++ = res * 255;
137 }
138 data0 += picref->linesize[0];
139 }
140
141 return ff_filter_frame(outlink, picref);
142}
143
144static int query_formats(AVFilterContext *ctx)
145{
146 enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
147
148 return ff_set_common_formats_from_list(ctx, pix_fmts);
149}
150
151static const AVFilterPad perlin_outputs[] = {
152 {
153 .name = "default",
154 .type = AVMEDIA_TYPE_VIDEO,
155 .request_frame = request_frame,
156 .config_props = config_props,
157 },
158};
159
160const AVFilter ff_vsrc_perlin = {
161 .name = "perlin",
162 .description = NULL_IF_CONFIG_SMALL("Generate Perlin noise"),
163 .priv_size = sizeof(PerlinContext),
164 .priv_class = &perlin_class,
165 .init = init,
166 .inputs = NULL,
167 FILTER_OUTPUTS(perlin_outputs),
168 FILTER_QUERY_FUNC(query_formats),
169};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t