IOS系统中H.264视频流如何实现硬件解码
TOP1 810
通过使用VideoToolbox来实现H.264视频流的硬件解码的步骤:1、创建 VTDecompressionSessionRef 对象;2、使用 VTDecompressionSessionRef 进行解码;3、销毁 VTDecompressionSessionRef 对象。
1、创建 VTDecompressionSessionRef 对象
首先需要创建decompression session,通过调用 VTDecompressionSessionCreate 来创建。
VTDecompressionSessionCreate 的定义如下:
- allocator 是decompression session的分配器,如果没有特殊要求, 传入 NULL即可,session会使用默认的分配器.
- videoFormatDescription 是用来描述视频格式信息的对象, 如果是H.264解码的话, 跟Android的MediaCodec一样需要先得到h264的sps和pps信息, 再根据sps和pps来创建对应的视频格式描述对象. 伪代码如下:
- videoDecoderSpecification: 用来指定所需要创建的解码器, 通常可以传入NULL, 让系统根据视频格式描述来自动选择创建合适的解码器.
- destinationImageBufferAttributes: 用来指定解码输出的像素格式,视频宽度, 高度等信息, 通常为了性能优异起见,像素格式应选择YUV420的格式, 如: kCVPixelFormatType_420YpCbCr8Planar 等
- outputCallback: 解码输出的回调, 它是一个结构体, 定义如下:
decompressionOutputCallback 就是回调函数, decompression session解码输出是通过这个回调异步输出的。
强调:当解码器不是工作在同步模式时,这里的异步输出线程是从系统的线程池中获取空闲线程作为回调线程的,所以开发者不能假定这个回调来自同一线程.
decompressionOutputRefCon 是开发者自定义的对象, decompression session会把这个指针作为回调函数的名列前茅个参数回传给开发者.
2、使用 VTDecompressionSessionRef 进行解码
解码的函数定义如下:
- session 就是decompression session
- sampleBuffer 是输入解码的数据,这里需要注意的是, 虽然H264 NAL是标准所定义的H264解码器能处理的最小解码单元, 但是apple的这个硬件解码器是不行的,ios的硬件解码器只能输入完整的一帧数据,这就意味,当要解码的H264是以 multi-slice方式编码的话,需要将一帧的多个slice组合成一个frame再提交给解码器,而且组合的frame中slice的边界不是H.264标准Annex B所定义的 nal start code 这种,这里采用了AVCC 格式.
- decodeFlag: 解码器的一些可设置的工作模式.
- sourceFrameRefCon: 开发者定义的参考帧, 可以传入 NULL.
- infoFlagsOut: 解码的状态, 可以根据需要决定是否要监视这些状态.伪代码如下:
3、销毁 VTDecompressionSessionRef 对象
销毁decompression sessio非常简单,调用VTDecompressionSessionInvalidate 和 CFRelease 就可以,伪代码如下:
需要注意的是,因为解码是一个异步过程, 而且通常解码会延迟输出,销毁的时候开发者有可能希望将输入的h264流全部解码输出,所以在销毁前需要调用 VTDecompressionSessionFinishDelayedFrames 将缓存的Frame输出.