我的目标是编写一个自定义相机视图控制器:
实施(在iOS 4.2 / Xcode 3.2.5上):
由于要求(3),我需要下载到AVFoundation。
我从Technical Q&A QA1702开始并进行了这些更改:
我遇到的问题是处理预览图像的效果(预览“视频”的一帧)。
首先,我从imageFromSampleBuffer:
获取样本缓冲区的captureOutput:didOutputSampleBuffer:fromConnection:
的UIImage结果。然后,我使用CGGraphicsContext对屏幕进行缩放和旋转。
此时,帧速率已低于会话视频输出中指定的15 FPS,当我添加效果时,它会降至10或10左右。由于内存不足,应用程序很快崩溃
我已经取得了一些成功,将iPhone 4的帧速率降至9 FPS,iPod Touch(第4代)的帧速率降至8 FPS。
我还在一些代码中添加了“刷新”调度队列,但我不确定它实际上有多大帮助。基本上,每隔8-10帧,设置一个标志,表示captureOutput:didOutputSampleBuffer:fromConnection:
立即返回,而不是处理帧。在输出调度队列上的同步操作完成后,该标志将被重置。
此时我甚至不介意低帧速率,但显然我们无法提供低内存崩溃。任何人都知道如何采取措施来防止这种情况下的内存不足(和/或更好地“刷新”调度队列)?
答案 0 :(得分:4)
要防止内存问题,只需在captureOutput:didOutputSampleBuffer:fromConnection:
中创建一个自动释放池。
这是有道理的,因为imageFromSampleBuffer:
返回一个自动释放的UIImage对象。另外,它可以立即释放由图像处理代码创建的任何自动释放的对象。
// Delegate routine that is called when a sample buffer was written
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Create a UIImage from the sample buffer data
UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
< Add your code here that uses the image >
[pool release];
}
我的测试表明,即使请求的FPS非常高(例如60)并且图像处理非常慢(例如0.5秒),这将在iPhone 4或iPod Touch(第4代)上没有内存警告的情况下运行。< / p>
OLD SOLUTION:
正如Brad指出的那样,Apple建议将图像处理放在后台线程上,以免干扰UI响应。在这种情况下我没有注意到多少延迟,但最佳实践是最佳实践,因此请使用上述解决方案和自动释放池,而不是在主调度队列/主线程上运行它。
要防止内存问题,只需使用主调度队列而不是创建新队列。
这也意味着当您想要更新UI时,您不必切换到captureOutput:didOutputSampleBuffer:fromConnection:
中的主线程。
在setupCaptureSession
中,更改FROM:
// Configure your output.
dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
[output setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
TO:
// we want our dispatch to be on the main thread
[output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
答案 1 :(得分:2)
一个从根本上说更好的方法是使用OpenGL为你处理与图像相关的繁重工作(正如我在your latest attempt中尝试的那样)。但是,即使这样,您也可能会遇到构建要处理的帧的问题。
虽然在处理帧时遇到内存累积似乎很奇怪(根据我的经验,如果你不能足够快地处理它们就停止获取它们),Grand Central Dispatch队列可能会因为它们而被堵塞等待I / O.
也许调度信号量可以让您限制向处理队列添加新项目。有关这方面的更多信息,我强烈推荐Mike Ash的“GCD Practicum”文章,他将着眼于使用调度信号量优化I / O绑定缩略图处理操作。