2022前端最新面试题知乎 2022前端最新面试题( 五 )


(H264视频帧的SPS、PPS引用关系,图片来自Apple)
如果视频帧引用的VPS,PPS,SPS任一发生变化,则按照VideoToolbox的要求,需要重新配置解码Session:
鉴于我们需要支持HDR,因此需要判断一下视频是否为Main10/RextProfile,并调整输出为gfx::BufferFormat::P010
在上述步骤后,硬解关键流程基本完工,目前代码已合入Chromium104(main分支),macOS平台具体实现过程和代码Diff可以追溯Crbug() 。
有了macOS硬解的开发经验,尝试Windows硬解相对变得容易了一些,尽管也踩了一些坑 。
文章开头已经介绍了,实际上在Windows平台,如果你可以安装HEVC视频扩展,则是可以在Edge浏览器硬解HEVC的,因此我最初的思路也是和Edge一样,通过引导HEVC视频扩展,完成硬解支持 。
首先,使用Edge,打开任意HEVC视频,发现,Edge使用VDAVideoDecoder进行HEVC硬解:
因此尝试搜索发现Windows平台VDAVideoDecoder代码实现均位于dxva_video_decode_accelerator_win.cc文件内,继续寻找蛛丝马迹,发现,在开源的Chromium项目内,并不存在HEVC硬解相关的任何实现,这说明Edge是自己基于某个时期的ChromiumMedia模块“魔改”出来的HEVC硬解支持,同时在这个过程发现了个有趣的现象:
好吧,尽管没少吐槽Edge,但是他确实是Windows平台唯一支持HEVC硬解的浏览器(当然,马上就不是了) 。
接着看dxva_video_decode_accelerator_win.cc的实现,从上述Edge解码需要安装AV1插件的逻辑反推,如果我们照着AV1的方式实现HEVC,是否可行?答案是肯定的 。
观察SupportedProfile,然后将我们需要支持的HEVCPROFILE_MAIN、HEVCPROFILE_MAIN10加入:
之后按照AV1的逻辑,加入HEVCCodec,同时值得一提的是必须在调用SetOutput方法前设置分辨率(这块坑了我大概一天的时间Debug),代码如下:
接着实现一下HEVCDecoder的获取逻辑:
同时将HEVCMain,Main10Profile加入到supported_profile_helpers.cc:
最后,还需要修改一下引导逻辑,强制让HEVC编码格式使用VDAVideoDecoder而不是D3D11VideoDecoder:
后面省略了一些透传Profile的代码 。
在上述步骤执行后,一切大功告成,代码实现基本完成,HEVC视频扩展帮我们处理了大部分的解码逻辑,所以实现过程相当简单 。
但,问题来了!由于HEVC视频扩展插件在1.0.31823之后的版本存在抖动问题,而1.0.50361虽然解决了抖动的问题,但其官网文档并没有明确详述如何配置Decoder解决该问题(注:欢迎贡献配置方法),因此,如果我们需要用HEVC视频扩展的方案,则必须限制用户本地强行使用1.0.31823版本 。
为此我尝试写过nsh脚本,试图在用户电脑存在非31823版本HEVC视频扩展的情况,强制卸载并重装1.0.31823版本的HEVC视频扩展,但,因为Windows商店会默认对Appx扩展自动更新,这导致如果希望用户电脑不更新HEVC视频扩展,则必须强迫用户关闭Windows商店的自动更新,这无疑意味着这个方案是个半成品,很可能需要换技术方案了,但我们的选择真的不多 。
然而就在即将放弃的时候,我突然想到为啥不照着Chromium把D3D11VA的方案实现一遍呢?MediaFoundation绝不是唯一解!时间点是2022年的2月中旬,我抱着尝试的态度,打开了source.chromium.org这个网站,试图学习下其他格式D3D11VA的解码方法,并在media文件夹偶然间瞥到了一个叫d3d11_h265_accelerator.cc的文件,这是啥?怎么可能?Windows不是没有人实现过HEVC硬解么?然后我果断看了下提交时间,发现在2月8号,这个文件才被合入到Chromium!感谢作者@JianlinQiu(来自Intel的大佬),把Windows的D3D11硬解加速实现的差不多 。
Trace了下@JianlinQiu实现相关的crbug(#c18),合入其代码,简单做了下测试发现一半的视频可以播(早期版本有些小问题,目前均已解决) 。

推荐阅读