一、一些指令
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 -C display
[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
width: 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/
目錄下面找到相關的庫檔案。
NVCUVID
是
CUDA
的元件,包含在最新的
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
進行圖象的拉伸處理和使用
x264
的
opencl
封裝。這個項目缺點在于文檔不是很豐富,研究起來有一定的難度。
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 is an API developed by NVIDIA which enables the use of NVIDIA GPU cards to perform H.264 and HEVC(就是H.265) encoding. FFmpeg supports NVENC through the h264_nvenc and hevc_nvenc encoders. In order to enable it in FFmpeg you need:
- A supported GPU
- Supported drivers
- ffmpeg configured without --disable-nvenc
Visit NVIDIA Video Codec SDK to 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 with ffmpeg -h encoder=h264_nvenc or ffmpeg -h encoder=hevc_nvenc.
Note: If you get the No NVENC capable devices found error make sure you're encoding to a supported pixel format. See encoder info as shown above.
CUDA/CUVID/NvDecode
CUVID, which is also called nvdec by Nvidia now, can be used for decoding on 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 for libnpp, 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_device option 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
- 作者:踏雪無痕
- 出處:http://www.cnblogs.com/chenpingzhao/
- 本文版權歸作者和部落格園共有,如需轉載,請聯系 pingzhao1990#163.com