我的目标是编写一个自定义的相机视图控制器,该控制器:

  1. 可以使用后置摄像头和前置摄像头(如果有)在所有四个界面方向拍照。
  2. 正确旋转和缩放预览“视频”以及全分辨率照片。
  3. 允许将(简单)效果应用于预览“视频”和全分辨率照片。

    实施(在iOS 4.2 / Xcode 3.2.5上):

    由于要求(3),我需要下拉至AVFoundation。

    我从技术问答QA1702 开始,更改:

    1. 将sessionPreset更改为AVCaptureSessionPresetPhoto。
    2. 在开始会话之前,添加了AVCaptureStillImageOutput作为附加输出。

      我遇到的问题是处理预览图像(预览“视频”的一帧)的性能。

      首先,我从imageFromSampleBuffer:获取样本缓冲区上captureOutput:didOutputSampleBuffer:fromConnection:的UIImage结果。然后,我使用CGGraphicsContext缩放并旋转到屏幕上。

      在这一点上,帧速率已经低于会话视频输出中指定的15 FPS,当我添加效果时,它降至10以下或大约10。由于内存不足,应用很快崩溃了

      在将iPhone 4的帧速率降至9 FPS并将iPod Touch(第4代)的帧速率降至8 FPS方面,我取得了一些成功。

      我还添加了一些代码来“刷新”调度队列,但是我不确定它实际上有多大帮助。基本上,每8到10帧设置一个标志,该信号通知captureOutput:didOutputSampleBuffer:fromConnection:立即返回而不是处理该帧。在输出调度队列上的同步操作完成后,将重置该标志。

      在这一点上,我什至都不介意低帧速率,但是显然我们不能随内存不足崩溃而交付。任何人都知道如何在这种情况下采取措施防止内存不足(和/或“刷新”调度队列的更好方法)?

有帮助吗?

解决方案

要防止出现内存问题,只需在captureOutput:didOutputSampleBuffer:fromConnection:中创建一个自动释放池即可。

这很有意义,因为imageFromSampleBuffer:返回了一个自动释放的UIImage对象。另外,它可以立即释放由图像处理代码创建的所有自动释放的对象。 通用标签

我的测试表明,即使请求的FPS非常高(例如60)并且图像处理非常慢(例如0.5+秒),iPhone 4或iPod Touch(第4代)也可以在没有内存警告的情况下运行。 / p>

旧解决方案:

正如Brad所指出的那样,Apple建议在后台线程上进行图像处理,以免干扰UI响应能力。在这种情况下,我没有注意到太多延迟,但是最佳实践是最佳实践,因此将上述解决方案与自动释放池一起使用,而不要在主调度队列/主线程上运行它。

要防止出现内存问题,只需使用主调度队列,而不要创建一个新的队列。

这还意味着,当您要更新UI时,不必切换到captureOutput:didOutputSampleBuffer:fromConnection:中的主线程。

setupCaptureSession中,更改为: 通用标签

收件人: 通用标签

其他提示

从根本上更好的方法是使用OpenGL为您处理尽可能多的与图像相关的繁重工作(正如我所看到的,您正在您的最新尝试)。但是,即使那样,您也可能在构建要处理的帧时遇到问题。

虽然在处理帧时会遇到内存累积的现象很奇怪(以我的经验,如果不能足够快地处理它们,您就停止获取它们),但如果它们出现,大中央调度队列可能会阻塞正在等待I / O。

也许调度信号量可以让您限制向处理队列中添加新项目。有关更多信息,我强烈推荐Mike Ash的“ GCD实践”一文,他着眼于使用调度信号量优化I / O绑定缩略图处理操作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top