[FFmpeg-trac] #6127(avfilter:new): non-intuitive behavior of random() function used in zoompan filter's expressions
FFmpeg
trac at avcodec.org
Sun Feb 5 01:07:11 EET 2017
#6127: non-intuitive behavior of random() function used in zoompan filter's
expressions
----------------------------------+--------------------------------------
Reporter: pbasista | Type: defect
Status: new | Priority: normal
Component: avfilter | Version: git-master
Keywords: zoompan | Blocked By:
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
----------------------------------+--------------------------------------
Summary of the bug:
when random() function is used in a naive way (i.e. "`random(0)`", without
previously setting the internal variable `0`) inside an expression for
zoompan filter's options, it always returns the *same* number which is
very close to zero:
{{{
$ /usr/bin/ffmpeg -loop 1 -i alley.png -filter
"zoompan='s=1920x1200:fps=60:z=3:y=y+print(random(0)*1000000000):x=x+print(random(1)*1000000000)'"
-frames 600 output.hevc -y
ffmpeg version 3.2.2-2 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 6.3.0 (Debian 6.3.0-4) 20170121
configuration: --prefix=/usr --extra-version=2 --toolchain=hardened
--libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu
--enable-gpl --disable-stripping --enable-avresample --enable-avisynth
--enable-gnutls --enable-ladspa --enable-libass --enable-libbluray
--enable-libbs2b --enable-libcaca --enable-libcdio --enable-libebur128
--enable-libflite --enable-libfontconfig --enable-libfreetype --enable-
libfribidi --enable-libgme --enable-libgsm --enable-libmp3lame --enable-
libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse
--enable-librubberband --enable-libshine --enable-libsnappy --enable-
libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-
libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack
--enable-libwebp --enable-libx265 --enable-libxvid --enable-libzmq
--enable-libzvbi --enable-omx --enable-openal --enable-opengl --enable-
sdl2 --enable-libdc1394 --enable-libiec61883 --enable-chromaprint
--enable-frei0r --enable-libopencv --enable-libx264 --enable-shared
libavutil 55. 34.100 / 55. 34.100
libavcodec 57. 64.101 / 57. 64.101
libavformat 57. 56.100 / 57. 56.100
libavdevice 57. 1.100 / 57. 1.100
libavfilter 6. 65.100 / 6. 65.100
libavresample 3. 1. 0 / 3. 1. 0
libswscale 4. 2.100 / 4. 2.100
libswresample 2. 3.100 / 2. 3.100
libpostproc 54. 1.100 / 54. 1.100
[png_pipe @ 0x557e77849f00] Stream #0: not enough frames to estimate rate;
consider increasing probesize
Input #0, png_pipe, from 'alley.png':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: png, rgb24(pc), 7360x4912, 25 tbr, 25 tbn, 25 tbc
x265 [info]: HEVC encoder version 0.0
x265 [info]: build info [Linux][GCC 6.2.0][64 bit] 8bit+10bit+12bit
x265 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX AVX2
FMA3 LZCNT BMI2
x265 [info]: Main 4:4:4 profile, Level-5 (Main tier)
x265 [info]: Thread pool created using 8 threads
x265 [info]: Slices : 1
x265 [info]: frame threads / pool features : 3 / wpp(19 rows)
x265 [info]: Coding QT: max CU size, min CU size : 64 / 8
x265 [info]: Residual QT: max TU size, max depth : 32 / 1 inter / 1 intra
x265 [info]: ME / range / subpel / merge : hex / 57 / 2 / 2
x265 [info]: Keyframe min / max / scenecut : 25 / 250 / 40
x265 [info]: Cb/Cr QP Offset : 6 / 6
x265 [info]: Lookahead / bframes / badapt : 20 / 4 / 2
x265 [info]: b-pyramid / weightp / weightb : 1 / 1 / 0
x265 [info]: References / ref-limit cu / depth : 3 / on / on
x265 [info]: AQ: mode / str / qg-size / cu-tree : 1 / 1.0 / 32 / 1
x265 [info]: Rate Control / qCompress : CRF-28.0 / 0.60
x265 [info]: tools: rd=3 psy-rd=2.00 rskip signhide tmvp strong-intra-
smoothing
x265 [info]: tools: lslices=7 deblock sao
Output #0, hevc, to 'output.hevc':
Metadata:
encoder : Lavf57.56.100
Stream #0:0: Video: hevc (libx265), gbrp, 1920x1200, q=2-31, 60 fps,
60 tbn, 60 tbc
Metadata:
encoder : Lavc57.64.101 libx265
Stream mapping:
Stream #0:0 -> #0:0 (png (native) -> hevc (libx265))
Press [q] to stop, [?] for help
0.054964
Last message repeated 1 times
0.054964 1 fps=0.0 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A
speed= 0x
Last message repeated 19 times
0.054964 11 fps=8.5 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A
speed= 0x
Last message repeated 15 times
[swscaler @ 0x557e79781500] Warning: data is not aligned! This can lead to
a speedloss
0.054964
Last message repeated 5 times
0.054964 22 fps= 12 q=0.0 size= 0kB time=00:00:00.00 bitrate=N/A
speed= 0x
Last message repeated 15 times
0.054964 30 fps= 13 q=-0.0 size= 6kB time=-00:00:00.01 bitrate=N/A
speed=N/A
Last message repeated 15 times
0.054964 38 fps= 13 q=-0.0 size= 7kB time=00:00:00.11 bitrate=
501.0kbits/s speed=0.04x
Last message repeated 17 times
0.054964 47 fps= 14 q=-0.0 size= 9kB time=00:00:00.26 bitrate=
261.3kbits/s speed=0.077x
Last message repeated 17 times
0.054964 56 fps= 14 q=-0.0 size= 10kB time=00:00:00.41 bitrate=
190.8kbits/s speed=0.104x
Last message repeated 17 times
0.054964 65 fps= 14 q=-0.0 size= 11kB time=00:00:00.56 bitrate=
152.7kbits/s speed=0.125x
Last message repeated 15 times
0.054964 73 fps= 14 q=-0.0 size= 12kB time=00:00:00.70 bitrate=
141.1kbits/s speed=0.139x
Last message repeated 17 times
0.054964 82 fps= 15 q=-0.0 size= 13kB time=00:00:00.85 bitrate=
127.0kbits/s speed=0.152x
Last message repeated 15 times
...
}}}
The output above is from Debian's version of ffmpeg, but the same behavior
can be experienced in git-master version as of today.
'''Explanation:'''
zoompan filter uses the internal formula evaluator to *parse* and evaluate
the expressions for its options. The parsing is done for *every* frame
(see function `output_single_frame` in `libavfilter/vf_zoompan.c`, line
135). This means that for every frame, the evaluator initializes the
parser's internal variables 0-9 for each of the parsed expressions to zero
(see function `av_expr_parse` in `libavutil/eval.c`, line 667). Therefore,
no function is able to store its internal state into one of the internal
variables and use it during the next evaluation (which is typically for
the next frame), because there will always be only a ''single'' evaluation
for every parsed expression.
This breaks the intuitive behavior of functions which require internal
state, like random(). It uses an internal variable to store its current
"seed" from which it calculates the next pseudorandom number (see function
`eval_expr` in `libavutil/eval.c`, line 220). When the seed value is
always the same (i.e. zero), the generated "pseudorandom" number is always
the same as well.
'''Suggestion:'''
This non-intuitive behavior is caused by the fact that the expressions are
parsed for every frame. If the expressions were parsed only during the
filter's initialization and evaluated for every frame, the internal
variables would be preserved and the above described problem would not
exist. Some other filters, like the crop filter, use this technique and I
believe it would be better if zoompan used it as well.
--
Ticket URL: <https://trac.ffmpeg.org/ticket/6127>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list