Log in

View Full Version : x264 settings for zero-delay encoding?


genesys
16th April 2012, 00:36
I'm trying to encode a video with zero delay (I'm doing this in my own application using ffmpeg) using x264 codec. By this I mean i want instant results after each frame i feed into the encoder. I already set b-frames to 0 and threads to 1 but i still get a delay that is gop_size+1. Can someone tell me what settings I need in order to get zero-delay encoding? (i can also provide my c++ code if that helps answering the question, but won't post it for the time being as most people here probably use x264 through the commandline tool)

nm
16th April 2012, 02:05
What rc-lookahead value do you use? The code might help too.

Have you read this blog post (and comments) about low latency encoding with x264: http://x264dev.multimedia.cx/archives/249

genesys
16th April 2012, 08:49
hey nm, thank you for your response

yes I saw that post already and a bit further down someone asks a similar question regarding low latency and the author recommends editing the ffmpeg sourcecode - but as I'm on msvc++ I use a precompiled build of ffmpeg and I also don't need this ultra-low-latency between encoder and decoder, I just need the encoding result right after the first frame was fed into the encoder.

I was already looking for the rc_lookahead setting as i suspect it to be relevant to my problem, but the rc_lookahead setting was removed from AVCodecContext sometime last year and replaced by a "private option" which I do not know how to read or set (http://ffmpeg.org/pipermail/ffmpeg-cvslog/2011-August/039836.html)


this is my code for the setup of the codeccontext:

static AVStream* add_video_stream(AVFormatContext *oc, enum CodecID codec_id, int w, int h, int fps)
{
AVCodecContext *c;
AVStream *st;
AVCodec *codec;

/* find the video encoder */
codec = avcodec_find_encoder(codec_id);
if (!codec) {
fprintf(stderr, "codec not found\n");
exit(1);
}

st = avformat_new_stream(oc, codec);
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}

c = st->codec;

/* Put sample parameters. */
c->bit_rate = 400000;
/* Resolution must be a multiple of two. */
c->width = w;
c->height = h;
/* timebase: This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented. For fixed-fps content,
* timebase should be 1/framerate and timestamp increments should be
* identical to 1. */
c->time_base.den = fps;
c->time_base.num = 1;
c->gop_size = 12; /* emit one intra frame every twelve frames at most */

c->codec = codec;
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->coder_type = FF_CODER_TYPE_VLC;
c->me_method = 7; //motion estimation algorithm
c->me_subpel_quality = 4;
c->delay = 0;
c->max_b_frames = 0;
c->thread_count = 1; // more than one threads seem to increase delay
c->refs = 3;

c->pix_fmt = PIX_FMT_YUV420P;

/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;

return st;
}

genesys
16th April 2012, 10:52
okay - i figured out how to set coder private options and set rc-lookahead to 0, which broght my framedelay down to 1 independant of gop_size. Still one frame too much.
ffmpeg dumps me this info about the used settings:

[libx264 @ 000000000057DAA0] profile High, level 3.0
[libx264 @ 000000000057DAA0] 264 - core 120 r2146 bcd41db - H.264/MPEG-4 AVC cod
ec - Copyleft 2003-2011 - http://www.videolan.org/x264.html - options: cabac=0 r
ef=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=4 psy=1 psy_rd=1.00:0.00 mixed
_ref=1 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pski
p=1 chroma_qp_offset=0 threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 b
luray_compat=0 constrained_intra=0 bframes=0 weightp=2 keyint=12 keyint_min=1 sc
enecut=40 intra_refresh=0 rc=abr mbtree=0 bitrate=400 ratetol=1.0 qcomp=0.60 qpm
in=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'out2.mp4':
Stream #0:0: Video: h264, yuv420p, 640x480, q=-1--1, 400 kb/s, 90k tbn, 25 t
bc


Any idea what else i need to change to get 0 frames delay?

nm
16th April 2012, 11:18
See what --tune zerolatency does:


- zerolatency:
--bframes 0 --force-cfr --no-mbtree
--sync-lookahead 0 --sliced-threads
--rc-lookahead 0


I guess you need to set sync-lookahead to 0 (it's 1 by default with zero b-frames) and perhaps switch off mbtree.

Note that you can use sliced threads to speed up encoding.

genesys
18th April 2012, 18:20
this works! thank you very much :)