使用libavformat的视频流错误:未设置VBV缓冲区大小,多路复用可能会失败

时间:2014-01-15 14:30:32

标签: ffmpeg streaming libavcodec libavformat

我使用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需要一个缓冲区来填充一些量,以便它可以开始显示流。我是对的吗?

1 个答案:

答案 0 :(得分:0)

您可以使用以下命令设置流的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 properties documentation) 。或者,您可以将这些值设置为适合您特定用例的任何值。只是不要忘记分配这些字段,因为它们不会自动初始化。