Ошибка при потоковой передаче видео с использованием libavformat: не установлен размер буфера VBV, может произойти сбой мультиплексирования

Я транслирую видео с помощью libavformat следующим образом:

static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,
                        enum AVCodecID codec_id)
{
AVCodecContext *c;
AVStream *st;
/* find the encoder */
*codec = avcodec_find_encoder(codec_id);
if (!(*codec)) {
    fprintf(stderr, "Could not find encoder for '%s'\n",
            avcodec_get_name(codec_id));
    exit(1);
}
st = avformat_new_stream(oc, *codec);
if (!st) {
    fprintf(stderr, "Could not allocate stream\n");
    exit(1);
}
st->id = oc->nb_streams-1;
c = st->codec;
switch ((*codec)->type) {
case AVMEDIA_TYPE_AUDIO:
    c->sample_fmt  = (*codec)->sample_fmts ?
        (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
    c->bit_rate    = 64000;
    c->sample_rate = 44100;
    c->channels    = 2;
    break;
case AVMEDIA_TYPE_VIDEO:
    c->codec_id = codec_id;
    c->bit_rate = 400000;
    /* Resolution must be a multiple of two. */
    c->width    = outframe_width;
    c->height   = outframe_height;
    /* 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 = STREAM_FRAME_RATE;
    c->time_base.num = 1;
    c->gop_size      = 12; /* emit one intra frame every twelve frames at most */
    c->pix_fmt       = STREAM_PIX_FMT;
    if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
        /* just for testing, we also add B frames */
        c->max_b_frames = 2;
    }
    if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
        /* Needed to avoid using macroblocks in which some coeffs overflow.
         * This does not happen with normal video, it just happens here as
         * the motion of the chroma plane does not match the luma plane. */
        c->mb_decision = 2;
    }
break;
default:
    break;
}
/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
    c->flags |= CODEC_FLAG_GLOBAL_HEADER;
return st;
}

Но когда я запускаю этот код, я получаю следующую ошибку/предупреждение:

[mpeg @ 01f3f040] VBV buffer size not set, muxing may fail

Вы знаете, как я могу установить размер буфера VBV в коде? На самом деле, когда я использую ffplay для отображения потокового видео, ffplay ничего не показывает для коротких видео, но для длинных видео он сразу начинает отображать видео. Итак, похоже, что ffplay нуждается в некотором заполнении буфера, чтобы он мог начать отображать поток. Я прав?


person Blue Sky    schedule 15.01.2014    source источник
comment
похоже, это установлено здесь, если это поможет. github.com/ffmpeg/ffmpeg/blob/master/libavformat/ mpegenc.c#L390 Я знаю, что в прошлом ffplay вводил собственную задержку, поэтому... возможно, ему нужен какой-то буфер. --fflags nobuffer может помочь? (звучит как ошибка в ffplay для меня, хотя...)   -  person rogerdpack    schedule 15.01.2014


Ответы (1)


Вы можете установить размер буфера VBV потока с помощью:

AVCPBProperties *props;
props = (AVCPBProperties*) av_stream_new_side_data(
    st, AV_PKT_DATA_CPB_PROPERTIES, sizeof(*props));
props->buffer_size = 230 * 1024;
props->max_bitrate = 0;
props->min_bitrate = 0;
props->avg_bitrate = 0;
props->vbv_delay = UINT64_MAX;

Где st — указатель на структуру AVStream. Минимальная скорость передачи данных, максимальная скорость передачи данных и средняя скорость передачи данных установлены на 0, а задержка VBV установлена ​​на UINT64_MAX в этом примере, поскольку эти значения указывают неизвестные или неуказанные значения для этих полей (см. документация по свойствам AVCPB). В качестве альтернативы вы можете установить эти значения в соответствии с вашим конкретным вариантом использования. Только не забудьте назначить эти поля, потому что они не будут инициализированы автоматически.

person Joost Huizinga    schedule 18.10.2017