【问题标题】:x264 encoding with libav使用 libav 进行 x264 编码
【发布时间】:2014-03-26 04:25:20
【问题描述】:

我尝试使用 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。

【问题讨论】:

  • 很可能它与 PTS/DTS 值有关(当您没有 b 帧/延迟时,这可能是解决方法)。我猜你没有正确设置它们,并且 mp4 muxer 没有 AVFMT_NOTIMESTAMPS 标志,所以它们需要正确。

标签: x264 libav


【解决方案1】:

您需要将 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”错误,我会感到震惊。

【讨论】:

    猜你喜欢
    • 2012-10-04
    • 2011-04-02
    • 2014-02-06
    • 1970-01-01
    • 2023-03-31
    • 2023-03-03
    • 2015-05-13
    • 2013-01-27
    • 1970-01-01
    相关资源
    最近更新 更多