Aaron Colwell
2005-Feb-17 11:25 UTC
[Theora-dev] Fix a bug that causes the encoder to spend way to many bits on keyframes
Here is a fix that prevents the encoder from spending too many bits on keyframes. The main problem is that the old code computes the target keyframe bitrate incorrectly. This causes the code that computes the Q for the frame to think that it has tons of bits to spend. It selects a high Q value for the keyframe. Since so many bits were spend on the keyframe the the inter-frames have to use a much lower Q. This ends up causing a "popping" artifact where everything is clear for a keyframe, but gets progressively blurry for each successive inter-frame. This change fixes the keyframe bitrate computation so that it is closer to the inter-frame bitrate, which I believe is what the original author intended. This prevents the huge difference in Q between keyframes and inter-frames. Index: encoder_toplevel.c ==================================================================--- encoder_toplevel.c (revision 8940) +++ encoder_toplevel.c (working copy) @@ -862,8 +862,8 @@ /* Set key frame data rate target; this is nominal keyframe size */ cpi->Configuration.KeyFrameDataTarget = (c->keyframe_data_target_bitrate * - c->fps_numerator / - c->fps_denominator ) / 8; + c->fps_denominator / + c->fps_numerator ) / 8; /* Note the height and width in the pre-processor control structure. */ cpi->ScanConfig.VideoFrameHeight = cpi->pb.info.height; I'm also playing around with the following change to help remove the "popping" artifact that I mentioned above. This change removes the restriction that keyframe Q must be in the range 20 <= Q <= 50. For encodes that tend to use Q lower than 20 you see the "popping" artifact if the inter-frame Q is lower than 20. The results look good so far, but I want to do more testing on various source content to make sure this is a good change. Index: misc_common.c ==================================================================--- misc_common.c (revision 8940) +++ misc_common.c (working copy) @@ -255,14 +255,6 @@ /* QIndex should now indicate the optimal Q. */ cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[QIndex]; - /* Apply range restrictions for key frames. */ - if ( GetFrameType(&cpi->pb) == BASE_FRAME ) { - if ( cpi->pb.ThisFrameQualityValue > cpi->pb.QThreshTable[20] ) - cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[20]; - else if ( cpi->pb.ThisFrameQualityValue < cpi->pb.QThreshTable[50] ) - cpi->pb.ThisFrameQualityValue = cpi->pb.QThreshTable[50]; - } - /* Limit the Q value to the maximum available value */ if (cpi->pb.ThisFrameQualityValue > cpi->pb.QThreshTable[cpi->Configuration.ActiveMaxQ]) { Aaron
Ivan Popov
2005-Feb-18 09:49 UTC
[Theora-dev] Fix a bug that causes the encoder to spend way to many bits on keyframes
Hi Aaron, On Thu, Feb 17, 2005 at 11:22:11AM -0800, Aaron Colwell wrote:> Here is a fix that prevents the encoder from spending too many bits on > keyframes. The main problem is that the old code computes the target keyframe > bitrate incorrectly. This causes the code that computes the Q for the frame to> have to use a much lower Q. This ends up causing a "popping" artifact where > everything is clear for a keyframe, but gets progressively blurry for each > successive inter-frame.I have been looking for the reason of that (or similar) effect. No one on the list answered when I asked. Now I tested the encoder with your change, and unfortunately it did not improve the cases where I see artifacts - still your change looks right, if I can believe the comments in encoder_toplevel.c. I see terrible artifacts on "text screens" with e.g. theora-encoder -a 0 -V 400 -o newref.400.ogg AmelieArchive.mpg e.g. during the seconds 4 and 5 or very spectacular ones with theora-encoder -a 0 -V 2000 -o newref.2000.ogg AmelieArchive.mpg e.g. during the seconds 13-16... (http://www.archive.org/download/AmelieArchive/AmelieArchive.mpg) theora-encoder script runs theoraenc which (and the library) is from today's svn. Would you - or anybody - comment on my observations? Best regards, -- Ivan