View Full Version : x264 rgb vs i444 - What's the difference?
mzso
27th February 2014, 15:41
What does info() say after ffvideosource()?
How did you create your "original" screenshot?
How did you create your "x264_pc709-ffms2" screenshot?
It say RGB32.
For the screenshots I used print screen with full screen Poptplayer+LAV+madVR.
Used the jump to middle for the original. And found the frame for the second because for some reason it's frame 112 for the second what was frame 107. For some reason with avisynth the frame numbers don't match.
mzso
27th February 2014, 15:50
I decided to upload the whole file I used for testing: https://drive.google.com/file/d/0ByfdfPvnoDuzcFpvNWtOWlptQ0E/edit?usp=sharing
Maybe someone will have time to spend and figures out the problem is.
sneaker_ger
27th February 2014, 16:10
I encountered no problems using x264cli.
Script for "original" screenshot:
ffvideosource("motor2.avi")
info()
ConvertToYV24(matrix="PC.709")
ConvertToRGB24(matrix="PC.709")
Script for pipe to x264:
ffvideosource("motor2.avi")
info()
ConvertToYV24(matrix="PC.709")
Script for "output" screenshot:
ffvideosource("output.mkv")
ConvertToRGB24(matrix="PC.709")
x264 command-line:
avs2pipemod -y4mp 444.avs | x264 - --demuxer y4m --output-csp i444 -o output.mkv --input-range pc --range pc --crf 16
http://abload.de/img/112_originalitb03.png
http://abload.de/img/112_outputevzud.png
mzso
27th February 2014, 17:19
I encountered no problems using x264cli.
[...]
Your screenshots do look right... I'll investigate.
I used it like this: x264 --input-range PC --preset slower --crf 18 --output-csp i444 --range PC -o output.mkv pc709.avs
with
FFVideoSource("e:\Videó Felvételek\motor2.avi")
ConvertToYV24(matrix="PC.709")
My command line doesn't seem to be much different. Except that I fed the avs file to x264 directly, instead of that tool, which is unfamiliar to me.
Can you make it work with ffmpeg also?
sneaker_ger
27th February 2014, 17:25
Then the files are probably correct but your method of creating screenshots is flawed.
mzso
27th February 2014, 17:35
Then the files are probably correct but your method of creating screenshots is flawed.
It doesn't feel like it. (That'd mean an error in LAV or madVR though.) How did you make the screenshot?
Can you make it work with ffmpeg too? I could only get a too dark video when using full range PC.709.
Does this look right to you: https://drive.google.com/file/d/0ByfdfPvnoDuzXzFZWUJyOGZyX1k/edit?usp=sharing ?
sneaker_ger
27th February 2014, 17:54
Can you make it work with ffmpeg too?
No, always comes out too dark. There must be some unwanted conversion going on inside ffmpeg.
Does this look right to you:
Yes.
mzso
27th February 2014, 19:30
No, always comes out too dark. There must be some unwanted conversion going on inside ffmpeg.
Then I suppose I can't trust it when I let it decode the video. Maybe it decodes into limited range to encode into full range.
Yes.
Hm... I get similar differences if I use EVR-CP (http://screenshotcomparison.com/comparison/64643). Only the source looks more orange-ish.
Looks like I can't trust anything at all... Hard to make decisions this way.
How did you make the png snapshots?
sneaker_ger
27th February 2014, 19:34
I let AviSynth handle the conversion to RGB (see scripts above), loaded them into VirtualDub and copied source frames into the clipboard (ctrl+1). Then ctrl+v into IrfanView and save as png.
mzso
27th February 2014, 21:46
I let AviSynth handle the conversion to RGB (see scripts above), loaded them into VirtualDub and copied source frames into the clipboard (ctrl+1). Then ctrl+v into IrfanView and save as png.
Could you upload somewhere the video you transcoded from my sample for me to check?
mzso
28th February 2014, 00:09
If ffmpeg for avisynth input always shows something like this:
Stream #0:0: Video: rawvideo (444P / 0x50343434), yuv444p, 1600x1200, 27.96 fps, 27.96 tbr, 27.96 tbn, 27.96 tbc
Does it mean that it misidentified it as limited range? How can I get it to treat it as full range. Tried adding "-fix_fmt yuvj444p" for input. and "-vf scale=in_range=full:out_range=full", but it didn't work
raffriff42
28th February 2014, 04:53
I can get full range 4:2:0, but not full range 4:4:4. Full range YUV is not supported at all in most ffmpeg codecs, MJPEG being the only other one I know of - and it doesn't do 4:4:4 either.ffmpeg.exe -i "motor2.avi" -acodec pcm_s16le -ar 48000 -c:v libx264
-crf 18 -profile:v high444
-x264opts "colorprim=bt709:transfer=bt709:colormatrix=bt709" -pix_fmt yuvj444p
"motor2-x264-yuvj444.avi"
...
Input #0, avi, from 'motor2.avi':
Duration: 00:00:07.87, start: 0.000000, bitrate: 291034 kb/s
Stream #0:0: Video: utvideo (ULRG / 0x47524C55), rgb24, 1600x1200, 30 tbr, 30 tbn, 30 tbc
Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
...
Incompatible pixel format 'yuvj444p' for codec 'libx264', auto-selecting format 'yuvj420p'
EDIT I think the answer is, keep RGB as long as you can; when converting to YUV, accept that you must also convert to limited range; this is because your final distribution video *must* be TV range for player compatibility, and it is better to do both RGB-to-YUV and PC-to-TV at the same time, to avoid accumulation of rounding errors.
mzso
28th February 2014, 16:52
I can get full range 4:2:0, but not full range 4:4:4. Full range YUV is not supported at all in most ffmpeg codecs, MJPEG being the only other one I know of - and it doesn't do 4:4:4 either.ffmpeg.exe -i "motor2.avi" -acodec pcm_s16le -ar 48000 -c:v libx264
-crf 18 -profile:v high444
-x264opts "colorprim=bt709:transfer=bt709:colormatrix=bt709" -pix_fmt yuvj444p
"motor2-x264-yuvj444.avi"
...
Input #0, avi, from 'motor2.avi':
Duration: 00:00:07.87, start: 0.000000, bitrate: 291034 kb/s
Stream #0:0: Video: utvideo (ULRG / 0x47524C55), rgb24, 1600x1200, 30 tbr, 30 tbn, 30 tbc
Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
...
Incompatible pixel format 'yuvj444p' for codec 'libx264', auto-selecting format 'yuvj420p'
EDIT I think the answer is, keep RGB as long as you can; when converting to YUV, accept that you must also convert to limited range; this is because your final distribution video *must* be TV range for player compatibility, and it is better to do both RGB-to-YUV and PC-to-TV at the same time, to avoid accumulation of rounding errors.
"Incompatible pixel format 'yuvj444p' for codec 'libx264', auto-selecting format 'yuvj420p'"
Where is this from? I don't get such errors. Plus x264 actually can encode full range. I get a warning though about it being a deprecated pixel format, but that's probably false.
Edit: BTW that encodes fine here. Just the expected color issues happen. Did they change it in the past couple days? :)
poisondeathray
28th February 2014, 17:55
Yes it encodes as yuvj444p here too, maybe different binary issues
ffmpeg libx264 can encode full range when feeding an avs script (input levels = output levels), it's just that there is no way to flag it. The YUV data is correct but since the stream isn't flagged properly - this means some players might/will have problems
-yuvj444p expands the range when feeding an avs script, so you get an expansion beyond full range if feeding a full range avs script (pc matrix) , thus crushing both ends. It appears that ffmpeg "thinks" it's recieving standard range from the avs script, and it does another full range expansion
-vf scale=w=0:h=0:in_range=pc:out_range=pc => this appears to do nothing, or any combinations of in_range / out_range
-src_range 1 -dst_range 1 => appear to do nothing, nor any combinations.
It seems the only way to do it correctly is with x264.exe with --input-range pc --range pc --input-csp i444 --output-csp i444, with pc matrix .avs input . I tried different combinations of ffmpeg's -x264-params or -x264opts for input-range and range - it seems those switches don't work with ffmpeg libx264
raffriff42
28th February 2014, 18:06
Apologies, I was using the May 2013 version.
poisondeathray
28th February 2014, 18:42
I guess if you're "married" to ffmpeg you can flag it full range with this modified ffmpeg build, unfortunately this is a non encoding build hence the need for 2 ffmpeg binaries, 2 passes . I tested it, works ok
http://forum.doom9.org/showthread.php?t=152419
It would be nice if -x264-params or -x264opts input-range and range could be included in ffmpeg libx264, or if the -src_range , -dst_range switches worked
The benefit of ffmpeg is it can do audio concurrently, while "vanilla" x264 can't . (There are some x264 builds that can do audio, but there are issues with newer builds)
mzso
28th February 2014, 22:17
Okay. So in conclusion (http://forum.doom9.org/showpost.php?p=1671141&postcount=24061) there was a bug in madVR which if fixed now. The encode with the x264 avisynth combination resulted in an appropriate output. The ffmpeg output is still wrong, madVR just made it worse. (The ffmpeg+avisynth output is of course totally wrong)
I opened a ticket on the ffmpeg bugtracker: https://trac.ffmpeg.org/ticket/3409#comment:16
poisondeathray
28th February 2014, 23:17
If one of the issues was the low quality ffmpeg -vf colormatrix (I still have no idea why it produces poor quality, it was ported from avisynth) , -vf scale out_color_matrix appears to yield similar quality as avisynth method (you can check at crf 0 and compare to rule out compression artifacts, and at crf0 difference testing shows it to be identical to avisynth)
From RGB source, encoding full range YUV444, properly flagged with full range and 709 flags :
ffmpeg -i RGB_INPUT.avi -pix_fmt yuvj444p -vf scale=w=0:h=0:out_color_matrix=bt709 -c:v libx264 -crf 18 -x264opts colorprim=bt709:transfer=bt709:colormatrix=bt709 -an OUTPUT.mp4
I still would hesitate to use full range YUV, because of lack of proper player/decoder/renderer support
EDIT: it's weird though, at CRF 0, -vf colormatrix produces same output as well... That suggests it shouldn't be a filtering issue
It's only at "normal" CRF values where -vf colormatrix produces low quality results, -vf scale out_color_matrix produces better quality... not sure what's going on there something weird going on with -vf colormatrix interaction
mzso
28th February 2014, 23:54
Maybe you can add your findings to the bug? To be fair I forgot about -vf colormatrix because it also had the discoloration plus crappy quality, when I tried before.
It does seem to be alright though with "-vf scale=w=0:h=0:out_color_matrix=bt709" Not identical to the avisynth x264 one, but I guess that's not really relevant. (Maybe one of them is more accurate)
poisondeathray
1st March 2014, 00:47
Go ahead and report them, I'm still testing a few things out
Part of the problem is lack of complete documentation for switches and settings e.g. -in_range and -out_range look like they would be awesome and handy to use but don't really work. Same with -color_range or -colorspace
But -vf colormatrix quality is definitely buggered - I reported that back on page 1 . I'm pretty sure that has been officially reported to ffmpeg bug tracker a long time ago
It doesn't quite add up, because at crf 0/qp0 , or using any lossless codec the results are fine with either -vf colormatrix or -vf scale out_color_matrix. That suggests that the filter isn't the problem , that maybe libx264 is buggered. Maybe some guru can have a look at the actual code and figure out what's going on
mzso
1st March 2014, 01:21
Hmm... I was surprised that encoding with ffmpeg seemed to provide a more accurate result, but it turns out I forgot to specify a preset when I copied poisondeathray's command line. Using the slower preset seems to add some discoloration compared to not specifying one.
poisondeathray
1st March 2014, 03:22
Hmm... I was surprised that encoding with ffmpeg seemed to provide a more accurate result, but it turns out I forgot to specify a preset when I copied poisondeathray's command line. Using the slower preset seems to add some discoloration compared to not specifying one.
adding "-preset slower " ?
I get the same results in terms of levels and color
Quality is still worse than avisynth + x264 (with same encode settings) , but not as bad as -vf colormatrix
mzso
1st March 2014, 13:10
It's rather subtle. Might be something about how the encoder works. Mostly perceive it at the left side of the horizontal bar which has the lights. http://screenshotcomparison.com/comparison/64830
As for quality they look about the same for me. Some parts of the image are better looking for one and the other for the other.
What's left that's weird is the framerates. x264 always makes constant framerate. Either automatically some weird one or what I set manually. But the central frame (according to poptplayer) always skews compared to the source. While ffmpeg by default generates a variable framerate file, the central frame stays in place. Or if I force 30Hz the central frame also becomes different.
detmek
1st March 2014, 15:24
If you used Avisynth to parse input file output will always be constant framerate. Avisynth does not support VFR.
Reino
2nd March 2014, 21:44
@ mzso: Videogame-footage colour conversions
mzso
2nd March 2014, 22:40
@ mzso: Videogame-footage colour conversions
Cool. Though it lack full range RGB to whatever (in my preference also full range) conversions which I had with UT video.
Maybe it would be prudent to add also -x264opts colorprim=bt709:transfer=bt709:colormatrix=bt709 to properly flag the video stream.
By the way. Now that I think about it I never asked why does it even necessary to convert to bt709. Why is the captured video 601 and why is everything converted normally 709?
Reino
3rd March 2014, 01:00
During RGB->YUV conversion your RGB-source is considered tv601 and since its resolution is 1600x1200 (>576p, see 1.4 COLOR CHARACTERISTICS), it automatically becomes BT.709 by spec.
Asmodian
3rd March 2014, 04:36
By the way. Now that I think about it I never asked why does it even necessary to convert to bt709. Why is the captured video 601 and why is everything converted normally 709?
RGB is not BT.601 or BT.709; those are YCbCr only and describe how to convert the YCbCr back to RGB. You just need to use the same conversion from RGB as will be used when converting back to RGB. Whatever you are using to do the RGB -> YCbCr conversion always uses BT.601 while most players will ignore the flags and simply use a resolution threshold to decide between BT.601 and BT.709, like CoRoNe stated. If you could tell whatever is saving your YCbCr file to use RGB -> BT.709 YCbCr instead you wouldn't need the conversion.
mzso
3rd March 2014, 13:05
RGB is not BT.601 or BT.709; those are YCbCr only and describe how to convert the YCbCr back to RGB. You just need to use the same conversion from RGB as will be used when converting back to RGB. Whatever you are using to do the RGB -> YCbCr conversion always uses BT.601 while most players will ignore the flags and simply use a resolution threshold to decide between BT.601 and BT.709, like CoRoNe stated. If you could tell whatever is saving your YCbCr file to use RGB -> BT.709 YCbCr instead you wouldn't need the conversion.
Okay. What doesn't makes sense is why 601 the default conversion if 709 what assumed for >576p. (Or this is just an ffmpeg specific issue?)
Reino
3rd March 2014, 13:36
No, these are just the specifications (see link in my previous post).
Converting a 1024x576(16:9) or 720x576(4:3) RGB video to YCbCr involves a BT.601->BT.601 matrix-conversion.
Converting a 1152x648(16:9) or 800x600(4:3) RGB video to YCbCr involves a BT.601->BT.709 matrix-conversion.
Asmodian
7th March 2014, 01:19
RGB -> YCbCr isn't doing a BT.601 -> BT.601 matrix-conversion, that doesn't even make sense. It is simply RGB -> YCbCr using the BT.601 matrix or RGB -> YCbCr using the BT.709 matrix.
You can also do a YCbCr BT.601 -> YCbCr BT.709 matrix-conversion after the RGB -> YCbCr using BT.601.
Okay. What doesn't makes sense is why 601 the default conversion if 709 what assumed for >576p. (Or this is just an ffmpeg specific issue?)
BT.601 was first (SD video) so it is the default, simple as that. Adding more intelligence to ffdshow to auto pick the conversion matrix based on the resolution would probably be a good idea at this point, if anyone feels like doing it. :)
foxyshadis
7th March 2014, 02:52
LAV video already does that. ffdshow is dead, either specify the transfer primaries in the stream (it does read those) or switch to LAV.
Note: "Full-range" RGB is another phrase that doesn't make any sense, since RGB is always full-range. Again it's only YCbCr that's either full or compressed. For maximum quality at the expense of universal support, full is obviously preferred.
Personally, I plan on switching to 10-bit BT.2020 for everything from RGB sources, no matter what resolution (maybe even 12-bit down the line, see how that shapes up in x265). It represents substantially deeper colors than either 601 or 709, which have a nearly identical gamut... although it'd be pretty pointless on games from the Brown Age.
mzso
8th March 2014, 12:58
Brown age? What's the point in encoding 8 bit video to 10-12 bit?
detmek
8th March 2014, 13:50
Smaller file size for same quality, higher efficiency.
Asmodian
9th March 2014, 05:02
Also 8 bit RGB needs to goto 9/10 bit YCbCr to avoid data loss.
detmek
9th March 2014, 12:23
Realy?! RGB->YCbCr is not lossless in 8-bit? Didn't know that. Oh, well. I have never needed lossless YCbCr anyway.
foxyshadis
19th March 2014, 01:43
YCoCg only requires 8 bits for luma and 9 bits for each chroma. H.264 lossless gets around that by only storing the transformed residual as YCoCg, and using 10-bit operations to convert it back to RGB each frame. You never feed or consume YCoCg in H.264, only RGB; likewise, the internal content of H.264 RGB is never RGB, it's always YCoCg.
Dark Shikari
19th March 2014, 02:19
Perhaps some H.264 lossless encoder does that, but x264 definitely doesn't; it does not support different luma/chroma bit depths, and has no internal support for YCgCo decorrelation.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.