如何在iOS上通过硬件解码来解码H.264帧?

15

我一直在使用ffmpeg解码从我的IP摄像头接收到的每一帧。简短的代码如下:

-(void) decodeFrame:(unsigned char *)frameData frameSize:(int)frameSize{
   AVFrame frame;
   AVPicture picture;
   AVPacket pkt;
   AVCodecContext *context;
   pkt.data = frameData;
   pat.size = frameSize;
   avcodec_get_frame_defaults(&frame);
   avpicture_alloc(&picture, PIX_FMT_RGB24, targetWidth, targetHeight);
   avcodec_decode_video2(&context, &frame, &got_picture, &pkt);
}

该代码运行良好,但它是通过软件解码进行的。我想通过硬件解码来提高解码性能。经过大量研究,我知道可以通过AVFoundation框架实现。AVAssetReader类可能有所帮助,但我无法弄清下一步是什么。能否有人为我指出接下来的步骤?任何帮助将不胜感激。

2个回答

23

iOS没有直接访问硬件解码引擎的公共接口,因为在iOS上始终使用硬件来解码H.264视频。

因此,第513节提供了您需要的所有信息,以在iOS上允许逐帧解码。简而言之,根据该会话:

  • 从您的H.264 elementary stream生成单个网络抽象层单元(NALUs)。有很多关于如何完成此操作的在线信息。VCL NALUs(IDR和非IDR)包含您的视频数据,并将被馈送到解码器中。
  • 根据“AVCC”格式重新打包这些NALU,删除NALU起始码,并用4字节的NALU长度标头替换它们。
  • 通过CMVideoFormatDescriptionCreateFromH264ParameterSets()从您的SPS和PPS NALUs创建一个CMVideoFormatDescriptionRef
  • 按照第513节,将NALU帧打包为CMSampleBuffers。
  • 创建VTDecompressionSessionRef,并使用样本缓冲区调用 VTDecompressionSessionDecodeFrame()
    • 或者,使用AVSampleBufferDisplayLayer,其-enqueueSampleBuffer:方法可以省略创建自己的解码器的步骤。

5
截至 iOS 8 版本,此方法有效。请注意,4 字节的 NALU 长度头是大端序格式,因此如果您有 UInt32 值,则在复制到 CMBlockBuffer 之前必须进行字节交换(使用 CFSwapInt32 函数)。 - 12on
谢谢12on,我一直在为解码错误苦恼很长时间,直到我尝试像你说的那样交换字节。 - Greg
@rpj - 你能解释一下第三步(封装)吗?我应该封装多少个NALU帧(例如,所有帧号都相同)? - Tomasz Wójcik
这个链接提供了如何逐步解码h.264的更详细说明:https://dev59.com/OF0b5IYBdhLWcg3wLOg2#29525001 - ChihHao
2
一个令人烦恼的问题是:这个优秀的答案,talk 513和“著名”的链接答案完美地解释了如何从基本流通过NALU到VTDecompressionSession。然而!很难找到任何关于如何达到拥有准备好执行此操作的264流的示例或讨论!这可能需要很多工作.......... - Fattie

2

编辑:

此链接提供了如何逐步解码h.264的更详细说明: stackoverflow.com/a/29525001/3156169

原回答:

我昨天观看了WWDC 2014中的513“直接访问视频编码和解码”会议,并得到了自己问题的答案。

发言人说:

我们有Video Toolbox(在iOS 8中)。 Video Toolbox已经存在于OS X上一段时间,但现在它终于在iOS上填充了头文件。这提供了对编码器和解码器的直接访问。

因此,在iOS 7中无法逐帧进行硬件解码,但在iOS 8中可以实现。

是否有人找出如何在iOS 8中直接访问逐帧视频编码和解码?


非常感谢您提供的:“视频编码和解码的直接访问”。 - benchuk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接