[FFmpeg-trac] #9781(avfilter:closed): zscale adds distortion when resampling video data
FFmpeg
trac at avcodec.org
Fri May 13 15:35:57 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):
Thanks for taking the time to take a look at this, Paul!
I took a look at your changes and I think I am beginning to understand the
issue with the previous implementation: Essentially, the previous
implementation computed the active input area based on the job index and
number of jobs. Ignoring the adjustment to make the slice offsets
divisible by four and denoting the input height with `ih`, the output
height with `oh`, and the number of threads with `n`, the previous
implementation would thus assign an implicit resample ratio of `(ih %
floor(ih/n))/(oh % floor(oh/n))` to the last slice, and a resample ratio
of `floor(ih/n)/floor(oh/n)` to all others if `oh` was not divisible by
`n` and `n>1`. These ratios can differ significantly, leading to observed
distortion, and are bad approximations to the actual resample ratio
`ih/oh`.
Your commit improves this by computing the active input area based on the
actual resample ratio `ih/oh` instead. This will reduce the distortion
when `oh` is not divisible by `n` and `n > 1`, since the resample ratio of
the last slice `floor(((oh % ceil(oh/n)) * ih)/oh)/(oh % ceil(oh/n))` will
be closer to `floor((ceil(oh/n) * ih)/oh)/ceil(oh/n)`, with both
expressions being closer to `ih/oh` than the previous approximation. (When
`ceil(oh/n)` is odd, you need to replace it with `ceil(oh/n)+1` in the
above expressions.)
To reduce distortion, one should therefore at least ensure that `oh` is
divisible by `s` where `s` is equal to `floor((ceil(oh/n) + 1)/2)` or
choose `n=1`. For `n>1`, having `oh` being divisible by `s` is still no
guarantee for no distortion, however, you would also need `s * ih` to be
divisible by `oh` for that.
I did take a look at the z.lib/zimg API and it seems that the active area
does not have to be specified as an integer but is stored as floating-
point values, so a future improvement would be to use double precision
floating-point values when computing the active area of the input for each
output slice. Until then the filter may still show some distortion
depending on the input dimensions, output dimensions, and the thread
count. (I would honestly appreciate it if this defect would remain open
until this improvement is realized but am hesitant to re-open it myself.)
--
Ticket URL: <https://trac.ffmpeg.org/ticket/9781#comment:6>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list