[FFmpeg-trac] #9781(avfilter:closed): zscale adds distortion when resampling video data

FFmpeg trac at avcodec.org
Fri May 13 21:16:49 EEST 2022


#9781: zscale adds distortion when resampling video data
-------------------------------------+-------------------------------------
             Reporter:  Llyw         |                    Owner:  (none)
                 Type:  defect       |                   Status:  closed
             Priority:  normal       |                Component:  avfilter
              Version:  git-master   |               Resolution:  fixed
             Keywords:  zscale       |               Blocked By:
  distortion                         |
             Blocking:               |  Reproduced by developer:  0
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------
Comment (by Llyw):

 That's an easy question to ask, but a difficult one to answer ;)

 While I won't be able to answer your question to the full extent, I tried
 to gain a rough understanding on how the use of multiple slices might
 cause floating-point deviations: Internally, z.lib/zimg seems to convert
 from the input to the output coordinate system, see https://github.com
 /sekrit-twc/zimg/blob/release-3.0.4/src/zimg/resize/filter.cpp#L250, while
 the parallelization scheme is doing it the other way around. Since `oh/iw`
 is not necessarily equal to `1/(oh/ih)` in floating-point arithmetics that
 could lead to some minor deviations due to round-off. In relative terms,
 this deviation should be in the same order as the unit round-off for
 double precision floating-point arithmetic, so I do not think that this
 should be a reason to reopen this defect. I furthermore suspect that there
 might be no way around a minor loss of accuracy when parallelizing the
 execution of the `zscale` filter.

 It might make sense, however, to ask the question whether you will get
 identical results when using only a single slice. As `ih` and `oh`
 approach `INT_MAX` (not that this will happen any time soon) you could
 improve the following assignment, at least from a theoretical/academic
 point of view:
 {{{
         s->in_slice_start[i] = s->out_slice_start[i] * in_h /
 (double)out_h;
         s->in_slice_end[i]   = s->out_slice_end[i]   * in_h /
 (double)out_h;
 }}}

 When rewriting this as
 {{{
         s->in_slice_start[i] = in_h * (s->out_slice_start[i] /
 (double)out_h);
         s->in_slice_end[i]   = in_h * (s->out_slice_end[i]   /
 (double)out_h);
 }}}
 you can be certain (not withstanding my comment in the final paragraph
 down below) that this will reduce precisely to
 {{{
         s->in_slice_start[0] = 0.0;
         s->in_slice_end[0]   = in_h;
 }}}
 for a single slice since as in this case you have
 `s->out_slice_start[0]=0.0` and `s->out_slice_end[0]=(double)oh` with `oh`
 being equal to `out_h`: Since the dimensions of an AVFrame are 32-bit
 signed integers, see https://ffmpeg.org/doxygen/2.7/structAVFrame.html,
 and 32-bit signed integers can be exactly represented as double precision
 floating-point values, you can be certain that the expression
 `s->out_slice_end[0]/(double)out_h` will be equal to `1.0`, causing the
 endpoint of your slice to be exactly equal to `in_h`, which is also the
 default that `z.lib/zimg` assumes when the `active_area` member is not
 specified, see https://github.com/sekrit-
 twc/zimg/blob/release-3.0.4/src/zimg/api/zimg.cpp#L405, as was the case
 before the Intel-commit.

 Note, however, the default floating-point model will give the compiler
 some freedom when it comes to interpreting the source code and I am not
 sure whether the above reasoning will hold in general. If you want to
 investigate this further, I would recommend that you add some regression
 tests.

 I should also point out that I have not yet had the opportunity to try my
 reproducer commands with the updated code and even then I will be limited
 to a simple visual comparison. I strongly expect that I will not be able
 to tell a difference with my yuv420p video (when comparing the updated
 git-master to FFmpeg 5.0.1) when I get around to doing that, but will get
 back to you if this turns out not to be the case.
-- 
Ticket URL: <https://trac.ffmpeg.org/ticket/9781#comment:13>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list