Setting libx264 bitrate via API

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Setting libx264 bitrate via API

jettoblack
Hello,
I'm trying to do the equivalent of this via the API:
ffmpeg -i test.m2t -c:v libx264 -b:v 500000 -s 640x360 -ac 2 test.mov

This gives a ABR file at 500kbits/sec.

I thought setting the video bitrate should be as simple as:
    out_vcodec->bit_rate = 500000;

When using CODEC_ID_MPEG2VIDEO or CODEC_ID_MPEG4, this works fine, and the resulting file has the specified ABR.  However with libx264 (CODEC_ID_H264) the bitrate parameter seems to have no effect, even very small values like 50,000 or very large like 50,000,000 (for a 640x360 video) give the same output of around 200kbits/sec.  The input video is not a static picture and it's not like 200kbit/sec is giving a lossless result and more bits are unnecessary.

I also tried:
   out_vcodec->bit_rate = 500000;
   out_vcodec->rc_min_rate = 500000;
   out_vcodec->rc_max_rate = 500000;
   out_vcodec->rc_buffer_size = 500000;

But still, there is no change in the output bitrate no matter what values I put.  So I suspect these values are getting ignored or I'm not passing them into the codec correctly.

The only parameter that actually affects the libx264 output bitrate is setting out_vcodec->qmin and out_vcodec->qmax.  By playing with qmin and qmax I can at least affect the bitrate, but it doesn't give a predictable ABR or CBR result.

Any ideas?  Thanks!

I initialize the codec like this:

    AVCodec *vcodec = avcodec_find_encoder(CODEC_ID_H264);     // or CODEC_ID_MPEG2VIDEO, etc.
    AVCodecContext *out_vcodec = avcodec_alloc_context3(vcodec);
    avcodec_get_context_defaults3(out_vcodec, vcodec);
    if (vcodec->id == CODEC_ID_H264) {
        av_opt_set(out_vcodec->priv_data, "profile", "main", 0);
    }
    out_vcodec->bit_rate = 500000;
    out_vcodec->width = 640;
    out_vcodec->height = 360;
    out_vcodec->pix_fmt = PIX_FMT_YUV420P;

    r = avcodec_open2(out_vcodec, vcodec, NULL);

Thanks!
rsg
Reply | Threaded
Open this post in threaded view
|

Re: Setting libx264 bitrate via API

rsg

Hi,

I am also facing a similar issue.
When I set the bit rate using

        out_vcodec->bit_rate = 200000;

the quality of the video goes very bad. But when I set qmin and qmax, the bitrate setting is ignored.
Only when i set a high value (approx 100MB) for the bit rate, the quality of the video improves.

I think there is some bug in ffmpeg or I might be missing something.
Can anyone tell whats the problem?

Thanks



-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of jettoblack
Sent: Saturday, July 21, 2012 3:56 AM
To: [hidden email]
Subject: [Libav-user] Setting libx264 bitrate via API

Hello,
I'm trying to do the equivalent of this via the API:
ffmpeg -i test.m2t -c:v libx264 -b:v 500000 -s 640x360 -ac 2 test.mov

This gives a ABR file at 500kbits/sec.

I thought setting the video bitrate should be as simple as:
    out_vcodec->bit_rate = 500000;

When using CODEC_ID_MPEG2VIDEO or CODEC_ID_MPEG4, this works fine, and the
resulting file has the specified ABR.  However with libx264 (CODEC_ID_H264)
the bitrate parameter seems to have no effect, even very small values like
50,000 or very large like 50,000,000 (for a 640x360 video) give the same
output of around 200kbits/sec.  The input video is not a static picture and
it's not like 200kbit/sec is giving a lossless result and more bits are
unnecessary.

I also tried:
   out_vcodec->bit_rate = 500000;
   out_vcodec->rc_min_rate = 500000;
   out_vcodec->rc_max_rate = 500000;
   out_vcodec->rc_buffer_size = 500000;

But still, there is no change in the output bitrate no matter what values I
put.  So I suspect these values are getting ignored or I'm not passing them
into the codec correctly.

The only parameter that actually affects the libx264 output bitrate is
setting out_vcodec->qmin and out_vcodec->qmax.  By playing with qmin and
qmax I can at least affect the bitrate, but it doesn't give a predictable
ABR or CBR result.

Any ideas?  Thanks!

I initialize the codec like this:

    AVCodec *vcodec = avcodec_find_encoder(CODEC_ID_H264);     // or
CODEC_ID_MPEG2VIDEO, etc.
    AVCodecContext *out_vcodec = avcodec_alloc_context3(vcodec);
    avcodec_get_context_defaults3(out_vcodec, vcodec);
    if (vcodec->id == CODEC_ID_H264) {
        av_opt_set(out_vcodec->priv_data, "profile", "main", 0);
    }
    out_vcodec->bit_rate = 500000;
    out_vcodec->width = 640;
    out_vcodec->height = 360;
    out_vcodec->pix_fmt = PIX_FMT_YUV420P;

    r = avcodec_open2(out_vcodec, vcodec, NULL);

Thanks!




--
View this message in context: http://libav-users.943685.n4.nabble.com/Setting-libx264-bitrate-via-API-tp4655453.html
Sent from the libav-users mailing list archive at Nabble.com.
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user


::DISCLAIMER::
----------------------------------------------------------------------------------------------------------------------------------------------------

The contents of this e-mail and any attachment(s) are confidential and intended for the named recipient(s) only.
E-mail transmission is not guaranteed to be secure or error-free as information could be intercepted, corrupted,
lost, destroyed, arrive late or incomplete, or may contain viruses in transmission. The e mail and its contents
(with or without referred errors) shall therefore not attach any liability on the originator or HCL or its affiliates.
Views or opinions, if any, presented in this email are solely those of the author and may not necessarily reflect the
views or opinions of HCL or its affiliates. Any form of reproduction, dissemination, copying, disclosure, modification,
distribution and / or publication of this message without the prior written consent of authorized representative of
HCL is strictly prohibited. If you have received this email in error please delete it and notify the sender immediately.
Before opening any email and/or attachments, please check them for viruses and other defects.

----------------------------------------------------------------------------------------------------------------------------------------------------

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user
Reply | Threaded
Open this post in threaded view
|

Re: Setting libx264 bitrate via API

jettoblack
rsg wrote
Hi,

I am also facing a similar issue.
When I set the bit rate using

        out_vcodec->bit_rate = 200000;

the quality of the video goes very bad. But when I set qmin and qmax, the bitrate setting is ignored.
Only when i set a high value (approx 100MB) for the bit rate, the quality of the video improves.
Yes that is the same thing I'm seeing.  If qmin/qmax are left at -1 (default), then no matter what bitrate is specified, quality is very bad (and the bitrate is not honored).

The upper half/third of the image looks good and the lower area looks really bad.  The dividing line also changes every couple of frames. For example see this screenshot: https://dl.dropbox.com/u/7730988/encode_prob.png

The only way I found to avoid this problem is to set qmin/qmax but then the resulting video is not ABR/CBR.  Here is the same frame compressed with all settings the same as before, except set qmin=1, qmax=31:
https://dl.dropbox.com/u/7730988/qminqmax.png

Obviously ffmpeg can do it right so I'm sure we are doing something wrong, but I haven't yet found the difference in how ffmpeg is setting the libx264 options such as bitrate differently than what we are doing here.

Hope someone else has an idea...  Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: Setting libx264 bitrate via API

jettoblack
After digging through ffmpeg.c, I finally figured it out.  

My code was sending pictures into the encoder using a pts in the stream's time_base of 1/90000 (e.g. 3003, 6006, 9009).  The solution was to first rescale the AVFrame's pts from the stream's time_base to the codec time_base to get a simple frame number (e.g. 1, 2, 3).

pic->pts = av_rescale_q(pic->pts, ost->time_base, enc->time_base);
avcodec_encode_video2(enc, &newpkt, pic, &got_packet_ptr);

Then when a packet is received from the encoder, you need to rescale pts and dts back to the stream time_base.

newpkt.pts = av_rescale_q(newpkt.pts, enc->time_base, ost->time_base);
newpkt.dts = av_rescale_q(newpkt.dts, enc->time_base, ost->time_base);
av_interleaved_write_frame(out, &newpkt);

I guess not every codec requires this to be done, but libx264 does if you want to encode CBR/ABR.
rsg
Reply | Threaded
Open this post in threaded view
|

Re: Setting libx264 bitrate via API

rsg
Hi,

Your finding has fixed the issue in my case also.
Thanks for posting. It would certainly help others who are facing similar issue.

Regards,
Rakesh

-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of jettoblack
Sent: Sunday, August 05, 2012 10:10 AM
To: [hidden email]
Subject: Re: [Libav-user] Setting libx264 bitrate via API

After digging through ffmpeg.c, I finally figured it out.  

My code was sending pictures into the encoder using a pts in the stream's
time_base of 1/90000 (e.g. 3003, 6006, 9009).  The solution was to first
rescale the AVFrame's pts from the stream's time_base to the codec time_base
to get a simple frame number (e.g. 1, 2, 3).

pic->pts = av_rescale_q(pic->pts, ost->time_base, enc->time_base);
avcodec_encode_video2(enc, &newpkt, pic, &got_packet_ptr);

Then when a packet is received from the encoder, you need to rescale pts and
dts back to the stream time_base.

newpkt.pts = av_rescale_q(newpkt.pts, enc->time_base, ost->time_base);
newpkt.dts = av_rescale_q(newpkt.dts, enc->time_base, ost->time_base);
av_interleaved_write_frame(out, &newpkt);

I guess not every codec requires this to be done, but libx264 does if you
want to encode CBR/ABR.




--
View this message in context: http://libav-users.943685.n4.nabble.com/Setting-libx264-bitrate-via-API-tp4655453p4655531.html
Sent from the libav-users mailing list archive at Nabble.com.
_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user


::DISCLAIMER::
----------------------------------------------------------------------------------------------------------------------------------------------------

The contents of this e-mail and any attachment(s) are confidential and intended for the named recipient(s) only.
E-mail transmission is not guaranteed to be secure or error-free as information could be intercepted, corrupted,
lost, destroyed, arrive late or incomplete, or may contain viruses in transmission. The e mail and its contents
(with or without referred errors) shall therefore not attach any liability on the originator or HCL or its affiliates.
Views or opinions, if any, presented in this email are solely those of the author and may not necessarily reflect the
views or opinions of HCL or its affiliates. Any form of reproduction, dissemination, copying, disclosure, modification,
distribution and / or publication of this message without the prior written consent of authorized representative of
HCL is strictly prohibited. If you have received this email in error please delete it and notify the sender immediately.
Before opening any email and/or attachments, please check them for viruses and other defects.

----------------------------------------------------------------------------------------------------------------------------------------------------

_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user