Opened 3 years ago

Closed 3 years ago

Last modified 21 months ago

#9407 closed defect (duplicate)

Broken Conversion: yuv444p10le to yuv444p

Reported by: Michael Witten Owned by:
Priority: normal Component: swscale
Version: unspecified Keywords:
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Conversion from yuv444p10le to yuv444p produces erroneous results (and not just from expected losses).

I've attached a script that produces results for examination; save the script to "$dir" and then run it like so:

$ cd "$dir"
$ bash 00-commands.sh

In short, the following produces erroneous results:

#!/bin/bash

bad_output=04-rbg24-to-yuv444p10le-to-yuv444p-to-rgb24.png

args=(
  -hide_banner
  -loglevel quiet

  -f lavfi -i '
    color=0x7FFFD4:size=480x270, format=rgb24,
      setparams=prog:pc:bt709:iec61966-2-1:bt709
  '

  -vf '
    scale=out_range=pc, format=yuv444p10le,
      scale=out_range=pc, format=yuv444p,
        scale=out_range=pc, format=rgb24
  '

  -frames 1

  "$bad_output"
)

ffmpeg "${args[@]}"

The workaround is to convert to some non-yuv pixel format (e.g., rgb24) before converting to the desired yuv format:

#!/bin/bash

good_output=05-rbg24-to-yuv444p10le-to-rgb24-to-yuv444p-to-rgb24.png

args=(
  -hide_banner
  -loglevel quiet

  -f lavfi -i '
    color=0x7FFFD4:size=480x270, format=rgb24,
      setparams=prog:pc:bt709:iec61966-2-1:bt709
  '

  -vf '
    scale=out_range=pc, format=yuv444p10le,
      scale=out_range=pc, format=rgb24,
        scale=out_range=pc, format=yuv444p,
          scale=out_range=pc, format=rgb24
  '

  -frames 1

  "$good_output"
)

ffmpeg "${args[@]}"

Here is the output I got from running my script:

Versions:
========

  bash:

    GNU bash, version 5.1.8(1)-release (aarch64-unknown-linux-gnu)

  tee:

    tee (GNU coreutils) 8.32

  sed:

    sed (GNU sed) 4.8

  ffmpeg:

    ffmpeg version n4.4 Copyright (c) 2000-2021 the FFmpeg developers
    built with gcc 10.2.0 (GCC)
    configuration: --prefix=/usr --disable-debug --disable-static 
    --disable-stripping --enable-amf --enable-avisynth 
    --enable-cuda-llvm --enable-fontconfig --enable-gmp 
    --enable-gnutls --enable-gpl --enable-ladspa --enable-libass 
    --enable-libbluray --enable-libdav1d --enable-libdrm 
    --enable-libfreetype --enable-libfribidi --enable-libgsm 
    --enable-libiec61883 --enable-libjack --enable-libmodplug 
    --enable-libmp3lame --enable-libopencore_amrnb 
    --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus 
    --enable-libpulse --enable-librsvg --enable-libsoxr 
    --enable-libspeex --enable-libsrt --enable-libssh 
    --enable-libtheora --enable-libv4l2 --enable-libvidstab 
    --enable-libvorbis --enable-libvpx --enable-libwebp 
    --enable-libx264 --enable-libx265 --enable-libxcb 
    --enable-libxml2 --enable-libxvid --enable-libzimg 
    --enable-shared --enable-version3 --host-cflags='"-fPIC"'
    libavutil      56. 70.100 / 56. 70.100
    libavcodec     58.134.100 / 58.134.100
    libavformat    58. 76.100 / 58. 76.100
    libavdevice    58. 13.100 / 58. 13.100
    libavfilter     7.110.100 /  7.110.100
    libswscale      5.  9.100 /  5.  9.100
    libswresample   3.  9.100 /  3.  9.100
    libpostproc    55.  9.100 / 55.  9.100

  identify:

    Version: ImageMagick 7.1.0-4 Q16 aarch64 2021-07-18 
    https://imagemagick.org

  md5sum:

    md5sum (GNU coreutils) 8.32

  diff:

    diff (GNU diffutils) 3.8

Making files:
============

  01-rgb24.png
  02-rbg24-to-yuv444p-to-rgb24.png
  03-rbg24-to-yuv444p10le-to-rgb24.png
  04-rbg24-to-yuv444p10le-to-yuv444p-to-rgb24.png
  05-rbg24-to-yuv444p10le-to-rgb24-to-yuv444p-to-rgb24.png

Analyzing:
=========

  md5sums:

    1bb5e65fe0865e210333e46416893d8e:

      02-rbg24-to-yuv444p-to-rgb24.png
      05-rbg24-to-yuv444p10le-to-rgb24-to-yuv444p-to-rgb24.png

    f10bf43eae733b375657074b31c72407:

      01-rgb24.png
      03-rbg24-to-yuv444p10le-to-rgb24.png

    3c8326c3640cf4b6ce10ae70c562730d:

      04-rbg24-to-yuv444p10le-to-yuv444p-to-rgb24.png

  rgb24 -> yuv444p is imperceptibly lossy:

    @@ -1,5 +1,5 @@
     Image:
    -  Filename: 01-rgb24.png
    +  Filename: 02-rbg24-to-yuv444p-to-rgb24.png
       Format: PNG (Portable Network Graphics)
       Mime type: image/png
       Class: DirectClass
    @@ -19,13 +19,13 @@
       Channel statistics:
         Pixels: 129600
         Red:
    -      min: 127  (0.498039)
    -      max: 127 (0.498039)
    -      mean: 127 (0.498039)
    -      median: 127 (0.498039)
    +      min: 126  (0.494118)
    +      max: 126 (0.494118)
    +      mean: 126 (0.494118)
    +      median: 126 (0.494118)
           standard deviation: 0 (0)
    -      kurtosis: 8.25856e+54
    -      skewness: -9.425e+37
    +      kurtosis: -2.67166e+54
    +      skewness: 7.86719e+36
           entropy: 0
         Green:
           min: 255  (1)
    @@ -47,17 +47,17 @@
           entropy: 0
       Image statistics:
         Overall:
    -      min: 127  (0.498039)
    +      min: 126  (0.494118)
           max: 255 (1)
    -      mean: 198 (0.776471)
    -      median: 198 (0.776471)
    +      mean: 197.667 (0.775163)
    +      median: 197.667 (0.775163)
           standard deviation: 0 (0)
           kurtosis: -1.50001
    -      skewness: -0.376606
    +      skewness: -0.3818
           entropy: 0
       Colors: 1
       Histogram:
    -    129600: (127,255,212) #7FFFD4 aquamarine
    +    129600: (126,255,212) #7EFFD4 srgb(126,255,212)
       Rendering intent: Perceptual
       Gamma: 0.454545
       Chromaticity:
    @@ -88,13 +88,13 @@
         png:IHDR.width,height: 480, 270
         png:pHYs: x_res=1, y_res=1, units=0
         png:sRGB: intent=0 (Perceptual Intent)
    -    signature: 9c96d87924efacd9cd67c296a85efd4dc1aaa4b7053b7ed4410f2944911752f9
    +    signature: d8f3dc9f8e5d5fdfe8db73baf881f8660f38afc0617dc3130c3fbc484b87cd74
       Artifacts:
         verbose: true
       Tainted: False
       Filesize: 1054B
       Number pixels: 129600
    -  Pixels per second: 12.2981MP
    -  User time: 0.010u
    -  Elapsed time: 0:01.010
    +  Pixels per second: 22.1496MP
    +  User time: 0.000u
    +  Elapsed time: 0:01.005
       Version: ImageMagick 7.1.0-4 Q16 aarch64 2021-07-18 https://imagemagick.org

  yuv444p10le -> yuv444p is bonkers:
  (it SHOULD be the same as rgb24 -> yuv444p)

    @@ -1,5 +1,5 @@
     Image:
    -  Filename: 02-rbg24-to-yuv444p-to-rgb24.png
    +  Filename: 04-rbg24-to-yuv444p10le-to-yuv444p-to-rgb24.png
       Format: PNG (Portable Network Graphics)
       Mime type: image/png
       Class: DirectClass
    @@ -19,14 +19,14 @@
       Channel statistics:
         Pixels: 129600
         Red:
    -      min: 126  (0.494118)
    -      max: 126 (0.494118)
    -      mean: 126 (0.494118)
    -      median: 126 (0.494118)
    -      standard deviation: 0 (0)
    -      kurtosis: -2.67166e+54
    -      skewness: 7.86719e+36
    -      entropy: 0
    +      min: 130  (0.509804)
    +      max: 133 (0.521569)
    +      mean: 131.141 (0.514279)
    +      median: 131 (0.513725)
    +      standard deviation: 0.705121 (0.00276518)
    +      kurtosis: 2.83967
    +      skewness: 1.6718
    +      entropy: 0.556059
         Green:
           min: 255  (1)
           max: 255 (1)
    @@ -37,27 +37,30 @@
           skewness: 1e+36
           entropy: 0
         Blue:
    -      min: 212  (0.831373)
    -      max: 212 (0.831373)
    -      mean: 212 (0.831373)
    -      median: 212 (0.831373)
    -      standard deviation: 0 (0)
    -      kurtosis: 1.00773e+56
    -      skewness: -4.0775e+38
    -      entropy: 0
    +      min: 225  (0.882353)
    +      max: 228 (0.894118)
    +      mean: 227.89 (0.893687)
    +      median: 228 (0.894118)
    +      standard deviation: 0.438325 (0.00171892)
    +      kurtosis: 27.3528
    +      skewness: -5.0219
    +      entropy: 0.285571
       Image statistics:
         Overall:
    -      min: 126  (0.494118)
    +      min: 130  (0.509804)
           max: 255 (1)
    -      mean: 197.667 (0.775163)
    -      median: 197.667 (0.775163)
    -      standard deviation: 0 (0)
    -      kurtosis: -1.50001
    -      skewness: -0.3818
    -      entropy: 0
    -  Colors: 1
    +      mean: 204.677 (0.802656)
    +      median: 204.667 (0.802614)
    +      standard deviation: 0.381149 (0.0014947)
    +      kurtosis: -1.49956
    +      skewness: -0.571858
    +      entropy: 0.280543
    +  Colors: 4
       Histogram:
    -    129600: (126,255,212) #7EFFD4 srgb(126,255,212)
    +    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
       Chromaticity:
    @@ -88,13 +91,13 @@
         png:IHDR.width,height: 480, 270
         png:pHYs: x_res=1, y_res=1, units=0
         png:sRGB: intent=0 (Perceptual Intent)
    -    signature: d8f3dc9f8e5d5fdfe8db73baf881f8660f38afc0617dc3130c3fbc484b87cd74
    +    signature: 0dd1f909b586d9a254b25a7d4f8d9e742fe189c35c1a65e63c9dffde72614506
       Artifacts:
         verbose: true
       Tainted: False
    -  Filesize: 1054B
    +  Filesize: 1577B
       Number pixels: 129600
    -  Pixels per second: 21.2168MP
    +  Pixels per second: 12.2899MP
       User time: 0.010u
    -  Elapsed time: 0:01.006
    +  Elapsed time: 0:01.010
       Version: ImageMagick 7.1.0-4 Q16 aarch64 2021-07-18 https://imagemagick.org

Conclusion:
==========

  As indicated by the hashes, the *workaround* is to convert
  "yuv444p10le" to some other class of pixel format (like "rgb24")
  before converting to another "yuv*" pixel format:

    scale=out_range=pc, format=yuv444p10le,
      scale=out_range=pc, format=rgb24,     <--------- workaround
        scale=out_range=pc, format=yuv444p

  Nevertheless, a workaround should not even be necessary. There
  is a bug that should be investigated and fixed.

  (As an aside, look at all that "out_range" gibberish; it should
  not be necessary to do that little dance.)

Attachments (2)

00-commands.sh (3.6 KB ) - added by Michael Witten 3 years ago.
Bash script that produces tests results
06-log.txt (8.3 KB ) - added by Michael Witten 3 years ago.
The log output from when I ran the script

Download all attachments as: .zip

Change History (15)

by Michael Witten, 3 years ago

Attachment: 00-commands.sh added

Bash script that produces tests results

by Michael Witten, 3 years ago

Attachment: 06-log.txt added

The log output from when I ran the script

comment:1 by jeeb, 3 years ago

If I understand the note regarding color_range correctly, that is due to the logic in swscale/vf_scale that if the user wants YCbCr output, then the default range would be limited. For RGB it should be full range output by default. And thus yes, for full range output with YCbCr, one needs to set the range specifically.

comment:2 by Elon Musk, 3 years ago

Resolution: invalid
Status: newclosed

If you need full range yuv without properly tagged input, you must set in_range and out_range.

comment:3 by Balling, 3 years ago

For RGB it should be full range output by default

No. It is always limited range bt.601 (hey, we discussed that already!!). Zscale defaults to source range though. It is not enough to do scale=out_range=pc. You must also specify the matrix in scale and tag it all, including -color_range pc.

As an aside, look at all that "out_range" gibberish; it should not be necessary to do that little dance.

We cannot change the default of always limited range, that will be very public API break, that cannot be broken. Use zscale.

Oh and BTW, while convertion from rgb24 (8 bit) to yuv444p10le (10 bit) is lossless, it may not be backwards from yuv444p10le, since ycbcr is bigger than rgb.

you must set in_range

Yes, though setpatams not working is of course a bug or may be you should have used ycbcr instead of rgb24, since setparams' matrix makes not sence for rgb. -f lavfi -i color=0x7FFFD4:size=480x270, format=rgb24,

Last edited 3 years ago by Balling (previous) (diff)

comment:4 by Michael Witten, 3 years ago

Resolution: invalid
Status: closedreopened

I don't understand why this was marked "invalid" or closed, or indeed why the discussion is focused on my parenthesized aside about out_range.

Please explain why this should be closed before closing again.

comment:5 by pdr0, 3 years ago

Resolution: invalid
Status: reopenedclosed

You're missing the scale=in_range=pc argument for the last conversion from yuv444p to rgb24

If it's not clear:

ffmpeg -f lavfi -i color=0x7FFFD4:size=480x270 -frames:v 1 orig.png

ffmpeg -f lavfi -i color=0x7FFFD4:size=480x270 -vf scale=out_range=pc:out_color_matrix=bt709,format=yuv444p10le,format=yuv444p,scale=out_range=pc,format=rgb24 -frames:v 1 wrong.png

ffmpeg -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 right.png

Last edited 3 years ago by pdr0 (previous) (diff)

comment:6 by Balling, 3 years ago

Wait a second. This is just a duplicate of #3345! Moreover https://trac.ffmpeg.org/ticket/4614#comment:12 suggests workaround as here through rgb24.

Last edited 3 years ago by Balling (previous) (diff)

comment:7 by Michael Witten, 3 years ago

Resolution: invalid
Status: closedreopened

Thank you, pdr0, for your explanation.

  • NOT THE PROBLEM IN QUESTION:

    • The issues with "color_range" are incidental, and they probably require their own tickets.

    • I believe that I have been handling the "color_range" correctly (see below).

    • Your examples, however, do not handle the "color_range" correctly (see below).

    • I can see now that my attempt to control the color space is also broken, which probably requires its own ticket (see below).

  • THE ACTUAL PROBLEM:

    • The conversion from "yuv444p10le" to "yuv444p" produces multiple colors rather than just one.

    • Perhaps this is some kind of forced dithering problem, as hinted by Balling's find on issue #3345, where the workaround is indeed to convert to something else (e.g., "rgb24") as an intermediary pixel format between "yuv444p10le" and "yuv444p".

    • 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.

  • All of this confusion is why it is unwise to close a report or mark it as "invalid" when the very author of that report is still here to discuss it; otherwise, you are just introducing overhead and aggravation for all parties involved.

"color_range"

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:

  color_range:unknown color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:bt709 color_primaries:bt709 color_trc:iec61966-2-1
  color_range:unknown color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown

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:

#!/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:

  color_range:unknown color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:pc color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:tv color_space:unknown color_primaries:unknown color_trc:unknown
  color_range:tv color_space:unknown color_primaries:unknown color_trc:unknown

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:
      [auto_scaler_0 @ 0x7b0940] w:iw h:ih flags:'bicubic' interl:0
      [Parsed_format_2 @ 0x7ab5c0] auto-inserting filter 'auto_scaler_0' between the filter 'Parsed_format_1' and the filter 'Parsed_format_2'
      [auto_scaler_0 @ 0x7b0940] w:480 h:270 fmt:yuv444p10le sar:1/1 -> w:480 h:270 fmt:yuv444p sar:1/1 flags:0x4
    

Color Metadata

As shown above (and as noted by Balling), the metadata specified by "setparams" in the "lavfi" input is just thrown out upon injection of the frames into the main filter graph; clearly, this is a bug all on its own.

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
    
  1. 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
    
  1. 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
    
  1. 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):
    $ 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
    
  1. 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.

comment:8 by pdr0, 3 years ago

Apologies Michael, I read the ticket too quickly

1) A YUV to YUV conversion is a no-op in terms of range - when in_range and out_range are the same. You can explicitly list full in and full out, or limited in and limited out, or omit. The metadata does not carry though as you observed, so is not even required - which leads to the next point:

2) What is important for current versions ffmpeg to work as expected , for actual results - is specifying the in_range before any YUV to RGB conversion (as you can see omitting produces wrong result), or out_range for RGB to YUV conversion. ie. Always specify the range in the YUV direction. If nothing is specified, limited range is assumed.

Maybe somewhere in the future when metadata works and passes correctly we won't have to do it this way. But this is the way it works now.

3) The "multiple colors" is from dithering. Disable dithering

ffmpeg -f lavfi -i color=0x7FFFD4:size=480x270 -vf scale=out_range=pc:out_color_matrix=bt709,format=yuv444p10le,scale=sws_flags=sws_dither=0=format=yuv444p,scale=in_range=pc:in_color_matrix=bt709,format=rgb24 -frames:v 1 output.png

comment:9 by Balling, 3 years ago

I think a transfer function issue

a) we do not support EOTF awared scale, see #6694
b) ycbcr to ycbcr does not require going to linear RGB. Everything is done on R'G'B'. (The exceptions are of course newer ICtCp, BT.2020-cl (everything on Blu-ray and streams uses bt.2020-ncl though)) and chromaticity derived constant luminance systems. Those operate on linear light.)

c) Please note that Imagemagick has a bug that it says it is sRGB when it only has 2.2 gAMA chunk without sRGB chunk, it is present on all from svg images on wikipedia, an insane bug that destroyes colors, there is a bug still open publicly for that in wikimedia phabricator and now Imagemagick github too. And also that 0.4545445 is just 2.2 pure gamma which is not sRGB, in this case ffmpeg appears to set the gAMA tag of 2.2 and even says it is perceptual rendering intent inside sRGB chunk. Now, perceptual can be handled very differently by different software, so... also please note that it is tagged as sRGB, but the correct is gAMA chunk of 1/2.4, since BT.709 transfer must be presented using 2.4 pure gamma on perfect display. This is also a bug in ffmpeg, of course. We do not change the transfer either.

Now, I do not know how you think we will fix it if it were not fixed in the past 10 years or so... As for dither I will try to test it.

Last edited 3 years ago by Balling (previous) (diff)

comment:10 by Elon Musk, 3 years ago

Resolution: duplicate
Status: reopenedclosed

This is PEBKAC, dithering is enabled by default and color range must be set explicitly for both inputs and outputs always for now.

comment:11 by Balling, 3 years ago

scale=sws_flags=sws_dither=0 is wrong. The correct command is scale=sws_dither=0 or scale=sws_dither=none (that is producing same results, somewhere none is made the same as 0). That makes a change in #3345, please test!! There is no such thing as sws_flags in scale only flags. While there is a separate -sws_flags option.

Last edited 3 years ago by Balling (previous) (diff)

in reply to:  11 comment:12 by pdr0, 3 years ago

Replying to Balling:

scale=sws_flags=sws_dither=0 is wrong. The correct command is scale=sws_dither=0 or scale=sws_dither=none (that is producing same results, somewhere none is made the same as 0). That makes a change in #3345, please test!! There is no such thing as sws_flags in scale only flags. While there is a separate -sws_flags option.

You're rigth - "sws_dither=none" is the correct switch ,
https://github.com/FFmpeg/FFmpeg/blob/master/libswscale/options.c

"sws_dither=0" gives the same result... at least for now

That 3345 ticket is 8 years old . OP claims that issue isn't present with libav. You get bit identical results with libav. Libav dithers by default too now too. Maybe it didn't 8 years ago.

comment:13 by Carl Eugen Hoyos, 21 months ago

Component: ffmpegswscale
Keywords: pix_fmt yuv yuv444p10le yuv444p 10-bit format removed
Note: See TracTickets for help on using tickets.