【FFMPEG】关于硬解码和软解码

摘要:
一、一些命令1、显示所有可用的硬件加速器[root@tranCodeing~]#ffmpeg-hwaccelsffmpegversion4.1Copyright(c)2000-2018theFFmpegdevelopersbuiltwithgcc4.8.5(GCC)20150623(RedHat4.8.5-39)configuration:--prefix=/home/local/ffmpeg_s

一、一些命令

1、显示所有可用的硬件加速器

[root@tranCodeing ~]# ffmpeg -hwaccels
ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-39)
  configuration: --prefix=/home/local/ffmpeg_sources/ffmpeg_build --pkg-config-flags=--static --extra-cflags='-I /home/local/ffmpeg_sources/ffmpeg_build/include -I/usr/local/cuda/include' --extra-ldflags='-L /home/local/ffmpeg_sources/ffmpeg_build/lib -L/usr/local/cuda/lib64' --extra-libs=-lpthread --extra-libs=-lm --bindir=/root/bin --enable-gpl --enable-libfdk_aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree --enable-libfreetype --enable-cuda --enable-cuvid --enable-nvenc --enable-libnpp
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Hardware acceleration methods:
cuda
cuvid

2、watch -n 10 nvidia-smi

Every 10.0s: nvidia-smi                                                                                                                                              Tue Feb 25 00:11:20 2020

Tue Feb 25 00:11:20 2020
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.44       Driver Version: 440.44       CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce RTX 2080    On   | 00000000:01:00.0 Off |                  N/A |
|  0%   45C    P0    40W / 225W |      0MiB /  7979MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

3、lspci -vnn | grep VGA -A 12

[root@tranCodeing ~]# lspci -vnn | grep VGA -A 12 
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU104 [GeForce RTX 2080 Rev. A] [10de:1e87] (rev a1) (prog-if 00 [VGA controller])
        Subsystem: eVga.com. Corp. Device [3842:2183]
        Flags: bus master, fast devsel, latency 0, IRQ 153
        Memory at a3000000 (32-bit, non-prefetchable) [size=16M]
        Memory at 90000000 (64-bit, prefetchable) [size=256M]
        Memory at a0000000 (64-bit, prefetchable) [size=32M]
        I/O ports at 4000 [size=128]
        [virtual] Expansion ROM at a4000000 [disabled] [size=512K]
        Capabilities: [60] Power Management version 3
        Capabilities: [68] MSI: Enable+ Count=1/1 Maskable- 64bit+
        Capabilities: [78] Express Legacy Endpoint, MSI 00
        Capabilities: [100] Virtual Channel
        Capabilities: [250] Latency Tolerance Reporting

4、lshw-Cdisplay

[root@tranCodeing ~]# lshw -C display
  *-display                 
       description: VGA compatible controller
       product: TU104 [GeForce RTX 2080 Rev. A]
       vendor: NVIDIA Corporation
       physical id: 0
       bus info: pci@0000:01:00.0
       version: a1
        64 bits
       clock: 33MHz
       capabilities: pm msi pciexpress vga_controller bus_master cap_list rom
       configuration: driver=nvidia latency=0
       resources: irq:153 memory:a3000000-a3ffffff memory:90000000-9fffffff memory:a0000000-a1ffffff ioport:4000(size=128) memory:a4000000-a407ffff

5、nvidia-smi  

[root@tranCodeing ~]# nvidia-smi 
Tue Feb 25 00:13:32 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.44       Driver Version: 440.44       CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce RTX 2080    On   | 00000000:01:00.0 Off |                  N/A |
|  0%   45C    P0    40W / 225W |      0MiB /  7979MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

二、常识简介

1、软编码和硬编码如何区分

  • 软编码:使用CPU进行编码
  • 硬编码:使用非CPU进行编码,如显卡GPU、专用的DSP、FPGA、ASIC芯片等

2、软编码和硬编码比较

  • 软编码:实现直接、简单,参数调整方便,升级易,但CPU负载重,性能较硬编码低,低码率下质量通常比硬编码要好一点。

  • 硬编码:性能高,低码率下通常质量低于软编码器,但部分产品在GPU硬件平台移植了优秀的软编码算法(如X264)的,质量基本等同于软编码。

3、目前的主流GPU加速平台

INTEL、AMD、NVIDIA

4、目前主流的GPU平台开发框架

  • CUDA:NVIDIA的封闭编程框架,通过框架可以调用GPU计算资源

  • AMD APP:AMD为自己的GPU提出的一套通用并行编程框架,标准开放,通过在CPU、GPU同时支持OpenCL框架,进行计算力融合。

  • OpenCL:开放计算语言,为异构平台编写程序的该框架,异构平台可包含CPU、GPU以及其他计算处理器,目标是使相同的运算能支持不同平台硬件加速。

  • Inel QuickSync:集成于Intel显卡中的专用视频编解码模块。

5、N卡和A卡

A卡指的的ATI,一个显卡厂商

N指的是NVIDIA,另一个显卡厂商。

N卡的产品有GeForce Ti系列,GeForce FX系列等,A卡作品有镭X系列。N卡和A卡在技术上的不同之处在于,N卡注重3D性能和速度,A卡注重2D平面画质。

A卡和N卡的区别如下:

1、概念不同。A卡早期是采用ATI显卡芯片的显卡,目前ATI已经被AMD收购,A卡称之为AMD显卡,A卡作品有 镭、X系列。N卡是采用NVIDIA显卡芯片的显卡,N卡作品有GeForce(GTX)系列,GeForce FX(GT)系列等等。

2、优劣势不同。N卡的优势为GPU中每个流处理器都具有完整的ALU功能,在发出一条操作指令时每个流处理器都能充分工作。显卡频率可以达到近乎100%的状态。劣势为功耗较大。A卡的优势为浮点运算能力强大。劣势为软件优化度不够。

6、流程区别

硬解软编: read(ffmpeg) -》 decoder(NVIDIA) -》 | Queue -》 encoder(ffmpeg)
软解软编: read(ffmpeg)-》 decoder(ffmpeg) -》encoder(ffmpeg)

解码与编码之间维护一个队列,队列长度定为20(因为解码速度快于编码速度,数据被覆盖,丢帧)

7、并行计算

GPU 是用来处理图形任务的图形处理器,其中一个非常大的优势在于它的并行处理能力。面对单指令流多数据流(SIMD),并且数据处理的运算量远大于数据调度和传输的需要时,GPU 的并行处理效率要高于传统的 CPU 的处理。

为了充分的利用 GPU 的并行处理能力,大部分的显卡厂商都推出了自己的 GPU 开发 SDK,比如:

  • NVIDIA —— CUDA
  • Intel —— Intel® Media SDK
  • AMD —— AMD APP SDK(前身是 ATI Stream)

8、OpenCL

OpenCL(Open Computing Language,开放计算语言),是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。这种语言主要是为了异构平台的并行运行设计的。

从本质上来说,它和 CDUA 等等 SDK 上是不同的,它是一种语言,相当于是 JAVA 语言这个级别,而后者是一个开发包,相当于 JDK 这个级别。

OpenCL 目前的语言规范已经到了 2.1(Preview),支持最好的 AMD 的 SDK,最新版本已经支持了 OpenCL 2.0,其他两个只支持 OpenCL 1.2。

OpenCL 提供了一个统一的 API,这个 API 在上述的厂商的 SDK 中都有实现。所以安装 CUDA 会包含 OpenCL 组件,它是英伟达对于 OpenCL 语言的一种实现。

9、OpenCL API VS SDK

OpenCL API 最大的优势在于它的跨平台,可以在不同的架构上运行,所以理论上它比 SDK 更有竞争力。但是它最大的问题在于它的 API Level 比较基础,直接使用它进行视频的编解码处理难度比较大。此外 OpenCL API 的实现是依赖于底层的 GPU 架构的,不同的厂商提供了不同的实现,使用之前需要安装不同厂商提供的实现,从这个角度考虑 OpenCL 的跨平台并没有想象中那么完美。

SDK 的问题在于不同的厂商的 SDK 是不兼容的。但是它提供了比 OpenCL API 更加丰富的功能,比如 NVIDIA 直接提供了视频编解码相关的接口,使用起来会比 OpenCL API 更加的轻松。

三、NVIDIA硬件编解码方案

硬件编解码可以使用如下几种方案:

1、基于 OpenCL 的 API 自己写一个编解码器

这的难度非常大,首先你需要对于 OpenCL API 非常的熟悉,其次你需要对于编解码的知识了解的非常透彻。这两个问题的任何一个都有非常大的难度,以目前已有的技术来说成功的概念不是特别大。MainConcept 公司做了这件事情,它提供了基于 OpenCL 的 H264/AVC 编码器,但是这个编码器是商用的(此外它还提供了基于 CUDA 的编码器和基于 Intel QSV 的编解器,以及包装过前面几者的编码器)。

所以从技术可行性上来说这个是可行的,只是目前来说个人还不具备这个实力。

2、使用 SDK 中的编解码接口

英伟达关于视频的编解码提供了两个相关的 SDK

  • NVENC
  • NVCUVID

前者负责硬件编码,二后者负责硬件解码。

NVENC是一个单独的 SDK,集成在最新的显卡驱动上面,安装最新的驱动之后可以找到相关的库文件。在 Ubuntu 14.04 中,可以在/usr/lib/nvidia-352/目录下面找到相关的库文件。

NVCUVIDCUDA的组件,包含在最新的CUDA Toolkit中。不过在显卡的类库中可以找到libnvcuvid.so这个库文件。在之前版本的显卡驱动中其他还包含一个称之为NVCUVENC的硬件编码器和NVCUVID相对应,不过目前这个组件已经被NVENC替代了。

3、使用编码器对于 OpenCL 和 SDK 的封装

这种方式是个人认为最理想的方式,FFMPEG 目前存在一个编码器nvenc是对于英伟达的NVENC的封装,通过使用它可以和 FFMPEG 无缝的整合起来。此外它也包含对于Intel QSV的封装。AMD 的相关接口目前没有找到相关的资料。

不过 FFMPEG 只存在NVENC的接口,不存在NVCUVID的封装。如果需要实现相关的解码器可能需要自己实现 FFMPEG 接口。

libx264有对于 OpenCL 的封装,不过我在 windows 中尝试这个功能的时候并没有成功。

另外还存在一个开源的格式转换器HandBrake,它包含对于Intel QuickSync的封装,以及使用OpenCL进行图象的拉伸处理和使用x264opencl封装。这个项目缺点在于文档不是很丰富,研究起来有一定的难度。

4、NVIDIA硬件解码器分析

可以参考:https://www.cnblogs.com/lifan3a/articles/7463357.html

5、解码器的代码分析

SDK 中的 sample 文件夹下的 NvTranscoder 中包含了编码器和解码器的用法,编码器的内容不在这里分析,因为 FFMPEG 中已经包含了相关的代码,不需要其他的处理。

解码器在 SDK 中有一份封装,主要是 NvTranscoder 下的 VideoDecoder 类。目前这个类的具体用法还不是特别的清楚。分析将会从 main 函数开始。

6、私有驱动

nvenc本身是依赖于nvidia底层的私有驱动的,所以想要使用编码器首先需要安装nvidia的私有驱动

[root@tranCodeing ~]# lsmod | grep nvidia
nvidia_uvm            930831  0 
nvidia_drm             43690  0 
nvidia_modeset       1109452  1 nvidia_drm
nvidia              20364967  2 nvidia_modeset,nvidia_uvm
drm_kms_helper        186531  1 nvidia_drm
drm                   456166  3 drm_kms_helper,nvidia_drm
ipmi_msghandler        56728  2 ipmi_devintf,nvidia

7、 FFMPEG

要想在 FFMPEG 中使用nvenc编码器,你需要在编译选项中加入enable-nvenc选项(老版本,新版本是自动检测,显示提供disable-nvenc的选项)。

这个选项依赖于nvEncodeAPI.h头文件,这个头文件并没有包含在私有驱动中,你需要到NVIDIA VIDEO CODEC SDK中下载 SDK,解压后在Samples/common/inc目录下有这个头文件,把它拷贝到可以链接到的目录中去。

之后编译就可以顺利的通过,得到包含nvenc编码器的库。

8、使用 nvenc

NVENC

NVENC is an API developed by NVIDIA which enables the use of NVIDIA GPU cards to performH.264 and HEVC(就是H.265)encoding. FFmpeg supports NVENC through theh264_nvencandhevc_nvencencoders. In order to enable it in FFmpeg you need:

  • A supported GPU
  • Supported drivers
  • ffmpegconfigured without--disable-nvenc

Visit​NVIDIA Video Codec SDKto download the SDK and to read more about the supported GPUs and supported drivers.

Usage example:

ffmpeg -i input -c:v h264_nvenc -profile high444p -pixel_format yuv444p -preset default output.mp4

You can see available presets, other options, and encoder info withffmpeg -h encoder=h264_nvencorffmpeg -h encoder=hevc_nvenc.

Note:If you get theNo NVENC capable devices founderror make sure you're encoding to a supported pixel format. See encoder info as shown above.

CUDA/CUVID/NvDecode

CUVID, which is also callednvdecby Nvidia now, can be used fordecodingon Windows and Linux. In combination with nvenc it offers full hardware transcoding.

CUVID offers decoders for H264, HEVC, MJPEG, mpeg1/2/4, vp8/9, vc1. Codec support varies by hardware. The full set of codecs being available only on Pascal hardware, which adds VP9 and 10 bit support.

While decoding 10 bit video is supported, it is not possible to do full hardware transcoding currently (See the partial hardware example below).

Sample decode using CUVID, the cuvid decoder copies the frames to system memory in this case:

ffmpeg -c:v h264_cuvid -i input output.mkv

Full hardware transcode with CUVID and NVENC:

ffmpeg -hwaccel cuvid -c:v h264_cuvid -i input -c:v h264_nvenc -preset slow output.mkv 

Partial hardware transcode, with frames passed through system memory (This is necessary for transcoding 10bit content):

ffmpeg -c:v h264_cuvid -i input -c:v h264_nvenc -preset slow output.mkv

If ffmpeg was compiled with support forlibnpp, it can be used to insert a GPU based scaler into the chain:

ffmpeg -hwaccel_device 0 -hwaccel cuvid -c:v h264_cuvid -i input -vf scale_npp=-1:720 -c:v h264_nvenc -preset slow output.mkv

The-hwaccel_deviceoption can be used to specify the GPU to be used by the cuvid hwaccel in ffmpeg.

HEVC 是 H264 的后继版本,又称 H265,高效视频编码(High Efficiency Video Coding)

ffmpeg -encoders | grep nv

[root@tranCodeing ~]# ffmpeg -encoders | grep nv  
ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-39)
  configuration: --prefix=/home/local/ffmpeg_sources/ffmpeg_build --pkg-config-flags=--static --extra-cflags='-I /home/local/ffmpeg_sources/ffmpeg_build/include -I/usr/local/cuda/include' --extra-ldflags='-L /home/local/ffmpeg_sources/ffmpeg_build/lib -L/usr/local/cuda/lib64' --extra-libs=-lpthread --extra-libs=-lm --bindir=/root/bin --enable-gpl --enable-libfdk_aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree --enable-libfreetype --enable-cuda --enable-cuvid --enable-nvenc --enable-libnpp
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
 V..... h264_nvenc           NVIDIA NVENC H.264 encoder (codec h264)
 V..... nvenc                NVIDIA NVENC H.264 encoder (codec h264)
 V..... nvenc_h264           NVIDIA NVENC H.264 encoder (codec h264)
 V..... nvenc_hevc           NVIDIA NVENC hevc encoder (codec hevc)
 V..... hevc_nvenc           NVIDIA NVENC hevc encoder (codec hevc)

h264_nvenc ==nvenc ==nvenc_h264 nvenc_hevc ==hevc_nvenc

参考文章:

https://trac.ffmpeg.org/wiki/HWAccelIntro

https://developer.nvidia.com/ffmpeg

免责声明:文章转载自《【FFMPEG】关于硬解码和软解码》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇PS如何把印章颜色加重更加清晰?如何查看Oracle,MySQL,SQLServer三大数据库的事务隔离级别下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[机器学习] 深度学习之caffe1——软件配置与测试

caffe的编译配置真的是很让人头疼啊,不知道试过多少次了~~~ 重装系统了七八次,搞得linux的一些常用命令倒是很熟悉了~~~ 我有洁癖~~~某一个点上出了错,我一定要把它搞好了,再重新来一次,我怕会因为某一点的小错误会影响到其它重要的地方。。。(有同感的默默在心里举个爪~~~^_^~~~) 又折腾了好几次,参考了很多的博客,总结出一整套的安装配置流...

Chromium base 基础库概览

Chromium 基础库概览 Chromium 基础库包括的内容十分繁杂,我把其中的主要部分大致分为以下几类: 1. 容器类型Chromium 的代码主要使用 STL 容器类型,比如 std::vector,std::list,另外 GCC 和 MSVC 提供的 STL 扩展容器类型 hash_map 和 hash_set 也在 Chromium 中使用...

OpenCL编程基本流程及完整示例

1. 选择OpenCL平台并创建一个上下文平台(Platform)是指主机和OpenCL管理框架下的若干个设备构成的可以运行OpenCL程序的完整硬件系统,这个是跑OpenCL程序的基础,所以第一步要选择一个可用的OpenCL品台。一台机器上可以有不止一个这样的品台,一个平台也可以有不止一个GPU。 主要涉及的函数:clGetPlatformIDs(),用...

Dotnet中Span, Memory和ReadOnlySequence之浅见

过年啦,写个短点的。同时,提前给大家拜个年。   总有小伙伴们跑过来讨论关于Span和Memory的使用,眼瞅是最近关于Span的文章有点多,看飞了。 今天写这个,就是往回拉一拉。 写之前,先声明一下。这些内容是我自己使用的一些经验,并不代表这些类的全部内容就是这些,只是说,我是这么用的,而且用得很好。 1. Span Span在我的概念中,就是一个快速的...

C#使用FFMPEG推流,并且获取流保存在本地,随时取媒体进行播放!

最近开发了基于C#的推流器一直不大理想,终于在不懈努力之后研究了一点成果,这边做个笔记;本文着重在于讲解下如何使用ffmpeg进行简单的推流,看似简单几行代码没有官方的文档很吃力。并获取流的源代码:如下→ #region RTMP推流(**已成功推流至服务器**)Network.Create() ....

windows编译ffmpeg出错记录

./configure --toolchain=msvc --enable-cross-compile --arch=x86_64 --extra-ldflags="-static-libgcc" --extra-cflags=-I/usr/include --extra-ldflags=-L/usr/libcl.exe is unable to crea...