Log in

View Full Version : x264 constant quality first pass


Pages : [1] 2

omion
19th October 2005, 02:16
I'm using x264 build 333, and have a question regarding rate control.

I have been encoding using a first pass at quantizer 21, then setting the bitrate of the second pass to be equal to the first. This way, more complex episodes (I encode mainly anime) will be larger and simpler ones will be smaller, and all of them will have the same overall quality.

What I'm looking for now is a first pass setting that will turn on the "curve compression" like the second pass does, but still with no desired bitrate. Basically I want something that will encode "easy" frames at q20 and "difficult" frames at maybe q26 or so.

I had heard that using "--bitrate xx --ratetol inf" will do that, but I am having doubts. I encoded one episode with "--bitrate 800" and one with "--bitrate 1500". Here's what I got:
http://people.ucsc.edu/~rswilson/other/x264%20Differing%20bitrates.png
(I apologize for the large dimensions. It looked smaller on my 1600x1200 monitor :D )
x is frame number, y is quantizer. I applied a smoother to the data to tame it.
Blue is "--bitrate 1500"
Green is "--bitrate 800" (*)
Black is the difference between the two (plus a constant to make it show up)
Ignore the red ;)

As you can see, the black line seems to "recover" from the high-quantizer intro, indicating that there is some sort of target bitrate thing going on.

I want curve compression, and I want each frame's quantizer to be entirely dependant on that frame, not any others. Is there any way to do this?



(*) The command line I used for both encodes is:
--no-psnr --mixed-refs --pass 1 --zones 2662,5586,b=0.25 --bitrate xx --ratetol inf --stats ".\stat.stats" --subme 5 --ref 8 --progress --min-keyint 25 --me umh --merange 16 --bframes 7 --weightb --b-pyramid --analyse all -o "1st.mp4" ".\Script.avs"

Sirber
19th October 2005, 02:43
"--no-psnr" is bad, since the codec use PSNR calculs to choose what to do.

akupenguin
19th October 2005, 04:07
@omion
You specify a bitrate, and expect it not to use that as a target? If there were an "average quant" option, it would not involve '--bitrate'.

@Sirber
No, PSNR calculations are independent of RD. Because (a) PSNR is after loopfilter, RD is before, (b) you're not using RD for 1st pass anyway, (c) it would just be stupid to make a cosmetic option like --psnr influence the coding decisions.

omion
19th October 2005, 05:02
@omion
You specify a bitrate, and expect it not to use that as a target? If there were an "average quant" option, it would not involve '--bitrate'.

That's actually what made me question it in the first place. I had heard that using "--ratetol inf" will get me constant quality, yet it only works with "--bitrate", which seems like it would have a feedback mechanism. This is what prompted the test.

I figured that the "--bitrate" option would set some default quantizer options which tend to result in the desired bitrate. Then those assumptions would be updated based on the "--ratetol" option. Therefore, if "--ratetol inf" turned off the updating, it should do just what I wanted.
However, that seems to not be the case... :(

Is there any way to only do curve compression?

btw: I wouldn't really call what I want an "average quant" option, as I don't want any feedback of the previous frames used to calculate the current one. It's more of a "constant quant with curve-compression fudge factor" option :D

[ edit: I was mostly basing my initial assumption on Bond's post here (http://forum.doom9.org/showthread.php?p=704838#post704838) and akupenguin's post here (http://forum.doom9.org/showthread.php?p=699406#post699406) ]

hitbit
19th October 2005, 20:15
I'm curious. You:
A) - make a single pass CQ encode;
- pick the bitrate;
- make a single pass with that bitrate and --ratetol inf
or:
B) - make a first pass CQ;
- pick the bitrate;
- make a SECOND pass with that bitrate and --ratetol inf (thus reading first pass stats)?

I'm wondering if the two methods are equivalent...

Sharktooth
19th October 2005, 21:00
I'm wondering if the two methods are senseless...

hitbit
19th October 2005, 21:29
Senseless?.... mmmmm...
Ok: let's say that I'm moderately satisfied with the quality/size ratio that a given
CQ gives to me, but I'd like to squeeze some extra quality.
I'm wrong in assuming that a second pass at the bitrate derived from the CQ first pass will do the job? And if I'm wrong (likely, since I'm not a techie), why?

stephanV
19th October 2005, 21:44
In principle you are not wrong since constant quantizer is not the same as constant quality (uhm... I guess you could say the sum of the quality would still be the same, but the distribution of quality would be better or more even). Method B must be better AFAICT, because method A would still result in some sort of abr encoding while method B is really vbr.

I don't know how accurate file size prediction is though, but that doesn't seem to be the issue here.

akupenguin
19th October 2005, 22:48
x264 keeps track of the "complexity" of each frame, and then determines quantizer from that using the ratecontrol equation (rc_eq) and a quantity called "rate_factor". Assuming an ideal rc_eq, then constant rate_factor would be optimal perceptual RD (not constant quality, but allocating a little more quality in places where it doesn't cost much).
ABR and 2pass use the same rc_eq, the primary difference is in how they determine rate_factor. In ABR, we only have statistics about the past frames, so we continually update the estimate of the rate_factor needed to meet the target bitrate. In 2pass, we have all the stats, so we pick the right rate_factor to begin with.
To make a 1pass encode that is nearly identical to a 2pass, you'd need to specify rate_factor instead of bitrate or QP. (There will still be some differences: 1pass uses SATD for complexity, 2pass uses 1st pass's bitsize; I-frame quants are selected differently.)

omion
20th October 2005, 05:37
@akupenguin:
That rate_factor thing is exactly what I want. Is there any way to force the specified rate_factor? It doesn't look like there is any command-line option for it.

@hit_bit:
I'm actually doing the following:
- Make 1st pass CQ (This was where I was using "--ratetol inf", but it looks like it's not quite what I want)
- Select the bitrate of the first pass for the second pass
- Make the second pass reading the stats from the first.

@all:
The reason I'm doing this is that I want constant quality across episodes in a series. I was previously using a constant quantizer first pass as a bitrate measurement. However, that gives more bits than necessary to episodes with high complexity. Assuming a constant QP of 22 for P, 24 for B, here's what happens:
- A consistenty low-complexity episode will have a "normal" number of B-frames, and therefore will have an average quantizer of maybe 23.
- A high-complexity episode will have fewer B-frames and more P-frames, resulting in an average quantizer of maybe 22.5.
- Since the rate control is applied on the second pass, the complex scenes of the complex episode might be given an average second-pass quantizer of ~25.
- In order to even everything out, the simple scenes in the complex episode would have to get much lower quantizers than the complex scenes, so they might have an average of 18 in the second pass.
- HOWEVER, the simple scenes in the simple episode will have a similar QP as the first pass, at ~22.5.

(Assuming you've made it this far: :p )
The result of this is that if the same scene is in a high-complexity episode and a low-complexity episode, it will look better in the high-complexity one! This is clearly not constant quality, so I've been looking for an alternative.

hitbit
20th October 2005, 14:02
I think that setting ratetol=inf in CQ mode is useless, since bitrate is allowed anyway to freely fluctuate according to the quantizers (that's why I assumed you use it in second pass).
Maybe a more interesting value to play with could be qcomp, but AFAIK it's not available in CQ mode, too.

(slightly OT: anyone knows how to set ratetol=inf in mencoder?)

omion
20th October 2005, 17:59
I think that setting ratetol=inf in CQ mode is useless, since bitrate is allowed anyway to freely fluctuate according to the quantizers (that's why I assumed you use it in second pass).
Maybe a more interesting value to play with could be qcomp, but AFAIK it's not available in CQ mode, too.

(slightly OT: anyone knows how to set ratetol=inf in mencoder?)
You are correct that in constant quantizer mode, the quantizers are the same (imagine that) but what I want is not quite constant quantizers. I want the quantizers to change according to the complexity of the frame being encoded, in order to get a more consistent quality across encodes.

I was under the impression that "--ratetol inf" wouldn't do anything in the second pass, as the encoder already has the information about all the frames. The second pass target bitrate is always hit because it doesn't need to guess at the complexity of the following frames.

hitbit
20th October 2005, 18:43
Well, I'm only guessing here, so don't flame me:
From the mencoder docs:
"qcomp=<0-1> (ABR or two pass)
quantizer compression (default: 0.6). A lower value makes the bitrate more constant, while a higher value makes the quantization parameter more constant."
So, if I understood correctly, qcomp=1 should give you (again) constant quantizer.
Now, maybe you could try to encode your second pass with a qcomp very close to one (let's say 0.95) to obtain something similar to what you need, i.e "almost CQ".

Anyway, personally I like the CQ 2-pass method (let's call it that way). Let me (us?) aware of your efforts!

akupenguin
20th October 2005, 19:34
Patch (http://students.washington.edu/lorenm/src/x264/x264_crf.0.diff). "--crf <quality>" should work, though please tell me if it's consistently off from the specified nominal QP (of course it will vary, I just mean on average).

Sharktooth
20th October 2005, 20:15
builds including --crf are ready. check the sticky.

omion
20th October 2005, 22:52
Thanks, akupenguin and Sharktooth! I'll test it out!

omion
21st October 2005, 03:54
Just did an encode with "--crf 21", and part with "--zones x,y,b=0.25". Results:
Average P quantizer in "normal" zone: 20.98 (as perfect as anyone can expect!)
Average overall quantizer in "normal" zone: 22.0
Average P quantizer in 0.25 zone: 34.0
Average overall quantizer in 0.25 zone: 34.6
(it looks like using the b=0.25 zone results in a quantizer 13 more than full bitrate, instead of the 12 I expected. Oh well. Not a problem :) )

I also compared two 3-pass encodes, one with "--crf 21" for the first pass, and one with constant quantizer of 21 for the first pass. The second pass from the --crf encode had a quantizer distribution very similar to the third pass of the other encode (*). I think this is due to the fact that quantizers from the first pass already look a lot like a second pass distribution.

Thank you again, akupenguin! You've made my day!


(*) "very similar" means that the peaks in quantizers were the same magnitude. I have noticed that the more passes I do with x264 (from constant quantizer) the larger the quantizer varies. The high quantizers from the second pass will be higher in the third pass, and the low quantizers will be lower.

[ edit: now that I think about it, is there any reason that I even need a second pass? Is the knowledge of all the frames' complexity used for anything other than hitting the right bitrate? ]

akupenguin
21st October 2005, 09:53
As I said above, there are a couple of decisions that are done slightly better in 2pass than 1pass, regardless of the primary ratecontrol algorithm. I think the only important one is:
In 2pass, the QPs used for I-frames depend on the complexities of the following scene. In 1pass (all modes), they depend on the complexities of previous frames. This wastes some bits if it guesses wrong.
This is fixable, but it will involve some reorganization of ratecontrol and frame-type handling code, so don't expect a fix soon. And I haven't run a numerical comparison recently, so it might be a negligible effect.

Doom9
21st October 2005, 19:10
hmm.. in which scenarios can the crf patch be used? does it act like a qp (with the same parameters that can be used), or is it more like the title of this thread suggests, a different method to do the first pass (and thus all settings that apply to a bitrate based first pass apply to it as well)?

akupenguin
21st October 2005, 19:40
It takes all the same modifiers as ABR, except not --ratetol. (leaving: qcomp, qpmin/max, qpstep, vbv*, zones, ...)
While the --crf argument is on a scale similar to QP, that's only because I tuned it so. (And I tuned it for qcomp=0.6, it's probably totally off for other values.) Code-wise, it's really ABR with a different target (no feedback from achieved bitrate).

edit: like ABR, no --qblur

Doom9
21st October 2005, 20:07
just to make sure: for now I have the following two parameters as not supported in abr mode:
--cplxblur 21
--qblur 1.0

this stems from the mplayer manpage but it has been a while and I currently cannot connect to the mplayer site. So, for --crf I would additionally disable --ratetol and thats it?

akupenguin
22nd October 2005, 00:09
The x264cli defaults are 20 and 0.5, but yes that's all.

hpn
22nd October 2005, 22:03
What program was used to create the frame number/quantizer graphic in the first post? :thanks:

Doom9
22nd October 2005, 22:21
The x264cli defaults are 20 and 0.5Same in MeGUI but in order to find out what commandline an option in the GUI turns into I had to devicate from the defaults..

akupenguin
22nd October 2005, 23:22
I don't know what omion used, but I generate such graphs using gnuplot (http://www.gnuplot.info/), after extracting the data from either x264_2pass.log or `x264 -v` using perl (http://www.perl.org/).

hpn
23rd October 2005, 00:10
Thank you, I'll try the same. I was thinking about processing the .log in Excel and making a few similar graphs with it.

omion
23rd October 2005, 06:51
What program was used to create the frame number/quantizer graphic in the first post? :thanks:
I wrote a Perl script to read an x264 stats file and output a Mathematica expression. The data was then loaded into Mathematica, where I made the graph.

Just in case anyone has Perl, Mathematica, and wants to try it out, here's the Perl script:
#!/usr/bin/perl

open(IN, $ARGV[0]) or die "ERROR: Can't open file '$ARGV[0]' for reading!\n$!\n";

while(<IN>) {
/in:(\d+) out:(\d+) type:(.) q:(\d+\.\d+) itex:(\d+) ptex:(\d+) mv:(\d+) misc:(\d+) imb:\d+ pmb:\d+ smb:\d+;/ or next;

$in[$1] = {'type' => $3, 'q' => $4, 'itex' => $5, 'ptex' => $6, 'mv' => $7, 'misc' => $8};
$out[$2] = {'type' => $3, 'q' => $4, 'itex' => $5, 'ptex' => $6, 'mv' => $7, 'misc' => $8};
}

print "frameData=Transpose[{\n";

for my $frameNum (0 .. $#in) {
my %frame = %{$in[$frameNum]};
print " {", join(",", ('"' . $frame{'type'} . '"', $frame{'q'}, $frame{'itex'}, $frame{'ptex'}, $frame{'mv'}, $frame{'misc'}, $frame{'itex'} + $frame{'ptex'} + $frame{'mv'} + $frame{'misc'})), "}";
($frameNum == $#in) ? print "\n" : print ",\n";
}

print "}];\n";

I made it a bit more generalized than it needs to be... oh well.

Running "perl script.pl statsfile" will output something like:
frameData=Transpose[{{...},{...},...}]
which should be piped to a file. Read it in Mathematica with
<<"Path/to/file.txt"
In Mathematica, frameData[[1]] is the type of each frame ("I","i","P","B","b").
frameData[[2]] is the quantizer (which is what the top graph is of)
[[3]] - [[6]] are the breakdown of the frame sizes (itex, mv, etc.).
[[7]] is the frame size in bits (It always seems to be divisible by 8, though, so each frame is an integral number of bytes).

For the plot, I used MultipleListPlot from Graphics`MultipleListPlot` and MovingAverage with a window of 256 from Statistics`DataSmoothing`.

(If you use the script on a stats file which is not finished, the last few entries in the Perl output might be blank. You should delete them or Mathematica will complain)

hpn
23rd October 2005, 19:39
Thank you for the detailed explanation!

LiFe
1st January 2006, 01:25
Sorry to dredge this up. I have read this entire thread and it's meaning still escapes me. Can someone please dumb down the difference between QP and CRF? Thanks.

foxyshadis
1st January 2006, 03:42
It attempts to keep roughly the same average size/quality as constant quantizer would, while allowing complex scenes to take more bits from less complex scenes (but not scaled quite as accurately as 2-pass) to look a bit better.

It's a halfway between the two 1-pass modes, with a "quality" factor instead of a bitrate, like vorbis (so size is unpredictable, but visual quality is more stable than cq).

omion
1st January 2006, 03:51
Well, it really uses fewer bits in more complex scenes than constant QP. It's designed as the highest-quality that you can get without using two passes. However, as foxyshadis says, you give up the ability to predict the final file size.

LiFe
1st January 2006, 04:43
Yeah um OK, still not making some sort of crucial connection for me.

QP mode encodes each frame at the same quantizer, with small variences for frame types as per default settings (ie B frames Quantizer are a little lowwer?). In theory you should have a file where every frame has the same visual quality, regardless of bitrate. File size is unpredictable. In theory 1 pass should be all that's needed, with no improvement in 2 pass.

Now I don't understand what CRF is trying to do. It takes a Quantizer as a setting but somehow factors rate control into this? I assume it acts more like ABR instead of VBR, allowing less bits to complex scenes and more bits to less complex scenes but without an actual target bitrate? This would mean quality would be less constant? Which seems to be the opposite of what you're trying to explain to me.

(sorry!)

omion
1st January 2006, 05:29
In theory you should have a file where every frame has the same visual quality, regardless of bitrate.
In theory, yes. And this even holds for objective measurements like PSNR. However, your eyes don't work like that. In high-motion scenes, your eyes get 'overloaded' and don't see artifacts as well. This means that you can take away bits in high-motion scenes (by raising the quantizer) and give them to low motion scenes (by lowering their quantizer). The end result is that subjective quality is improved, even though PSNR would be reduced.

CRF takes the motion into account, whereas constant QP does not.

It's not really like ABR because the bit rate depends on how complex a scene is. However, your explanation of how you think it works is actually quite good. But as I said, the result is more constant visual quality than in constant QP mode.

Also, keep in mind that higher quantizer means lower quality. And yes, even constant QP does change the QP depending on frame type. (B has a higher QP, and I has a lower QP)

LiFe
1st January 2006, 07:22
Brilliant - Understood!

I assume one only needs to do 1 pass on QP and CRF modes?

Or for CRF mode do you first create a stat file in QP mode, and then re-run with same quantizer in CRF mode to allow better bitrate calculations?

(Now I need to condense this into 4 lines to fit into MeGUI.)

berrinam
1st January 2006, 07:41
How about this as a short explanation?
CRF mode:
Does a 1-pass quality-based VBR encode. Similar to a constant QP encode, but gives better quality because the rate control is allowed to reduce quality where it is not so important, increasing the overall quality, or decreasing the required bitrate.

I assume one only needs to do 1 pass on QP and CRF modes?Correct.

omion
1st January 2006, 08:09
I assume one only need to do 1 pass on QP and CRF modes?
There are still a few things that can only be done in 2 passes.

In the 2nd pass, x264 determines the optimal quantizer for an I-frame based on how many frames are dependant on it. The idea is that you take some quality from a short scene and give it to a long scene, where the quality will be transferred to more frames, and therefore be 'worth' more.

I don't see any use for doing 2 passes with constant QP (hereinafter CQP) as the first pass. The problem is that the other 1-pass methods (ABR, CRF) are better than CQP for whatever you do. If you need a bitrate target, use ABR. If you want constant quality, use CRF. CQP gives you neither of those.

So it boils down to this:
* If you want a predictable file size with good quality, use 2-pass with ABR as the first pass
* If you want good quality and don't want to wait too long, use 1-pass CRF
* If you want the best quality, use 2-pass with CRF as the first. (the quality won't be too much better than 1-pass CRF, but it will be better)

The other options aren't so good:
* 1-pass ABR gives bad results for unpredictable sources
* 1-pass CQP is pointless (you might as well be using CRF)
* Come to think of it, 2-pass CQP is also pointless. CRF is closer to the result of a 2-pass encode, so 2 passes based on CRF will look more like 3 passes based on CQP

Or for CRF mode do you first create a stat file in QP mode, and then re-run with same quantizer in CRF mode to allow better bitrate calculations?
All these methods (CRF, ABR, CQP) are ways for x264 to guess the answer to the question "What should this frame's quantizer be?" However, a stats file from the first pass provides much more detailed information than anything else, so using any of them on the second pass doesn't make sense. In fact, I'm fairly certain x264 will ignore the --crf, --qp, etc options if you also give a --pass [2|3]. The stats file allows for a much better answer to that question than anything else.

foxyshadis
1st January 2006, 17:10
Omion's right, I accidentally swapped the high/low complexity factor. And his explanations gave me some new insight too! :D

shae
27th September 2006, 12:26
It seems to me that high quality (/low figure) QP can be better than CRF, at least if you ignore output size. If I understand correctly, CRF will lower the quality of fast-motion parts and improve it for low-motion.

But if the target quantizer is high enough to begin with, this won't be necessary and QP will improve the quality of high-motion at the expense of more file size.

This may not matter much for normal viewing, but as stills it'd look better.

akupenguin
27th September 2006, 17:40
The answer to any question that begins with "if you ignore output size..." is: Use lossless (CQP=0).
The fact that you're compressing a video at all means that you obviously aren't ignoring output size. So I can't address the rest of that post until you rephrase it with a plausible premise.

shae
27th September 2006, 17:53
I thought what I meant was obvious, but here's an elaboration:

Of course the idea is to compress, but in many cases adding 50% or 100% to file size is tolerable or even desirable if you want better quality also for fast-motion frames. Also as such it still is massive compression compared with lossless.

BTW, when I said "But if the target quantizer is high enough to begin with..." it meant low value/high quality quantizer.

So the idea, assuming I use static Q16, is that there's no need to turn some fast-motion to Q20 in order to improve low-motion because Q16 is already good enough for it.

akupenguin
27th September 2006, 18:15
Two problems with that:
* Assuming CRF16 assigns QP20 in high motion and QP12 in low motion, then most likely you'll get the same total bitrate from CQP18 or similar. You can reduce the low-motion QP by a lot while taking only a little bit away from the high motion scenes.
* If QP16 is good enough for low motion, then some higher QP is good enough for high motion. Maybe CRF isn't tuned perfectly to your eyes, but the optimal solution still isn't to use the same QP everywhere. Modify qcomp and/or qpmin.

Sharktooth
27th September 2006, 18:16
I thought what I meant was obvious, but here's an elaboration:

Of course the idea is to compress, but in many cases adding 50% or 100% to file size is tolerable or even desirable if you want better quality also for fast-motion frames. Also as such it still is massive compression compared with lossless.

BTW, when I said "But if the target quantizer is high enough to begin with..." it meant low value/high quality quantizer.

So the idea, assuming I use static Q16, is that there's no need to turn some fast-motion to Q20 in order to improve low-motion because Q16 is already good enough for it.
objection: in fast motion scenes the human eye cant see fine details.
So it's better to spare bits for lo-mo scenes where you can see perfectly any artifacts.

shae
27th September 2006, 22:57
objection: in fast motion scenes the human eye cant see fine details. So it's better to spare bits for lo-mo scenes where you can see perfectly any artifacts.
That depends on your goals.

A possible example; you want to make available an example of a 3D rendering of yours, and want to let people examine single frames in all their glory, may they be fast or slow motion.

I didn't have a problem with the assertion that for typical uses CRF can yield better subjective quality for a given average bitrate, or smaller file size.

naugas
9th October 2006, 21:56
I just tried crf with the latest x264 and got this:
"x264 [error]: constant rate-factor is incompatible with 2pass.
x264 [error]: x264_encoder_open failed"

I guess there have been some change since I last tried it. How can bitrate allocation between scenes work without two passes? How does crf differ from constant quality now?

x264 core:53 svn-584M (built by Sharktooth)
used this command: x264.exe --crf 21 --pass 2 --stats ".stats" ...etc

akupenguin
9th October 2006, 22:23
crf has never been compatible with 2nd pass.
crf doesn't "allocate bitrate between scenes". It encodes at constant quality, and lets the bitrate come out at whatever is needed for that quality level.

naugas
9th October 2006, 23:36
Sorry, my head is upside down. I was trying what omion said on the page before, post760312 (http://forum.doom9.org/showthread.php?p=760312#post760312) ("If you want the best quality...), and it should be a normal second pass after the first pass crf encode, aiming for the same bitrate as the crf encode produced.

What I'm wondering now is if those two passes must have the same settings otherwise, or if it would work well with a fast crf setting to produce the stats file. And if so, maybe aim for a slightly lower bitrate than the fast crf encode gave, to compensate for lower compression?

foxyshadis
10th October 2006, 04:51
For the last, oh, 8 months or so I've always run fast crf 26 to get a good bitrate (that averages around 23-24 with slow settings) followed by two-pass. Depending on how in the mood for messing with it I am, I'll sometimes consolidate them (it'll work fine) but sometimes I just don't care since it's a lot easier to do them separate, in MeGUI. Comes out looking very nice.

rbt01
19th July 2007, 09:50
who can tell me what is sad_x3, sad_x4 is within structure x264_pixel_function_t in pixel.h

Manao
19th July 2007, 10:14
sad_x3 computes three SADs at the same time.
sad_x4 computed four SADs at the same time.

rbt01
9th October 2007, 10:03
thank you Manao