使用libav进行x264编码

时间:2014-03-24 02:17:50

标签: x264 libav

我尝试使用libav将原始图像数据编码为x264:

AVPacket vpkt = { 0 };
av_init_packet(&vpkt);

int got;
int ret = avcodec_encode_video2(vcodec, &vpkt, frameyuv.get(), &got);

if (!ret && got && vpkt.size) {
    if (vpkt.pts != AV_NOPTS_VALUE) {
        vpkt.pts = av_rescale_q(vpkt.pts, vcodec->time_base, videost->time_base);
    }
    if (vpkt.dts != AV_NOPTS_VALUE) {
        vpkt.dts = av_rescale_q(vpkt.dts, vcodec->time_base, videost->time_base);
    }

    vpkt.stream_index = videost->index;

    if(vcodec->coded_frame->key_frame) {
        vpkt.flags |= AV_PKT_FLAG_KEY;
    }
    /* -> will return -22 if max_b_frames > 0 */
    ret = av_interleaved_write_frame(oc, &vpkt);
}

当vcodec-> max_b_frames设置为0时运行正常,但在任何其他值上av_interleaved_write_frame返回-22(无效参数)。

/* will fail */
c->max_b_frames = 3;
/* -> ok*/
c->max_b_frames = 0;

为什么呢?我错过了什么吗?

编解码器选项

AVDictionary *opts = NULL;
av_dict_set(&opts, "vprofile", "baseline", 0);

/* ... */
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->bit_rate = 500 * 1000;
c->width = VideoWidth;
c->height = VideoHeight;
c->time_base.den = fps;
c->time_base.num = 1;
c->pix_fmt = AV_PIX_FMT_YUV420P;

容器格式为mp4。

1 个答案:

答案 0 :(得分:0)

您需要将av_rescale_q放入输出上下文的时基,而不是视频流。您正在做的事情与av_rescale_q无关。尝试:

av_rescale_q(vpkt.pts, vcodec->time_base, [output context]->time_base);

如果您继续遇到问题,几乎总是B帧问题表明DTS值不好。考虑将DTS设置为AV_NOPTS_VALUE,让解复用器自行解决。

请记住解码一个B帧,你必须知道它的两侧的帧,因此它们必须首先被解复用,考虑3帧:

I B I

必须首先解码第一帧,然后是第三帧,最后是第二帧。此信息来自DTS。

最后,通过跟随this stack overflow找出你获得-22的原因。如果它不是“非单调增加的PTS / DTS”错误,我会感到震惊。