我正在编写一个库,使用AVFoundation将资源导出到文件中。我创建了一个读取器,一个写入器,将输入和输出连接到这些,然后在输入上调用requestMediaDataWhenReadyOnQueue
方法以开始提取数据。提供给此方法的块回调看起来有点像这样:
[input requestMediaDataWhenReadyOnQueue:queue usingBlock:^{
while ([input isReadyForMoreMediaData]) {
CMSampleBufferRef buffer;
// The track has some more data for us
if ([reader status] == AVAssetReaderStatusReading
&& (buffer = [output copyNextSampleBuffer])) {
BOOL result = [input appendSampleBuffer:buffer];
CFRelease(buffer);
if (!result) {
// handle error
break;
}
// The track is finished, for whatever reason
} else {
[input markAsFinished]; ⬅
switch ([reader status]) {
// inspect the status and act accordingly
}
}
}
}];
这在iOS 5上完美运行,但在iOS 4上,代码在标有⬅箭头的行之后死于EXC_BAD_ACCESS。经过一番探索之后,我觉得在将输入标记为完成后,块会立即以某种方式被销毁。在执行坏行之前完全有效的self
指针会以某种方式变为0xfff…
或调试器报告的某些垃圾值。但之前指向它的对象很好,正如僵尸工具所证实的那样,它不会被解除分配。
我错过了什么?
答案 0 :(得分:1)
看到相同(类似)的问题。 iOS5开心,iOS4.3.5,不开心。有兴趣了解您最终找到的内容。
通过在requestMedatWhenReadyOnQueue块之前显式保留writer,writer输入,reader,reader输出并在else子句的最后明确释放所有四个来解决它。
文档确实说标记完成后,“块应该退出”。也许他们不是在开玩笑。如果您执行除退出以外的任何操作,则会出错。上述解决方法似乎有效。
更新:我仍然发现,即使在保留并释放所有资产对象后,它偶尔也会崩溃。正如您的问题所指出的那样,在您将编写器输入标记为已完成之后不久就会崩溃,就好像块本身正在被释放一样。而不是仅仅将块作为函数的一部分传递。我创建了一个复制的块属性,它是长期存在的对象的一部分。我用Block_copy初始化它,只在长寿命对象的析构函数中释放它。这似乎可以解决问题。我从那以后没有看到任何4.3.5崩溃。
答案 1 :(得分:0)
尝试[self retain]作为块的第一行,[self release]作为最后一行。
另一个关键问题是,如果App使用requestMediaDataWhenReadyOnQueue暂停(进入后台),您需要明确覆盖所有[reader status]值,因为它会在应用重启时失败。在某些情况下,我发现该块运行了多次失败状态标志。在具有类似代码的其他帖子中,有很多[保留] AV变量,然后在块结束时释放。因为该块可以运行多次,所以当应用程序进入后台状态时,此方法不起作用。
我发现以下内容在“开关”(上图)中运行良好:
case AVAssetReaderStatusReading:
break;
case AVAssetReaderStatusCompleted:
[videoWriterInput markAsFinished];
//do something else, like add an audio stream
[videoWriter finishWriting];
break;
case AVAssetReaderStatusFailed:
[videoWriterInput markAsFinished];
[videoWriter finishWriting];
break;
case AVAssetReaderStatusCancelled:
case AVAssetReaderStatusUnknown:
[videoWriterInput markAsFinished];
[videoWriter cancelWriting];
break;
}
dispatch_sync(dispatch_get_main_queue(), ^{
//hide any progress indicators
});
break;
除了“自我”之外,什么都没有保留。如果需要,块应自动保留变量。