保存CMSampleBufferRef以供以后处理

时间:2011-12-15 08:00:56

标签: cmsamplebufferref

我正在尝试使用AVFoundation框架快速捕获来自AVCaptureStillImageOutput的“系列”静止图像,就像某些相机中的连拍模式一样。我想使用完成处理程序

    [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection 
                                              completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 

并将imageSampleBuffer传递给NSOperation对象以供稍后处理。但是我找不到在NSOperation类中保留缓冲区的方法。

    [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection 
                                              completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 

    //Add to queue
    SaveImageDataOperation *saveOperation = [[SaveImageDataOperation alloc] initWithImageBuffer:imageSampleBuffer];
    [_saveDataQueue addOperation:saveOperation];
    [saveOperation release];

    //Continue
    [self captureCompleted];
}];

有人知道我在这里做错了什么吗?有没有更好的方法来做到这一点?

2 个答案:

答案 0 :(得分:8)

“重要信息:CMSampleBuffer的客户端必须通过调用CFRetain和CFRelease显式管理保留计数,即使在使用垃圾回收的进程中也是如此。”

消息来源:CoreMedia.Framework CMSampleBuffer.h

答案 1 :(得分:2)

我最近在CMSampleBuffer对象上做了很多工作,并且我已经了解到在实时操作期间由OS提供的大多数媒体缓冲区都是从池中分配的。如果AVFoundation(或CoreVideo / CoreMedia)用完了池中的缓冲区(即,您在一段时间内CFR获取缓冲区),则该过程的实时方面将受到影响或阻塞,直到您CF将缓冲区释放回池中。

因此,除了操作CMSampleBuffer上的CFRetain / CFRelease计数之外,您应该只保留缓冲区足够长的时间来解压缩(深度复制位)CMBlockBuffer / CMFormat并创建一个新的CMSampleBuffer以传递给您的NSOperationQueue或dispatch_queue_t供以后处理。

在我的情况下,我想通过网络从VideoToolbox传递压缩的CMSampleBuffers。我基本上创建了CMSampleBuffer的深层副本,我的应用程序可以完全控制内存分配/生命周期。从那里,我将复制的CMSampleBuffer放在队列中供网络I / O使用。

如果压缩样本数据,深度复制应该相对较快。在我的应用程序中,我使用NSKeyedArchiver从源CMSampleBuffer的相关部分创建NSData对象。对于H.264视频数据,这意味着CMBlockBuffer内容,SPS / PPS头字节以及SampleTimingInfo。通过序列化这些元素,我可以在网络的另一端重建CMSampleBuffer,其行为与VideoToolbox给我的相同。特别是,AVSampleBufferLayer能够将它们显示为在机器上原生来源。

对于您的申请,我建议如下:

  1. 获取源CMSampleBuffer并压缩像素数据。如果你 可以,使用VideoToolbox中的硬件编码器仅创建I帧 H.264图像质量非常高。 VT编码器 显然对电池寿命来说非常好,可能很多 优于JPEG,除非他们有硬件JPEG编解码器 系统也是如此。
  2. 深层复制压缩的CMSampleBuffer输出 VideoToolbox,VT将CFRelease原来的CMSampleBuffer 到捕获子系统使用的池。
  3. 仅保留VT压缩的CMSampleBuffer足够长的时间,以便将深层副本排入队列以供以后处理。
  4. 由于AVFoundation电影录制器可以实时执行步骤#1和#2而不会耗尽缓冲区,因此您应该能够在dispatch_queue上深度复制和排队数据,而不会耗尽视频捕获组件使用的缓冲池和VideoToolbox组件。