[FFmpeg-trac] #9407(ffmpeg:reopened): Broken Conversion: yuv444p10le to yuv444p
FFmpeg
trac at avcodec.org
Mon Sep 6 02:27:44 EEST 2021
#9407: Broken Conversion: yuv444p10le to yuv444p
-------------------------------------+-------------------------------------
Reporter: Michael | Owner: (none)
Witten |
Type: defect | Status: reopened
Priority: normal | Component: ffmpeg
Version: unspecified | Resolution:
Keywords: pix_fmt yuv | Blocked By:
yuv444p10le yuv444p 10-bit format |
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
-------------------------------------+-------------------------------------
Changes (by Michael Witten):
* status: closed => reopened
* resolution: invalid =>
Comment:
Thank you, ''pdr0'', for ''your'' explanation.
{{{#!html
<ul>
<li>
<p><b>NOT THE PROBLEM IN QUESTION:</b></p>
<ul>
<li><p>The issues with "<span style="font-family:monospace; font-
size:90%">color_range</span>" are incidental, and they probably require
their own tickets.</p></li>
<li><p>I believe that I have been handling the "<span style="font-
family:monospace; font-size:90%">color_range</span>" correctly (<a
href="#color_range-0" style="font-weight:bold;
color:#0000e0">see below</a>).</p></li>
<li><p>Your examples, however, do not handle the "<span style="font-
family:monospace; font-size:90%">color_range</span>" correctly (<a
href="#color_range-1" style="font-weight:bold;
color:#0000e0">see below</a>).</p></li>
<li><p>I can see now that my attempt to control the color space is
also broken, which probably requires its own ticket (<a href="#setparams-
fail" style="font-weight:bold;
color:#0000e0">see below</a>).</p></li>
</ul>
</li>
<li>
<p><b>THE ACTUAL PROBLEM:</b></p>
<ul>
<li><p>The conversion from "<b style="font-family:monospace; font-
size:90%">yuv444p10le</b>" to "<b style="font-family:monospace; font-
size:90%">yuv444p</b>" produces <a href="#multiple-colors" style="font-
weight:bold; color:#0000e0">multiple</a> colors rather than just
one.</p></li>
<li><p>Perhaps this is some kind of forced dithering problem, as
hinted by <i>Balling</i>'s find on issue <a class="open ticket"
href="/ticket/3345" title="#3345: defect: Bias in planar YUV to YUV bit
depth conversion (open)">#3345</a>, where the workaround is indeed to
convert to something else (<i>e.g.,</i> "<b style="font-family:monospace;
font-size:90%">rgb24</b>") as an intermediary pixel format between "<i
style="font-family:monospace; font-size:90%">yuv444p10le</i>" and "<i
style="font-family:monospace; font-size:90%">yuv444p</i>".</p></li>
<li><p>My own videos brought this issue to my attention, and what I
noticed was a change in exposure akin to applying the wrong transfer
function; maybe this is still the result of some kind of dithering, but I
would not be surprised if there are other issues at play as well, which is
why I was trying to control all that metadata.</p></li>
</ul>
</li>
<li><p>All of this confusion is why it is unwise to close a report or
mark it as "invalid" when the very <em>author</em> of that report is
<em>still</em> here to discuss it; otherwise, you are just introducing
overhead and aggravation for all parties involved.</p></li>
</ul>
}}}
= "`color_range`" [=#color_range-0] =
My example attempted to be (and I believe it did indeed succeeded in
being) very careful with "`color_range`"; the following sprinkles
"`showinfo`" around, in order to prove this:
{{{
#!/bin/bash
bad_output=04-rbg24-to-yuv444p10le-to-yuv444p-to-rgb24.png
args=(
-hide_banner
-loglevel verbose
-f lavfi -i '
color=0x7FFFD4:size=480x270, format=rgb24, showinfo,
setparams=prog:pc:bt709:iec61966-2-1:bt709, showinfo
'
-vf '
showinfo, scale=out_range=pc, showinfo, format=yuv444p10le, showinfo,
showinfo, scale=out_range=pc, showinfo, format=yuv444p, showinfo,
showinfo, scale=out_range=pc, showinfo, format=rgb24, showinfo
'
-frames 1
-y "$bad_output"
)
ffmpeg "${args[@]}" |& grep -o 'color_range:.*' |
grep --color=always 'color_range:[^ ]\{1,\}'
}}}
Here is the output: [=#setparams-fail]
{{{#!html
<pre class="wiki literal-block">
<strong style="color:#f00">color_range:unknown</strong>
color_space:unknown color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:bt709
color_primaries:bt709 color_trc:iec61966-2-1
<strong style="color:#f00">color_range:unknown</strong>
color_space:unknown color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
</pre>
}}}
As you can see:
* Where it ''matters'', my "`color_range`" metadata is correct.
* The "`setparams`" filter works correctly inside my "`lavfi`" input.
* However, all the info from "`setparams`" is thrown out when the
"`lavfi`" input is pumped into my filter graph; clearly this is a bug.
* ''Nevertheless'', to state it again, the "`color_range`" metadata is
correct where it matters.
Please note that your own "good" example does not maintain "`color_range`"
metadata correctly: [=#color_range-1]
{{{
#!/bin/bash
your_example=(
# 'showinfo' has been sprinkled about, and '-y' added:
ffmpeg -f lavfi -i color=0x7FFFD4:size=480x270 -vf
showinfo,scale=out_range=pc:out_color_matrix=bt709,format=yuv444p10le,showinfo,format=yuv444p,showinfo,scale=in_range=pc:in_color_matrix=bt709,format=rgb24,showinfo
-frames:v 1 -y right.png
)
"${your_example[@]}" |& grep -o 'color_range:.*' |
grep --color=always 'color_range:[^ ]\{1,\}'
}}}
Here is what your example is doing:
{{{#!html
<pre class="wiki literal-block">
<strong style="color:#f00">color_range:unknown</strong>
color_space:unknown color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:pc</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:tv</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
<strong style="color:#f00">color_range:tv</strong> color_space:unknown
color_primaries:unknown color_trc:unknown
</pre>
}}}
As you can see:
* Your "`lavfi`" input has unknown metadata, as expected.
* Your filter graph immediately sets "`color_range`" to "`pc`", as
desired.
* On the conversion from "**`yuv444p10le`**" to "**`yuv444p`**",
"`out_range`" is set to "`tv`"! This happens because an
**''auto_scaler''** is inserted, which by ''default'' sets
"`out_range=tv`"; that is why I was always explicitly creating the scaler:
{{{
scale=out_range=pc
}}}
You can see this by changing the above example slightly:
{{{
#!/bin/bash
your_example=(
# Added '-loglevel verbose' and '-y':
ffmpeg -loglevel verbose -f lavfi -i color=0x7FFFD4:size=480x270 -vf
scale=out_range=pc:out_color_matrix=bt709,format=yuv444p10le,format=yuv444p,scale=in_range=pc:in_color_matrix=bt709,format=rgb24
-frames:v 1 -y right.png
)
"${your_example[@]}" |& grep --color=always 'auto_scaler[^ ]\{1,\}'
}}}
Here is the output:
{{{#!html
<pre class="wiki literal-block">
[<strong style="color:#f00">auto_scaler_0</strong> @ 0x7b0940] w:iw
h:ih flags:'bicubic' interl:0
[Parsed_format_2 @ 0x7ab5c0] auto-inserting filter '<strong
style="color:#f00">auto_scaler_0</strong>' between the filter
'Parsed_format_1' and the filter 'Parsed_format_2'
[<strong style="color:#f00">auto_scaler_0</strong> @ 0x7b0940] w:480
h:270 fmt:yuv444p10le sar:1/1 -> w:480 h:270 fmt:yuv444p sar:1/1 flags:0x4
</pre>
}}}
= Color Metadata =
{{{#!html
<p>As shown <a href="#setparams-fail" style="font-weight:bold;
color:#0000e0">above</a> (and as noted by <i>Balling</i>), the metadata
specified by "<span style="font-family:monospace; font-
size:90%">setparams</span>" in the "<span style="font-family:monospace;
font-size:90%">lavfi</span>" input is just thrown out upon injection of
the frames into the main filter graph; clearly, this is a bug all on its
own.</p>
}}}
= **''THE ACTUAL PROBLEM''** =
1. Here is the original data; there is one color:
{{{
$ f=01-rgb24.png
$ identify -verbose "$f" | sed -n '/Colors:/,/Gamma:/s/^ //p'
Colors: 1
Histogram:
129600: (127,255,212) #7FFFD4 aquamarine
Rendering intent: Perceptual
Gamma: 0.454545
}}}
2. Here is the data, after experiencing conversion to "**`yuv444p10le`**"
(it's the same as the original):
{{{
$ f=03-rbg24-to-yuv444p10le-to-rgb24.png
$ identify -verbose "$f" | sed -n '/Colors:/,/Gamma:/s/^ //p'
Colors: 1
Histogram:
129600: (127,255,212) #7FFFD4 aquamarine
Rendering intent: Perceptual
Gamma: 0.454545
}}}
3. Here is the data, after experiencing conversion to "**`yuv444p`**"
(it's imperceptibly lossy; 1 color, where the red component is 126 rather
than 127):
{{{
$ f=02-rbg24-to-yuv444p-to-rgb24.png
$ identify -verbose "$f" | sed -n '/Colors:/,/Gamma:/s/^ //p'
Colors: 1
Histogram:
129600: (126,255,212) #7EFFD4 srgb(126,255,212)
Rendering intent: Perceptual
Gamma: 0.454545
}}}
4. As shown in the initial description, the conversion from
"**`yuv444p10le`**" to "**`yuv444p`**" produces not only perceptibly bad
results (I think a transfer function issue), but also 4 different colors
(maybe a dithering issue): [=#multiple-colors]
{{{
$ f=04-rbg24-to-yuv444p10le-to-yuv444p-to-rgb24.png
$ identify -verbose "$f" | sed -n '/Colors:/,/Gamma:/s/^ //p'
Colors: 4
Histogram:
2040: (130,255,225) #82FFE1 srgb(130,255,225)
8100: (130,255,227) #82FFE3 srgb(130,255,227)
105240: (131,255,228) #83FFE4 srgb(131,255,228)
14220: (133,255,228) #85FFE4 srgb(133,255,228)
Rendering intent: Perceptual
Gamma: 0.454545
}}}
5. However, using "**`rgb24`**" as an intermediate pixel format basically
solves that problem (the results are the same as in "3." above):
{{{
$ f=05-rbg24-to-yuv444p10le-to-rgb24-to-yuv444p-to-rgb24.png
$ identify -verbose "$f" | sed -n '/Colors:/,/Gamma:/s/^ //p'
Colors: 1
Histogram:
129600: (126,255,212) #7EFFD4 srgb(126,255,212)
Rendering intent: Perceptual
Gamma: 0.454545
}}}
In short, the conversion from "**`yuv444p10le`**" to "**`yuv444p`**" is
broken.
--
Ticket URL: <https://trac.ffmpeg.org/ticket/9407#comment:7>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list