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 等商品开发工具可以用于精细的性能分析和调优。

NVIDIA FFmpeg 转码技术分析的更多相关文章

  1. FFmpeg源码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  2. FFmpeg源码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  3. java运用FFMPEG视频转码技术

    基于windows系统安装FFMPEG转码技术 http://wenku.baidu.com/link?url=z4Tv3CUXxxzLpa5QPI-FmfFtrIQeiCYNq6Uhe6QCHkU- ...

  4. FFmpeg源码结构图 - 解码

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  5. FFmpeg资料来源简单分析:libswscale的sws_getContext()

    ===================================================== FFmpeg库函数的源代码的分析文章: [骨架] FFmpeg源码结构图 - 解码 FFmp ...

  6. FFmpeg源码结构图 - 编码

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  7. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  8. 最新版ffmpeg源码分析

    最新版ffmpeg源码分析一:框架 (ffmpeg v0.9) 框架 最新版的ffmpeg中发现了一个新的东西:avconv,而且ffmpeg.c与avconv.c一个模样,一研究才发现是libav下 ...

  9. FFmpeg的HEVC解码器源码简单分析:概述

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

随机推荐

  1. Linux系统应急响应

    目录 排查用户相关的信息 排查进程端口相关的信息 查找恶意程序并杀掉 斩草除根 判断入侵方式,修复漏洞 当我们被告知一台Linux服务器被黑客入侵,黑客利用该服务器进行挖矿,并且在该服务器上放置了木马 ...

  2. RHCE7 认证之学习笔记

    -------------------------------------------------------------------------------------------初始化:两台服务器 ...

  3. 深入浅出带你玩转sqlilabs(三)--GET,POST,COOKIE,万能密码注入

    常见提交方式下的注入漏洞 WEB应用在数据传递接受中,针对SQL注入安全漏洞,由于数据大小,格式等原因,脚本在接受传递时会有多种传递方式,传递方式的不同将影响到安全测试的不同 第一点:数据常见提交方式 ...

  4. (二)SQL语句

    语法规则 不区分大小写,但是建议关键字大写,表名.列名小写 SELECT * FROM user; 支持多行编写sql语言(在SQLyog中可以用F12来快速格式化语句) # 查询cno=20201/ ...

  5. intellij idea的Maven项目运行报程序包找不到的错误

    概括一句话:IDEA的Terminal命令行输入mvn idea:idea或者mvn idea:module , 即可解决 重做过开发环境后在intellij idea中载入java工程,通过mave ...

  6. 【转】Python调用C语言动态链接库

    转自:https://www.cnblogs.com/fariver/p/6573112.html 动态链接库在Windows中为.dll文件,在linux中为.so文件.以linux平台为例说明py ...

  7. 数据人必读!玩转数据可视化用这个就够了——高德LOCA API 2.0升级来袭!

    引言 "一图胜千言",大数据时代来临,数据与人们生活密切相关.复杂难懂且体量庞大的数据给人的感觉总是冷冰冰的,让人难以获取到重点信息,也找不出规律和特征,数据价值发挥不出来.空间数 ...

  8. 使用C#进行数据库增删改查ADO.NET(一)

    这节讲一下如何使用C#进行数据库的增删改查操作,本节以SQL Server数据库为例. .NET 平台,使用ADO.NET 作为与数据库服务器的桥梁,我们通过ADO.NET就可以使用C#语言操作数据库 ...

  9. Mybatis学习之自定义持久层框架(二) 自定义持久层框架设计思路

    前言 上一篇文章讲到了JDBC的基本用法及其问题所在,并提出了使用Mybatis的好处,那么今天这篇文章就来说一下该如何设计一个类似Mybatis这样的持久层框架(暂时只讲思路,具体的代码编写工作从下 ...

  10. 关于Annotation注解的理解

    在编Java程序的时候,我们经常会碰到annotation.比如:@Override 我们在子类继承父类的时候,会经常用到这个annotation.它告诉编译器这个方法是override父类的方法的. ...