0%

AVFoundation视频解码API

视频解码API概述

AVFoundation

  • AVAssetReader
  • AVSampleBufferGenerator

Video Toolbox

  • VTDecompressionSession

Core Video

  • CVPixelBuffer integration with Metal

使用AVFoundation的AVPlayer、AVAssetExportSession、AVAssetReader和Video Toolbox的VTDecompressSesion都自动进行硬件加速以及CMSampleBuffer的RPC优化。

视频核心数据结构

CVPixelBuffer:原始图像+图像元数据

CMBlockBuffer:任意类型的二进制数据(压缩图像)+元数据

CMSampleBuffer:

  • CVPixelBuffer+时间信息+帧元数据(CMFormatDescription)
  • CMBlockBuffer+时间信息+帧元数据
  • 只包含元数据

IOSurface:不同框架、设备中交换图像数据的高速通道,应用在:

  • 不同框架之间:CoreVideo和Metal
  • 不同进程之间:解码进程和App进程
  • 不同的内存区:显存和内存

CVPixelBufferPool:实现了CVPixelBuffer中的IOSurface的复用与回收。

解码流程

解码流程

在解码的过程中如果配置的输出格式与原始数据格式不一致,还会发生转码,触发内存拷贝,要尽量避免。

获取解封装后的数据

要想获得解码前的裸数据,即解封装后的裸数据(输出为CMSampleBuffer),可以通过以下方式实现:

  • AVAssetReader:创建track ouput时把outputSetting设为nil。
  • AVSampleBufferGenerator:只能读出未解码的裸数据。
  • 自己生成CMSampleBuffer:把数据读取出来,构建CMBlockBuffer,再加上时间信息,构建出CMSampleBuffer。这样的CMSampleBuffer不带RPC优化。

使用Video Toolbox解码

VTDecompressionSession包含三部分:

  • 解码器
  • CVPixelBufferPool
  • VTPixelTransferSession

使用VTDecompressionSession的步骤:

  1. 创建VTDecompressionSession;
  2. 通过VTSessionSetProperty配置session;
  3. 传递CMSampleBuffer视频帧给session解码。
  4. 从回调中获取解码CMSampleBuffer。

虽然回调是异步的,但回调中的逻辑仍会反向影响解码器的性能。常见的做法是把回调中的解码帧用队列缓存起来,在另外的线程处理。

CVPixelBuffer与Metal交互

拿到了解码帧CMSampleBuffer,就可以从中取出CVPixelBuffer,接下来就是如何处理和渲染了,这里使用Metal完成。

CVPixelBuffer与Metal交互方式:

  • 直接使用IOSurface。即直接通过从CVPixelBuffer取出的IOSurface创建Metal纹理,但要手动处理IOSurface的内存释放(通过IOSurfaceIncrementUseCountIOSurfaceDecrementUseCount)。
  • 使用CVMetalTextureCache。
    1. 创建CVMetalTextureCache:CVMetalTextureCacheCreate
    2. 通过向CVMetalTextureCache传入CVPixelBuffer创建CVMetalTexture:CVMetalTextureCacheCreateTextureFromImage
    3. 通过CVMetalTexture创建MTLTexture:CVMetalTextureGetTexture

参考

欢迎关注我的其它发布渠道