FFmpeg H.265透明视频解码

作者:quink
来源:Fun With FFmpeg
链接:https://mp.weixin.qq.com/s/xzKF0k7V3mh1bnB-Vduzng

一、透明视频的应用场景和现有方案

复杂的特效动画往往使用透明视频来实现。在AI火爆之后,透明视频又有了一个业务场景:数字人。透明视频有多种实现方式:

  1. mp4格式支持PNG图片编码,所以最简单的方案是在mp4里放PNG图片;
  2. webm/mkv格式VP9编码,数字人用的比较多。和PNG相比,VP9编码大大提升了压缩效率;
  3. H.264、H.265视频编码,图像上下或左右分成两半,一半是普通YUV内容,一半的Y plane用来保存alpha信息,解码后处理时把YUV转成RGBA。和VP9相比,编解码器可选的更多,支持更好。缺点是后处理麻烦,要小心对半处理碰上硬件解码crop切边问题,处理不好可能中心找偏了。

二、Alpha HEVC透明视频标准原理

其实H.265标准本身支持透明视频编码,描述在Annex F:Common specifications for multi-layer extensions. H.265 nalu header设计时考虑了扩展性:

nal_unit_header( ) {
  forbidden_zero_bit f(1)
  nal_unit_type u(6)
  nuh_layer_id u(6)
  nuh_temporal_id_plus1 u(3)
}

nuh_temporal_id_plus1标记了时域分层信息,时域分层SVC编码在流媒体直播业务中大量使用。而nuh_layer_id用的就很少了,大家可能忽略了它的价值。MV-HEVC和Alpha HEVC都依赖nuh_layer_id。

和MV-HEVC相比,Alpha HEVC的实现很简单:

  1. 用nuh_layer_id = x编码base层(x一般是0),也就是普通的YUV内容,
  2. 用nuh_layer_id = y编码alpha层(y一般是1),alpha层也是按照YUV三个plane去编码的,Y plane是alpha信息,UV plane忽略
  3. alpha层和base层具有相同的编码参考结构,相同的POC,alpha层的视频帧和base层同时解码输出,输出时可以简单操作,由两个YUV组合成一个YUVA
  4. base层和alpha层有各自的SPS/PPS,所以至少有两个SPS和PPS,如图所示
FFmpeg H.265透明视频解码

MV-HEVC有跨层的参考,Alpha HEVC没有跨层参考,实际上可以单读解码base层和alpha层,如下图所示:

FFmpeg H.265透明视频解码

可以看到图中相邻两帧POC相同,前一个是base层,后一个是alpha层。

Alpha HEVC的基本原理讲完了,它还有两个辅助工具:

  1. VPS扩展部分,描述了是否包含alpha扩展,各层之间的关系。这里不得不吐槽,VPS extension是典型的overengineering,为了节省几个bit,做出了类似C语言的指针的指针的指针的指针的指针的指针的设计,能够支持N多层的编码。实际上,知道是透明视频,忽略VPS extension照样解码。Apple发布的Alpha HEVC的样片,就搞错了VPS extension
  2. SEI里标记alpha视频信息。和VPS extension相比,SEI alpha_channel_info还算简单。

三、FFmpeg支持Alpha HEVC透明视频解码

虽然H.265标准支持透明视频,真正让Alpha HEVC落地的是Apple。Apple在WWDC19时推出了它们的方案,也就是在videotoolbox硬件编解码上实现了Alpha HEVC。

FFmpeg支持用videotoolbox编码Alpha HEVC:

./ffmpeg -i bunny.mp4 -i basketball.mp4 \
	-filter_complex '[1:v][0:v]alphamerge,format=bgra[vout]’ \
	-c:v hevc_videotoolbox \
	-pix_fmt bgra \
	-alpha_quality 0.5 \
	-map '[vout]' -tag:v hvc1 alpha.mp4

但因为集成方式问题,FFmpeg不支持videotoolbox解码Alpha HEVC视频,也不支持纯软件解码Alpha HEVC。

自从Anton给FFmpeg加了MV-HEVC解码支持之后,我就在考虑Alpha HEVC的解码。

Alpha HEVC解码最麻烦的处理是解析VPS extension,我硬着头皮糊了一个,能够

  • 正常解析Apple videotoolbox编码的Alpha HEVC
  • 也支持x265编码的Alpha HEVC,虽然x265的VPS extension不太标准
  • 不支持Apple 2019年放出来的样片,前面说了,Apple弄错了VPS extension
  • Nvidia nvenc说是支持Alpha HEVC,但是编码输出的VPS/SPS/PPS是乱套的,大概也不支持

剩下的解码部分基本可以复用MV-HEVC的工作。但有个很大的差异,MV-HEVC是输出两个frame的,左眼和右眼。对于Alpha HEVC来说,单独输出base层的YUV和alpha层的YUV,对用户不友好,FFmpeg自己的工具也不好处理这种两个frame,所以应当输出YUVA。我做了一个取巧的设计,让alpha层AVFrame的data[0]指向base层AVFrame的data[3],解码到alpha层AVFrame的Y,也就解码输出到base层的YUVA的A plane。

FFmpeg命令行解码Alpha HEVC,单独查看alpha plane:

./ffmpeg -i ~/Movies/alpha.mp4 -an \
  -vf extractplanes=planes=a \
  -c:v rawvideo -f nut - |ffplay -

如下图所示:

FFmpeg H.265透明视频解码

单独提取Y plane,如下图所示:

FFmpeg H.265透明视频解码

四、展望

H.265相比VP9(至少在国内)生态上成熟很多。Alpha HEVC有Apple硬件编解码的支持,有x265软件编码的支持,现在又有了FFmpeg软件解码的支持,后续加上硬件解码不成问题。万事俱备,只差一个产品经理了:怎么把Alpha HEVC用起来。

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

  • H.264 与 H.265:直播流媒体常用协议的区别

    深入了解 H.264 与 H.265 之间的差异 正如俗话说的一般,技术总是在进步,以便为用户提供更多便利。有时这些差异可能是巨大的,而在其他时候,几乎是微不足道的。但在不断扩展的…

    2023年3月31日
  • H.265编码原理入门

    视频编码的目的是为了压缩原始视频,压缩的主要思路是从空间、时间、编码、视觉等几个主要角度去除冗余信息。由于 H.264 出色的数据压缩比率和视频质量,成为当前市场上最为流行的编解码…

    2022年6月17日

发表回复

登录后才能评论