【问题标题】:Tell libavcodec/ffmpeg to drop frame告诉 libavcodec/ffmpeg 丢帧
【发布时间】:2011-09-29 03:59:17
【问题描述】:

我正在构建一个用于创建视频的应用。 问题是,有时(嗯......大部分时间)帧获取过程不够快。

如果我迟到了,我目前正在做的是跳过当前帧采集,但是 FFMPEG/libavcodec 将我传递给它的每一帧都视为下一帧,所以如果我从 2 帧中删除 1 帧,一个 20 秒的视频只会持续 10 秒。我添加声音后会出现更多问题,因为声音处理速度要快得多......

我想告诉 FFMPEG:“最后一帧的持续时间应该是最初预期的两倍”,或者任何可以让我实时处理的东西。

我试图在某个点上堆叠帧,但这最终会耗尽我所有的内存(我还尝试在硬盘中“堆叠”我的帧,这很慢,正如我所料)

我想我将不得不手动处理 pts,但我所有的尝试都失败了,并且阅读其他一些使用 ffmpeg 的应用程序代码(例如 VLC)并没有太大帮助......所以任何建议将不胜感激!

提前非常感谢!

【问题讨论】:

    标签: c ffmpeg video-encoding libavcodec


    【解决方案1】:

    您的输出可能会被视为可变帧速率 (vfr),但您可以简单地在帧到达时使用挂钟时间生成时间戳,并在编码之前将其应用于您的 AVFrame。那么该帧将在播放时显示在正确的时间。

    有关如何执行此操作的示例(至少指定您自己的时间戳部分),请参阅 ffmpeg 发行版中的 doc/examples/muxing.c(我当前的 git pull 中的第 491 行):

    frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
    

    在这里,作者将视频编解码器的时基中的帧时间戳增加 1,重新调整为视频流的时基,但在您的情况下,您可以简单地重新调整自开始从任意时基捕获帧到输出视频以来的秒数流的时基(如上例所示)。例如,如果您的任意时基是 1/1000,并且您在开始捕获后 0.25 秒内收到一帧,那么请执行以下操作:

    AVRational my_timebase = {1, 1000};
    frame->pts = av_rescale_q(250, my_timebase, avstream->time_base);
    

    然后像往常一样对帧进行编码。

    【讨论】:

      【解决方案2】:

      许多(大多数?)视频格式不允许遗漏帧。相反,当您无法及时获得新视频帧时,请尝试重复使用旧视频帧。

      【讨论】:

      • 大多数容器实际上都支持省略框架。 MP4 仅存储每个帧的持续时间,不必对所有帧都相同。 mkv 存储演示时间戳。 IDK关于avi;也许不是,但无论如何,AVI 并不适合现代编解码器。 (没有那么多通用的视频容器,不包括像 ogm 这样的晦涩难懂的容器,或者像 nut 这样的真正晦涩难懂的容器。)
      【解决方案3】:

      只是一个想法..当处理滞后时,您是否尝试再次将同一帧传递给它(并丢弃当前帧)?也许它可以快速处理重复的帧。

      【讨论】:

      • 嗯,它改进了一点,但视频还是太快了......我想这来自我的调度算法(我不能称之为真正诚实的算法......)明天我会尝试改进它,如果这改进了一些东西,我会回复。无论如何感谢您的帮助(你和黄昏)!
      【解决方案4】:

      有这个 ffmpeg 命令行开关 -threads ... 用于多核处理,所以你应该能够用 API 做类似的事情(虽然我不知道怎么做)。这可能会解决您的问题。

      【讨论】:

        猜你喜欢
        • 2015-05-19
        • 2018-03-16
        • 2013-08-04
        • 2012-03-31
        • 2018-01-15
        • 1970-01-01
        • 2012-01-26
        • 1970-01-01
        • 2020-02-16
        相关资源
        最近更新 更多