Opened 11 days ago

Closed 11 days ago

Last modified 4 days ago

#11182 closed defect (invalid)

yuvtestsrc and yuv444p->rgba->yuv444p conversion result in huge difference

Reported by: Andrew-R Owned by:
Priority: normal Component: swscale
Version: unspecified Keywords: colorspace color_primaries
Cc: MasterQuestionable Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug:
How to reproduce:

bash-5.1$ /dev/shm/ffmpeg/ffmpeg -f lavfi -color_range 2 -i yuvtestsrc -frames 1 -r 25 -vf format=rgba,format=yuv444p -color_range 2 /dev/shm/yuv-mpeg-rgba-yuv444p.y4m -debug log
ffmpeg version N-115741-g8a314e3f11 Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 11.2.0 (GCC)
  configuration: --disable-debug
  libavutil      59. 36.100 / 59. 36.100
  libavcodec     61. 12.100 / 61. 12.100
  libavformat    61.  5.101 / 61.  5.101
  libavdevice    61.  2.100 / 61.  2.100
  libavfilter    10.  2.102 / 10.  2.102
  libswscale      8.  2.100 /  8.  2.100
  libswresample   5.  2.100 /  5.  2.100
 matched as AVOption 'debug' with argument 'log'.
Trailing option(s) found in the command: may be ignored.
Finished splitting the commandline.
Parsing a group of options: global .
Successfully parsed a group of options.
Parsing a group of options: input url yuvtestsrc.
Applying option f (force container format (auto-detected otherwise)) with argument lavfi.
Successfully parsed a group of options.
Opening an input file: yuvtestsrc.
detected 4 logical cores
[Parsed_yuvtestsrc_0 @ 0xb791780] size:320x240 rate:25/1 duration:-1.000000 sar:1/1
[AVFilterGraph @ 0xb790fc0] query_formats: 2 queried, 3 merged, 0 already done, 0 delayed
[lavfi @ 0xb790900] All info found
Input #0, lavfi, from 'yuvtestsrc':
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #0:0, 1, 1/25: Video: wrapped_avframe, 1 reference frame, yuv444p(pc), 320x240 [SAR 1:1 DAR 4:3], 0/1, 25 fps, 25 tbr, 25 tbn
Successfully opened the file.
Parsing a group of options: output url /dev/shm/yuv-mpeg-rgba-yuv444p.y4m.
Applying option frames (set the number of frames to output) with argument 1.
Applying option r (override input framerate/convert to given output framerate (Hz value, fraction or abbreviation)) with argument 25.
Applying option vf (alias for -filter:v (apply filters to video streams)) with argument format=rgba,format=yuv444p.
Successfully parsed a group of options.
Opening an output file: /dev/shm/yuv-mpeg-rgba-yuv444p.y4m.
[out#0/yuv4mpegpipe @ 0xb7cdb40] No explicit maps, mapping streams automatically...
[vost#0:0/wrapped_avframe @ 0xb7ce340] Created video stream from input stream 0:0
[AVFilterGraph @ 0xb7cf940] Setting 'pix_fmts' to value 'rgba'
[AVFilterGraph @ 0xb7cf940] Setting 'pix_fmts' to value 'yuv444p'
File '/dev/shm/yuv-mpeg-rgba-yuv444p.y4m' already exists. Overwrite? [y/N] y
[file @ 0xb7d1f40] Setting default whitelist 'file,crypto,data'
Successfully opened the file.
Stream mapping:
  Stream #0:0 -> #0:0 (wrapped_avframe (native) -> wrapped_avframe (native))
[vost#0:0/wrapped_avframe @ 0xb7ce340] Starting thread...
[vf#0:0 @ 0xb7cf5c0] Starting thread...
[vist#0:0/wrapped_avframe @ 0xb7cd580] [dec:wrapped_avframe @ 0xb7d1240] Starting thread...
[in#0/lavfi @ 0xb790680] Starting thread...
Press [q] to stop, [?] for help
[AVFilterGraph @ 0xf4100a40] Setting 'pix_fmts' to value 'rgba'
[AVFilterGraph @ 0xf4100a40] Setting 'pix_fmts' to value 'yuv444p'
[graph -1 input from stream 0:0 @ 0xf4101f80] Setting 'video_size' to value '320x240'
[graph -1 input from stream 0:0 @ 0xf4101f80] Setting 'pix_fmt' to value '5'
[graph -1 input from stream 0:0 @ 0xf4101f80] Setting 'time_base' to value '1/25'
[graph -1 input from stream 0:0 @ 0xf4101f80] Setting 'pixel_aspect' to value '1/1'
[graph -1 input from stream 0:0 @ 0xf4101f80] Setting 'colorspace' to value '2'
[graph -1 input from stream 0:0 @ 0xf4101f80] Setting 'range' to value '2'
[graph -1 input from stream 0:0 @ 0xf4101f80] Setting 'frame_rate' to value '25/1'
[graph -1 input from stream 0:0 @ 0xf4101f80] w:320 h:240 pixfmt:yuv444p tb:1/25 fr:25/1 sar:1/1 csp:unknown range:pc
[auto_scale_0 @ 0xf4103d80] w:iw h:ih flags:'' interl:0
[Parsed_format_0 @ 0xf41015c0] auto-inserting filter 'auto_scale_0' between the filter 'graph -1 input from stream 0:0' and the filter 'Parsed_format_0'
[auto_scale_1 @ 0xf410e940] w:iw h:ih flags:'' interl:0
[Parsed_format_1 @ 0xf41018c0] auto-inserting filter 'auto_scale_1' between the filter 'Parsed_format_0' and the filter 'Parsed_format_1'
[AVFilterGraph @ 0xf4100a40] query_formats: 4 queried, 3 merged, 6 already done, 0 delayed
[swscaler @ 0xf4119040] [swscaler @ 0xf4122480] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4119040] [swscaler @ 0xf413c140] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4119040] [swscaler @ 0xf4155600] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4119040] [swscaler @ 0xf416f2c0] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4119040] [swscaler @ 0xf4188780] Forcing full internal H chroma due to input having non subsampled chroma
[auto_scale_0 @ 0xf4103d80] w:320 h:240 fmt:yuv444p csp:unknown range:pc sar:1/1 -> w:320 h:240 fmt:rgba csp:gbr range:pc sar:1/1 flags:0x00000004
[auto_scale_0 @ 0xf4103d80] [framesync @ 0xf4103e14] Selected 1/25 time base
[auto_scale_0 @ 0xf4103d80] [framesync @ 0xf4103e14] Sync level 1
[auto_scale_1 @ 0xf410e940] w:320 h:240 fmt:rgba csp:gbr range:pc sar:1/1 -> w:320 h:240 fmt:yuv444p csp:unknown range:pc sar:1/1 flags:0x00000004
[auto_scale_1 @ 0xf410e940] [framesync @ 0xf410ea14] Selected 1/25 time base
[auto_scale_1 @ 0xf410e940] [framesync @ 0xf410ea14] Sync level 1
[graph -1 input from stream 0:0 @ 0xf4101f80] video frame properties congruent with link at pts_time: 0
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-mpeg-rgba-yuv444p.y4m':
  Metadata:
    encoder         : Lavf61.5.101
  Stream #0:0, 0, 1/25: Video: wrapped_avframe, 1 reference frame, yuv444p(pc, progressive), 320x240 [SAR 1:1 DAR 4:3], 0/1, q=2-31, 200 kb/s, 25 fps, 25 tbn
      Metadata:
        encoder         : Lavc61.12.100 wrapped_avframe
[out#0/yuv4mpegpipe @ 0xb7cdb40] Starting thread...
[out#0/yuv4mpegpipe @ 0xb7cdb40] sq: send 0 ts 0.04
[out#0/yuv4mpegpipe @ 0xb7cdb40] sq: 0 frames_max 1 reached
[out#0/yuv4mpegpipe @ 0xb7cdb40] sq: finish 0; head ts 0.04
[out#0/yuv4mpegpipe @ 0xb7cdb40] sq: finish queue
[out#0/yuv4mpegpipe @ 0xb7cdb40] sq: receive 0 ts 0.04 queue head 0 ts 0.04
[vf#0:0 @ 0xb7cf5c0] All consumers returned EOF
[vost#0:0/wrapped_avframe @ 0xb7ce340] Encoder thread received EOF
[vost#0:0/wrapped_avframe @ 0xb7ce340] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xb7cdb40] All streams finished
[out#0/yuv4mpegpipe @ 0xb7cdb40] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xb7cdb40] sq: 0 EOF
[out#0/yuv4mpegpipe @ 0xb7cdb40] sq: finish queue
[vf#0:0 @ 0xb7cf5c0] Terminating thread with return code 0 (success)
[vist#0:0/wrapped_avframe @ 0xb7cd580] [dec:wrapped_avframe @ 0xb7d1240] Decoder returned EOF, finishing
[vist#0:0/wrapped_avframe @ 0xb7cd580] [dec:wrapped_avframe @ 0xb7d1240] Terminating thread with return code 0 (success)
[vist#0:0/wrapped_avframe @ 0xb7cd580] All consumers of this stream are done
[in#0/lavfi @ 0xb790680] All consumers are done
[in#0/lavfi @ 0xb790680] Terminating thread with return code 0 (success)
[AVIOContext @ 0xb7cfc00] Statistics: 230473 bytes written, 0 seeks, 1 writeouts
[out#0/yuv4mpegpipe @ 0xb7cdb40] Output file #0 (/dev/shm/yuv-mpeg-rgba-yuv444p.y4m):
[out#0/yuv4mpegpipe @ 0xb7cdb40]   Output stream #0:0 (video): 1 frames encoded; 1 packets muxed (308 bytes);
[out#0/yuv4mpegpipe @ 0xb7cdb40]   Total: 1 packets (308 bytes) muxed
[out#0/yuv4mpegpipe @ 0xb7cdb40] video:0KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 74728.896104%
frame=    1 fps=0.0 q=-0.0 Lsize=     225KiB time=00:00:00.04 bitrate=46094.6kbits/s speed=3.08x
[in#0/lavfi @ 0xb790680] Input file #0 (yuvtestsrc):
[in#0/lavfi @ 0xb790680]   Input stream #0:0 (video): 19 packets read (5852 bytes); 10 frames decoded; 0 decode errors;
[in#0/lavfi @ 0xb790680]   Total: 19 packets (5852 bytes) demuxed

====

compare with file made with this command:

bash-5.1$ /dev/shm/ffmpeg/ffmpeg -f lavfi -color_range 2 -i yuvtestsrc -frames 1 -r 25 -color_range 2 /dev/shm/yuv-mpeg-yuv444p.y4m -debug log
ffmpeg version N-115741-g8a314e3f11 Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 11.2.0 (GCC)
  configuration: --disable-debug
  libavutil      59. 36.100 / 59. 36.100
  libavcodec     61. 12.100 / 61. 12.100
  libavformat    61.  5.101 / 61.  5.101
  libavdevice    61.  2.100 / 61.  2.100
  libavfilter    10.  2.102 / 10.  2.102
  libswscale      8.  2.100 /  8.  2.100
  libswresample   5.  2.100 /  5.  2.100
 matched as AVOption 'debug' with argument 'log'.
Trailing option(s) found in the command: may be ignored.
Finished splitting the commandline.
Parsing a group of options: global .
Successfully parsed a group of options.
Parsing a group of options: input url yuvtestsrc.
Applying option f (force container format (auto-detected otherwise)) with argument lavfi.
Successfully parsed a group of options.
Opening an input file: yuvtestsrc.
detected 4 logical cores
[Parsed_yuvtestsrc_0 @ 0xca3b700] size:320x240 rate:25/1 duration:-1.000000 sar:1/1
[AVFilterGraph @ 0xca3af80] query_formats: 2 queried, 3 merged, 0 already done, 0 delayed
[lavfi @ 0xca3a8c0] All info found
Input #0, lavfi, from 'yuvtestsrc':
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #0:0, 1, 1/25: Video: wrapped_avframe, 1 reference frame, yuv444p(pc), 320x240 [SAR 1:1 DAR 4:3], 0/1, 25 fps, 25 tbr, 25 tbn
Successfully opened the file.
Parsing a group of options: output url /dev/shm/yuv-mpeg-yuv444p.y4m.
Applying option frames (set the number of frames to output) with argument 1.
Applying option r (override input framerate/convert to given output framerate (Hz value, fraction or abbreviation)) with argument 25.
Successfully parsed a group of options.
Opening an output file: /dev/shm/yuv-mpeg-yuv444p.y4m.
[out#0/yuv4mpegpipe @ 0xca77d80] No explicit maps, mapping streams automatically...
[vost#0:0/wrapped_avframe @ 0xca78580] Created video stream from input stream 0:0
File '/dev/shm/yuv-mpeg-yuv444p.y4m' already exists. Overwrite? [y/N] y
[file @ 0xca7b900] Setting default whitelist 'file,crypto,data'
Successfully opened the file.
Stream mapping:
  Stream #0:0 -> #0:0 (wrapped_avframe (native) -> wrapped_avframe (native))
[vost#0:0/wrapped_avframe @ 0xca78580] Starting thread...
[vf#0:0 @ 0xca79800] Starting thread...
[vist#0:0/wrapped_avframe @ 0xca77740] [dec:wrapped_avframe @ 0xca7ac00] Starting thread...
[in#0/lavfi @ 0xca3a640] Starting thread...
Press [q] to stop, [?] for help
[graph -1 input from stream 0:0 @ 0xf41016c0] Setting 'video_size' to value '320x240'
[graph -1 input from stream 0:0 @ 0xf41016c0] Setting 'pix_fmt' to value '5'
[graph -1 input from stream 0:0 @ 0xf41016c0] Setting 'time_base' to value '1/25'
[graph -1 input from stream 0:0 @ 0xf41016c0] Setting 'pixel_aspect' to value '1/1'
[graph -1 input from stream 0:0 @ 0xf41016c0] Setting 'colorspace' to value '2'
[graph -1 input from stream 0:0 @ 0xf41016c0] Setting 'range' to value '2'
[graph -1 input from stream 0:0 @ 0xf41016c0] Setting 'frame_rate' to value '25/1'
[graph -1 input from stream 0:0 @ 0xf41016c0] w:320 h:240 pixfmt:yuv444p tb:1/25 fr:25/1 sar:1/1 csp:unknown range:pc
[AVFilterGraph @ 0xf4100a40] query_formats: 3 queried, 6 merged, 0 already done, 0 delayed
[graph -1 input from stream 0:0 @ 0xf41016c0] video frame properties congruent with link at pts_time: 0
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-mpeg-yuv444p.y4m':
  Metadata:
    encoder         : Lavf61.5.101
  Stream #0:0, 0, 1/25: Video: wrapped_avframe, 1 reference frame, yuv444p(pc, progressive), 320x240 [SAR 1:1 DAR 4:3], 0/1, q=2-31, 200 kb/s, 25 fps, 25 tbn
      Metadata:
        encoder         : Lavc61.12.100 wrapped_avframe
[out#0/yuv4mpegpipe @ 0xca77d80] Starting thread...
[out#0/yuv4mpegpipe @ 0xca77d80] sq: send 0 ts 0.04
[out#0/yuv4mpegpipe @ 0xca77d80] sq: 0 frames_max 1 reached
[out#0/yuv4mpegpipe @ 0xca77d80] sq: finish 0; head ts 0.04
[out#0/yuv4mpegpipe @ 0xca77d80] sq: finish queue
[out#0/yuv4mpegpipe @ 0xca77d80] sq: receive 0 ts 0.04 queue head 0 ts 0.04
[vf#0:0 @ 0xca79800] All consumers returned EOF
[vost#0:0/wrapped_avframe @ 0xca78580] Encoder thread received EOF
[vost#0:0/wrapped_avframe @ 0xca78580] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xca77d80] sq: 0 EOF
[out#0/yuv4mpegpipe @ 0xca77d80] sq: finish queue
[vf#0:0 @ 0xca79800] Terminating thread with return code 0 (success)
[vist#0:0/wrapped_avframe @ 0xca77740] [dec:wrapped_avframe @ 0xca7ac00] Decoder returned EOF, finishing
[vist#0:0/wrapped_avframe @ 0xca77740] All consumers of this stream are done
[in#0/lavfi @ 0xca3a640] All consumers are done
[in#0/lavfi @ 0xca3a640] Terminating thread with return code 0 (success)
[vist#0:0/wrapped_avframe @ 0xca77740] [dec:wrapped_avframe @ 0xca7ac00] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xca77d80] All streams finished
[out#0/yuv4mpegpipe @ 0xca77d80] Terminating thread with return code 0 (success)
[AVIOContext @ 0xca76a00] Statistics: 230473 bytes written, 0 seeks, 1 writeouts
[out#0/yuv4mpegpipe @ 0xca77d80] Output file #0 (/dev/shm/yuv-mpeg-yuv444p.y4m):
[out#0/yuv4mpegpipe @ 0xca77d80]   Output stream #0:0 (video): 1 frames encoded; 1 packets muxed (308 bytes);
[out#0/yuv4mpegpipe @ 0xca77d80]   Total: 1 packets (308 bytes) muxed
[out#0/yuv4mpegpipe @ 0xca77d80] video:0KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 74728.896104%
frame=    1 fps=0.0 q=-0.0 Lsize=     225KiB time=00:00:00.04 bitrate=46094.6kbits/s speed=9.44x
[in#0/lavfi @ 0xca3a640] Input file #0 (yuvtestsrc):
[in#0/lavfi @ 0xca3a640]   Input stream #0:0 (video): 19 packets read (5852 bytes); 10 frames decoded; 0 decode errors;
[in#0/lavfi @ 0xca3a640]   Total: 19 packets (5852 bytes) demuxed

I compared two files using YUView (requires qt5): https://github.com/IENT/YUView

I also tried to define colorimetry info harder:

bash-5.1$ /dev/shm/ffmpeg/ffmpeg -f lavfi -color_range 2 -color_primaries bt709 -colorspace bt709 -color_trc bt709 -i yuvtestsrc -frames 1 -r 25 -vf format=rgba,scale,format=yuv444p,scale -color_range 2 -color_primaries bt709 -colorspace bt709 -color_trc bt709 /dev/shm/yuv-mpeg-rgba-yuv444p.y4m -debug log

but it does not change outcome

Attachments (4)

yuv-mpeg.y4m (225.1 KB ) - added by Andrew-R 11 days ago.
no conversion version
yuv-mpeg-rgba-yuv444p.y4m (225.1 KB ) - added by Andrew-R 11 days ago.
with format/scale combo
yuv444-rgba-problem1.png (6.1 KB ) - added by Andrew-R 11 days ago.
how it looks
swscale.c-mod.log (8.4 KB ) - added by MasterQuestionable 6 days ago.
͏    Prints: ͏    https://trac.ffmpeg.org/attachment/ticket/11182/swscale.c-mod.log#L87

Download all attachments as: .zip

Change History (53)

by Andrew-R, 11 days ago

Attachment: yuv-mpeg.y4m added

no conversion version

by Andrew-R, 11 days ago

Attachment: yuv-mpeg-rgba-yuv444p.y4m added

with format/scale combo

by Andrew-R, 11 days ago

Attachment: yuv444-rgba-problem1.png added

how it looks

comment:1 by Andrew-R, 11 days ago

Summary: testyuvsrc and yuv444p->rgba->yuv44p conversion result in huge differencetestyuvsrc and yuv444p->rgba->yuv444p conversion result in huge difference

comment:2 by Balling, 11 days ago

Your command is wrong. -color_primaries bt709 -colorspace bt709 -color_trc bt709 just changes metadata, to manipulate actual pixels as you see in YUView you need to use -vf scale=out_range=tv:out_color _matrix=bt709. That BTW is only colorspace, transfer and primaries are separate and not fully supported by scale, you need to use zscale.

In your case you also need to set -vf scale=in_range=tv:in_color_matrix=bt709 when going from YCbCr to RGB. Also, it is not wise to go to RGB, since RGB cannot preserve very wide space of YCbCr, 6 times bigger than RGB.

Last edited 10 days ago by Balling (previous) (diff)

comment:3 by Balling, 11 days ago

Resolution: invalid
Status: newclosed

comment:4 by Andrew-R, 10 days ago

I was going for full range testing due to our (?) bug:

https://www.cinelerra-gg.org/bugtracker/view.php?id=665

I do not think we want to integrate zscale yet (I tried to do this some times ago and got crashes).

For some reason with git ffmpeg I need to set
/dev/shm/ffmpeg/ffmpeg -f lavfi -color_range 1 -i yuvtestsrc -frames 1 -r 25 -vf scale=in_range=pc:out_range=tv -color_range 1 /dev/shm/yuv-mpeg-yuv444p.y4m -debug log

in_range/out_range, not in_color_range/out_color_range.

If I understand correctly swscale also doing internal rgb transfer if we try to change range on yuv data, so may be it exaggregates our problem when we exactly try to avoid yuv->rgba->yuv change by using yuva8 internally ...

comment:5 by Andrew-R, 10 days ago

I also tried this command (bt2020 colorspace, rgba64le intermediate step)

bash-5.1$ /dev/shm/ffmpeg/ffmpeg -f lavfi -color_range 1 -i yuvtestsrc -frames 1 -r 25 -vf scale=out_color_matrix=bt2020:out_range=pc:in_color_matrix=bt2020:in_range=pc,format=rgba64le,scale=out_color_matrix=bt2020:out_range=pc,format=yuv444p,scale=out_color_matrix=bt2020:out_range=tv /dev/shm/yuv-mpeg-rgba-yuv444p.y4m -debug log
ffmpeg version N-115741-g8a314e3f11 Copyright (c) 2000-2024 the FFmpeg developers

built with gcc 11.2.0 (GCC)
configuration: --disable-debug
libavutil 59. 36.100 / 59. 36.100
libavcodec 61. 12.100 / 61. 12.100
libavformat 61. 5.101 / 61. 5.101
libavdevice 61. 2.100 / 61. 2.100
libavfilter 10. 2.102 / 10. 2.102
libswscale 8. 2.100 / 8. 2.100
libswresample 5. 2.100 / 5. 2.100

matched as AVOption 'debug' with argument 'log'.

Trailing option(s) found in the command: may be ignored.
Finished splitting the commandline.
Parsing a group of options: global .
Successfully parsed a group of options.
Parsing a group of options: input url yuvtestsrc.
Applying option f (force container format (auto-detected otherwise)) with argument lavfi.
Successfully parsed a group of options.
Opening an input file: yuvtestsrc.
detected 4 logical cores
[Parsed_yuvtestsrc_0 @ 0xb4e46c0] size:320x240 rate:25/1 duration:-1.000000 sar:1/1
[AVFilterGraph @ 0xb4e3f00] query_formats: 2 queried, 3 merged, 0 already done, 0 delayed
[lavfi @ 0xb4e3840] All info found
Input #0, lavfi, from 'yuvtestsrc':

Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0, 1, 1/25: Video: wrapped_avframe, 1 reference frame, yuv444p(tv), 320x240 [SAR 1:1 DAR 4:3], 0/1, 25 fps, 25 tbr, 25 tbn

Successfully opened the file.
Parsing a group of options: output url /dev/shm/yuv-mpeg-rgba-yuv444p.y4m.
Applying option frames (set the number of frames to output) with argument 1.
Applying option r (override input framerate/convert to given output framerate (Hz value, fraction or abbreviation)) with argument 25.
Applying option vf (alias for -filter:v (apply filters to video streams)) with argument scale=out_color_matrix=bt2020:out_range=pc:in_color_matrix=bt2020:in_range=pc,format=rgba64le,scale=out_color_matrix=bt2020:out_range=pc,format=yuv444p,scale=out_color_matrix=bt2020:out_range=tv.
Successfully parsed a group of options.
Opening an output file: /dev/shm/yuv-mpeg-rgba-yuv444p.y4m.
[out#0/yuv4mpegpipe @ 0xb520cc0] No explicit maps, mapping streams automatically...
[vost#0:0/wrapped_avframe @ 0xb521480] Created video stream from input stream 0:0
[AVFilterGraph @ 0xb5226c0] Setting 'out_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xb5226c0] Setting 'out_range' to value 'pc'
[AVFilterGraph @ 0xb5226c0] Setting 'in_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xb5226c0] Setting 'in_range' to value 'pc'
[AVFilterGraph @ 0xb5226c0] Setting 'pix_fmts' to value 'rgba64le'
[AVFilterGraph @ 0xb5226c0] Setting 'out_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xb5226c0] Setting 'out_range' to value 'pc'
[AVFilterGraph @ 0xb5226c0] Setting 'pix_fmts' to value 'yuv444p'
[AVFilterGraph @ 0xb5226c0] Setting 'out_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xb5226c0] Setting 'out_range' to value 'tv'
[Parsed_scale_0 @ 0xb523680] w:iw h:ih flags: interl:0
[Parsed_scale_2 @ 0xb51f640] w:iw h:ih flags:
interl:0
[Parsed_scale_4 @ 0xb51fe80] w:iw h:ih flags: interl:0
File '/dev/shm/yuv-mpeg-rgba-yuv444p.y4m' already exists. Overwrite? [y/N] y
[file @ 0xb51f880] Setting default whitelist 'file,crypto,data'
Successfully opened the file.
Stream mapping:

Stream #0:0 -> #0:0 (wrapped_avframe (native) -> wrapped_avframe (native))

[vost#0:0/wrapped_avframe @ 0xb521480] Starting thread...
[vf#0:0 @ 0xb5223c0] Starting thread...
[vist#0:0/wrapped_avframe @ 0xb5205c0] [dec:wrapped_avframe @ 0xb53f900] Starting thread...
[in#0/lavfi @ 0xb4e35c0] Starting thread...
Press [q] to stop, ? for help
[AVFilterGraph @ 0xf4200a40] Setting 'out_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xf4200a40] Setting 'out_range' to value 'pc'
[AVFilterGraph @ 0xf4200a40] Setting 'in_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xf4200a40] Setting 'in_range' to value 'pc'
[AVFilterGraph @ 0xf4200a40] Setting 'pix_fmts' to value 'rgba64le'
[AVFilterGraph @ 0xf4200a40] Setting 'out_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xf4200a40] Setting 'out_range' to value 'pc'
[AVFilterGraph @ 0xf4200a40] Setting 'pix_fmts' to value 'yuv444p'
[AVFilterGraph @ 0xf4200a40] Setting 'out_color_matrix' to value 'bt2020'
[AVFilterGraph @ 0xf4200a40] Setting 'out_range' to value 'tv'
[Parsed_scale_0 @ 0xf42023c0] w:iw h:ih flags: interl:0
[Parsed_scale_2 @ 0xf420bcc0] w:iw h:ih flags:
interl:0
[Parsed_scale_4 @ 0xf4215680] w:iw h:ih flags: interl:0
[graph -1 input from stream 0:0 @ 0xf4220580] Setting 'video_size' to value '320x240'
[graph -1 input from stream 0:0 @ 0xf4220580] Setting 'pix_fmt' to value '5'
[graph -1 input from stream 0:0 @ 0xf4220580] Setting 'time_base' to value '1/25'
[graph -1 input from stream 0:0 @ 0xf4220580] Setting 'pixel_aspect' to value '1/1'
[graph -1 input from stream 0:0 @ 0xf4220580] Setting 'colorspace' to value '2'
[graph -1 input from stream 0:0 @ 0xf4220580] Setting 'range' to value '1'
[graph -1 input from stream 0:0 @ 0xf4220580] Setting 'frame_rate' to value '25/1'
[graph -1 input from stream 0:0 @ 0xf4220580] w:320 h:240 pixfmt:yuv444p tb:1/25 fr:25/1 sar:1/1 csp:unknown range:tv
[AVFilterGraph @ 0xf4200a40] query_formats: 7 queried, 18 merged, 0 already done, 0 delayed
[swscaler @ 0xf4224b40] [swscaler @ 0xf422ddc0] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4224b40] [swscaler @ 0xf424b180] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4224b40] [swscaler @ 0xf4267d40] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4224b40] [swscaler @ 0xf4284d00] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf4224b40] [swscaler @ 0xf42a1cc0] Forcing full internal H chroma due to input having non subsampled chroma
[Parsed_scale_0 @ 0xf42023c0] w:320 h:240 fmt:yuv444p csp:unknown range:tv sar:1/1 -> w:320 h:240 fmt:rgba64le csp:gbr range:pc sar:1/1 flags:0x00000004
[Parsed_scale_0 @ 0xf42023c0] [framesync @ 0xf4202494] Selected 1/25 time base
[Parsed_scale_0 @ 0xf42023c0] [framesync @ 0xf4202494] Sync level 1
[Parsed_scale_2 @ 0xf420bcc0] w:320 h:240 fmt:rgba64le csp:gbr range:pc sar:1/1 -> w:320 h:240 fmt:yuv444p csp:bt2020nc range:pc sar:1/1 flags:0x00000004
[Parsed_scale_2 @ 0xf420bcc0] [framesync @ 0xf420bd94] Selected 1/25 time base
[Parsed_scale_2 @ 0xf420bcc0] [framesync @ 0xf420bd94] Sync level 1
[Parsed_scale_4 @ 0xf4215680] w:320 h:240 fmt:yuv444p csp:bt2020nc range:pc sar:1/1 -> w:320 h:240 fmt:yuv444p csp:bt2020nc range:tv sar:1/1 flags:0x00000004
[Parsed_scale_4 @ 0xf4215680] [framesync @ 0xf4215714] Selected 1/25 time base
[Parsed_scale_4 @ 0xf4215680] [framesync @ 0xf4215714] Sync level 1
[graph -1 input from stream 0:0 @ 0xf4220580] video frame properties congruent with link at pts_time: 0
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-mpeg-rgba-yuv444p.y4m':

Metadata:

encoder : Lavf61.5.101

Stream #0:0, 0, 1/25: Video: wrapped_avframe, 1 reference frame, yuv444p(tv, bt2020nc/unknown/unknown, progressive), 320x240 [SAR 1:1 DAR 4:3], 0/1, q=2-31, 200 kb/s, 25 fps, 25 tbn

Metadata:

encoder : Lavc61.12.100 wrapped_avframe

[out#0/yuv4mpegpipe @ 0xb520cc0] Starting thread...
[out#0/yuv4mpegpipe @ 0xb520cc0] sq: send 0 ts 0.04
[out#0/yuv4mpegpipe @ 0xb520cc0] sq: 0 frames_max 1 reached
[out#0/yuv4mpegpipe @ 0xb520cc0] sq: finish 0; head ts 0.04
[out#0/yuv4mpegpipe @ 0xb520cc0] sq: finish queue
[out#0/yuv4mpegpipe @ 0xb520cc0] sq: receive 0 ts 0.04 queue head 0 ts 0.04
[vf#0:0 @ 0xb5223c0] All consumers returned EOF
[vost#0:0/wrapped_avframe @ 0xb521480] Encoder thread received EOF
[vost#0:0/wrapped_avframe @ 0xb521480] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xb520cc0] All streams finished
[out#0/yuv4mpegpipe @ 0xb520cc0] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xb520cc0] sq: 0 EOF
[out#0/yuv4mpegpipe @ 0xb520cc0] sq: finish queue
[vf#0:0 @ 0xb5223c0] Terminating thread with return code 0 (success)
[vist#0:0/wrapped_avframe @ 0xb5205c0] [dec:wrapped_avframe @ 0xb53f900] Decoder returned EOF, finishing
[vist#0:0/wrapped_avframe @ 0xb5205c0] [dec:wrapped_avframe @ 0xb53f900] Terminating thread with return code 0 (success)
[vist#0:0/wrapped_avframe @ 0xb5205c0] All consumers of this stream are done
[in#0/lavfi @ 0xb4e35c0] All consumers are done
[in#0/lavfi @ 0xb4e35c0] Terminating thread with return code 0 (success)
[AVIOContext @ 0xb540040] Statistics: 230476 bytes written, 0 seeks, 1 writeouts
[out#0/yuv4mpegpipe @ 0xb520cc0] Output file #0 (/dev/shm/yuv-mpeg-rgba-yuv444p.y4m):
[out#0/yuv4mpegpipe @ 0xb520cc0] Output stream #0:0 (video): 1 frames encoded; 1 packets muxed (308 bytes);
[out#0/yuv4mpegpipe @ 0xb520cc0] Total: 1 packets (308 bytes) muxed
[out#0/yuv4mpegpipe @ 0xb520cc0] video:0KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 74729.870130%
frame= 1 fps=0.0 q=-0.0 Lsize= 225KiB time=00:00:00.04 bitrate=46095.2kbits/s speed=2.17x
[in#0/lavfi @ 0xb4e35c0] Input file #0 (yuvtestsrc):
[in#0/lavfi @ 0xb4e35c0] Input stream #0:0 (video): 19 packets read (5852 bytes); 10 frames decoded; 0 decode errors;
[in#0/lavfi @ 0xb4e35c0] Total: 19 packets (5852 bytes) demuxed

and colorbars at their ends very much still here .. :(

comment:6 by Andrew-R, 10 days ago

Now reading:

https://web.archive.org/web/20180423091842/http://www.equasys.de/colorconversion.html

https://stackoverflow.com/questions/17892346/how-to-convert-rgb-yuv-rgb-both-ways
From last link it seems that RGB (8bit per channel) color space is bigger than YUV (8 bit per channel, limited range), so if yuvtestsrc makes all values in yuv (full range?) space anyway, there should be no loss from doing yuv -> rgba -> yuv ?

comment:7 by Andrew-R, 10 days ago

Summary: testyuvsrc and yuv444p->rgba->yuv444p conversion result in huge differenceyuvtestsrc and yuv444p->rgba->yuv444p conversion result in huge difference

comment:8 by Andrew-R, 10 days ago

Interesting!

Using this command (colorspace and trc set to "5" according to https://trac.ffmpeg.org/wiki/colorspace) :

bash-5.1$ /dev/shm/ffmpeg/ffmpeg -color_range 2 -color_trc 5 -colorspace 5 -i /dev/shm/yuv-mpeg-yuv444p.y4m -frames 1 -r 25 /dev/shm/yuv-mpeg-rgba-yuv444p.bmp -debug log

resulting bpm and yuv files match, if I set YUView's colorspace mode for this yuv file to bt601 full!

Files do not match if I use bt709 as trc/colorspace for this one stage yuv->rgb conversion.

ffmpeg version N-115788-ga3f79fd22a Copyright (c) 2000-2024 the FFmpeg developers

built with gcc 11.2.0 (GCC)
configuration: --disable-debug
libavutil 59. 36.100 / 59. 36.100
libavcodec 61. 13.100 / 61. 13.100
libavformat 61. 5.101 / 61. 5.101
libavdevice 61. 2.100 / 61. 2.100
libavfilter 10. 2.102 / 10. 2.102
libswscale 8. 2.100 / 8. 2.100
libswresample 5. 2.100 / 5. 2.100

matched as AVOption 'debug' with argument 'log'.

Trailing option(s) found in the command: may be ignored.
Finished splitting the commandline.
Parsing a group of options: global .
Successfully parsed a group of options.
Parsing a group of options: input url /dev/shm/yuv-mpeg-yuv444p.y4m.
Successfully parsed a group of options.
Opening an input file: /dev/shm/yuv-mpeg-yuv444p.y4m.
[AVFormatContext @ 0xc530880] Opening '/dev/shm/yuv-mpeg-yuv444p.y4m' for reading
[file @ 0xc530e80] Setting default whitelist 'file,crypto,data'
[yuv4mpegpipe @ 0xc530880] Format yuv4mpegpipe probed with size=2048 and score=100
[yuv4mpegpipe @ 0xc530880] Before avformat_find_stream_info() pos: 67 bytes read:32768 seeks:0 nb_streams:1
[yuv4mpegpipe @ 0xc530880] All info found
[yuv4mpegpipe @ 0xc530880] After avformat_find_stream_info() pos: 230473 bytes read:230473 seeks:0 frames:1
Input #0, yuv4mpegpipe, from '/dev/shm/yuv-mpeg-yuv444p.y4m':

Duration: 00:00:00.04, start: 0.000000, bitrate: 46094 kb/s
Stream #0:0, 1, 1/25: Video: rawvideo, 1 reference frame (444P / 0x50343434), yuv444p(pc, bt470bg/unknown/bt470bg, progressive), 320x240, 0/1, SAR 1:1 DAR 4:3, 25 fps, 25 tbr, 25 tbn

Successfully opened the file.
Parsing a group of options: output url /dev/shm/yuv-mpeg-rgba-yuv444p.bmp.
Applying option frames (set the number of frames to output) with argument 1.
Applying option r (override input framerate/convert to given output framerate (Hz value, fraction or abbreviation)) with argument 25.
Successfully parsed a group of options.
Opening an output file: /dev/shm/yuv-mpeg-rgba-yuv444p.bmp.
[out#0/image2 @ 0xc533f40] No explicit maps, mapping streams automatically...
[vost#0:0/bmp @ 0xc532fc0] Created video stream from input stream 0:0
File '/dev/shm/yuv-mpeg-rgba-yuv444p.bmp' already exists. Overwrite? [y/N] y
Successfully opened the file.
Stream mapping:

Stream #0:0 -> #0:0 (rawvideo (native) -> bmp (native))

[vost#0:0/bmp @ 0xc532fc0] Starting thread...
[vf#0:0 @ 0xc536d40] Starting thread...
[vist#0:0/rawvideo @ 0xc533900] [dec:rawvideo @ 0xc5380c0] Starting thread...
[in#0/yuv4mpegpipe @ 0xc530600] Starting thread...
Press [q] to stop, ? for help
[in#0/yuv4mpegpipe @ 0xc530600] EOF while reading input
[in#0/yuv4mpegpipe @ 0xc530600] Terminating thread with return code 0 (success)
[rawvideo @ 0xc5387c0] PACKET SIZE: 230400, STRIDE: 960
[vist#0:0/rawvideo @ 0xc533900] [dec:rawvideo @ 0xc5380c0] Decoder thread received EOF packet
[vist#0:0/rawvideo @ 0xc533900] [dec:rawvideo @ 0xc5380c0] Decoder returned EOF, finishing
[vist#0:0/rawvideo @ 0xc533900] [dec:rawvideo @ 0xc5380c0] Terminating thread with return code 0 (success)
detected 4 logical cores
[graph -1 input from stream 0:0 @ 0xf51016c0] Setting 'video_size' to value '320x240'
[graph -1 input from stream 0:0 @ 0xf51016c0] Setting 'pix_fmt' to value '5'
[graph -1 input from stream 0:0 @ 0xf51016c0] Setting 'time_base' to value '1/25'
[graph -1 input from stream 0:0 @ 0xf51016c0] Setting 'pixel_aspect' to value '1/1'
[graph -1 input from stream 0:0 @ 0xf51016c0] Setting 'colorspace' to value '5'
[graph -1 input from stream 0:0 @ 0xf51016c0] Setting 'range' to value '2'
[graph -1 input from stream 0:0 @ 0xf51016c0] Setting 'frame_rate' to value '25/1'
[graph -1 input from stream 0:0 @ 0xf51016c0] w:320 h:240 pixfmt:yuv444p tb:1/25 fr:25/1 sar:1/1 csp:bt470bg range:pc
[format @ 0xf5102280] Setting 'pix_fmts' to value 'bgra|bgr24|rgb565le|rgb555le|rgb444le|rgb8|bgr8|rgb4_byte|bgr4_byte|gray|pal8|monob'
[auto_scale_0 @ 0xf5104080] w:iw h:ih flags: interl:0
[format @ 0xf5102280] auto-inserting filter 'auto_scale_0' between the filter 'Parsed_null_0' and the filter 'format'
[AVFilterGraph @ 0xf5100a40] query_formats: 4 queried, 6 merged, 3 already done, 0 delayed
[auto_scale_0 @ 0xf5104080] picking bgr24 out of 12 ref:yuv444p alpha:0
[swscaler @ 0xf510e800] [swscaler @ 0xf5117d80] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf510e800] [swscaler @ 0xf512c240] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf510e800] [swscaler @ 0xf513ff00] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf510e800] [swscaler @ 0xf51543c0] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf510e800] [swscaler @ 0xf5168080] Forcing full internal H chroma due to input having non subsampled chroma
[auto_scale_0 @ 0xf5104080] w:320 h:240 fmt:yuv444p csp:bt470bg range:pc sar:1/1 -> w:320 h:240 fmt:bgr24 csp:gbr range:pc sar:1/1 flags:0x00000004
[auto_scale_0 @ 0xf5104080] [framesync @ 0xf5104154] Selected 1/25 time base
[auto_scale_0 @ 0xf5104080] [framesync @ 0xf5104154] Sync level 1
[graph -1 input from stream 0:0 @ 0xf51016c0] video frame properties congruent with link at pts_time: 0
Output #0, image2, to '/dev/shm/yuv-mpeg-rgba-yuv444p.bmp':

Metadata:

encoder : Lavf61.5.101

Stream #0:0, 0, 1/25: Video: bmp, 1 reference frame, bgr24(pc, gbr/unknown/bt470bg, progressive), 320x240 [SAR 1:1 DAR 4:3], 0/1, q=2-31, 200 kb/s, 25 fps, 25 tbn

Metadata:

encoder : Lavc61.13.100 bmp

[out#0/image2 @ 0xc533f40] Starting thread...
[out#0/image2 @ 0xc533f40] sq: send 0 ts 0.04
[out#0/image2 @ 0xc533f40] sq: 0 frames_max 1 reached
[out#0/image2 @ 0xc533f40] sq: finish 0; head ts 0.04
[out#0/image2 @ 0xc533f40] sq: finish queue
[out#0/image2 @ 0xc533f40] sq: receive 0 ts 0.04 queue head 0 ts 0.04
[vf#0:0 @ 0xc536d40] All consumers returned EOF
[out#0/image2 @ 0xc533f40] sq: 0 EOF
[out#0/image2 @ 0xc533f40] sq: finish queue
[vf#0:0 @ 0xc536d40] Terminating thread with return code 0 (success)
[image2 @ 0xc534040] The specified filename '/dev/shm/yuv-mpeg-rgba-yuv444p.bmp' does not contain an image sequence pattern or a pattern is invalid.
[image2 @ 0xc534040] Use a pattern such as %03d for an image sequence or use the -update option (with -frames:v 1 if needed) to write a single image.
[image2 @ 0xc534040] Opening '/dev/shm/yuv-mpeg-rgba-yuv444p.bmp' for writing
[vost#0:0/bmp @ 0xc532fc0] Encoder thread received EOF
[vost#0:0/bmp @ 0xc532fc0] Terminating thread with return code 0 (success)
[file @ 0xf4d00500] Setting default whitelist 'file,crypto,data'
[AVIOContext @ 0xf4d00f00] Statistics: 230454 bytes written, 0 seeks, 1 writeouts
[out#0/image2 @ 0xc533f40] All streams finished
[out#0/image2 @ 0xc533f40] Terminating thread with return code 0 (success)
[out#0/image2 @ 0xc533f40] Output file #0 (/dev/shm/yuv-mpeg-rgba-yuv444p.bmp):
[out#0/image2 @ 0xc533f40] Output stream #0:0 (video): 1 frames encoded; 1 packets muxed (230454 bytes);
[out#0/image2 @ 0xc533f40] Total: 1 packets (230454 bytes) muxed
[out#0/image2 @ 0xc533f40] video:225KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown
frame= 1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=5.13x
[in#0/yuv4mpegpipe @ 0xc530600] Input file #0 (/dev/shm/yuv-mpeg-yuv444p.y4m):
[in#0/yuv4mpegpipe @ 0xc530600] Input stream #0:0 (video): 1 packets read (230400 bytes); 1 frames decoded; 0 decode errors;
[in#0/yuv4mpegpipe @ 0xc530600] Total: 1 packets (230400 bytes) demuxed
[AVIOContext @ 0xc539200] Statistics: 230473 bytes read, 0 seeks

comment:9 by Andrew-R, 10 days ago

really strange, may be YUView actually at fault here :/ I added third (intermediate) bmp to it and by moving all 3 files in and out Difference sequence item I got match :/

in reply to:  2 comment:10 by MasterQuestionable, 10 days ago

Cc: MasterQuestionable added
Component: undeterminedswscale
Keywords: color_primaries added

͏    "RGB cannot preserve very wide space of YCbCr, 6 times bigger than RGB."
<^>    Mathematically makes no sense:
͏    At the same bit-depth, where comes such difference?

͏    "Also, it is not wise to go to RGB"
<^>    While most (if not all?) displays expect RGB from hardware aspect..?
͏    So are the OS (Operation Systems).

͏    See also:
͏    https://trac.ffmpeg.org/ticket/9898#comment:24
͏    https://trac.ffmpeg.org/wiki/colorspace#color_primaries

comment:11 by Balling, 10 days ago

Mathematically makes no sense: At the same bit-depth, where comes such difference?

In the case with full range RGB to full range YCbCr... There are some values in YCbCr that will be negative R', G', B'. (For example in limited range YCbCr BT.709 values 139, 151, 24 will be limited (!) RGB -21, 182, 181 and full RGB -43, 194, 192.) https://stackoverflow.com/questions/32321631/is-converting-ycbcr-to-rgb-reversible

The bit depth does not play any role. Even 12 bit YCbCr is still 6 times bigger than RGB. What makes the change is if you use BT.2020 linear RGB now, that would be bigger than YCbCr and that is how:

While most (if not all?) displays expect RGB from hardware aspect..?

My LG C9 supports direct rendering of YCbCr data (and so do Intel and Nvidia), there is no RGB in it, it is WRGB. Moreover the way this works is that the color engagement works through XYZ, not RGB.

Last edited 10 days ago by Balling (previous) (diff)

comment:12 by Balling, 10 days ago

really strange, may be YUView actually at fault here :/ I added third (intermediate) bmp to it and by moving all 3 files in and out Difference sequence item I got match :/

BMP uses bgr, not rgb, there are bugs with handling bgr to yuv420p and from yuv420p to bgr. If you are using it always add -vf scale=flags=accurate_rnd. No, YUView is accurate.

I tried to do this some times ago and got crashes

There were all kinds of crashes with zscale and swscale. So what.

in_range/out_range, not in_color_range/out_color_range.

That was a typo, sorry

Last edited 10 days ago by Balling (previous) (diff)

in reply to:  6 comment:13 by MasterQuestionable, 10 days ago

͏    The "8-bit YUV" is misleading:
͏    https://stackoverflow.com/questions/17892346/how-to-convert-rgb-yuv-rgb-both-ways#72518720
͏    .
͏    220 * 225 * 225?
͏    It's artificially limited range.
͏    Full range would be as well 256^3.

͏    Note also this:
͏    https://trac.ffmpeg.org/wiki/colorspace#colorspace_yuv444p10le

comment:14 by Balling, 10 days ago

MasterQuestionable, it is never that simple with this stuff... You did not understand the main factor. In the case with full range RGB to full range YCbCr... There are some values in YCbCr that will be negative R', G', B'. (For example in limited range YCbCr BT.709 values 139, 151, 24 will be limited (!) RGB -21, 182, 181 and full RGB -43, 194, 192.)

Full range would be as well 2563.

No, it will not be. In YCbCr full range 0, 128, 128 would be the same for all x, y values of 0, x, y. All of the are just black.

It's artificially limited range.

Limited range is not artificial. It is used everywhere except for Dolby Vision profile 5 IPTPQc2 and s-Log used in Sony cameras and V-Log used in Panasonic cameras. That is all I know of.

comment:15 by Balling, 10 days ago

220 * 225 * 225?

LOL, no. All values are allowed, besides (for 8 bit) 0 and 255. 0 and 255 values are used in limited range RGB and limited range YCbCr for sync in HDMI and Display Port. So that means 250, 128, 128 would be more white than 100% white. That is called Superwhite.

in reply to:  11 comment:16 by MasterQuestionable, 10 days ago

͏    Data, are no more than data. It is all upon: the interpretation.
͏    RGB and YUV:
͏    Both would have some interpreted values unrepresentable by another.
͏    But that doesn't change that they're of the same possibilities. (at the same bit-depth)

͏    The display may accept raw YUV alike, while the application does not necessarily provide.
͏    Based on predominance of RGB: displays tend to assert which default.
͏    (which means the eventual implicit conversion)

͏    "through XYZ, not RGB."
<^>    The very reason things ended up in total havoc...

͏    But one must admit, this:
͏    https://trac.ffmpeg.org/ticket/11002#comment:5
͏    .
͏    "The very White could never be the very White"

Last edited 10 days ago by MasterQuestionable (previous) (diff)

comment:17 by Balling, 10 days ago

"The very White could never be the very White"

Yes. Even during Photo CD era this was well understood, now HDR white is not paper white. https://en.wikipedia.org/wiki/Photo_CD

An oddity of this encoding scheme is that it allows Photo CD images to represent colors which are above 100% (up to 140.2%), "whiter than white".[31] At the time of Photo CD's introduction, this allowed the display of images on the analog televisions of the day to show brighter, more vivid colors than would otherwise be the case. This was acceptable as the analog televisions of the day were designed to be driven beyond their 100% level without abruptly clipping

The display may accept raw YUV alike, while the application does not necessarily provide.

The display has its own color science. It does not directly accept YUV. Modern LG C9 TV is full linux machine, rather powerful.

PS C:\Users\ZAQU> ssh root@192.168.1.72

root@192.168.1.72's password: (well, standard password here is alpine)
NEVER EVER OVERWRITE SYSTEM PARTITIONS LIKE KERNEL, ROOTFS, TVSERVICE.
Your TV will be bricked, guaranteed! See https://rootmy.tv/warning for more info.

/!\ Your system is using a default password.
/!\ Insert SSH public key into /home/root/.ssh/authorized_keys and perform a reboot to remove this warning.

root@LGwebOSTV:~# uname -a
Linux LGwebOSTV 4.4.84-169.gld4tv.4 #1 SMP PREEMPT Wed Feb 28 14:01:22 KST 2024 aarch64 GNU/Linux

in reply to:  17 comment:18 by MasterQuestionable, 10 days ago

͏    Actually the existence of the limited-range thing much derives from the analog legacy...

͏    "Smart TV" indeed... sometimes "Stupid TV":
͏    Blob of adware and malware + spyware.

͏    Maybe somewhat off-topic:
͏    But is your device this type?
͏    https://github.com/MasterInQuestion/talk/discussions/30#5342695a-243c-48a0-87bc-801c5c8e7c95
͏    .
͏    “... live on, unconsciously become part of botnet.
͏    With their overzealous high-performance hardware: ideal for cloud computing.”

͏    Potential way of hacking your TV:
͏    https://www.oligo.security/blog/0-0-0-0-day-exploiting-localhost-apis-from-the-browser ("local")

Last edited 9 days ago by MasterQuestionable (previous) (diff)

comment:19 by Balling, 9 days ago

Actually the existence of the limited-range thing much derives from the analog legacy

No, it really does not, reference black was for example 7.5 IRE, 53.57 mV, but in others analog formats it was different. Moreover it was a form of amplitude modulation, which means you need to sync to it to understand final values.

https://en.wikipedia.org/wiki/IRE_(unit)


YUV was using different matrix and some analog TV was not even using any matrix, it was linear RGB (only SECAM IV used linear RGB) or non-linear R'G'B'. Besides, 16-235 was not even a thing initially. They were planning to set black and white level at quite different values, white at 32...

Last edited 9 days ago by Balling (previous) (diff)

comment:20 by MasterQuestionable, 9 days ago

͏    But in digital system limited-range wouldn't make sense:
͏    The over/under-shooting doesn't occur.
͏    .
͏    It would be only, pointlessly wasted bit-depth.

comment:21 by Balling, 9 days ago

The over/under-shooting doesn't occur.

Both occur due to lossy x264 behaviour or due to 420 conversion or when you render Sony playstation games it used Superwhite quite often. LG C9 provides 109% superwhite option in Hollywood calibration settings, Calman for LG. You can also add it artifiically to encode wide color gamut, as was done in limited range only, never full range xvYCC, xvYCC was use on so called SONY's (of course) "Mastered in 4K" blu-rays, there is Spider-man movie in xvYCC. I have that Blu-ray. https://www.soundandvision.com/content/blu-ray-review-spider-man-mastered-4k-version-page-2

Besides that some of other Blu-rays even have test samples with xvYCC WCG content. This is year 2013. https://drive.google.com/file/d/1eRX92itsxdVSehLAPJbvdw4KP0j-9JLy/view?usp=drivesdk (they only get to xvYCC in photos).

Last edited 9 days ago by Balling (previous) (diff)

comment:22 by MasterQuestionable, 9 days ago

͏    Isn't this much what mentioned in:
͏    https://trac.ffmpeg.org/ticket/11002#comment:9
͏    .
͏    Unjustifiable complexity..?

͏    And whether things truly work intended... much questionable.

Last edited 9 days ago by MasterQuestionable (previous) (diff)

comment:23 by Balling, 9 days ago

Unjustifiable complexity..?

The difference almost no one uses Dolby Atmos with all the objects or even Vision or even png gAMA chunk. Everyone uses YCbCr. It needs to be bitperfect, h264 decoder or x264 encoder, or 420 — 420 — rgb convertions. That is in practice achieved with ffmpeg accurate_rnd. And Nvidia is bitoerfect. And AMD, Intel is almost bitperfect, but some bugs there.

Last edited 9 days ago by Balling (previous) (diff)

comment:25 by Andrew-R, 9 days ago

There are other bugs still open

https://trac.ffmpeg.org/ticket/3345
https://trac.ffmpeg.org/ticket/7978

I also tried to compare y4m files with vbindiff (console program) and they surely differ :(

I also found suggestion by Paul (?) that input/output range must be always set, explicitly. I wonder how to handle this in our cinelerra-GG, given this data not always present at container/codec level, so we easily can get unknown....

https://trac.ffmpeg.org/ticket/9407#comment:10

also see top of https://trac.ffmpeg.org/ticket/3785#comment:16

https://trac.ffmpeg.org/ticket/3801 - still open, but I am not worried about +/-1 right now .

May be I should try dither=0 sws flag too

comment:26 by Balling, 8 days ago

I also found suggestion by Paul (?)

Yes, Paul renamed himself Elon...

#3345 is about dither. That only happens if you do not disable dither, in zscale dither is disabled by default, use that. "Default is none." https://ffmpeg.org/ffmpeg-filters.html#zscale-1

#7978 does not happen with zscale either.

so we easily can get unknown

If it SD it is BT.601 vs BT.709 for HD

comment:27 by Andrew-R, 8 days ago

If it SD it is BT.601 vs BT.709 for HD

And what if it bmp? :) (we do not have native bmp reader/writer, so we use libavcodec's)

I also wonder where bugs (?) about libs , not ffmpeg cli application should go ?

comment:28 by Balling, 8 days ago

And what if it bmp

BMP does not support YCbCr, there is no color matrix, whether 601 or 709. Or in other words it uses "identity color matrix".

Last edited 8 days ago by Balling (previous) (diff)

comment:29 by Andrew-R, 8 days ago

But if I want to turn bmp into yuv (y4m) stream, or import it on YUVA8 timeline at some point there will be rgb->yuv conversion via libswscale, and if it need color range/colorspace on *both sides* of conversion predefined ... May be I really should try and add GUI overrides for those two params per file.

comment:30 by Andrew-R, 7 days ago

ah, found this technical reference:

https://techpubs.jurassic.nl/library/manuals/3000/007-3513-001/sgi_html/ch08.html

`
Constant Hue

In addition to the standard color-space conversion model, the OCTANE Digital Video color-space feature provides a constant-hue algorithm. This algorithm allows illegal YUV values to survive a YUV-to-RGB-to-YUV conversion. In normal conversion, YUV values that cannot be represented in the RGB color space are clamped or otherwise forced into the legal RGB range. Because the YUV (YCrCb) color space is a superset of the RGB color space, illegal RGB values can be generated when YUV is converted to RGB. If the constant-hue block is disabled, then the illegal RGB values are clipped by the output LUT. The lost (clipped) information can result in significantly degraded quality when the image is subsequently transformed back to YUV for video output.

The constant-hue algorithm saves the normally lost information in a correction factor that can be stored in the alpha channel. To restore the original YUV image, this correction factor must be saved with the pixel data.

If the constant-hue algorithm is enabled, the illegal RGB values are converted into legal R'G'B' values. A constant-hue factor, used to restore R'G'B' to the original YUV values, can optionally be stored in the alpha channel. If the constant-hue factor is not saved, then the R'G'B' image appears as if it were range-compressed. The VL_MGV_CSC_ALPHA_CORRECTION control determines whether the alpha channel is replaced by the constant-hue factors, or if the alpha from the color-space converter's input is retained.

Note that because the correction factor computed by the algorithm is directly related to the pixel value, the correction factor is invalidated if the pixel value is recalculated (for example, during compositing).
`

Interesting technology, but probably not something ffmpeg can do (or expose to external use). Honestly, until now I was under impression RGB was superset of YUV, not other way around ... I was wrong!

comment:31 by Balling, 7 days ago

"Interesting technology, but probably not something ffmpeg can do (or expose to external use). "

Yes, encoding negative RGB into alpha channel is insane. It does utilise it, as zscale support xvYCC, which is what those "illegal" YCbCr values are (at the time where Silicon graphics was Nvidia, lol, it may have been illegal, but even then BBC wrote some quides how to limit data in YCbCr, https://www.bbc.com/rd/publications/rdreport_1987_22). Paul fixed some code so some of the LUTs are also preserving these data. 97b5b9dbea2fd51861218416dafc46984e286826

Last edited 7 days ago by Balling (previous) (diff)

comment:32 by Andrew-R, 6 days ago

so, I modded ffmpeg like this:

`
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index df0d5708aa..c33082ca2a 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -538,9 +538,12 @@ av_cold void ff_sws_init_range_convert(SwsContext *c)

if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {

if (c->dstBpc <= 14) {

if (c->srcRange) {

+ printf("luma range from full to limied\n");

c->lumConvertRange = lumRangeFromJpeg_c;
c->chrConvertRange = chrRangeFromJpeg_c;

} else {

+ printf("luma range from limited to full, srcrange %i dstrange = %i \n", c->srcRange, c->dstRange);
+

c->lumConvertRange = lumRangeToJpeg_c;
c->chrConvertRange = chrRangeToJpeg_c;

}

`

and now it prints:

`
bash-5.1$ /dev/shm/ffmpeg/ffmpeg -color_range 2 -colorspace 5 -i /dev/shm/yuv-mpeg-yuv444p.y4m -sws_dither 0 -vf format=rgb24 -pix_fmt yuv444p -frames 2 -r 25 -color_range 2 -colorspace 5 /dev/shm/yuv-mpeg-rgba-yuv444p.y4m -debug log
ffmpeg version N-115843-gc079ebdc57 Copyright (c) 2000-2024 the FFmpeg developers

built with gcc 11.2.0 (GCC)
configuration: --disable-debug
libavutil 59. 36.100 / 59. 36.100
libavcodec 61. 13.100 / 61. 13.100
libavformat 61. 5.101 / 61. 5.101
libavdevice 61. 2.101 / 61. 2.101
libavfilter 10. 2.102 / 10. 2.102
libswscale 8. 2.100 / 8. 2.100
libswresample 5. 2.100 / 5. 2.100

matched as AVOption 'debug' with argument 'log'.

Trailing option(s) found in the command: may be ignored.
Finished splitting the commandline.
Parsing a group of options: global .
Successfully parsed a group of options.
Parsing a group of options: input url /dev/shm/yuv-mpeg-yuv444p.y4m.
Successfully parsed a group of options.
Opening an input file: /dev/shm/yuv-mpeg-yuv444p.y4m.
[AVFormatContext @ 0xc5baa00] Opening '/dev/shm/yuv-mpeg-yuv444p.y4m' for reading
[file @ 0xc5bafc0] Setting default whitelist 'file,crypto,data'
[yuv4mpegpipe @ 0xc5baa00] Format yuv4mpegpipe probed with size=2048 and score=100
[yuv4mpegpipe @ 0xc5baa00] Before avformat_find_stream_info() pos: 67 bytes read:32768 seeks:0 nb_streams:1
[yuv4mpegpipe @ 0xc5baa00] All info found
[yuv4mpegpipe @ 0xc5baa00] After avformat_find_stream_info() pos: 230473 bytes read:230473 seeks:0 frames:1
Input #0, yuv4mpegpipe, from '/dev/shm/yuv-mpeg-yuv444p.y4m':

Duration: 00:00:03.00, start: 0.000000, bitrate: 46081 kb/s
Stream #0:0, 1, 1/25: Video: rawvideo, 1 reference frame (444P / 0x50343434), yuv444p(pc, bt470bg/unknown/unknown, progressive), 320x240, 0/1, SAR 1:1 DAR 4:3, 25 fps, 25 tbr, 25 tbn

Successfully opened the file.
Parsing a group of options: output url /dev/shm/yuv-mpeg-rgba-yuv444p.y4m.
Applying option vf (alias for -filter:v (apply filters to video streams)) with argument format=rgb24.
Applying option pix_fmt (set pixel format) with argument yuv444p.
Applying option frames (set the number of frames to output) with argument 2.
Applying option r (override input framerate/convert to given output framerate (Hz value, fraction or abbreviation)) with argument 25.
Successfully parsed a group of options.
Opening an output file: /dev/shm/yuv-mpeg-rgba-yuv444p.y4m.
[out#0/yuv4mpegpipe @ 0xc5bdb80] No explicit maps, mapping streams automatically...
[vost#0:0/wrapped_avframe @ 0xc5be380] Created video stream from input stream 0:0
[AVFilterGraph @ 0xc5bfc40] Setting 'pix_fmts' to value 'rgb24'
File '/dev/shm/yuv-mpeg-rgba-yuv444p.y4m' already exists. Overwrite? [y/N] y
[file @ 0xc5c1d80] Setting default whitelist 'file,crypto,data'
Successfully opened the file.
Stream mapping:

Stream #0:0 -> #0:0 (rawvideo (native) -> wrapped_avframe (native))

[vost#0:0/wrapped_avframe @ 0xc5be380] Starting thread...
[vf#0:0 @ 0xc5bf8c0] Starting thread...
[vist#0:0/rawvideo @ 0xc5bd540] [dec:rawvideo @ 0xc5c0ec0] Starting thread...
[in#0/yuv4mpegpipe @ 0xc5ba740] Starting thread...
Press [q] to stop, ? for help
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[AVFilterGraph @ 0xf5900a40] Setting 'pix_fmts' to value 'rgb24'
detected 4 logical cores
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[graph -1 input from stream 0:0 @ 0xf5901980] Setting 'video_size' to value '320x240'
[graph -1 input from stream 0:0 @ 0xf5901980] Setting 'pix_fmt' to value '5'
[graph -1 input from stream 0:0 @ 0xf5901980] Setting 'time_base' to value '1/25'
[graph -1 input from stream 0:0 @ 0xf5901980] Setting 'pixel_aspect' to value '1/1'
[graph -1 input from stream 0:0 @ 0xf5901980] Setting 'colorspace' to value '5'
[graph -1 input from stream 0:0 @ 0xf5901980] Setting 'range' to value '2'
[graph -1 input from stream 0:0 @ 0xf5901980] Setting 'frame_rate' to value '25/1'
[graph -1 input from stream 0:0 @ 0xf5901980] w:320 h:240 pixfmt:yuv444p tb:1/25 fr:25/1 sar:1/1 csp:bt470bg range:pc
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[format @ 0xf5902a00] Setting 'pix_fmts' to value 'yuv444p'
[format @ 0xf5902a00] Setting 'color_spaces' to value 'bt470bg'
[format @ 0xf5902a00] Setting 'color_ranges' to value 'pc'
[auto_scale_0 @ 0xf5903e40] Setting 'sws_dither' to value '0'
[auto_scale_0 @ 0xf5903e40] w:iw h:ih flags: interl:0
[Parsed_format_0 @ 0xf5901440] auto-inserting filter 'auto_scale_0' between the filter 'graph -1 input from stream 0:0' and the filter 'Parsed_format_0'
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[auto_scale_1 @ 0xf590ecc0] Setting 'sws_dither' to value '0'
[auto_scale_1 @ 0xf590ecc0] w:iw h:ih flags:
interl:0
[format @ 0xf5902a00] auto-inserting filter 'auto_scale_1' between the filter 'Parsed_format_0' and the filter 'format'
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[AVFilterGraph @ 0xf5900a40] query_formats: 4 queried, 3 merged, 6 already done, 0 delayed
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[swscaler @ 0xf5919800] [swscaler @ 0xf5922d80] Forcing full internal H chroma due to input having non subsampled chroma
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[swscaler @ 0xf5919800] [swscaler @ 0xf5937240] Forcing full internal H chroma due to input having non subsampled chroma
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960

Last message repeated 1 times

[swscaler @ 0xf5919800] [swscaler @ 0xf594af00] Forcing full internal H chroma due to input having non subsampled chroma
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[swscaler @ 0xf5919800] [swscaler @ 0xf595efc0] Forcing full internal H chroma due to input having non subsampled chroma
[swscaler @ 0xf5919800] [swscaler @ 0xf5973480] Forcing full internal H chroma due to input having non subsampled chroma
[auto_scale_0 @ 0xf5903e40] w:320 h:240 fmt:yuv444p csp:bt470bg range:pc sar:1/1 -> w:320 h:240 fmt:rgb24 csp:gbr range:pc sar:1/1 flags:0x00000004
[auto_scale_0 @ 0xf5903e40] [framesync @ 0xf5903f14] Selected 1/25 time base
[auto_scale_0 @ 0xf5903e40] [framesync @ 0xf5903f14] Sync level 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
[auto_scale_1 @ 0xf590ecc0] w:320 h:240 fmt:rgb24 csp:gbr range:pc sar:1/1 -> w:320 h:240 fmt:yuv444p csp:bt470bg range:pc sar:1/1 flags:0x00000004
[auto_scale_1 @ 0xf590ecc0] [framesync @ 0xf590ed94] Selected 1/25 time base
[auto_scale_1 @ 0xf590ecc0] [framesync @ 0xf590ed94] Sync level 1
[graph -1 input from stream 0:0 @ 0xf5901980] video frame properties congruent with link at pts_time: 0
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-mpeg-rgba-yuv444p.y4m':

Metadata:

encoder : Lavf61.5.101

Stream #0:0, 0, 1/25: Video: wrapped_avframe, 1 reference frame, yuv444p(pc, bt470bg/unknown/unknown, progressive), 320x240 [SAR 1:1 DAR 4:3], 0/1, q=2-31, 200 kb/s, 25 fps, 25 tbn

Metadata:

encoder : Lavc61.13.100 wrapped_avframe

[out#0/yuv4mpegpipe @ 0xc5bdb80] Starting thread...
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: send 0 ts 0.04
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: receive 0 ts 0.04 queue head 0 ts 0.04
[rawvideo @ 0xc5c15c0] PACKET SIZE: 230400, STRIDE: 960
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: send 0 ts 0.08
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: 0 frames_max 2 reached
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: finish 0; head ts 0.08
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: finish queue
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: receive 0 ts 0.08 queue head 0 ts 0.08
[vf#0:0 @ 0xc5bf8c0] All consumers returned EOF
[vost#0:0/wrapped_avframe @ 0xc5be380] Encoder thread received EOF
[vost#0:0/wrapped_avframe @ 0xc5be380] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xc5bdb80] All streams finished
[out#0/yuv4mpegpipe @ 0xc5bdb80] Terminating thread with return code 0 (success)
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: 0 EOF
[out#0/yuv4mpegpipe @ 0xc5bdb80] sq: finish queue
[vf#0:0 @ 0xc5bf8c0] Terminating thread with return code 0 (success)
[vist#0:0/rawvideo @ 0xc5bd540] [dec:rawvideo @ 0xc5c0ec0] Decoder returned EOF, finishing
[vist#0:0/rawvideo @ 0xc5bd540] [dec:rawvideo @ 0xc5c0ec0] Terminating thread with return code 0 (success)
[vist#0:0/rawvideo @ 0xc5bd540] All consumers of this stream are done
[in#0/yuv4mpegpipe @ 0xc5ba740] All consumers are done
[in#0/yuv4mpegpipe @ 0xc5ba740] Terminating thread with return code 0 (success)
[AVIOContext @ 0xc5bf5c0] Statistics: 460879 bytes written, 0 seeks, 2 writeouts
[out#0/yuv4mpegpipe @ 0xc5bdb80] Output file #0 (/dev/shm/yuv-mpeg-rgba-yuv444p.y4m):
[out#0/yuv4mpegpipe @ 0xc5bdb80] Output stream #0:0 (video): 2 frames encoded; 2 packets muxed (616 bytes);
[out#0/yuv4mpegpipe @ 0xc5bdb80] Total: 2 packets (616 bytes) muxed
[out#0/yuv4mpegpipe @ 0xc5bdb80] video:1KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 74718.019481%
frame= 2 fps=0.0 q=-0.0 Lsize= 450KiB time=00:00:00.08 bitrate=46087.9kbits/s speed=4.72x
[in#0/yuv4mpegpipe @ 0xc5ba740] Input file #0 (/dev/shm/yuv-mpeg-yuv444p.y4m):
[in#0/yuv4mpegpipe @ 0xc5ba740] Input stream #0:0 (video): 20 packets read (4608000 bytes); 11 frames decoded; 0 decode errors;
[in#0/yuv4mpegpipe @ 0xc5ba740] Total: 20 packets (4608000 bytes) demuxed
[AVIOContext @ 0xc5c3240] Statistics: 4608187 bytes read, 0 seeks
`

why it calls limited to full if src already in full range ?

in reply to:  30 comment:33 by MasterQuestionable, 6 days ago

͏    Why bother such complexity, when even using lossy codecs meddling..?
͏    (however true lossless may not be meaningful whatsoever)

͏    And to accomplish such, we don't really need alpha:
͏    Mere increasing the bit-depth (e.g. 10 bpc) shall accomplish much the same...
͏    (( (8 * 3 + 8) / 3 = 10.( 2/3 ) ))

Last edited 4 days ago by MasterQuestionable (previous) (diff)

in reply to:  32 comment:34 by MasterQuestionable, 6 days ago

͏    "Why it calls limited to full if src already in full range?"
<^>    Looks like a valid bug?
͏    But the formatting...

͏    diff --git "a/libswscale/swscale.c" "b/libswscale/swscale.c"
͏    index df0d5708aa..c33082ca2a 100644

  • libswscale/swscale.c

    a b av_cold void ff_sws_init_range_convert(SwsContext *c)  
    538538    if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
    539539        if (c->dstBpc <= 14) {
    540540            if (c->srcRange) {
     541               printf("luma range from full to limied\n");
    541542                c->lumConvertRange = lumRangeFromJpeg_c;
    542543                c->chrConvertRange = chrRangeFromJpeg_c;
    543544            } else {
     545               printf("luma range from limited to full, srcrange %i dstrange = %i \n", c->srcRange, c->dstRange);
     546
    544547                c->lumConvertRange = lumRangeToJpeg_c;
    545548                c->chrConvertRange = chrRangeToJpeg_c;
    546549            }

͏    ffmpeg -color_range 2 -colorspace 5 -i "yuv-mpeg-yuv444p.y4m" -sws_dither 0 -vf "format=rgb24" -pix_fmt yuv444p -frames 2 -r 25 -color_range 2 -colorspace 5 "yuv-mpeg-rgba-yuv444p.y4m" -debug log

Last edited 6 days ago by MasterQuestionable (previous) (diff)

by MasterQuestionable, 6 days ago

Attachment: swscale.c-mod.log added

comment:35 by Balling, 5 days ago

Honestly, until now I was under impression RGB was superset of YUV, not other way around ... I was wrong!

You just read one small text in ​https://stackoverflow.com/questions/17892346/how-to-convert-rgb-yuv-rgb-both-ways "Since the 8 bit YUV only uses Y values [16, 235] and U, V values [16, 240] it has less possible colors than RGB using [0, 255].", which is simply not true, there is a comment from me under that answer that says: It is not on any flagship TV. If you send YCbCr it will show superwhite and supercolors no problem. In some cases even xvYCC. LG C9 does it even in internal files player."

in reply to:  35 comment:36 by Andrew-R, 5 days ago

Replying to Balling:

Honestly, until now I was under impression RGB was superset of YUV, not other way around ... I was wrong!

You just read one small text in ​https://stackoverflow.com/questions/17892346/how-to-convert-rgb-yuv-rgb-both-ways "Since the 8 bit YUV only uses Y values [16, 235] and U, V values [16, 240] it has less possible colors than RGB using [0, 255].", which is simply not true, there is a comment from me under that answer that says: It is not on any flagship TV. If you send YCbCr it will show superwhite and supercolors no problem. In some cases even xvYCC. LG C9 does it even in internal files player."

Hm, well, I guess I just confused usual chroma subsampling and associated loss of information with colorspace itself.

There is post titled "U and V ranges for valid RGB" from 2010, it has animated illustration.

https://forum.doom9.org/showthread.php?t=154731

ffmpeg -i /dev/shm/yuv-mpeg-yuv444p.y4m -vf "signalstats,metadata=print:file=logfile.txt" -f null /dev/null

from logfile it says

frame:0    pts:0       pts_time:0
lavfi.signalstats.YMIN=0
lavfi.signalstats.YLOW=76
lavfi.signalstats.YAVG=127.733
lavfi.signalstats.YHIGH=178
lavfi.signalstats.YMAX=255
lavfi.signalstats.UMIN=0
lavfi.signalstats.ULOW=76
lavfi.signalstats.UAVG=127.733
lavfi.signalstats.UHIGH=178
lavfi.signalstats.UMAX=255
lavfi.signalstats.VMIN=0
lavfi.signalstats.VLOW=76
lavfi.signalstats.VAVG=127.733
lavfi.signalstats.VHIGH=178
lavfi.signalstats.VMAX=255



so full-range y4m file from yuvtestsrc contain all Y, U, V values (as requested!), even illegal (for RGB conversion later on) ones?

But then one method to kill illegal colors in yuv was said to be to convert it to rgb and back ....

Not sure how specific figure in YUView should look for invalid colors after such roundtrip? Right now it still look like limited range conversion was applied twice at the end of range?

comment:37 by Balling, 5 days ago

You did not read until comment #28 on doom9, it starts talking about xvYCC.

Not sure how specific figure in YUView should look for invalid colors after such roundtrip

Depends what algoritm it uses to clip YCbCr out-of-gamut values. Typically you need to use LittleCMS to see how to clip YCbCr color in xvYCC to closest value representative in RGB. But you can enable zoom box in Yuview and you will see actual values.

comment:38 by Balling, 5 days ago

so full-range y4m file from yuvtestsrc contain all Y, U, V values (as requested!), even illegal (for RGB conversion later on) ones?

Illegal RGB values (that means negative) are valid colors. That must be shown.

in reply to:  37 comment:39 by Andrew-R, 5 days ago

Replying to Balling:

You did not read until comment #28 on doom9, it starts talking about xvYCC.

but yuvtestsrc does not produce xvYCC by default?

Not sure how specific figure in YUView should look for invalid colors after such roundtrip

Depends what algoritm it uses to clip YCbCr out-of-gamut values. Typically you need to use LittleCMS to see how to clip YCbCr color in xvYCC to closest value representative in RGB. But you can enable zoom box in Yuview and you will see actual values.

Yes, I was using exactly zoom box to see values first!

I found patent from broadcom :)
https://patents.google.com/patent/EP1560417A2/en
"System and method for clipping values of pixels in one color space so not to exceed the limits of a second color space"

and algo from BBC on this constant hue method realized by SGI machinery.

But well, may be I just use wrong test source ???

comment:40 by Andrew-R, 5 days ago

using this command

ffmpeg -f lavfi -color_range 2 -i yuvtestsrc=s=640x480 -color_range 2 -frames 2 /dev/shm/yuv-pc-yuv444.y4m

and checking result with YUviewer I see that ffmpeg 4.4.5 and git behave differently on -vf format=rgba action :}

ffmpeg -color_range 2 -i /dev/shm/yuv-pc-yuv444.y4m -vf format=rgba -color_range 2 -frames 2 -pix_fmt yuv444p  /dev/shm/yuv-pc-rgba-yuv444.y4m
ffmpeg version 4.4.5 Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 11.2.0 (GCC)
  configuration: --prefix=/usr --libdir=/usr/lib --shlibdir=/usr/lib --docdir=/usr/doc/ffmpeg-4.4.5/html --mandir=/usr/man --disable-debug --enable-shared --disable-static --enable-gpl --enable-version3 --enable-avresample --arch=i586 --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-gnutls --enable-libass --enable-libbluray --enable-libcdio --enable-frei0r --enable-libgsm --enable-openal --enable-libopus --enable-librtmp --enable-libsnappy --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libmp3lame --enable-opencl --enable-opengl --enable-libopenjpeg --disable-libpulse --enable-libsmbclient --enable-libsvtav1 --enable-libxml2 --enable-librsvg --enable-libdrm --enable-libaom --enable-libdav1d --enable-libsoxr --enable-libzimg --enable-vapoursynth
  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
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  9.100 /  5.  9.100
  libswresample   3.  9.100 /  3.  9.100
  libpostproc    55.  9.100 / 55.  9.100
Input #0, yuv4mpegpipe, from '/dev/shm/yuv-pc-yuv444.y4m':
  Duration: 00:00:00.08, start: 0.000000, bitrate: 184327 kb/s
  Stream #0:0: Video: rawvideo (444P / 0x50343434), yuv444p(pc, progressive), 640x480, SAR 1:1 DAR 4:3, 25 fps, 25 tbr, 25 tbn, 25 tbc
File '/dev/shm/yuv-pc-rgba-yuv444.y4m' already exists. Overwrite? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> wrapped_avframe (native))
Press [q] to stop, [?] for help
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-pc-rgba-yuv444.y4m':
  Metadata:
    encoder         : Lavf58.76.100
  Stream #0:0: Video: wrapped_avframe, yuv444p(pc, progressive), 640x480 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn
    Metadata:
      encoder         : Lavc58.134.100 wrapped_avframe
frame=    2 fps=0.0 q=-0.0 Lsize=    1800kB time=00:00:00.08 bitrate=184327.9kbits/s speed=3.97x
video:1kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 232637.250000%

bash-5.1$ /dev/shm/bin/ffmpeg -color_range 2 -i /dev/shm/yuv-pc-yuv444.y4m -vf format=rgba -color_range 2 -frames 2 -pix_fmt yuv444p  /dev/shm/yuv-pc-rgba-yuv444.y4m
ffmpeg version N-115867-g3f84d1d1fb Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 11.2.0 (GCC)
  configuration: --disable-debug
  libavutil      59. 36.100 / 59. 36.100
  libavcodec     61. 13.100 / 61. 13.100
  libavformat    61.  5.101 / 61.  5.101
  libavdevice    61.  2.101 / 61.  2.101
  libavfilter    10.  2.102 / 10.  2.102
  libswscale      8.  2.100 /  8.  2.100
  libswresample   5.  2.100 /  5.  2.100
Input #0, yuv4mpegpipe, from '/dev/shm/yuv-pc-yuv444.y4m':
  Duration: 00:00:00.08, start: 0.000000, bitrate: 184327 kb/s
  Stream #0:0: Video: rawvideo (444P / 0x50343434), yuv444p(pc, progressive), 640x480, SAR 1:1 DAR 4:3, 25 fps, 25 tbr, 25 tbn
File '/dev/shm/yuv-pc-rgba-yuv444.y4m' already exists. Overwrite? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> wrapped_avframe (native))
Press [q] to stop, [?] for help
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-pc-rgba-yuv444.y4m':
  Metadata:
    encoder         : Lavf61.5.101
  Stream #0:0: Video: wrapped_avframe, yuv444p(pc, progressive), 640x480 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn
      Metadata:
        encoder         : Lavc61.13.100 wrapped_avframe
[out#0/yuv4mpegpipe @ 0xb9fc700] video:1KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 299133.603896%
frame=    2 fps=0.0 q=-0.0 Lsize=    1800KiB time=00:00:00.08 bitrate=184327.9kbits/s speed=3.84x

4.4.5 makes file that never clearly subtracts on any stripe, ffmpeg git makes file where Y subtract fully, but UV planes still not subtractable at the edges ...

so, ffmpeg git is closer to that I think it should do, and I better NOT to try this with 4.4.5 I recompiled on Slackware 15.0 just recently.

comment:41 by Balling, 4 days ago

Well, again. Color_range 2 does not work as input option and that is not how you handle ranges, you use -vf scale=in_range=pc:out_range=pc

Version 0, edited 4 days ago by Balling (next)

in reply to:  41 comment:42 by Andrew-R, 4 days ago

Replying to Balling:

Well, again. Color_range 2 does not work as input option and that is not how you handle ranges, you use -vf scale=in_range=pc:out_range=pc

well, but why color_range has no effect on input (in this case reading from lavfilter test source)? Is it stated in documentation? I think in my case autoscale tries to insert right flags, of course it may fail. At least colorspace seems to propagate from input ...

in reply to:  41 comment:43 by Andrew-R, 4 days ago

Replying to Balling:

Well, again. Color_range 2 does not work as input option and that is not how you handle ranges, you use -vf scale=in_range=pc:out_range=pc

I tried as you suggested, and difference still around, note that input file clearly says range PC in both cases (generating and converting)

bash-5.1$ /dev/shm/bin/ffmpeg -f lavfi -color_range 2 -i yuvtestsrc=s=640x480 -vf scale=in_range=pc:out_range=pc -color_range 2 -frames 2 /dev/shm/yuv-pc-yuv444.y4m
ffmpeg version N-115867-g3f84d1d1fb Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 11.2.0 (GCC)
  configuration: --disable-debug
  libavutil      59. 36.100 / 59. 36.100
  libavcodec     61. 13.100 / 61. 13.100
  libavformat    61.  5.101 / 61.  5.101
  libavdevice    61.  2.101 / 61.  2.101
  libavfilter    10.  2.102 / 10.  2.102
  libswscale      8.  2.100 /  8.  2.100
  libswresample   5.  2.100 /  5.  2.100
Input #0, lavfi, from 'yuvtestsrc=s=640x480':
  Duration: N/A, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: wrapped_avframe, yuv444p(**pc**), 640x480 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 25 tbn
File '/dev/shm/yuv-pc-yuv444.y4m' already exists. Overwrite? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (wrapped_avframe (native) -> wrapped_avframe (native))
Press [q] to stop, [?] for help
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-pc-yuv444.y4m':
  Metadata:
    encoder         : Lavf61.5.101
  Stream #0:0: Video: wrapped_avframe, yuv444p(pc, progressive), 640x480 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn
      Metadata:
        encoder         : Lavc61.13.100 wrapped_avframe
[out#0/yuv4mpegpipe @ 0xc54e340] video:1KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 299133.603896%
frame=    2 fps=0.0 q=-0.0 Lsize=    1800KiB time=00:00:00.08 bitrate=184327.9kbits/s speed=  10x


bash-5.1$ /dev/shm/bin/ffmpeg -color_range 2 -i /dev/shm/yuv-pc-yuv444.y4m -vf format=rgba -color_range 2 -frames 2 -pix_fmt yuv444p  /dev/shm/yuv-pc-rgba-yuv444.y4m
ffmpeg version N-115867-g3f84d1d1fb Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 11.2.0 (GCC)
  configuration: --disable-debug
  libavutil      59. 36.100 / 59. 36.100
  libavcodec     61. 13.100 / 61. 13.100
  libavformat    61.  5.101 / 61.  5.101
  libavdevice    61.  2.101 / 61.  2.101
  libavfilter    10.  2.102 / 10.  2.102
  libswscale      8.  2.100 /  8.  2.100
  libswresample   5.  2.100 /  5.  2.100
Input #0, yuv4mpegpipe, from '/dev/shm/yuv-pc-yuv444.y4m':
  Duration: 00:00:00.08, start: 0.000000, bitrate: 184327 kb/s
  Stream #0:0: Video: rawvideo (444P / 0x50343434), yuv444p(**pc**, progressive), 640x480, SAR 1:1 DAR 4:3, 25 fps, 25 tbr, 25 tbn
File '/dev/shm/yuv-pc-rgba-yuv444.y4m' already exists. Overwrite? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> wrapped_avframe (native))
Press [q] to stop, [?] for help
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
luma range from limited to full, srcrange 0 dstrange = 1
Output #0, yuv4mpegpipe, to '/dev/shm/yuv-pc-rgba-yuv444.y4m':
  Metadata:
    encoder         : Lavf61.5.101
  Stream #0:0: Video: wrapped_avframe, yuv444p(pc, progressive), 640x480 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 25 fps, 25 tbn
      Metadata:
        encoder         : Lavc61.13.100 wrapped_avframe
[out#0/yuv4mpegpipe @ 0xb6a4700] video:1KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 299133.603896%
frame=    2 fps=0.0 q=-0.0 Lsize=    1800KiB time=00:00:00.08 bitrate=184327.9kbits/s speed=4.12x

comment:44 by Balling, 4 days ago

"note that input file clearly says range PC in both cases"

What? You forced it to be PC, also known as full range. If you want limited -vf scale=in_range=tv:out_range=pc, if you want limited output -vf scale=in_range=tv:out_range=tv

If you want limited output but input is full range -vf scale=in_range=pc:out_range=tv

Same for the other 4 parameters (chroma siting (also known as chroma position or latice), primaries (also known as gamut), color matrix (also known as colorspace), transfer (also known as gamma, EOTF)), each produces different pixels, and each can use a different dither, dufferent upscale algorithm, different scaling algorithm, transfer aware resizing and also accurate_rnd stuff!

Just use zscale, I am begging you.

in reply to:  44 comment:45 by Andrew-R, 4 days ago

Replying to Balling:

"note that input file clearly says range PC in both cases"

What? You forced it to be PC, also known as full range.

without any of those parameters yuvtestsrc gives full-range output, as far as I can see? Can you double-check on your end with YUView?

Just use zscale, I am begging you.

I'm not programmer enough for making api changes in our program, so I am a bit stuck with libswscale ..?

comment:46 by Balling, 4 days ago

yuv444-rgba-problem1.png shows the difference only in the second raw and third raw because those values are out-of-gamut. Indeed, green is 0x80, 0x80, 0x0. That means it is full range, as 0x0 value is prohibited in limited range YCbCr. Now, let us use calculator https://res18h39.netlify.app/color

This calculator does not support full range YCbCr, so we should convert it to limited range. 128 in full range Y becomes float value 0.5019607843137254 that becomes *219+16 = 125.9294117647059, 126 Y limited range, Cb 128 becomes 0 float and that becomes 128 Cb; Cr at 0 becomes -0.5 float and that becomes 16 in limited range, so it is 126, 128, 16. In R'G'B' that is -76, 232, 128.

There is no bug, RGB cannot preserve such a value in R, red is negative.

in reply to:  46 comment:47 by Andrew-R, 4 days ago

Replying to Balling:

yuv444-rgba-problem1.png shows the difference only in the second raw and third raw because those values are out-of-gamut. Indeed, green is 0x80, 0x80, 0x0. That means it is full range, as 0x0 value is prohibited in limited range YCbCr. Now, let us use calculator https://res18h39.netlify.app/color

what about this calculator I found in mozilla bugtracker ?

https://kdashg.github.io/misc/colors/from-coeffs.html

does this mean that full-range yuv 8-bit signal will fit into 9-bit RGB (not counting undisplayable colors yet?)

comment:48 by Balling, 4 days ago

what about this calculator I found in mozilla bugtracker ?

It produces the same values... What about it? YCbCr 126, 128, 16 both calculators produce -50.67, 219.13, 128.08 if you use 601 matrix and narrow, that is limited, range.

Last edited 4 days ago by Balling (previous) (diff)

comment:49 by Balling, 4 days ago

I already see one mistake in mozilla calculator, they use Precision that is 5. It needs to be only 4 for r'g'b' to ycbcr, but Precision of ycbcr to r'g'b' matrix must be increased if you are working with 14 bits or 12 bits per channel. See: "The decoding matrix for BT.2020-NCL is this with 14 decimal places" here https://en.wikipedia.org/wiki/YCbCr

Let us check some stuff with that calculator. First of all there is a rule that when you convert 8 bit YCbCr to 10 bit YCbCr you just multiply by 4, even if this is suboptimal that was how ITU defined it. That means that 235 is just multiplied by 4 and you get 940 and that is the same value. Indeed, both 8 bit value of 235, 128, 128 and 940, 512, 512 decode to perfect values 255, 255, 255 and 1023, 1023, 1023, both of them are reference white. Very cute. Same for 64, 512, 512 is perfect 0, 0, 0.

Also 2nd raw of the matrix is multipled by 2. Why is that done??

Last edited 4 days ago by Balling (previous) (diff)
Note: See TracTickets for help on using tickets.