View Full Version : x264 rgb vs i444 - What's the difference?


mzso
8th June 2013, 01:33
Hello!
Probably a noob question. I was wondering what's difference between using "--output-csp rgb" and "--output-csp i444 --range PC"?
Apart from the fact that the latter is about half the size, while all other settings are the same. What does rgb mean? If I understand correctly the h.264 format can't encode into rgb.

LoRd_MuldeR
8th June 2013, 01:45
Well, "i444" stands for YUV 4:4:4, I think, while "rgb" stands for, well, RGB.

While the YUV 4:4:4 format is similar, in a way, to the RGB format in that it does not subsample the chroma and takes the same number of bits per pixel (as "raw" data), YUV (YCbCr) (http://en.wikipedia.org/wiki/YCbCr) and RGB (http://en.wikipedia.org/wiki/RGB) still a two different ways of storing "color" information.

Also I think x264 does support encoding in the RGB (or BGR) format for quite a while now:
http://git.videolan.org/?p=x264.git;a=commit;h=ffc41542d73811dffbe5814a23edda65db0e6aea

(I think encoding in RGB might be less efficient than YCbCr, because the latter decorrelates the "chromaticity" and "brightness" information. Maybe also related to what the CABAC contexts are optimized/designed for?)

vivan
8th June 2013, 02:50
If I understand correctly the h.264 format can't encode into rgb.It can. There's colormatrix BGR with coefficients like:
Y = B
Cb = G
Cr = R
You can even use subsampling (though it doesn't make any sense), 10+ bit depth and so on...

Technically, for x264 the only difference is --colormatrix (GBR vs undef, which would default to Rec709 for HD, but x264 would use Rec601 for rgb -> yuv conversion. That's why you should perform rgb -> yuv conversion using avisynth).
RGB encoding is very inefficient, at least because you can't increase chroma quantizer (well, you can, but result will be weird). I think the only reason to use it is for lossless encoding. But even in that case 10-bit YCgCo could be more efficient.

So if you want to lossy encode your fraps video I would recommend using 10-bit 4:4:4 YUV.

mzso
8th June 2013, 12:13
It can. There's colormatrix BGR with coefficients like:
Y = B
Cb = G
Cr = R
You can even use subsampling (though it doesn't make any sense), 10+ bit depth and so on...

Technically, for x264 the only difference is --colormatrix (GBR vs undef, which would default to Rec709 for HD, but x264 would use Rec601 for rgb -> yuv conversion. That's why you should perform rgb -> yuv conversion using avisynth).
RGB encoding is very inefficient, at least because you can't increase chroma quantizer (well, you can, but result will be weird). I think the only reason to use it is for lossless encoding. But even in that case 10-bit YCgCo could be more efficient.

So if you want to lossy encode your fraps video I would recommend using 10-bit 4:4:4 YUV.

Ok. So from a user viewpoint i444 would be more efficient but I can't use it because the colors will be borked?

While the YUV 4:4:4 format is similar, in a way, to the RGB format in that it does not subsample the chroma and takes the same number of bits per pixel (as "raw" data)

Well, 4:4:4 doesn't subsample either otherwise it wouldn't be 4:4:4. :)


Also I think x264 does support encoding in the RGB (or BGR) format for quite a while now:
http://git.videolan.org/?p=x264.git;a=commit;h=ffc41542d73811dffbe5814a23edda65db0e6aea

I thought the format was pretty much yuv only.

(I think encoding in RGB might be less efficient than YCbCr, because the latter decorrelates the "chromaticity" and "brightness" information. Maybe also related to what the CABAC contexts are optimized/designed for?)

This makes sense then.

mzso
8th June 2013, 12:24
One more thing. The x264 help claims that "--range" is not used by the encoder but the end result is different the pc range encode results in a somewhat larger output file and also the color is full range (verified with madvr) while without it it's limited range.

Dark Shikari
8th June 2013, 12:29
Ok. So from a user viewpoint i444 would be more efficient but I can't use it because the colors will be borked?I have no idea where this idea came from, but the colors in YUV mode are not "borked" in any way I can think of.

I thought the format was pretty much yuv only.Nope, it's not.

One more thing. The x264 help claims that "--range" is not used by the encoder but the end result is different the pc range encode results in a somewhat larger output file and also the color is full range (verified with madvr) while without it it's limited range.--range affects the output range used by the YUV conversion process. If you're trying to make x264 assume the input is a particular range, you might want to look at --input-range.

mzso
8th June 2013, 14:03
I have no idea where this idea came from, but the colors in YUV mode are not "borked" in any way I can think of.
Well, the output is wrong. (maybe it's lightness) How would you say it then? Any way to make the output look "right", without using another program? (People suggested using avisynth)


--range affects the output range used by the YUV conversion process. If you're trying to make x264 assume the input is a particular range, you might want to look at --input-range.

That's cool, but it's in the VUI section in the help, where it's stated: "The VUI settings are not used by the encoder but are merely suggestions to the playback equipment." So this isn't true.

LoRd_MuldeR
8th June 2013, 14:15
The "--input-range" is under the input/output options (not VUI) and it's used by x264 to handle colorspace conversions of the input, before the actual encoding.

At the same time "--range" is used to indicate the range that the decoder shall use for any colorspace conversions that may be required after decompressing the video.

As x264 is not involved in the decoding process, all it can do is write the desired "--range" into the VUI and hope that the decoder will take care of that...

(BTW: If you get any "wrong" colors with YUV 4:4:4 then there obviously is at least one "wrong" YUV/RGB conversion somewhere between your original RGB video that you feed into x264 and the final RGB output you get to see on the screen when watching the encoded video. There are many places where this can happen, including the encoder, the decoder and the video renderer)

mzso
8th June 2013, 14:38
The "--input-range" is under the input/output options (not VUI) and it's used by x264 to handle colorspace conversions of the input, before the actual encoding.

Really? This wasn't clear at all from the former comments. :)

At the same time "--range" is used to indicate the range that the decoder shall use for any colorspace conversions that may be required after decompressing the video.

As x264 is not involved in the decoding process, all it can do is write the desired "--range" into the VUI and hope that the decoder will take care of that...

(BTW: If you get any "wrong" colors with YUV 4:4:4 then there obviously is at least one "wrong" YUV/RGB conversion somewhere between your original RGB video that you feed into x264 and the final RGB output you get to see on the screen when watching the encoded video. There are many places where this can happen, including the encoder, the decoder and the video renderer)

DS just said that it "affects the output range used by the YUV conversion" and not just specify the range. Also with --range PC the output is like 13% larger.


I guess I'll try forcing "--input-range"

Dark Shikari
8th June 2013, 14:39
That's cool, but it's in the VUI section in the help, where it's stated: "The VUI settings are not used by the encoder but are merely suggestions to the playback equipment." So this isn't true.The conversion process is not part of the encoder. The range flag indeed does not affect the encoding process, but it does affect the conversion process if your input needs to be converted first by swscale.

Also, I kind of wrote the code. If the documentation says otherwise, the documentation is probably wrong. That particular line dates to around half a decade before x264cli even had the ability to perform colorspace conversion.

mzso
8th June 2013, 14:41
The conversion process is not part of the encoder. The range flag indeed does not affect the encoding process, but it does affect the conversion process if your input needs to be converted first by swscale.

Also, I kind of wrote the code. If the documentation says otherwise, the documentation is probably wrong. That particular line dates to around half a decade before x264cli even had the ability to perform colorspace conversion.

Ok, now I'm getting confused. So I get different file sizes because different color space conversion and so different input to the actual encoding process?

Anyway I just pointed out a conflict with help text, I'm sure what you say is valid.

Dark Shikari
8th June 2013, 14:51
Yup: there's four possible outputs of the conversion process:

1. Assume input is full range (--input-range), convert to full range (--range).
2. Assume input is full range, convert to limited range.
3. Assume input is limited range, convert to full range.
4. Assume input is limited range, convert to limited range.

The encoder then encodes the resulting stream and flags it based on --range. So based on which conversion is done, the output might be different. The "doesn't affect output" can be seen with cases 1 and 4: no conversion is done here, so the encoder will get the same input no matter what you do, so the output should be the same.

LoRd_MuldeR
8th June 2013, 15:18
Really? This wasn't clear at all from the former comments. :)

DS just said that it "affects the output range used by the YUV conversion" and not just specify the range. Also with --range PC the output is like 13% larger.

I think I was missing one point: The color conversion performed by x264 prior to the encoding is influenced by both, "--input-range" and "--range".

Still the value of "--range" (and only that one) also needs to be written into the VUI and we have to hope the decoder/renderer is going to take care of that properly...

mzso
8th June 2013, 17:26
I can't make it right with i444. It never looks right.
If the input range option isn't changed the result is similar, but subtly different. (Also if --range PC the sun seemingly increases). If I force the input range too the result is obviously too light.

Source:
http://abload.de/img/teszt.avi_20130608_13s6pc7.png

Rgb (rather indistinguishable):
http://abload.de/img/rgb.mkv_20130608_1345vgrwn.png

i444 (results in TV range.):
http://abload.de/img/xteszt-tvrange.mkv_20l7rpz.png

i444 --range PC:
http://abload.de/img/xteszt-pcrange.mkv_205yq21.png

i444 --input-range PC --range PC
http://abload.de/img/xteszt-inrange-outran0rqjh.png

vivan
8th June 2013, 18:11
As I said earlier this is rgb -> yuv conversion issue.
which would default to Rec709 for HD, but x264 would use Rec601 for rgb -> yuv conversion. That's why you should perform rgb -> yuv conversion using avisynth).
This is your "i444 (results in TV range.):" picture, converted to yv24 using Rec709 matrix and then back to rgb using Rec601 matrix.
http://5.firepic.org/5/images/2013-06/08/y63usdvxlsnv.png
Looks as source, right?

If you don't want to use avisynth for proper rgb -> yuv conversion you have to add --colormatrix bt470bg to x264 encdoing string. However it will work only with madVR + LAV video decoder, other renderers ignore colormatrix flag, and other decoders doesn't send it to the renderer.

As for i444 --input-range PC --range PCStrange that it doesn't look like just i444. Are you using madVR and LAV video decoder?

mzso
8th June 2013, 18:44
As I said earlier this is rgb -> yuv conversion issue.

This is your "i444 (results in TV range.):" picture, converted to yv24 using Rec709 matrix and then back to rgb using Rec601 matrix.
http://5.firepic.org/5/images/2013-06/08/y63usdvxlsnv.png
Looks as source, right?

If you don't want to use avisynth for proper rgb -> yuv conversion you have to add --colormatrix bt470bg to x264 encdoing string. However it will work only with madVR + LAV video decoder, other renderers ignore colormatrix flag, and other decoders doesn't send it to the renderer.

As for Strange that it doesn't look like just i444. Are you using madVR and LAV video decoder?

But why can't x264 do it properly, why do I need to use avisynth?

Yes, I use LAV + madVR.

Dark Shikari
8th June 2013, 19:24
x264 doesn't currently have the ability to select whether or not to use BT.709 or BT.601 matrixes when doing conversion; patches welcome.

This only matters when converting from RGB->YUV within x264 for input.

mzso
8th June 2013, 21:13
x264 doesn't currently have the ability to select whether or not to use BT.709 or BT.601 matrixes when doing conversion; patches welcome.

This only matters when converting from RGB->YUV within x264 for input.

Too bad...
I seem to always find something that's not doable. Whether it's ffmpeg or x264 doesn't matter.

poisondeathray
8th June 2013, 21:29
Too bad...
I seem to always find something that's not doable. Whether it's ffmpeg or x264 doesn't matter.

It's "doable" with avisynth

ffmpeg can do it with -vf colormatrix=bt601:bt709 , (and -pix_fmt yuv444p for i444), but for some reason the quality is noticably lower than doing it through avisynth (I suspect something is wrong with the colormatrix patch in ffmpeg)

mzso
8th June 2013, 21:45
It's "doable" with avisynth

ffmpeg can do it with -vf colormatrix=bt601:bt709 , (and -pix_fmt yuv444p for i444), but for some reason the quality is noticably lower than doing it through avisynth (I suspect something is wrong with the colormatrix patch in ffmpeg)

On the other hand you can't make ffmpeg to keep full range with libx264 nor can it encode into rgb.

I'll just stick with rgb. Even though I have to in two/three steps. A good encoder tool just doesn't exist.
(I even tried mencoder, but it doesn't accept output_csp even though it's in the documentation and fails with "FATAL: Cannot initialize video driver." which I can't even comprehend :) )

poisondeathray
8th June 2013, 21:52
Yes, ffmpeg libx264 doesn't seem to have all the switches or at least I don't know the equivalent syntax

Just curious - Why the aversion to avisynth + x264 ?

mzso
8th June 2013, 23:00
Yes, ffmpeg libx264 doesn't seem to have all the switches or at least I don't know the equivalent syntax

Just curious - Why the aversion to avisynth + x264 ?

Well, I don't feel like familiarizing myself with yet another program. I already wasted a lot of time trying to make ffmpeg, than x264 to do what I want.

STaRGaZeR
9th June 2013, 04:24
Well, I don't feel like familiarizing myself with yet another program. I already wasted a lot of time trying to make ffmpeg, than x264 to do what I want.

You wasted your time, indeed. All you need is a 2 line Avisynth script with ConvertToYV24 in it. No need to familiarize yourself with anything else. Now, if you want to keep full range or something exotic like that, it'll do it too without issues but forget about correct output outside of a very specific set of tools.

mzso
9th June 2013, 10:18
You wasted your time, indeed. All you need is a 2 line Avisynth script with ConvertToYV24 in it. No need to familiarize yourself with anything else. Now, if you want to keep full range or something exotic like that, it'll do it too without issues but forget about correct output outside of a very specific set of tools.

Kind of sad, that full range is considered exotic.

aufkrawall
9th June 2013, 13:12
Kind of sad, that full range is considered exotic.
Not really bad since eyes don't notice the difference.

mzso
9th June 2013, 14:12
Not really bad since eyes don't notice the difference.

It's an unreliable mess though. And it's absurd.

aufkrawall
9th June 2013, 14:49
It's an unreliable mess though. And it's absurd.
Why? Usually YUV isn't lossless and so why not categorically dump some information that aren't needed anyway?

Well, of course you can use full range. Works fine with MPC HC + LAV + madVR. Apart from that combo, I444/10bit support is hardly available anyway.
Problem are lazy developers of other A/V software. :(

STaRGaZeR
9th June 2013, 23:00
Kind of sad, that full range is considered exotic.

Indeed, but that's how things are. You should be happy about what you got, because if it were for the big guys in the industry you'd have never had the chance to even see how it looks.

You want compatibility, you have to play by the rules and use what almost everything else out there expects. You want the best quality, you have like 1 combination of tools that produce correct output (and that's if you flag the stuff properly). I stopped aiming for that little % of quality that you'll never see except in very specific situations and instead aim for better compatibility.

PS: Well, as compatible as a 4:4:4 file can get :D

mzso
22nd February 2014, 15:04
Did anything change? It'd nice if I could maintain proper color and range without having 2.5x the filesize (because of rgb colorspace).

mzso
22nd February 2014, 19:30
Apparently I only need to use yuvj444p with ffmpeg instead of yuv444p and I get proper output...

Asmodian
23rd February 2014, 06:13
It's "doable" with avisynth

ffmpeg can do it with -vf colormatrix=bt601:bt709 , (and -pix_fmt yuv444p for i444), but for some reason the quality is noticably lower than doing it through avisynth (I suspect something is wrong with the colormatrix patch in ffmpeg)

using -pix_fmt yuvj444p will use full range but you still need the -vf colormatrix=bt601:bt709 to get correct colors don't you?

mzso
23rd February 2014, 12:53
using -pix_fmt yuvj444p will use full range but you still need the -vf colormatrix=bt601:bt709 to get correct colors don't you?

I didn't think so. They looked about the same.

Now that you mention it there is some less obvious difference in lightness. But that might be inaccurate colorspace conversion right? Someone mentioned earlier that ffmpeg's is not the best. Anyway I don't have the original anymore to test it.

Images removed, becaus they're invalid

(By the way does anyone know which image hoster has that overlaid comparison feature, where I can switch between images by hovering with the cursor?)

mzso
23rd February 2014, 14:43
Okay so the previous snapshots can be considered invalid, because I used the player's snapshot feature which produces borked images.

Made some new ones:

Normal:

-vf:

Original:



Both seem to be brighter. Maybe with colormatrix=bt601:bt709 less so but surely a lot worse with a lot of detail lost.

Edit:
Removed images.

nevcairiel
23rd February 2014, 14:44
You want http://screenshotcomparison.com/

The difference in those images looks like the difference between 601 and 709 could cause.

mzso
23rd February 2014, 14:52
You want http://screenshotcomparison.com/

The difference in those images looks like the difference between 601 and 709 could cause.

Thanks for the info. You mean the original and "normal"?

If "-vf colormatrix=bt601:bt709" is no good for fixing it then what is?

Edit: apparently using -preset ultrafast also causes something like that. :)
I can't tell the difference with slower preset and crf15.
Original:

Slower, crf15:

Asmodian
25th February 2014, 04:01
If "-vf colormatrix=bt601:bt709" is no good for fixing it then what is?

Avisynth :p

Edit: apparently using -preset ultrafast also causes something like that. :)
I can't tell the difference with slower preset and crf15.

The detail lost could be due to -preset ultrafast but the color difference is due to the 601:709 issue.

"Normal" looks like watching 601 at 709 to me, "-vf" looks more like the original. I notice most of the difference between them in the reds, "Normal" has an oranger tint.

I think you used the same shot for both "Original" and "Slower, crf15" (they look identical and have the same file name).

mzso
25th February 2014, 14:55
The detail lost could be due to -preset ultrafast but the color difference is due to the 601:709 issue.

"Normal" looks like watching 601 at 709 to me, "-vf" looks more like the original. I notice most of the difference between them in the reds, "Normal" has an oranger tint.

I think you used the same shot for both "Original" and "Slower, crf15" (they look identical and have the same file name).

Yeah I messed up the links (I removed them) and who knows what. Also I'm quite sure I couldn't tell the difference locally. So I re-did it.
And it looks like you're right. Darn...
Original vs. Encode
http://screenshotcomparison.com/comparison/64322
Original vs. Encode with colormatrix=bt601:bt709
http://screenshotcomparison.com/comparison/64323

Well. maybe with the colormatrix filter the color deviation is less, but the quality is definitely a lot worse.

Back to square two (not one, because I can encode full range properly at least...) I probably couldn't tell the difference because my image viwer kind of turns (blinks) to black before showing the next image...

nevcairiel
25th February 2014, 15:21
The colormatrix filter is indeed not very high quality, probably a better idea to try to use AviSynth for such changes.

mzso
25th February 2014, 16:28
The colormatrix filter is indeed not every high quality, probably a better idea to try to use AviSynth for such changes.

It seems so. I wanted to avoid using(and learning to use) separate programs for one task.

mzso
25th February 2014, 22:35
Anyone know of a guide about setting up and using avisynth with ffmpeg?

mzso
25th February 2014, 23:10
Well I got as far as getting msvcr71.dll which ffmpeg missed when I opened an avs file.
But then I got: Script error: there is no function named "ConvertToYV24"
Which is supposed to be an internal filter. So I'm lost.

Blue_MiSfit
25th February 2014, 23:32
Are you running AviSynth 2.6? 2.5.8 doesn't support YV24.

mzso
26th February 2014, 00:12
I removed the old avisynth and installed Avisynth+

Used this CL and AVS script:
ffmpeg -i rec709.avs -acodec flac -compression_level 12 -vcodec libx264 -preset slower -crf 18 -pix_fmt yuvj444p avsteszt-rec709.mkv

AVISource("e:\Videó Felvételek\motor2.avi")
ConvertToYV24(matrix="PC.709")

And the result is about the same! :confused: http://screenshotcomparison.com/comparison/64382
So now I'm really confused. The exception is that for some reason when I used the jump the middle function of potplayer it jumped to frame 118 instead 117. So something is different just not in a useful way. (Edit: Maybe because of this: "Stream #0: not enough frames to estimate rate; consider increasing probesize" Don't know why I get it or what to do with it...)

PS:
It seemed to me that I should use PC.709 it's described as such: "Uses Rec.709 coefficients, keep full range"
But I got a way too dark picture.

mzso
26th February 2014, 00:45
Are you running AviSynth 2.6? 2.5.8 doesn't support YV24.

Yes, I was. Sorry, I didn't notice your comment at first.


Anyway. I noticed that I'm still getting this warning: "[swscaler @ 03ff88a0] deprecated pixel format used, make sure you did set range correctly"

So maybe ffmpeg still manipulates the image before it gets to libx264?

Or that's irrelevant and libx264 fails at encoding?

mzso
27th February 2014, 13:08
Why is that if I use x264 with avisynth I need to use "ConvertToYV24(matrix="PC.709")" to get proper lightness levels (otherwise too light), but if I use ffmpeg with libx264 I need to use "ConvertToYV24(matrix="Rec709")" otherwise the video is too light?
It looks like one of them is doing something something nasty. My bet is on ffmpeg because "PC.709" is supposed to be full range, yet it can't produce a full range output with it.

Otherwise the colors are just as wrong (the result being more orage-ish) if I encode with x264 and "ConvertToYV24(matrix="PC.709")".

sneaker_ger
27th February 2014, 13:35
Maybe there's a conversion already going on in the decoder. Instead of using AviSource() try L-Smash or ffms2 which usually keep the original colorspace (if your format is supported). Then do "ConvertToYV24(matrix="Rec709")" (most players assume limited range BT.709 for HD resolutions). Also, check what colorspace you actually have directly after the source filter ("info()"). Also, any reason for using -pix_fmt yuvj444p instead of -pix_fmt yuv444p? I'm not even sure it's needed. Might also want to test x264cli instead of ffmpeg.

mzso
27th February 2014, 14:31
Maybe there's a conversion already going on in the decoder. Instead of using AviSource() try L-Smash or ffms2 which usually keep the original colorspace (if your format is supported). Then do "ConvertToYV24(matrix="Rec709")" (most players assume limited range BT.709 for HD resolutions). Also, check what colorspace you actually have directly after the source filter ("info()"). Also, any reason for using -pix_fmt yuvj444p instead of -pix_fmt yuv444p? I'm not even sure it's needed. Might also want to test x264cli instead of ffmpeg.

""ConvertToYV24(matrix="Rec709")" (most players assume limited range BT.709 for HD resolutions)"
I want to preserve full range. So should I use tv.709? (madvr+LAV handles full range properly)

"-pix_fmt yuvj444p instead of -pix_fmt yuv444p"
With yuv444p got limited range output. I want full range.

sneaker_ger
27th February 2014, 14:36
I want to preserve full range. So should I use tv.709? (madvr+LAV handles full range properly)
Well, if you really want to preserve full range (why?) you'd use "PC.709".

mzso
27th February 2014, 15:12
Well, if you really want to preserve full range (why?) you'd use "PC.709".

This troubles me, because ffmpeg produces a way too dark image when I use it, as if it doesn't handle full range properly in this case (If I decode the stream with ffmpeg itself the output is correct in this regard.) Didn't figure out a way to get past it.

So I tried it with FFVideoSource. The source is an UT Video avi which LSMASHVideoSource doesn't support apparently. And I pretty much got the same result. http://screenshotcomparison.com/comparison/64616

sneaker_ger
27th February 2014, 15:15
What does info() say after ffvideosource()?
How did you create your "original" screenshot?
How did you create your "x264_pc709-ffms2" screenshot?

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.