我尝试将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]:发送到解除分配的实例的消息
当不调用此方法时,视频图像卡住并且“没有响应”(但实例可用)。
答案 0 :(得分:2)
您似乎正在为音频和视频设置一对环形缓冲区。但是您正在发布已放置在环形缓冲区中的CMSampleBuffers - 因此当您需要访问它们时,它们不在那里。快速解决方法是仅在使用新样本在环形缓冲区上覆盖CMSampleBuffer时释放它。无论何时将样本写入环形缓冲区,都应检查是否在该索引处覆盖现有样本,并仅在此时进行CFRelease。
然而这实际上并没有成功,因为你将破坏CMSampleBuffer内存模型,这将导致丢帧或更糟。
的内容如果您的应用程序通过长时间保留提供的CMSampleBufferRef对象导致丢弃样本,但需要长时间访问样本数据,请考虑将数据复制到新缓冲区然后释放样本缓冲区(如果以前保留过),以便可以重用它引用的内存。
WWDC 2011 video 419, Capturing from the Camera using AV Foundation on iOS 5在其中列出了Do's和Dont's(pdf第50页):
- 不要保留数据输出回调之外的样本缓冲区
- 不需要花费很长时间来处理数据输出回调中的缓冲区
Here是一个使用缓冲区复制的例子(不是我的 - 我还没有测试过它)。请注意警告:“但还有另一个问题,那就是超大的内存,所以这是为了谨慎使用视频。”
您可能需要重新考虑您的设计。无论您计划对环形缓冲区内容进行哪些处理,或许至少某些可以在向环形缓冲区添加数据之前进行,这样您就不会持有到CMSampleBuffers本身,而不是已处理的数据(希望减少内存密集)。