ffmpeg applies incorrect SMPTE170M transfer function?

I want to use ffmpeg to apply the SMPTE170M OETF to example input. I’ve tried:

# 1
ffmpeg -y -framerate 25 -i linear.png -sws_flags accurate_rnd+full_chroma_int \
  -vf "zscale=min=gbr:tin=linear:m=gbr:t=smpte170m" out1.png

#2
ffmpeg -y -framerate 25 -i linear.png -sws_flags accurate_rnd+full_chroma_int \
  -vf "colorspace=iall=bt709:itrc=linear:all=bt709" out2.png

With #1 the transformed values are all too high compared to a manual calculation. Eg, for a channel value of 200 the spec says:

V=200/255
1.099*V^.45 - 0.099 = 0.886185722 (aka 226)

but ffmpeg will produce 231. It produces this value given the same input regardless of channel.

With #2, the produced value changes per channel. I know there’s an RGB->YUV->RGB conversion being added around the colorspace filter but I’m not sure why that would cause such significant differences. E.g. for an input value of 200/255 in each channel I get:

0,0: (237,62,0)  #ED3E00  srgb(237,62,0)
0,0: (0,208,0)  #00D000  srgb(0,208,0)
0,0: (0,46,232)  #002EE8  srgb(0,46,232)
0,0: (226,226,226)  #E2E2E2  srgb(226,226,226)

Note that the greyscale value is actually the correct value I’m expecting.

How do I fix one/both incantations to produce the expected results?

Read more here: Source link