【问题标题】:FFMPEG's sws_scale for converting RGB to YUV420 image is extremely slowFFMPEG 用于将 RGB 转换为 YUV420 图像的 sws_scale 非常慢
【发布时间】:2020-11-07 05:23:39
【问题描述】:

我正在创建一个使用 FFMPEG 库调用来记录屏幕活动的基本应用程序。 我的程序流程如下 - 从帧缓冲区获取输入数据(RGB 格式) --> 转换为 YUV420 格式并缩放到所需的分辨率 -> 对帧进行编码并发送到 Muxer 以进行 MPEG2 转换。

我的程序的输入数据是 RGB 格式的原始帧缓冲区数据。我正在使用 FFMPEG 的 sws_scale api 将 RGB 转换为 YUV420 图像进行编码。 下面是转换像素格式的代码-

static int get_frame_buffer_data(AVFrame *pict, int frame_index, int width,
                      int height, enum AVPixelFormat pix_fmt, char *rawFrame)
 {
     struct SwsContext *sws_ctx = NULL;
     int ret = 0;
     rfbLog("[%s:%d]before conv_frame alloc:::pix_fmt = %d width = %d height = %d\n",__func__,__LINE__,pix_fmt,width,height);
     //picture->data[0] = (uint8_t*)&frameBuffer[0];
    picture->data[0] = (uint8_t*)&rawFrame[0];
     sws_ctx = sws_getCachedContext(sws_ctx,picture->width, picture->height, picture->format,width, height, pix_fmt,SWS_BICUBIC, NU       LL, NULL, NULL);
     if (!sws_ctx)
     {
         rfbLog("[%s:%d]Cannot initialize the conversion context\n",__func__,__LINE__);
         av_frame_free(&picture);
         sws_freeContext(sws_ctx);
         return -1;
     }
     rfbLog("[%s:%d]before sws_scale::: picture->linesize[0]=%d picture->height=%d pict->linesize = %d\n",__func__,__LINE__,picture       ->linesize[0],picture->height,pict->linesize[0]);
     ret = sws_scale(sws_ctx, (const uint8_t * const *)picture->data, picture->linesize, 0, picture->height, pict->data, pict->line       size);
     rfbLog("[%s:%d]after sws_scale::: picture->linesize[0]=%d picture->height=%d pict->linesize = %d returned height = %d\n",__fun       c__,__LINE__, picture->linesize[0],picture->height,pict->linesize[0], ret);
     if (ret < 0)
     {
         rfbLog("[%s:%d]could not convert to yuv420\n",__func__,__LINE__);
         sws_freeContext(sws_ctx);
         av_frame_free(&picture);
         return -1;
     }
     sws_freeContext(sws_ctx);
     return 0;
 }

我注意到添加此代码会使应用程序变得非常慢。分析数据为我提供了 sws_scale 将数据转换为 YUV420 花费大量时间的信息。它大约需要 200 毫秒,这使得 CPU 时间利用率非常高,并且有时会导致我的应用程序无响应。

我们能否对此进行优化或使用任何替代解决方案进行转换?我们如何才能实现这一目标?

【问题讨论】:

  • 我也遇到了同样的问题。颜色格式转换是一个比预期更严重的瓶颈。

标签: ffmpeg


【解决方案1】:

软件中的“优化”意味着用更少的指令达到相同的结果。您调用一个函数sws_scale 因此,除非您要修改 ffmpeg 源代码,否则您可以做的唯一“优化”是在编译时。编译了什么 ffmpeg 设置了什么选项?尝试使用-O3 重新编译。

其他选项:

切换到 zimg,它会快一点,但不会太多,因为颜色转换是一个复杂的过程。

使用速度更快的计算机。 200 毫秒非常慢,除非您要缩放非常大的图像,否则我怀疑这在性能不足的 CPU 上是惊人的。

使用更多线程。假设CPU有多个核心(或者机器有多个CPU)你可以运行sws_scale的多个实例每帧仍然是200ms,但是如果你可以同时做更多,它会带来平均下来。

【讨论】:

  • 感谢@szatmary 的回答。我更改了优化级别 O3 并构建。它没有提高性能。我想尝试 zimg 代替 sws_scale() 但不知道如何集成 zimg 并调用特定的 api 来完成缩放和将像素格式从 RGB 转换为 YUV420 的工作。我试图找到如何使用 zimg 并且无法获取 api 详细信息过滤器。您是否可以分享一些见解,我可以参考上述内容的任何文档或链接。那真的对我有很大帮助。谢谢
【解决方案2】:

我不认为问题出在 sws_scale 上,而且我不相信您可以真正优化它,只要转换发生在 CPU 上。

如果您真的想要良好的性能,您应该寻找后处理硬件 (GPU) 加速和像素着色器(基于您使用的操作系统,例如 Windows 的 DirectX)。

【讨论】:

    猜你喜欢
    • 2021-11-25
    • 2020-12-18
    • 2022-12-22
    • 1970-01-01
    • 2018-11-11
    • 2019-11-12
    • 2017-09-22
    • 2015-10-15
    • 2014-04-04
    相关资源
    最近更新 更多