dereks
dereks

Reputation: 564

Mathematically lossless video conversion with FFMPEG and nvenc hevc?

I take a linear gradient input in the range [0, 255], where each next pixel is greater than the previous one by 1 rgb value.

enter image description here

enter image description here

Then I convert it to lossless video, input - rgba(pc), output - yuv444p(tv, progressive):

ffmpeg -y -i %01d.png -c:v hevc_nvenc -pix_fmt yuv444p -tune lossless out.mov

And back to the image, input - yuv444p(tv, progressive), output - rgb24(pc, gbr/unknown/unknown, progressive):

ffmpeg -i "out.mov" "img/out-%03d.png"

The result is not lossless, almost every pixel differs from the original by -2...+2:

enter image description here

enter image description here

enter image description here

The same thing happens with other encoders, for example: ffmpeg -y -i %01d.png -crf 0 out.mov. Perhaps it is caused by the limited range of tv, how to set it to full? -dst_range 1 -color_range 2 doesn't seem to be working. Maybe there is something else?

Upvotes: 2

Views: 3043

Answers (1)

YCbCr to R'G'B' and back is not lossless and cannot be. 10 bit YCbCr is needed to preserve 8 bit R'G'B'.

Okay, first of all rgba (alpha in hevc) is only supported by Apple encoder in ffmpeg. Second of all, -vf format=gbrp should be used (you can just omit yuv444p mention). ffmpeg -h encoder=hevc_nvenc shows supported pixel formats (compare to ffmpeg -h encoder=libx264rgb) Supported pixel formats: yuv420p nv12 p010le yuv444p p016le yuv444p16le bgr0 rgb0 gbrp gbrp16le cuda d3d11

Also pix_fmt option is deprecated for use, besides rawvideo. Use pixel_format.

And instead of -dst_range 1 -color_range 2

You need -vf scale=out_range=pc:out_color_matrix=bt709 -color_range 2 -colorspace bt709

Upvotes: 0

Related Questions