FFmpeg上的硬件加速涉及以下三块:
- 硬件上下文 `libavutil/hwcontext*`
- 硬件编解码
- 硬件filter
hwcontext在硬件解码、硬件编码、硬件filter之间起到配置硬件、维护上下文、支持多种硬件加速API之间互操作的作用。如果不注意hwcontext的配合使用,硬件编解码也能运行,但是性能表现很差。很多人卡在这里,不知如何优化。
另一方面,即使指定了hwcontext,因为FFmpeg转码处理自动配置的流水线会引入CPU做计算的filter,又引入了性能损失。一方面是GPU拷贝到CPU再拷贝到GPU的数据拷贝开销,一方面是CPU filter的计算开销。
硬件加速性能优化核心是全流水线在GPU运行 + 砍去不必要的开销。
FFmpeg很早就支持macOS/iOS videotoolbox:
- FFmpeg 2.8 (2015年)支持videotoolbox解码
- FFmpeg 3.1 支持videotoolbox H.264编码
- FFmpeg 4.0 支持videotoolbox H.265编码
但总体来说,FFmpeg社区开发者多数不熟悉macOS平台开发,熟悉macOS的开发者又不熟悉FFmpeg,FFmpeg对videotoolbox的支持力度不够。我日常使用macOS,仅当作Unix来用,不是macOS/iOS开发者。用的过程中发现不少FFmpeg videotoolbox编解码bug,顺便试着修复了。
除了bug,我还发现FFmpeg缺少macOS平台的硬件filter。虽然理论上,FFmpeg支持vulkan filter,macOS也有vulkan SDK,但是FFmpeg vulkan要求最新的vulkan版本,macOS的vulkan SDK又是非原生支持的,FFmpeg + vulkan + macOS很难跑起来,目前看没有实用价值。
图像filter里最常用的功能是缩放、旋转、色彩空间转换。videotoolbox framework中除了编解码,还有:
- VTPixelTransferSession:实现了缩放和色彩空间转换等功能
- VTPixelRotationSession:图像旋转、反转等
https://developer.apple.com/documentation/videotoolbox/vtpixeltransfersession?language=objc
刚好满足了最常用的图像filter功能。我在FFmpeg libavfilter加上了这两个的封装:
- libavfilter/vf_scale_vt.c
- libavfilter/vf_transpose_vt.c
注意ffmpeg内的rotate filter是可以360°任意角度旋转的,不要求是90°的整数倍。transpose filter支持90°整数倍旋转和上下左右翻转。
全链路硬件加速转码示例如下:
./ffmpeg -hwaccel videotoolbox \
-hwaccel_output_format videotoolbox_vld \
-i ios-265.mov \
-c:v hevc_videotoolbox \
-profile:v main \
-b:v 3M \
-vf scale_vt=w=iw/2:h=ih/2:color_matrix=bt709:color_primaries=bt709:color_transfer=bt709 \
-c:a copy \
-tag:v hvc1 \
/tmp/test.mp4
- -hwaccel videotoolbox 提供videotoolbox硬件上下文,主要功能是硬件内存buffer分配;它的另一个功能是封装了CPU和GPU之间的数据传输拷贝,但在这个例子中用不到
- -hwaccel_output_format videotoolbox_vld 指定了硬件输出图像格式;
- 如不指定,一般默认会选中NV12
- 指定了videotoolbox_vld,FFmpeg不会自动插入CPU filter,图像在GPU内存,如果需要的话,可以用hwdownload filter下载到CPU
- 用软件解码器的时候,也可以用硬件filter,只需要先hwupload到GPU
- FFmpeg videotoolbox视频解码不是单独的一个解码器,是在h264、h265解码器上的加速。有几个硬件视频解码加速都是这么实现的,一个公共的管理调度 + 不同的硬件加速。最新的是av1解码,FFmpeg内置的av1解码器,没有软件实现,全靠硬件加速完成解码功能。指定了-hwaccel videotoolbox之后,FFmpeg自动启用videotoolbox解码
- -c:v hevc_videotoolbox指定编码器
- -vf scale_vt=w=iw/2:h=ih/2:color_matrix=bt709:color_primaries=bt709:color_transfer=bt709
- scale_vt是用VTPixelTransferSession实现的filter
- w=iw/2:h=ih/2 宽高缩小一半
- color_matrix=bt709:color_primaries=bt709:color_transfer=bt709 进行色彩空间转换
- -tag:v hvc1与mp4封装有关,Apple平台要求hvc1,不指定的话默认是hev1,Apple系统播放器不支持
示例中,输入文件是4K HDR视频,
Input: hevc (Main 10) (hvc1 / 0x31637668), yuv420p10le(tv, bt2020nc/bt2020/arib-std-b67), 3840×2160
缩放加色彩空间转换之后,视频信息如下:
Output: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709, progressive), 1920×1080
整个流程性能接近最优。编码器本身还有一些参数配置可以优化,以后再分析。
作者:quink
来源:Fun With FFmpeg
原文:https://mp.weixin.qq.com/s/Yjp3erEARiha5A0drB4OBg
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。