在将CMSampleBufferRef发送到AVAssetWriter之前保存它

时间:2014-04-06 13:03:46

标签: ios iphone objective-c

我尝试将didOutputSampleBuffer代表中的一些示例保存到AVAssetWriter的相册中。

这是保存样本的代码:

.h文件

@property (nonatomic) NSInteger audioIndex;
@property (nonatomic) NSInteger videoIndex;

@property (nonatomic) CMTime startTime;

@property (nonatomic) CFMutableArrayRef audioSamples;
@property (nonatomic) CFMutableArrayRef videoSamples;

.m文件

CFRetain(sampleBuffer);
if (CMSampleBufferDataIsReady(sampleBuffer)) {
    if (self.videoIndex == 0) {
        self.startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    }
    if (bVideo) {
        int count = 0;
        count = (int)CFArrayGetCount(self.videoSamples);
        if (count >= 1000) {
            CFArraySetValueAtIndex(self.videoSamples, self.videoIndex, sampleBuffer);
        }
        else {
            CFArrayAppendValue(self.videoSamples, sampleBuffer);
        }
        self.videoIndex = (self.videoIndex + 1) % 1000;
    }
    else {
        int count;
        count = (int)CFArrayGetCount(self.audioSamples);
        if (count >= 1000) {
            CFArraySetValueAtIndex(self.audioSamples, self.audioIndex, sampleBuffer);
        }
        else {
            CFArrayAppendValue(self.audioSamples, sampleBuffer);
        }
        self.audioIndex = (self.audioIndex + 1) % 1000;
    }
}

CFRelease(sampleBuffer);

问题是最后一行CFRelease, 在调用此方法时,我无法将示例用于以后获取错误:

  

[Not A Type retain]:发送到解除分配的实例的消息

当不调用此方法时,视频图像卡住并且“没有响应”(但实例可用)。

1 个答案:

答案 0 :(得分:2)

您似乎正在为音频和视频设置一对环形缓冲区。但是您正在发布已放置在环形缓冲区中的CMSampleBuffers - 因此当您需要访问它们时,它们不在那里。快速解决方法是仅在使用新样本在环形缓冲区上覆盖CMSampleBuffer时释放它。无论何时将样本写入环形缓冲区,都应检查是否在该索引处覆盖现有样本,并仅在此时进行CFRelease。

然而这实际上并没有成功,因为你将破坏CMSampleBuffer内存模型,这将导致丢帧或更糟。

以下是Apple docs advise

的内容
  

如果您的应用程序通过长时间保留提供的CMSampleBufferRef对象导致丢弃样本,但需要长时间访问样本数据,请考虑将数据复制到新缓冲区然后释放样本缓冲区(如果以前保留过),以便可以重用它引用的内存。

WWDC 2011 video 419, Capturing from the Camera using AV Foundation on iOS 5在其中列出了Do's和Dont's(pdf第50页):

  
      
  • 不要保留数据输出回调之外的样本缓冲区
  •   
  • 不需要花费很长时间来处理数据输出回调中的缓冲区
  •   

Here是一个使用缓冲区复制的例子(不是我的 - 我还没有测试过它)。请注意警告:“但还有另一个问题,那就是超大的内存,所以这是为了谨慎使用视频。”

您可能需要重新考虑您的设计。无论您计划对环形缓冲区内容进行哪些处理,或许至少某些可以在向环形缓冲区添加数据之前进行,这样您就不会持有到CMSampleBuffers本身,而不是已处理的数据(希望减少内存密集)。