• NVIDIA FFmpeg 转码技术分析


    NVIDIA FFmpeg 转码技术分析

    所有从 Kepler 一代开始的 NVIDIA GPUs 都支持完全加速的硬件视频编码,而从费米一代开始的所有 GPUs 都支持完全加速的硬件视频解码。截至 2019 年 7 月,Kepler、Maxwell、Pascal、Volta 和 Turing 一代 GPUs 支持硬件编码,Fermi、Kepler、Maxwell、Pascal、Volta 和 Turing 一代 GPUs 支持硬件解码。

    高质量视频应用的处理需求对广播和电信网络提出了限制。消费者行为已经发生了变化,这在 OTT 视频订阅和实时流媒体迅速普及的趋势中表现得很明显。现在所有的社交媒体应用程序都在各自的平台上加入了这一功能。随着消费者从观看点播视频转向观看直播视频,直播将推动手机和 Wi-Fi 的整体视频数据流量增长。

    分发给观众的视频内容通常被转换成几个自适应比特率( ABR )配置文件以进行传输。生产中的内容可能以大量编解码器格式之一到达,这些格式需要转换为另一种格式以供分发或存档。

    这使得视频转码成为高效视频管道中的一个关键部分——无论是 1 : N 还是 M : N 配置文件。理想的转码解决方案需要在成本(美元/流)和能效(瓦特/流)方面具有成本效益,同时为数据中心提供具有最大吞吐量的高质量内容。视频提供商希望降低向更多屏幕提供更多高质量内容的成本。

    在各个方面生成的大量视频内容需要对视频编码、解码和转码进行健壮的硬件加速。让我们看看 NVIDIA GPUs 是如何整合专用视频处理硬件的,以及如何利用它。

    NVIDIA 编解码硬件

    NVIDIA GPUs 上配备了片上硬件编码器和解码器单元,通常称为 NVENC 和 NVDEC。与 CUDA 核心分开, NVENC / NVDEC 运行编码或解码工作负载,不会减慢同时运行的图形或 CUDA 工作负载的执行。

    NVENC 和 NVDEC 支持许多重要的编解码编解码器。 NVIDIA 。最新的支持矩阵可以在 GPU 上找到。

    图 1 : GPU 硬件功能

    基于 FFmpeg 的硬件加速转码

    在对视频数据进行转码时,通常使用 FFmpeg 库 。硬件加速极大地提高了工作流的性能。图 2 显示了 FFmpeg 转换过程的不同元素。

    图片 2 :使用 NVIDIA 硬件加速的 FFmpeg 流水线转码

    FFmpeg 通过 h264_cuvid 、 hevc_cuvid 和 h264_nvenc 、 hevc_nvenc 模块支持硬件加速解码和编码。从源代码构建时激活对硬件加速的支持需要一些额外的步骤:

    • Clone FFmpeg git 存储库 https://git.ffmpeg.org/ffmpeg.git
    • 从 NVIDIA 网站 下载并安装兼容的驱动程序
    • 下载并安装 CUDA 工具箱
    • Clone nv-codec-headers 存储库 并仅使用此存储库作为头进行安装: make install
    • 使用以下命令配置 FFmpeg (使用正确的 CUDA 库路径):

    ./configure --enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree --enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64

    • 使用多个进程进行构建,以提高构建速度并抑制过度输出: make -j -s

    使用 FFmpeg 进行软件 1 : 1 转码非常简单:

    ffmpeg -i input.mp4 -c:a copy -c:v h264 -b:v 5M output.mp4

    但这将是缓慢的,它只使用基于 CPU 的软件编码器和解码器。使用硬件编码器 NVENC 和解码器 NVDEC 需要添加更多参数来告诉 ffmpeg 使用哪个编码器和解码器。最大化转码速度还意味着确保解码后的图像保存在 GPU 存储器中,以便编码器能够有效地访问它。

    ffmpeg -vsync 0 -hwaccel cuvid -c:v h264_cuvid -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4

    如果没有 -hwaccel-cuvid 选项,解码后的原始帧将通过 PCIe 总线复制回系统内存,如图 3 所示。稍后,相同的图像将通过 PCIe 复制回 GPU 内存,以便在 GPU 上进行编码。这两个额外的传输由于传输时间而造成延迟,并将增加 PCIe 带宽占用。

     图&& 3 :没有 hAccel 的内存流(& M )

    添加 -hwaccel-cuvid 选项意味着原始解码帧将不会被复制,转码将更快、使用更少的系统资源,如图 4 所示。

     

     hwaccel 的内存流

    给定 PCIe 带宽限制,复制未压缩的图像数据会使 PCIe 总线迅速饱和。防止系统和 GPU 内存之间不必要的复制,使用 -hwaccel-cuvid 的吞吐量比不使用 -hwccel-cuvid 的未优化调用高出 2 倍。

    处理筛选器

    代码转换通常不仅涉及到更改输入流的格式或比特率,还包括调整其大小。有两个选项可用于调整 GPU 上的大小:使用 npp_scale 过滤器或 nvcuvid resize 选项。当从一个输入到一个具有不同分辨率( 1 : 1 转码)的输出流转码时,可以使用 nvcuvid resize 选项。请参见下一行的示例。

    ffmpeg -vsync 0 –hwaccel cuvid -c:v h264_cuvid –resize 1280x720 -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4

    如果需要多个输出分辨率( 1 : N 转码),则 scale_npp 滤波器可以调整 GPU 上解码帧的大小。通过这种方式,可以生成具有多个不同分辨率的多个输出流,但对所有流只使用一个调整大小的步骤。关于 1 : 2 转码的示例,请参见下一行。

    ffmpeg -vsync 0 –hwaccel cuvid -c:v h264_cuvid -i input.mp4  -c:a copy –vf scale_npp=1280:720 -c:v h264_nvenc -b:v 5M output_720.mp4  -c:a copy -vf scale_npp=640:320 -c:v h264_nvenc -b:v 3M output_360.mp4

    使用 -vf "scale_npp=1280:720" 将设置 scale_npp 作为解码图像的过滤器。

    插值算法可以作为附加参数为 scale_npp 定义。默认情况下使用三次插值,但其它算法 MIG HT 会根据比例因子和图像提供更好的结果。建议在缩小尺度时使用超级采样算法以获得最佳质量。示例如下:

    ffmpeg -vsync 0 –hwaccel cuvid -c:v h264_cuvid -i input.mp4 -c:a copy –vf scale_npp=1280:720:interp_algo=super -c:v h264_nvenc -b:v 5M output_720.mp4

    混合 CPU 和 GPU 处理

    有时 MIG 需要混合使用 CPU 和 hwupload_cuda 处理。例如,可能需要在 CPU 上解码,因为 -hwaccel cuvid 解码器不支持该格式,或者 GPU 上没有滤波器。在这种情况下,不能使用 GPU 标志。相反,需要使用 GPU 过滤器将数据从系统上传到 GPU 内存。下面的示例中,由于未设置 -hwaccel cuvid ,在 GPU 上解码 H . 264 流并将其下载到系统内存中。进入滤波器应用于系统存储器中,并使用 hwupload_cuda 滤波器将处理后的图像上传到 GPU 存储器。最后,使用 scale_npp 缩放图像并在 GPU 上编码。

    ffmpeg -vsync 0 -c:v h264_cuvid -i input.264 -vf "fade,hwupload_cuda,scale_npp=1280:720" -c:v h264_nvenc output.264

    Multi-GPU

    当在一个系统中使用多个 GPUs 时,编码和解码工作必须显式地分配给 GPU。 GPUs 由其索引号标识;默认情况下,所有工作都在索引为 0 的 GPU 上执行。使用以下命令获取系统中所有 NVIDIA GPUs 及其相应的 ID 号的列表:

    ffmpeg -vsync 0 -i input.mp4 -c:v h264_nvenc -gpu list -f null –

    一旦理解了索引,就可以使用 -hwaccel_device 索引标志来设置解码和编码的活动 GPU 。在下面的例子中,工作将在索引为 1 的 GPU 上执行。

    ffmpeg -vsync 0 -hwaccel cuvid -hwaccel_device 1 -c:v h264_cuvid -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4

    优化

    为了获得最佳的吞吐量,所有的编码器和解码器单元都应该被尽可能地利用。 nvidia-smi 可用于生成有关 NVENC 、 NVDEC 和一般 GPU 利用率的实时信息。

    nvidia-smi dmon nvidia-smi -q -d UTILIZATION

    根据这些结果可以采取多种措施。如果编码器利用率低, MIG 可以引入另一个转码管道,该管道使用 CPU 解码和 NVENC 编码来为硬件编码器生成额外的工作负载。

    使用 CPU 筛选器时, PCIe 带宽 MIG ht 成为瓶颈。如果可能,筛选器应在 GPU 上运行。 FFmpeg 中有几个 CUDA 过滤器,可以用作模板来实现高性能 CUDA 过滤器。

    通过使用 GPU SDK 的 NVIDIA 可视化分析器分析 ffmpeg 应用程序,可以始终跟踪主机和设备之间的 GPU 利用率和内存传输。只需启动“ Run application to generateCPU and GPU timeline ”,然后选择带有相关 CLI 选项的 ffmpeg 应用程序。图 5 说明了应用程序

     图 5 :绿色块显示 CUDA 内核完成的颜色空间转换,而黄色块显示主机和设备之间的内存传输。使用 visual profiler ,用户可以轻松地跟踪在 GPU 上执行的操作,例如 CUDA 加速的过滤器和数据传输,以确保不会执行过多的内存拷贝。

    通过使用 --disable-stripping CLI 选项编译 ffmpeg 来收集 CPU – 端性能统计信息,以启用性能分析。

    这可以防止编译器剥离函数名,以便像 Gprof 或 visual studio profiler 这样的商品探查器可以收集性能统计信息。 CPU 在硬件加速开启的情况下,负载水平应较低,并且大部分时间应花费在视频代码 SDK API 调用中,这些调用标记为“外部代码”,因为函数名从驱动程序库中被删除。图 6 显示了一个示例屏幕截图。

     图 6 : visualstudio 的 ffmpeg 性能评测

     推荐

    有关如何使用 FFmpeg 的更多示例以及可用的高级质量设置,请查看“ 使用 FFmpeg 和 NVIDIA GPU 硬件加速 “向导。

    结论

    FFmpeg 是一个强大而灵活的开源视频处理库,具有硬件加速的解码和编码后端。允许快速的视频处理和完整的 NVIDIA GPU 硬件支持,只需几分钟。 Gprof 、 visualprofiler 和 microsoftvisualstudio 等商品开发工具可以用于精细的性能分析和调优。

    人工智能芯片与自动驾驶
  • 相关阅读:
    valgrind的使用
    php开启gzip压缩
    scrapy
    今天几个bug的排查过程
    awk使用多个分割符
    有用的url
    图片延迟加载
    用中间表提高互联网程序的开发效率
    百度技术沙龙
    vs2005/.NET2.0 控件演示之 文件上传 《FileUpload》
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/14147675.html
Copyright © 2020-2023  润新知