【问题标题】:ffmpeg speed encoding problemffmpeg速度编码问题
【发布时间】:2011-09-15 22:24:09
【问题描述】:

我目前正在开发一个应用程序,该应用程序使用 Qt Designer 工具和 C++ 下的 V4L2 和 ffmpeg 库在 Linux 上从网络摄像头捕获视频,使用 lib V4L2 捕获图像没有问题,因为那是一张图片准备好我将它发送到基于ffmpeg libs的编码器,最初编码器创建一个视频文件,并接收图像以将其编码到该文件中,我的问题如下:编码通常完成,但如果我开始播放录制的视频文件,速度似乎比正常速度更快!所以很清楚,问题在于视频编码, 我的问题是,是否有管理 ffmpeg 编码速度图片的方法或功能???? 谢谢你的帮助。

【问题讨论】:

  • 所以你的问题与C++或Qt无关,请适当标记。
  • 我只是想澄清我的问题,因为我使用的是 Qt,用 c++ 语言编程。
  • 但是只有 C++ 和 Qt 知识的人无法帮助您,尽管他们可能正在“监控”这些标签。

标签: ffmpeg encoder


【解决方案1】:

使用 FFMpeg 创建自定义编码视频时,您实际上需要在写入输出文件的每个 AVPacket 上设置 PTS。设置 AVCodecContext 的 time_base 只会告诉容器会发生什么。 PTS(演示时间戳)告诉解码器(当您查看视频时)何时实际显示该特定帧。

例如:

我有一个从 FFMpeg 的 V4L2 部分获得的 AVFrame。首先,使用 av_picture_copy 复制此图像更安全。 (因此编码器不会查看 AVFrame 结构中的所有额外信息。)

av_picture_copy( (AVPicture*) picture, (AVPicture*) pFrame, c->pix_fmt, c->width, c->height );

picture->pts = numFrames;

现在根据编码帧数设置 pts

pDestFrame->pts = numFrames;

现在编码

numEncodedBytes = avcodec_encode_video( AVCodecCtx, buffer, bufferSize, pDestFrame );

现在创建一个 AVPacket 并在重新缩放后再次设置时间戳

AVPacket pkt;
av_init_packet(&pkt);

pkt.pts = av_rescale_q( c->coded_frame->pts, c->time_base, mpVideoStr->time_base );

if ( c->coded_frame->key_frame ) pkt.flags |= AV_PKT_FLAG_KEY;

pkt.stream_index = mpVideoStr->index;
pkt.data = outbuf;
pkt.size = out_size;

终于可以把包写出来了

av_write_frame( formatCtx, &pkt );

我知道这适用于 H264 视频编码,但我不能 100% 确定它适用于其他类型的视频,因为我在写这篇文章时只关心 H264。

【讨论】:

    【解决方案2】:

    我认为您需要为图片添加时间戳。
    FFMpeg 将尽可能快地进行编码/解码。您需要自己编写同步。通常在视频解码和播放中,您的帧会附加时间戳,或者至少您可以使用音频时钟和帧速率创建一些时间戳。
    但这在很大程度上取决于您希望如何同步以及如何实现它。
    也许FFMpeg的tutorial给你一些额外的提示

    【讨论】:

    • 我看过这个教程,但是这个是专用于解码功能的,我的解码器工作得很好,更重要的是,我只是捕获了没有音频的视频流以使其更容易,这就是我强烈思考的原因tat 问题出在解码器中,目前,我正在修改编码器中的 pts,特别是 formatcontext、packet...
    • 您可以一目了然地看到同步是如何完成的。在这种情况下,视频如何与音频同步。在你的情况下,我假设没有音频。所以你需要确定一个视频帧需要显示多长时间。例如,通过使用帧速率或每帧的持续时间。
    • 对不起,我的意思是问题出在“编码器”中,因为解码器工作正常,如果我通过播放器(如 vlc)播放录制的视频,它似乎也在加速,所以问题出在编码器。
    • 好的,我以为它只在您的应用程序中。但是,如果流通常是错误的,那么实际上是错误的时间戳。你可以看看贝克特的回答。您需要为要编码的每个 AVPicture 设置上下文的帧速率和一个 pts 值。这应该为播放提供足够的信息
    • 我认为它已经完成了,看看:我在我的 createfile 函数中使用了这个pCodecCtx->bit_rate = Bitrate; pCodecCtx->width = getWidth(); pCodecCtx->height = getHeight(); pCodecCtx->time_base.den = 24; pCodecCtx->time_base.num = 1; pCodecCtx->gop_size = Gop; pCodecCtx->pix_fmt = ffmpeg::PIX_FMT_YUV420P;,这个用于第一个数据包pts:if (pCodecCtx->coded_frame->pts != ((unsigned)0x8000000000000000LL)) pkt.pts= av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, pVideoStream->time_base);
    【解决方案3】:

    当您创建 ffmpeg 文件时,您必须指定帧速率 取决于您使用的是哪个库,但要寻找类似的东西

    pCodecContext->time_base.den = frames_per_second;
    pCodecContext->time_base.num = 1;
    

    否则,如果您从网络摄像头生成 10-15 fps,但文件中的默认值为 30 fps,它将快速播放。

    请参阅http://code.google.com/p/qtffmpegwrapper/ 了解 Qt ffmpeg 包装器

    【讨论】:

    • 感谢重播,我目前正在使用 Qt ffmpeg 包装器中的一些功能,例如编码、解码,并且我刚刚更改了 pCodecContext->time_base.den 即使我把 1 !但还是同样的问题
    • 要么在你的网络摄像头设置中设置它,要么从之前的运行中测量它。或者,如果您真的很挑剔,全速运行网络摄像头,但丢弃图像以减少它,以便每“n”毫秒只留下一个新帧。最好的选择是猜测它是 10 到 15 - directshow amcap 示例或网络摄像头查看器应用程序会告诉你
    猜你喜欢
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    • 2016-11-10
    • 1970-01-01
    相关资源
    最近更新 更多