views:

333

answers:

3

I am attempting to encode video using libavcodec/libavformat. Audio works great, but when I try to encode video I get the following errors:

[libx264 @ 0x10182a000]broken ffmpeg default settings detected  
[libx264 @ 0x10182a000]use an encoding preset (vpre)  

easy to fix using the command line ffmpeg, but I am trying to do this in C. my options are

AVStream *pVideoOutStream = av_new_stream(pOutFormatCtx, 0);  
AVCodecContext *pVideoOutCodecCtx  = pVideoOutStream->codec;  

pVideoOutCodecCtx->codec_id        = CODEC_ID_H264;    
pVideoOutCodecCtx->codec_type      = CODEC_TYPE_VIDEO;  
pVideoOutCodecCtx->bit_rate        = pVideoInCodecCtx->bit_rate;  
pVideoOutCodecCtx->width           = pVideoInCodecCtx->width;    
pVideoOutCodecCtx->height          = pVideoInCodecCtx->height;  
pVideoOutCodecCtx->pix_fmt         = pVideoInCodecCtx->pix_fmt;    
pVideoOutCodecCtx->sample_rate     = pVideoInCodecCtx->sample_rate;    
pVideoOutCodecCtx->gop_size        = 30;  

but avcodec_open() fails.

What other values do I need to set to make x264 happy?

A: 

I encode YUV420P pictures into different formats, using different codecs. CodecID I take from AVOutputFormat after using guess_format(...) function. But other codec settings are (All of them has been taken from ffmpeg examples' source code):

c->codec_id = (CodecID)CODEC_ID_H264; //This is your codec id
c->codec_type = CODEC_TYPE_VIDEO;

c->bit_rate = 1000000;
c->width = <...>;
c->height = <...>;
c->time_base.den = 25;
c->time_base.num = 1;
c->gop_size = 12;
c->pix_fmt = PIX_FMT_YUV420P;
if (c->codec_id == CODEC_ID_MPEG1VIDEO) //It not necessary for you c->mb_decision=2;
// some formats want stream headers to be separate
if(oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;

This settings must work to most codecs, but I had a problem with fps: not all codecs supports any fps values (and some other parameters too).

Petroff
Thanks! I'll try it out today and see what happens.
SlimSCSI
A: 

Not sure whether you got it working, but the following parameters work for me.

ctx->bit_rate = 500*1000;

ctx->bit_rate_tolerance = 0;

ctx->rc_max_rate = 0;

ctx->rc_buffer_size = 0;

ctx->gop_size = 40;

ctx->max_b_frames = 3;

ctx->b_frame_strategy = 1;

ctx->coder_type = 1;

ctx->me_cmp = 1;

ctx->me_range = 16;

ctx->qmin = 10;

ctx->qmax = 51;

ctx->scenechange_threshold = 40;

ctx->flags |= CODEC_FLAG_LOOP_FILTER;

ctx->me_method = ME_HEX;

ctx->me_subpel_quality = 5;

ctx->i_quant_factor = 0.71;

ctx->qcompress = 0.6;

ctx->max_qdiff = 4;

ctx->directpred = 1;

ctx->flags2 |= CODEC_FLAG2_FASTPSKIP;


It is possible to look through the FFmpeg source code and determine how the preset files map to AVCodecContext parameters, but I forget exactly where the magic happens.

Shea
A: 

The following is how to interpret the ffmpeg's x264 presets.

Unfortunately I don't know of an easy way to import the presets like ffmpeg does. You can lookup the x264 preset values which are all stored in /usr/local/share/ffmpeg/libx264-{name}.ffpreset, where {name} is specified for ffmpeg as the -vpre {name} command-line argument. So typically ffmpeg would include libx264-medium.ffpreset and then libx264-main.ffpreset, specified as ffmpeg -vpre medium -vpre main

You can lookup all the options (as defined in the libx264-{name}.ffpreset files) to get their structure names by looking in the libavcodec/options.c file, which can be found in the ffmpeg SVN repositories.

Here's how the medium and main presets would be translated into C code:

// libx264-medium.ffpreset preset
ctx->coder_type = 1;  // coder = 1
ctx->flags|=CODEC_FLAG_LOOP_FILTER;   // flags=+loop
ctx->me_cmp|= 1;  // cmp=+chroma, where CHROMA = 1
ctx->partitions|=X264_PART_I8X8+X264_PART_I4X4+X264_PART_P8X8+X264_PART_B8X8; // partitions=+parti8x8+parti4x4+partp8x8+partb8x8
ctx->me_method=ME_HEX;    // me_method=hex
ctx->me_subpel_quality = 7;   // subq=7
ctx->me_range = 16;   // me_range=16
ctx->gop_size = 250;  // g=250
ctx->keyint_min = 25; // keyint_min=25
ctx->scenechange_threshold = 40;  // sc_threshold=40
ctx->i_quant_factor = 0.71; // i_qfactor=0.71
ctx->b_frame_strategy = 1;  // b_strategy=1
ctx->qcompress = 0.6; // qcomp=0.6
ctx->qmin = 10;   // qmin=10
ctx->qmax = 51;   // qmax=51
ctx->max_qdiff = 4;   // qdiff=4
ctx->max_b_frames = 3;    // bf=3
ctx->refs = 3;    // refs=3
ctx->directpred = 1;  // directpred=1
ctx->trellis = 1; // trellis=1
ctx->flags2|=CODEC_FLAG2_BPYRAMID+CODEC_FLAG2_MIXED_REFS+CODEC_FLAG2_WPRED+CODEC_FLAG2_8X8DCT+CODEC_FLAG2_FASTPSKIP;  // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip
ctx->weighted_p_pred = 2; // wpredp=2

// libx264-main.ffpreset preset
ctx->flags2|=CODEC_FLAG2_8X8DCT;c->flags2^=CODEC_FLAG2_8X8DCT;    // flags2=-dct8x8

You'll have to look at the ffmpeg source code if you want to parse those presets automatically.

I hope that the information I just gave would help you out a bit more :)

Pada