【问题标题】:Extremely slow ffmpeg/sws_scale() - only on heavy duty非常慢的 ffmpeg/sws_scale() - 仅在重载时
【发布时间】:2018-11-11 15:20:09
【问题描述】:

我正在使用 ffmpeg 编写视频播放器(仅限 Windows,Visual Studio 2015,64 位编译)。 对于普通视频(最高 4K @ 30FPS),它的效果非常好。但是对于我的最大目标 - 4K @ 60FPS,它失败了。解码仍然足够快,但是在 YUV/BGRA 转换方面它根本不够快,即使它是在 16 个线程中完成的(在 16/32 核机器上每帧一个线程)。

因此,作为第一个对策,我跳过了一些帧的转换并以这种方式获得了约 40 的稳定帧速率。在 Concurrency Visualizer 中对比两个版本,我发现一个奇怪的问题,我不知道原因。

.

这是跳帧版本的图像: 您会看到转换非常快(平均约为 35 毫秒) 因此,由于使用了多线程,它对于 60FPS 也应该足够快,但事实并非如此!

.

非跳帧版本的图片说明了原因: 单帧的转换速度比以前慢了十倍(平均大约 350 毫秒)。现在,由于 turbo 降低,许多内核上的繁重工作负载当然会导致每个内核的轻微减速——比如说 10% 或 20%。但绝不会出现约 1000% 的极端减速。

.

有趣的细节是,非跳帧版本的堆栈跟踪显示了一些我不太了解的系统活动 - 从ntoskrnl.exe!KiPageFault+0x373 开始。没有异常、其他错误消息等 - 它变得非常慢。

编辑:一位同事刚刚告诉我,乍一看,这看起来像是分页内存的内存问题 - 但我的内存利用率很低(低于 1GB,并且超过 20GB 可用)

谁能告诉我这是什么原因造成的?

【问题讨论】:

  • 它正在调用 yuv2rgb_c,一个 C 函数。这可能是放缓的原因。除了帧率,您的 4k30 和 4k60 ffmpeg 调用之间还有其他区别吗?可能一个是 10 位/组件,另一个是 8 位/组件,或者类似的东西?或者一个缩放到 RGB 而另一个不缩放?
  • 不,这都是同一部电影...两次都将 AV_PIX_FMT_YUV420P 作为源和 bgra 作为目标,没有缩放,只是转换。

标签: c++ windows visual-studio ffmpeg


【解决方案1】:

这可能太旧了,无法使用,但仅供记录:

可能发生的情况是您在多个线程中一遍又一遍地分配 4k 帧。 windows 分配器真的不喜欢这种访问模式。

malloc 本身不会显示在分析器中,因为只有在实际访问内存时,操作系统才会获取页面。这显示为ntoskrnl.exe!KiPageFault,并归因于首先访问新内存的函数。

解决方案包括:

  • 使用不同的分配器(例如 tbb_malloc、mimalloc 等)
  • 使用您自己的每个线程或每个进程的帧池。 ffmpeg 在内部做了类似的事情,也许你可以使用that

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-15
    • 2016-08-22
    • 2019-02-27
    • 2015-02-03
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 2017-09-22
    相关资源
    最近更新 更多