【FFMPEG】關於硬解碼和軟解碼


一、一些命令

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM