FFMetrics icon indicating copy to clipboard operation
FFMetrics copied to clipboard

How is PSNR calculated when the reference file is RGB and the encoded file is YUV?

Open JohnTravolski opened this issue 1 year ago • 9 comments

Given a 16 bpc RGB PNG sequence, if I encode it with:

ffmpeg -i regular%04d.png -c:v libx265 -pix_fmt gbrp12le -crf 1 out_gbrp12le.mp4

and then I encode that output into a lossless codec with a bigger pixel format:

ffmpeg -i .\out_gbrp12le.mp4 -c:v ffv1 -pix_fmt rgb48le libx265_gbrp12le_to_rgb48le.mkv

If I create a reference file with:

ffmpeg -i regular%04d.png -vcodec rawvideo -pix_fmt rgb48le lossless.nut

and I compare a plot of the two PSNRs to this reference file , they are extremely close:

image

This makes sense to me. gbrp12le is basically a subset of rgb48le so the PSNR plots should be identical. They are off slightly here, but it could just be rounding; no big deal.

However, as soon as I move to YUV, something odd happens. Take this example:

ffmpeg -i regular%04d.png -c:v libx265 -pix_fmt yuv444p12le -color_range pc -crf 1 out_yuv444p12le_pc.mp4

and then I encode that output with

ffmpeg -i .\out_yuv444p12le_pc.mp4 -c:v ffv1 -pix_fmt rgb48le libx265_yuv444p12le_pc_to_rgb48le.mkv

I get a notable difference in the PSNR values.

image

Why is there a difference? In order to calculate the PSNR, both files have to converted to the same pixel format, right? So when the reference is an RGB file and the encoded file is YUV, is ffmetrics converting the reference from RGB to YUV, or is it converting the encoded file from YUV to RGB?

Or is it something else entirely? I don't understand what's happening behind the scenes that causes a gap in the second chart when there is no gap in the first chart.

JohnTravolski avatar Nov 10 '24 23:11 JohnTravolski

I did some testing. Running ffmpeg myself, I found I was able to recreate those exact plot values with these commands:

ffmpeg -r 60 -i out_yuv444p12le_pc.mp4 -r 60 -i lossless.nut -lavfi "[0:v]setpts=N[out0];[1:v]setpts=N[out1];[out0][out1]psnr=stats_file={inpt}_psnr_logfile.txt" -f null -

gave me 76.26 for the first frame (matching the red line), and

ffmpeg -r 60 -i out_yuv444p12le_pc.mp4 -r 60 -i lossless.nut -lavfi "[0:v]format=rgb48le,setpts=N[out0];[1:v]setpts=N[out1];[out0][out1]psnr=stats_file={inpt}_psnr_logfile_force_rgb.txt" -f null -

gave me 72.83 for the first frame, matching the pink line.

So I'm guessing ffmpeg is converting the reference RGB file to YUV rather than the other way around.

For me, I have found this confusing and encountered several unintuitive results when using ffmetrics to compare files of different pixel formats. I think I'd rather have the encoded files converted to the same pixel_format format as the reference file, rather than the reference file converted to the pixel format of the encoded file.

Do you think it makes sense to give the user the option to choose how the different pixel format conversions are handled?

My thought is that you could add a simple toggle under the options menu. Leaving it disabled will continue to use the current behavior but enabling it would force the encoded files to match the pixel format of the reference file.

I would find this really helpful. I realize I this may be a little advanced, but it makes sense to me to have this option.

JohnTravolski avatar Nov 11 '24 00:11 JohnTravolski

Yep. FFMetrics do not do anything atm in this case. Check limitations section.

This is in my todo@, but no ETA, sorry.

P.S. You can always find out what FFMpeg commands were issued by FFMetrics: turn on option 'Write ffmpeg commands into log' and analyze FFMetrics.log.

fifonik avatar Nov 11 '24 10:11 fifonik

Yep. FFMetrics do not do anything atm in this case. Check limitations section.

This is in my todo@, but no ETA, sorry.

P.S. You can always find out what FFMpeg commands were issued by FFMetrics: turn on option 'Write ffmpeg commands into log' and analyze FFMetrics.log.

OK, thanks. You said it's in your todo, so I take it you were already considering this? How were you envisioning it working?

JohnTravolski avatar Nov 11 '24 17:11 JohnTravolski

FFMetrics already getting media info for all files (including colour space & range). I thought it will add colour conversion into ffmpeg mertic calculation command to convert distorted back into original colour space (the same logic as with different frame size). At this stage I have not investigated if this can be done.

fifonik avatar Nov 12 '24 10:11 fifonik

I think it should be doable. You should be able to get the pixel format of the reference file with:

ffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt -of default=noprint_wrappers=1:nokey=1 reference.mov

and you can convert the distorted file to that pixel format with:

ffmpeg ... -lavfi "[0:v]format=reference_file_pix_fmt,setpts=N[out0];[1:v]setpts=N[out1];[out0][out1]psnr=stats_file=psnr_logfile.txt" -f null -

or

ffmpeg ... -lavfi "[0:v]format=reference_file_pix_fmt,setpts=N[out0];[1:v]setpts=N[out1];[out0][out1]ssim=stats_file=ssim_logfile.txt" -f null -

It's possible I'm overlooking something but this seems to have worked for me so far.

JohnTravolski avatar Nov 12 '24 14:11 JohnTravolski

Hi, I noticed this text on the v1.6.0 beta 1 release:

New: Automatic pixel format conversion implemented. A list of currently supported formats: yuv420p (default), yuv422p, yuv444p. If ref's pixel format is not on the supported list, it will be converted to default format. Distorted file will be converted to ref's pixel format.

It seems like you're attempting to address what I brought up here. Am I correct? If so, do you plan to add other pixel formats to this list in the future? I'm particularly interested in support for RGB/BGR pixel formats (at varying bit depths) for the reference file. Thanks.

JohnTravolski avatar May 26 '25 17:05 JohnTravolski

It seems like you're attempting to address what I brought up here. Am I correct?

The issue that metric calculation can be not correct if files are in different pixel formats is known for me from very beginning. Your case is only one of many possible combinations. So I'm not trying to only fix your issue, but all possible combinations. However, it might give better results for your case as well. As for convertion to RGB -- If I remember correctly, VMAF require YUV, not RGB so at least for this metric it will not be possible to have what you want. I have plans to introduce a list of supported pixel formats per metric. In this case if metric support RGB and the source is in this format, then distorted will be converted to the format. But I will need to investigate first if PSNR and SSIM supports RGB and have the same output. Short term solution to make it better might be: convert RGB to yuv444 instead of yuv420

fifonik avatar May 27 '25 07:05 fifonik

It seems like you're attempting to address what I brought up here. Am I correct?

The issue that metric calculation can be not correct if files are in different pixel formats is known for me from very beginning. Your case is only one of many possible combinations. So I'm not trying to only fix your issue, but all possible combinations. However, it might give better results for your case as well. As for convertion to RGB -- If I remember correctly, VMAF require YUV, not RGB so at least for this metric it will not be possible to have what you want. I have plans to introduce a list of supported pixel formats per metric. In this case if metric support RGB and the source is in this format, then distorted will be converted to the format. But I will need to investigate first if PSNR and SSIM supports RGB and have the same output. Short term solution to make it better might be: convert RGB to yuv444 instead of yuv420

Have you had a chance to look at adding support for RGB pixel formats? It would be ideal if the reference file isn't converted to YUV. Whenever an RGB reference file is used, VMAF could be disabled.

JohnTravolski avatar Nov 04 '25 04:11 JohnTravolski

Sorry, I was distracted by some other stuff (job, personal life and other FFMetrics issues) and do not remember at what stage the colour conversion is atm. As I mentioned earlier, I'm planning to implement automatic colour spaces conversion. Will try to check it out when I have time and report back.

fifonik avatar Nov 06 '25 07:11 fifonik