[Ffmpeg-devel] Intra-frame rate control

RLopez rlopez
Thu Apr 12 22:12:33 CEST 2007


>On Thur, 12 Apr 2007, Baptiste Coudurier wrote:
>> On Wed, 11 Apr 2007, RLopez wrote:
>> 
>>>> libavcodec supports adapting QP based on spatial and or temporal
>>>> complexity
>>>> of macroblocks, if you want to find out how then do as i said and
>>>> Read The Fine Manual
>>>
>>> Can you point me to where the manual discusses this?  I looked through
>>> all
>>> the manuals on the ffmpeg website and didn't see any mention of adaptive
>>> spatial QP for MPEG2.  Are there other manuals elsewhere that I don't
>>> know
>>> about?
>> 
>> See all the options whose names end in _mask
>
>See also -mbd rd -flags +qprd

Do these switches work for MPEG2?  Do they slow down the encoding when you
use them?  I'm trying to replace the MPEG2 encoder we use with avcodec.lib
but I'm having problems getting bitrates that stay within an acceptable
range.  I thought the problem was because avcodec.lib was only adjusting the
QP at frame boundaries.  See the test I ran below.  Would using some of the
switches mentioned give me better results?

I did a test where I encoded 10 flat gray frames(1920x1080) followed by 10
frames of random data using avcodec.lib and again using Pexeltool MPEG2
encoder at 20 Mbs.  Here are the results:

                    avcodec               Pixeltools
Frame #   Frames size  QP values    Frames size  QP values
=======   =======================   ======================
   1         30987    Fixed at 2      83245       1 - 3
   2         30987    Fixed at 2      83242       1 - 3
   3         30987    Fixed at 2      83239     Fixed at 1
   4         30987    Fixed at 2      83239     Fixed at 1
   5         30987    Fixed at 2      83239     Fixed at 1
   6         30987    Fixed at 2      83239     Fixed at 1
   7         30987    Fixed at 2      83239     Fixed at 1
   8         30987    Fixed at 2      83239     Fixed at 1
   9         30987    Fixed at 2      83239     Fixed at 1
  10         30987    Fixed at 2      83239     Fixed at 1
  11       3102876    Fixed at 2      86344       1 - 27
  12       3103653    Fixed at 2      85680      12 - 31
  13       1846080    Fixed at 5      83110      18 - 31
  14       1498372    Fixed at 7      83141      27 - 31
  15       1178371    Fixed at 10     83210      25 - 30
  16        972263    Fixed at 13     83174      24 - 30
  17        819350    Fixed at 16     83189      25 - 29
  18        701635    Fixed at 19     83210      26 - 29
  19        611076    Fixed at 22     83135      28 - 31
  20        535178    Fixed at 25     83227      27 - 31

The average frame size should be 83416.  Avcodec only changes the QP at
picture boundaries and when it hits frame 11 (the first random frame) the
bitrate skyrockets and it only adjusts the Q value by about 3 for each
subsequent frame.  The Pixeltools encoder varies the Q throughout the frame
to keep the bitrate around 20 Mbs.  I attached the code I used for the
avcodec test.

#include "avformat.h"

int picturebuf[1920*1080/2];
unsigned char outbuf[4*1024*1024];
AVCodecContext ffenc;
AVFrame        picture;

int main(int argc, char* argv[])
{
    int i,j,k,random,size1,size2;
    FILE *fid;
    AVCodec        *codec;

    int bitrate  = 20000000; 
    int width    = 1920; 
    int height   = 1080; 
    int gopsize  = 1;
    int bframes  = 0;
    int ratenum  = 1001;
    int rateden  = 30000;

    av_register_all();
    av_log_set_level(-1);

    avcodec_get_frame_defaults(&picture);
    avpicture_fill((AVPicture *)&picture, 0, PIX_FMT_YUV420P, width,
height);
    size1 = picture.data[1] - picture.data[0];
    size2 = picture.data[2] - picture.data[1];
    avcodec_get_context_defaults(&ffenc);

    ffenc.codec_id                = CODEC_ID_MPEG2VIDEO;
    ffenc.codec_type              = CODEC_TYPE_VIDEO;

    ffenc.sample_aspect_ratio.num = 1;
    ffenc.sample_aspect_ratio.den = 1;
    ffenc.bit_rate                = bitrate;
    ffenc.width                   = width;  
    ffenc.height                  = height;
    ffenc.profile                 = 4;
    ffenc.level                   = 4;
    ffenc.time_base.num           = ratenum;
    ffenc.time_base.den           = rateden;
    ffenc.gop_size                = gopsize;
    ffenc.max_b_frames            = bframes;

    ffenc.scenechange_threshold   = 1000000000;
    ffenc.bit_rate_tolerance      = 4000*1000;
    ffenc.qblur                   = 0.5;
    ffenc.rc_buffer_aggressivity  = 1.0;
    ffenc.pix_fmt                 = PIX_FMT_YUV420P;
    codec = avcodec_find_encoder(ffenc.codec_id);
    avcodec_open(&ffenc, codec);
    
    fid = fopen("c:\\test.mpg","wb");
    for (random=0;random<2;random++) {
        if (!random) for (j=0;j<(1920*1080/2);j++) picturebuf[j] =
0x80808080;
        for (i=0;i<10;i++) {
            if (random) for (j=0;j<(1920*1080/2);j++) picturebuf[j] =
rand();
            picture.data[0] = (unsigned char*) picturebuf;
            picture.data[1] = picture.data[0] + size1;
            picture.data[2] = picture.data[1] + size2;
            k = avcodec_encode_video(&ffenc, outbuf, 16*1024*1024,
&picture);
            fwrite(outbuf,1,k,fid);
        }
    }
    fclose(fid);
    avcodec_close(&ffenc);
    return 0;
}






More information about the ffmpeg-devel mailing list