我已经看过将libavcodec与vaapi一起用于加速解码的各种示例,但是如何使用它来加速编码?
答案 0 :(得分:8)
截至今天,FFmpeg和libav已经在支持的平台和硬件SKU上通过VAAPI实现了硬件加速编码,I have written a write-up on the same将使您能够设置,部署和使用ffmpeg和libav来实现相同的目标效果。
在同一个说明中,我添加了对硬件表面限制的引用,以便您了解哪些硬件平台支持用于VAAPI编码的特定视频编解码器。
通过环境模块系统加载的示例FFmpeg构建如下所示,一步一步:
在Skylake验证测试平台上构建支持VP8 / 9解码并编码硬件加速的VAAPI启用的FFmpeg作为示例:
构建平台:Ubuntu 16.04LTS。
首先要做的事情:
首先构建依赖关系链。
这是适用于英特尔G45的媒体运行时GPU内核管理器的C& HD Graphics系列。 它是构建intel-hybrid-driver包的先决条件。
git clone https://github.com/01org/cmrt
cd cmrt
./autogen.sh
./configure
time make -j$(nproc) VERBOSE=1
sudo make -j$(nproc) install
sudo ldconfig -vvvv
此软件包为WebM项目VPx编解码器提供支持。 GPU加速 通过在英特尔GEN GPU上执行的媒体内核提供。混合驱动程序提供CPU 绑定熵(例如,CPBAC)解码并管理GEN GPU媒体内核参数和缓冲区。
这是使用所需配置构建libva的先决条件,因此我们可以在支持的硬件配置上访问VPX系列混合解码功能。
git clone https://github.com/01org/intel-hybrid-driver
cd intel-hybrid-driver
./autogen.sh
./configure
time make -j$(nproc) VERBOSE=1
sudo make -j$(nproc) install
sudo ldconfig -vvv
此软件包为Intel GEN Graphics系列SKU提供VA-API(视频加速API)用户模式驱动程序。
当前的视频驱动程序后端通过打包缓冲区和命令提供到GEN GPU的桥接,以便发送到i915驱动程序,以执行视频解码,编码和处理的硬件和着色器功能。
当调用它以在受支持的硬件上处理VP8 / 9混合解码任务时,它还为intel-hybrid-driver提供了一个包装器(必须使用--enable-hybrid-codec
选项配置)。
git clone https://github.com/01org/intel-vaapi-driver
cd intel-vaapi-driver
./autogen.sh
./configure --enable-hybrid-codec
time make -j$(nproc) VERBOSE=1
sudo make -j$(nproc) install
sudo ldconfig -vvvv
Libva是VA-API(视频加速API)的实现
VA-API是一个开源库和API规范,可以访问图形硬件加速功能以进行视频处理。它由一个主库和每个受支持的硬件供应商的特定于驱动程序的加速后端组成。
git clone https://github.com/01org/libva
cd libva
./autogen.sh
./configure
time make -j$(nproc) VERBOSE=1
sudo make -j$(nproc) install
sudo ldconfig -vvvv
完成后,运行vainfo:
测试VAAPI支持的功能集vainfo
我当前测试平台的输出是:
libva info: VA-API version 0.40.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/local/lib/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_0_40
libva info: va_openDriver() returns 0
vainfo: VA-API version: 0.40 (libva 1.7.3)
vainfo: Driver version: Intel i965 driver for Intel(R) Skylake - 1.8.3.pre1 (glk-alpha-58-g5a984ae)
vainfo: Supported profile and entrypoints
VAProfileMPEG2Simple : VAEntrypointVLD
VAProfileMPEG2Simple : VAEntrypointEncSlice
VAProfileMPEG2Main : VAEntrypointVLD
VAProfileMPEG2Main : VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointEncSliceLP
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointEncSliceLP
VAProfileH264MultiviewHigh : VAEntrypointVLD
VAProfileH264MultiviewHigh : VAEntrypointEncSlice
VAProfileH264StereoHigh : VAEntrypointVLD
VAProfileH264StereoHigh : VAEntrypointEncSlice
VAProfileVC1Simple : VAEntrypointVLD
VAProfileVC1Main : VAEntrypointVLD
VAProfileVC1Advanced : VAEntrypointVLD
VAProfileNone : VAEntrypointVideoProc
VAProfileJPEGBaseline : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointEncPicture
VAProfileVP8Version0_3 : VAEntrypointVLD
VAProfileVP8Version0_3 : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileVP9Profile0 : VAEntrypointVLD
制作可用的FFmpeg版本来测试编码器:
现在,我们将构建一个FFmpeg二进制文件,利用VAAPI来测试Skylake上的编码和解码功能,使用自定义前缀,因为我们通过测试平台上的environment-modules系统加载FFmpeg。
首先准备目标目录:
sudo mkdir -p /apps/ffmpeg/dyn
sudo chown -Rc $USER:$USER /apps/ffmpeg/dyn
mkdir -p ~/ffmpeg_sources
根据需要添加额外组件:
<强>(a)中。构建和部署nasm: Nasm是x264和FFmpeg使用的x86优化的汇编程序。强烈推荐或您的结果可能非常慢。
请注意,我们现在已经从Yasm切换到nasm,因为这是x265,x264等采用的当前汇编程序。
cd ~/ffmpeg_sources
wget wget http://www.nasm.us/pub/nasm/releasebuilds/2.14rc0/nasm-2.14rc0.tar.gz
tar xzvf nasm-2.14rc0.tar.gz
cd nasm-2.14rc0
./configure --prefix="/apps/ffmpeg/dyn" --bindir="/apps/ffmpeg/dyn/bin"
make -j$(nproc) VERBOSE=1
make -j$(nproc) install
make -j$(nproc) distclean
<强>(b)中。静态构建和部署libx264: 该库提供H.264视频编码器。有关更多信息和用法示例,请参阅H.264 Encoding Guide。 这需要使用 - enable-gpl - enable-libx264 配置ffmpeg。
cd ~/ffmpeg_sources
wget http://download.videolan.org/pub/x264/snapshots/last_x264.tar.bz2
tar xjvf last_x264.tar.bz2
cd x264-snapshot*
PATH="/apps/ffmpeg/dyn/bin:$PATH" ./configure --prefix="/apps/ffmpeg/dyn" --bindir="/apps/ffmpeg/dyn/bin" --enable-static --disable-opencl
PATH="/apps/ffmpeg/dyn/bin:$PATH" make -j$(nproc) VERBOSE=1
make -j$(nproc) install VERBOSE=1
make -j$(nproc) distclean
<强>(c)中。构建和配置libx265: 该库提供H.265 / HEVC视频编码器。有关更多信息和用法示例,请参阅H.265 Encoding Guide。
sudo apt-get install cmake mercurial
cd ~/ffmpeg_sources
hg clone https://bitbucket.org/multicoreware/x265
cd ~/ffmpeg_sources/x265/build/linux
PATH="$/apps/ffmpeg/dyn/bin:$PATH" cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/apps/ffmpeg/dyn" -DENABLE_SHARED:bool=off ../../source
make -j$(nproc) VERBOSE=1
make -j$(nproc) install VERBOSE=1
make -j$(nproc) clean VERBOSE=1
<强>(d)中。构建和部署libfdk-aac库: 这提供了AAC音频编码器。有关更多信息和用法示例,请参阅AAC Audio Encoding Guide。 这需要使用 - enable-libfdk-aac 配置ffmpeg(如果还包含 - enable-gpl ,则 - enable-nonfree >)。
cd ~/ffmpeg_sources
wget -O fdk-aac.tar.gz https://github.com/mstorsjo/fdk-aac/tarball/master
tar xzvf fdk-aac.tar.gz
cd mstorsjo-fdk-aac*
autoreconf -fiv
./configure --prefix="/apps/ffmpeg/dyn" --disable-shared
make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean
<强>(E)。构建和配置libvpx
cd ~/ffmpeg_sources
git clone https://github.com/webmproject/libvpx/
cd libvpx
./configure --prefix="/apps/ffmpeg/dyn" --enable-runtime-cpu-detect --enable-vp9 --enable-vp8 \
--enable-postproc --enable-vp9-postproc --enable-multi-res-encoding --enable-webm-io --enable-vp9-highbitdepth --enable-onthefly-bitpacking --enable-realtime-only \
--cpu=native --as=yasm
time make -j$(nproc)
time make -j$(nproc) install
time make clean -j$(nproc)
time make distclean
<强>(F)。构建LibVorbis
cd ~/ffmpeg_sources
wget -c -v http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.xz
tar -xvf libvorbis-1.3.5.tar.xz
cd libvorbis-1.3.5
./configure --enable-static --prefix="/apps/ffmpeg/dyn"
time make -j$(nproc)
time make -j$(nproc) install
time make clean -j$(nproc)
time make distclean
(适用克)。构建FFmpeg:
cd ~/ffmpeg_sources
git clone https://github.com/FFmpeg/FFmpeg -b master
cd FFmpeg
PATH="/apps/ffmpeg/dyn/bin:$PATH" PKG_CONFIG_PATH="/apps/ffmpeg/dyn/lib/pkgconfig" ./configure \
--pkg-config-flags="--static" \
--prefix="/apps/ffmpeg/dyn" \
--extra-cflags="-I/apps/ffmpeg/dyn/include" \
--extra-ldflags="-L/apps/ffmpeg/dyn/lib" \
--bindir="/apps/ffmpeg/dyn/bin" \
--enable-debug=3 \
--enable-vaapi \
--enable-libvorbis \
--enable-libvpx \
--enable-gpl \
--cpu=native \
--enable-opengl \
--enable-libfdk-aac \
--enable-libx264 \
--enable-libx265 \
--enable-nonfree
PATH="/apps/ffmpeg/dyn/bin:$PATH" make -j$(nproc)
make -j$(nproc) install
make -j$(nproc) distclean
hash -r
注意:要获取调试版本,请省略distclean
步骤,然后在sources子目录下找到ffmpeg_g
二进制文件。
我们经常需要在问题出现时进行调试构建,并且可能需要gdb跟踪来进行调试。
FFmpeg的环境模块文件(如果您的前缀不同,则根据需要进行编辑,并在需要时添加冲突):
less /usr/share/modules/modulefiles/ffmpeg/vaapi
#%Module1.0#####################################################################
##
## ffmpeg media transcoder modulefile
## By Dennis Mungai <dmngaie@gmail.com>
## February, 2016
##
# for Tcl script use only
set appname ffmpeg
set version dyn
set prefix /apps/${appname}/${version}
set exec_prefix ${prefix}/bin
conflict ffmpeg/git
prepend-path PATH ${exec_prefix}
prepend-path LD_LIBRARY_PATH ${prefix}/lib
要加载并测试,请运行:
module load ffmpeg/vaapi
通过以下方式确认一切正常:
which ffmpeg
预期产出:
/apps/ffmpeg/dyn/bin/ffmpeg
示例代码段以测试新编码器:
确认已成功构建VAAPI编码器:
ffmpeg -hide_banner -encoders | grep vaapi
V..... h264_vaapi H.264/AVC (VAAPI) (codec h264)
V..... hevc_vaapi H.265/HEVC (VAAPI) (codec hevc)
V..... mjpeg_vaapi MJPEG (VAAPI) (codec mjpeg)
V..... mpeg2_vaapi MPEG-2 (VAAPI) (codec mpeg2video)
V..... vp8_vaapi VP8 (VAAPI) (codec vp8)
请参阅相关编码器的帮助文档:
ffmpeg -hide_banner -h encoder='encoder name'
测试编码器;
使用GNU parallel,我们将使用以下示例将系统上〜/ src路径上的一些mp4文件(4k H.264测试样本,每个40分钟,AAC 6声道音频)分别编码为VP8和HEVC。请注意,我已根据我的使用情况调整了编码器,并启用了重新调整为1080p的功能。根据需要进行调整。
对于VP8,同时启动10个编码作业:
parallel -j 10 --verbose '/apps/ffmpeg/dyn/bin/ffmpeg -loglevel debug -threads 4 -hwaccel vaapi -i "{}" -vaapi_device /dev/dri/renderD129 -c:v vp8_vaapi -loop_filter_level:v 63 -loop_filter_sharpness:v 15 -b:v 4500k -maxrate:v 7500k -vf 'format=nv12,hwupload,scale_vaapi=w=1920:h=1080' -c:a libvorbis -b:a 384k -ac 6 -f webm "{.}.webm"' ::: $(find . -type f -name '*.mp4')
使用GNU Parallel的HEVC:
到HEVC Main Profile,同时启动10个编码作业:
parallel -j 4 --verbose '/apps/ffmpeg/dyn/bin/ffmpeg -loglevel debug -threads 4 -hwaccel vaapi -i "{}" -vaapi_device /dev/dri/renderD129 -c:v hevc_vaapi -qp:v 19 -b:v 2100k -maxrate:v 3500k -vf 'format=nv12,hwupload,scale_vaapi=w=1920:h=1080' -c:a libvorbis -b:a 384k -ac 6 -f matroska "{.}.mkv"' ::: $(find . -type f -name '*.mp4')
有些说明:
嘿伙计们,小更新:现在可以为FFmpeg提供VP9硬件加速编码。但是,您需要一个基于Intel Kabylake的集成GPU才能利用此功能。
现在,使用新的vp9_vaapi编码器,这就是我们得到的。
现在提供编码器选项:
ffmpeg -h vp9_vaapi
<强>输出:强>
Encoder vp9_vaapi [VP9 (VAAPI)]:
General capabilities: delay
Threading capabilities: none
Supported pixel formats: vaapi_vld
vp9_vaapi AVOptions:
-loop_filter_level <int> E..V.... Loop filter level (from 0 to 63) (default 16)
-loop_filter_sharpness <int> E..V.... Loop filter sharpness (from 0 to 15) (default 4)
当你试图在不受支持的硬件上解决这个问题时会发生什么,比如Skylake?
请参阅下面的示例输出:
[Parsed_format_0 @ 0x42cb500] compat: called with args=[nv12]
[Parsed_format_0 @ 0x42cb500] Setting 'pix_fmts' to value 'nv12'
[Parsed_scale_vaapi_2 @ 0x42cc300] Setting 'w' to value '1920'
[Parsed_scale_vaapi_2 @ 0x42cc300] Setting 'h' to value '1080'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'video_size' to value '3840x2026'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'pix_fmt' to value '0'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'time_base' to value '1/1000'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'pixel_aspect' to value '1/1'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'sws_param' to value 'flags=2'
[graph 0 input from stream 0:0 @ 0x42cce00] Setting 'frame_rate' to value '24000/1001'
[graph 0 input from stream 0:0 @ 0x42cce00] w:3840 h:2026 pixfmt:yuv420p tb:1/1000 fr:24000/1001 sar:1/1 sws_param:flags=2
[format @ 0x42cba40] compat: called with args=[vaapi_vld]
[format @ 0x42cba40] Setting 'pix_fmts' to value 'vaapi_vld'
[auto_scaler_0 @ 0x42cd580] Setting 'flags' to value 'bicubic'
[auto_scaler_0 @ 0x42cd580] w:iw h:ih flags:'bicubic' interl:0
[Parsed_format_0 @ 0x42cb500] auto-inserting filter 'auto_scaler_0' between the filter 'graph 0 input from stream 0:0' and the filter 'Parsed_format_0'
[AVFilterGraph @ 0x42ca360] query_formats: 6 queried, 4 merged, 1 already done, 0 delayed
[auto_scaler_0 @ 0x42cd580] w:3840 h:2026 fmt:yuv420p sar:1/1 -> w:3840 h:2026 fmt:nv12 sar:1/1 flags:0x4
[hwupload @ 0x42cbcc0] Surface format is nv12.
[AVHWFramesContext @ 0x42ccbc0] Created surface 0x4000000.
[AVHWFramesContext @ 0x42ccbc0] Direct mapping possible.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000001.
[AVHWFramesContext @ 0x42c3e40] Direct mapping possible.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000002.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000003.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000004.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000005.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000006.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000007.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000008.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x4000009.
[AVHWFramesContext @ 0x42c3e40] Created surface 0x400000a.
[vp9_vaapi @ 0x409da40] Encoding entrypoint not found (19 / 6).
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
[AVIOContext @ 0x40fdac0] Statistics: 0 seeks, 0 writeouts
[aac @ 0x40fcb00] Qavg: -nan
[AVIOContext @ 0x409f820] Statistics: 32768 bytes read, 0 seeks
Conversion failed!
有趣的比特是在这个特定平台上没有VP9编码的入口点警告,正如vainfo的输出所证实的那样:
libva info: VA-API version 0.40.0
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/local/lib/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_0_40
libva info: va_openDriver() returns 0
vainfo: VA-API version: 0.40 (libva 1.7.3)
vainfo: Driver version: Intel i965 driver for Intel(R) Skylake - 1.8.4.pre1 (glk-alpha-71-gc3110dc)
vainfo: Supported profile and entrypoints
VAProfileMPEG2Simple : VAEntrypointVLD
VAProfileMPEG2Simple : VAEntrypointEncSlice
VAProfileMPEG2Main : VAEntrypointVLD
VAProfileMPEG2Main : VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointEncSliceLP
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointEncSliceLP
VAProfileH264MultiviewHigh : VAEntrypointVLD
VAProfileH264MultiviewHigh : VAEntrypointEncSlice
VAProfileH264StereoHigh : VAEntrypointVLD
VAProfileH264StereoHigh : VAEntrypointEncSlice
VAProfileVC1Simple : VAEntrypointVLD
VAProfileVC1Main : VAEntrypointVLD
VAProfileVC1Advanced : VAEntrypointVLD
VAProfileNone : VAEntrypointVideoProc
VAProfileJPEGBaseline : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointEncPicture
VAProfileVP8Version0_3 : VAEntrypointVLD
VAProfileVP8Version0_3 : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileVP9Profile0 : VAEntrypointVLD
VP9配置文件0的VLD(用于可变长度解码)入口点是Skylake在VP9硬件加速方面最远的。
使用Kabylake试验台,运行这些编码测试并报告: - )
答案 1 :(得分:0)
FFMPEG目前(截至2014年10月1日)不支持使用VAAPI进行编码。它目前仅支持使用VAAPI进行解码。
答案 2 :(得分:0)
此时似乎尚未实施。它出现在google summer of code goals for 2013。
但是可以使用其中一个libva utils(h264encode)来使用vaapi hwaccel: 据我所知,它只适用于你可以从v4l2获得的rawvideo文件(fourcc NV12,IYUV,YV12,UYVY):
ffmpeg -i / dev / video0 -c:v rawvideo -pix_fmt nv12 -vframes 1000 -y yourfilm.yuv
棘手的是你必须知道帧数和大小,因为h264encode无法从rawvideo中猜出它们,那么你可以:
h264encode -w 640 -h 480 -n 1000 --srcyuv yourfilm.yuv
h264编码文件默认在/tmp/test.264中丢失,您当然可以修改它。
编码的速度和最终质量非常惊人(在不到两秒的时间内达到440Mo到8Mo,并且没有明显的质量损失)
现在,在ffmpeg中使用可以直接使用GPU资源的编解码器会不会很棒。有没有人在ffmpeg编解码器开发中有任何文件,或者至少可以指向一个接近vaapi_hwaccel编码的编解码器?