Mat
Mat

Reputation: 4501

c++, FFMPEG, H264, creating zero-delay stream

I'm trying to encode video (using h264 codec at the moment, but other codecs would be fine too if better suited for my needs) such that the data needed for decoding is available directly after a frame (including the first frame) was encoded (so, i want only I and P frames, no B frames).

How do I need to setup the AVCodecContext to get such a stream? So far my testing arround with the values still always resulted in avcodec_encode_video() returning 0 on the first frame.

//edit: this is currently my setup code of the AVCodecContext:

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;
}

but with this avcodec_encode_video() will buffer 13 frames before returning any bytes (after that, it will return bytes on every frame). if I set gop_size to 0, then avcodec_encode_video() will return bytes only after the second frame was passed to it. I need a zero delay though.

This guy apparently was successful (even with larger gop): http://mailman.videolan.org/pipermail/x264-devel/2009-May/005880.html but I don't see what he is doing differently

Upvotes: 5

Views: 7945

Answers (1)

Muad'Dib
Muad'Dib

Reputation: 47

For me this piece of code did the trick:

av_opt_set(context->priv_data, "tune", "zerolatency", 0);

(Call this function before you open your context.)

Upvotes: 3

Related Questions