• H265视频硬解


    硬解,使用非CPU进行编码,如显卡GPU、专用的DSP、FPGA、ASIC芯片等。目前的主流GPU加速平台:INTEL、AMD、NVIDIA。

    一、软编码和硬编码比较

    软编码:实现直接、简单,参数调整方便,升级易,但CPU负载重,性能较硬编码低,低码率下质量通常比硬编码要好一点。
    硬编码:性能高,低码率下通常质量低于软编码器,但部分产品在GPU硬件平台移植了优秀的软编码算法(如X264)的,质量基本等同于软编码。

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

    CUVID:NVIDIA的封闭编程框架,通过框架可以调用GPU计算资源,N卡专用。
    AMD APP:AMD为自己的GPU提出的一套通用并行编程框架,标准开放,通过在CPU、GPU同时支持OpenCL框架,进行计算力融合。
    OpenCL:开放计算语言,为异构平台编写程序的该框架,异构平台可包含CPU、GPU以及其他计算处理器,目标是使相同的运算能支持不同平台硬件加速。
    Inel QuickSync:集成于Intel显卡中的专用视频编解码模块,核显专用。
    CUDA只能够在NVIDIA的GPU硬件上运行。但是,OpenCL的目标是面向任何一种并行处理器,OpenCL是第一种真正的开放自由版权编程标准,适用于异构系统上的通用计算。而异构平台可由CPU、GPU、DSP、FPGA或其他类型的处理器搭建。
    DXVA:DXVA是DirectX Video Acceleration的简称,中文译为视频硬件加速。DXVA是微软公司专门定制的视频加速规范,它共有两个版本,分别是DXVA 1.0和DXVA 2.0,几乎所有的显卡都具备硬件加速能力。

    三、流程区别

    硬解软编: read(ffmpeg) -》 decoder(NVIDIA) -》 | Queue -》 encoder(ffmpeg)
    软解软编:  read(ffmpeg) -》 decoder(ffmpeg) -》encoder(ffmpeg)
    解码与编码之间维护一个队列,队列长度定为20(因为解码速度快于编码速度,数据被覆盖,丢帧)

    四、NVIDIA CUVID,Intel QuickSync和DXVA2,其中DXVA2又分为DXVA2 (copy-back)和DXVA2 (native),那么这几种解码方式有什么区别?

    NVIDIA CUVID是NVIDIA专用硬体解码介面,可以开启硬体去交错处理。
    Intel QuickSync:Intel內显专用硬体解码介面,CPU使用率比其余硬解模式稍高5~10%左右,可以开启硬体去交错处理。
    DXVA2 (copy-back):为微软开发的硬体加速介面,AMD,NVIDIA,Intel显示卡均可使用,会將解码完成的资讯回传给记忆体,由于多个回传动作,故效能会比native略差,不过优势为可以在解码器与渲染器中间添加滤镜。
    DXVA2 (native):为微软开发的硬体加速介面,同样AMD,NVIDIA,Intel显示卡均可使用,会將解码完成的资讯將不会传给记忆体,直接渲染,故效能比copy-back佳,缺点为限制较多。
    所以解码方式推荐:DXVA2 (native) > DXVA2 (copy-back) > NVIDIA CUVID 或 Intel QuickSync。

    五、NVIDIA硬件编解码方案

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

    英伟达关于视频的编解码提供了两个相关的 SDK
    NVENC --负责硬件编码
    NVCUVID --负责硬件解码
    NVENC是一个单独的 SDK,集成在最新的显卡驱动上面,安装最新的驱动之后可以找到相关的库文件。在 Ubuntu 14.04 中,可以在/usr/lib/nvidia-352/目录下面找到相关的库文件。
    NVCUVID是CUDA的组件,包含在最新的CUDA Toolkit中。不过在显卡的类库中可以找到libnvcuvid.so这个库文件。在之前版本的显卡驱动中其他还包含一个称之为NVCUVENC的硬件编码器和NVCUVID相对应,不过目前这个组件已经被NVENC替代了。

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

    这种方式是个人认为最理想的方式,FFMPEG 目前存在一个编码器nvenc是对于英伟达的NVENC的封装,通过使用它可以和 FFMPEG 无缝的整合起来。此外它也包含对于Intel QSV的封装。AMD 的相关接口目前没有找到相关的资料。
    不过 FFMPEG 只存在NVENC的接口,不存在NVCUVID的封装。如果需要实现相关的解码器可能需要自己实现 FFMPEG 接口。
    libx264有对于 OpenCL 的封装,不过我在 windows 中尝试这个功能的时候并没有成功。
    另外还存在一个开源的格式转换器HandBrake,它包含对于Intel QuickSync的封装,以及使用OpenCL进行图象的拉伸处理和使用x264的opencl封装。这个项目缺点在于文档不是很丰富,研究起来有一定的难度。

    要想在 FFMPEG 中使用nvenc编码器,你需要在编译选项中加入enable-nvenc选项(老版本,新版本是自动检测,显示提供disable-nvenc的选项)。
    这个选项依赖于nvEncodeAPI.h头文件,这个头文件并没有包含在私有驱动中,你需要到NVIDIA VIDEO CODEC SDK中下载 SDK,解压后在Samples/common/inc目录下有这个头文件,把它拷贝到可以链接到的目录中去。之后编译就可以顺利的通过,得到包含nvenc编码器的库。

    六、ffmpeg硬解码绘制视频,cpu依然占用高。

    cpu占用高主要是因为av_hwframe_transfer_data(sw_frame, frame, 0)占用了cpu,不要用这个函数,应该用d3d+dxva2 或者cuda+opengl硬渲染。
    OpenCL主要用于通用的并行计算,它基于预定义的数据结构和代码,可以让GPU处理各种通用的计算任务,例如视频处理、金融建模、科学计算和影像处理等,充分利用现代GPU的并行可扩展性。OpenCL可以在多个硬件平台上运行,包括CPU、GPU和FPGA,并且与OpenGL、Direct3D和其他API无关,因此可以与不同的图形API进行交互。
    而OpenGL专注于计算机图形处理和渲染,它提供了一个强大的渲染管道,具有着广泛的支持和广泛的用途。在游戏和虚拟现实应用程序中,OpenGL被用作实时图形渲染的标准API。但是,OpenGL无法执行通用的计算任务,这要求我们使用其他API,例如OpenCL或CUDA。

    七、常用命令

    1、如何用ffmpeg命令列举支持的硬件解码器:

    ffmpeg -hwaccels


    2、ffmpeg硬解命令:

    1. ffmpeg -hwaccel cuvid -hwaccel_device 0 -c:v hevc_cuvid -y -i d:\input.mp4 -c:v h264_nvenc d:\output.mp4
    2. 或者
    3. ffmpeg -hwaccel cuda -hwaccel_device 0 -c:v hevc_cuvid -y -i d:\input.mp4 -c:v h264_nvenc d:\output.mp4


    ffmpeg 转码过程中输出的 frame ,fps,q,size, bitrate ,speed 的意义。
    frame表示视频当前第几帧;fps表示一秒编码了多少个视频帧;q表示编码质量;size表示写入文件的数据大小;bitrate表示比特率(单位是 kbits/s  1000位/秒);time表示当前处理文件位置时长;speed表示编码速度(多少秒视频帧/多少秒ffmpeg处理时间)。
    根据speed可以计算出ffmpeg耗时,一个视频文件ffmpeg处理完成时间为:视频时长秒/speed。

    1. ffmpeg version 4.4-full_build-www.gyan.dev Copyright (c) 2000-2021 the FFmpeg developers
    2.   built with gcc 10.2.0 (Rev6, Built by MSYS2 project)
    3.   configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libdav1d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libaom --enable-libopenjpeg --enable-libvpx --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-d3d11va --enable-dxva2 --enable-libmfx --enable-libglslang --enable-vulkan --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
    4.   libavutil      56. 70.100 / 56. 70.100
    5.   libavcodec     58.134.100 / 58.134.100
    6.   libavformat    58. 76.100 / 58. 76.100
    7.   libavdevice    58. 13.100 / 58. 13.100
    8.   libavfilter     7.110.100 /  7.110.100
    9.   libswscale      5.  9.100 /  5.  9.100
    10.   libswresample   3.  9.100 /  3.  9.100
    11.   libpostproc    55.  9.100 / 55.  9.100
    12. Input #0, mpeg, from 'd:\input.mp4':
    13.   Duration: 03:37:39.62, start: 37915.032111, bitrate: 354 kb/s
    14.   Stream #0:0[0x1e0]: Video: hevc (Main), yuvj420p(pc, bt709), 960x576, 50 fps, 25 tbr, 90k tbn, 50 tbc
    15.   Stream #0:1[0x1c0]: Audio: pcm_mulaw, 8000 Hz, mono, s16, 64 kb/s
    16. Stream mapping:
    17.   Stream #0:0 -> #0:0 (hevc (hevc_cuvid) -> h264 (h264_nvenc))
    18. Press [q] to stop, [?] for help
    19. Output #0, mp4, to 'd:\ch01_202203302130002-hw3.mp4':
    20.   Metadata:
    21.     encoder         : Lavf58.76.100
    22.   Stream #0:0: Video: h264 (Main) (avc1 / 0x31637661), nv12(pc, bt709, progressive), 960x576 [SAR 1:1 DAR 5:3], q=2-31, 4000 kb/s, 25 fps, 12800 tbn
    23.     Metadata:
    24.       encoder         : Lavc58.134.100 h264_nvenc
    25.     Side data:
    26.       cpb: bitrate max/min/avg: 0/0/4000000 buffer size: 8000000 vbv_delay: N/A
    27. frame=200781 fps=728 q=9.0 size= 3945472kB time=02:13:51.12 bitrate=4024.5kbits/s dup=0 drop=5 speed=29.1x

    3、显示英伟达显卡nvidia-smi命令
    3.1显示GPU当前的状态:

    nvidia-smi

    参数详解:
    **GPU:**本机中的GPU编号(有多块显卡的时候,从0开始编号)
    **Fan:**风扇转速(0%-100%),N/A表示没有风扇,这个速度是计算机期望的风扇转速,实际情况下如果风扇堵转,可能打不到显示的转速。
    **Name:**GPU类型,图上GPU的类型是:GeForce MX250/RTX 2080Ti
    **Temp:**GPU的温度(GPU温度过高会导致GPU的频率下降)
    **Perf:**GPU的性能状态,从P0(最大性能)到P12(最小性能)
    **Persistence-M:**持续模式的状态,持续模式虽然耗能大,但是在新的GPU应用启动时花费的时间更少。
    **Pwr:Usager/Cap:**能耗表示,Usage:用了多少,Cap总共多少
    **Bus-Id:**GPU总线相关显示,domain:bus:device.function
    **Disp.A:**Display Active ,表示GPU的显示是否初始化
    **Memory-Usage:**显存使用率
    **Volatile GPU-Util:**GPU使用率
    **Uncorr. ECC:**关于ECC的东西,是否开启错误检查和纠正技术,0/disabled,1/enabled
    **Compute M:**计算模式,0/DEFAULT,1/EXCLUSIVE_PROCESS,2/PROHIBITED
    **Processes:**显示每个进程占用的显存使用率、进程号、占用的哪个GPU
    **type:**进程类型。C 表示计算进程,G 表示图形进程,C+G 表示都有。
    3.2隔几秒刷新一下显存状态:

    nvidia-smi -l 秒数

    3.3将监控结果写入文件,并且指定写入文件的监控字段:

    nvidia-smi -l 1 --format=csv --filename=report.csv --query-gpu=timestamp,name,index,utilization.gpu,memory.total,memory.used,power.draw

    参考资料:
    https://tool.4xseo.com/a/169.html
    https://www.cnblogs.com/huty/p/8517141.html
    https://blog.csdn.net/qq_40594137/article/details/124959608
    https://deepinout.com/opencl/opencl-tutorials/22_difference_between_opencl_and_opengl.html

  • 相关阅读:
    计算机基础知识56
    openGauss学习笔记-128 openGauss 数据库管理-设置透明数据加密(TDE)
    Codeforces Round 910 (Div. 2) D. Absolute Beauty
    使用groupby统计不同组的缺失值
    Nature 哈佛新型超材料Metafluid粘度、透明度、弹性可变,可用于编程液压机器人
    Azure DevOps Server 入门实践与安装部署
    【Python从入门到精通】(六)Python内置的数据类型-列表(list)和元组(tuple),九浅一深,十个章节,不信你用不到
    解读「软考机考」!附赠0基础备考资料
    SpringBoot Windows 自启动 - 通过 Windows Service 服务实现
    python爬虫语法
  • 原文地址:https://blog.csdn.net/byxdaz/article/details/132699279