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


遂观察其实现逻辑,发现Windows的硬解实现逻辑与macOS完全不同,在macOS,尽管我会对SPS/PPS/VPS/SliceHeader进行Parse,但是实际上,最终调用CMVideoFormatDescriptionCreateFromHEVCParameterSets方法创建解码Format时,传给VT的参数是包含了VPS,SPS,PPS的NaluData的数组,也就是说理论上如果我们不计算POC,不Reorder,直接将NaluData塞给VideoToolbox,也可以解码,只是帧组会抖动罢了 。
但到了Windows和Linux这里,实现起来要麻烦的多 。
根据Mircosoft官网,可知D3D11VA硬解的实际流程可参考这篇文章(-us/windows/win32/medfound/supporting-direct3d-11-video-decoding-in-media-foundation#open-a-device-handle),总结起来其实主要工作在于对每一个视频帧的图片参数拼装 。
GPU是否支持硬解,这里的逻辑,首先假定默认是不支持HEVCMain/Main10的,然后调用D3D11Device提供的GetVideoDecoderConfig方法,拿到支持的Codec列表,若列表中存在HEVC则认为支持:
如上流程可知,根据DXVAHEVCSpec,要正确实现解码,需要自己提前解析好其要的PictureParams,以HEVC的PictureParams为例,结构体如下,每一个参数都不能缺少,这本身工作量就不小,但好在@Jeffery大佬在实现Linux的H265Decoder和H265Parser时已经完成了大部分工作,因此@Jianlin大佬的工作主要是如何正确的将这些已经Parse好的Params拼装和计算,并塞给D3D11 。
实现硬解加速本身不需要实现解码逻辑,因此其实H265Accelerator本身的功能主要在于拼装DXVA所要的PictureParams,并正确提交 。这个过程,首先需要填充默认的PictureParams:
下面基本都是一些枯燥的流程,利用H265Parser解析后的结果,去填充PictureParams:
PictureParams还需要从PPS,SliceHeader,以及计算好的RefPicList,Picture填充,考虑到内容过于繁琐,这里暂时省略,整体思路可以概括为参数拼装 。
现实中的实际视频,尤其是在WebRTC场景产生的视频,可能存在分辨率或者色彩深度突变的情况,因此,在实际实现Decoder的过程中,处理这种情况至关重要,如果处理不好,轻则会导致视频花屏、绿屏,重则会导致D3D11devicecontextlost,并最终导致GPU进程崩溃 。
可以看到在返回kConfigChange后,实际上是重新创建了一个新的D3D11Decoder,这个过程用户在前端完全无感知,创建速度非常快,整体视频播放不会感受到一丝卡顿,是连贯的,相比VLC处理的体验更好 。
根据HEVCSpec2021,HEVC一共存在11种Profile,具体视频使用哪种Profile可由SPS中的general_profile_idc的值来判断,由于之前Chromium没有定义其他8种Profile,导致其他Profile会被当作MainProfile,并使FFMpegVideoDecoder的兜底逻辑失败,因此在这个CL(-review.googlesource.com/a/202606/chromium/src/+/3552293)中将其他几种Profile添加解决了这个问题 。
HEVC的11种Profile:
Profile的赋值逻辑:
当Profile能力补齐后,就可以支持将硬解不支持的Profile自动fallback到FFMpegVideoDecoder软解的能力了,这样可以确保我们目前可见的所有HEVCProfile都可以正常播放(能走硬解走硬解,否则走软解) 。
之前版本的Chromium提取色彩空间的逻辑要么是利用ffmpeg的avcodec_parameters_to_context获取,最终利用ffmpeg解析mov或者mp4container的逻辑获取,要么在demux阶段提取FOURCC_COLRBox获取,这样做对于标准的mov,mp4视频并没有什么问题,然而很多编码器在实现时并没有将色彩空间信息写入容器,导致Chromium的之前的逻辑无法正确提取到HEVC视频的色彩空间 。
因此我们需要利用解析好的HEVCDecoderConfigurationRecord,在demux阶段对SPS进行解析,并提取其sps->vui_parameters->colour_primaries,sps->vui_parameters->transfer_characteristics,sps->vui_parameters->matrix_coeffs,以及sps->vui_parameters->video_full_range_flag以生成VideoColorSpace 。