首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iPhone摄像机预览“视频”的应用效果

iPhone摄像机预览“视频”的应用效果
EN

Stack Overflow用户
提问于 2011-02-04 01:18:32
回答 2查看 6.8K关注 0票数 3

我的目标是编写一个自定义摄像机视图控制器,用于:

  1. 可以在所有四个界面方向与背面,并在可用时,前相机拍摄照片。
  2. 正确旋转和缩放预览“视频”以及完整的分辨率照片。
  3. 允许一个(简单的)效果同时适用于预览“视频”和全分辨率照片。

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

由于需求(3),我需要跳转到AVFoundation。

我从技术问答QA1702开始并做了以下修改:

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

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

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

此时,帧速率已经低于会话的视频输出中指定的15 FPS,当我加上效果时,它会下降到10以下或10左右。由于内存不足,应用程序会很快崩溃。

我已经成功地将iPhone 4上的帧速率降到9 FPS,在iPod Touch上降低到8 FPS (第4代)。

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

在这一点上,我甚至不介意低帧率,但很明显,我们不能与低内存崩溃。在这种情况下,有谁知道如何采取行动防止内存不足(和/或更好的“刷新”调度队列的方法)?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-02-04 21:47:17

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

这是有意义的,因为imageFromSampleBuffer:返回一个自动释放的UIImage对象。另外,它会立即释放由图像处理代码创建的任何自动释放的对象。

代码语言:javascript
复制
// 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];
}

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

旧解决方案:

正如布拉德所指出的,苹果建议图像处理应该放在后台线程上,这样就不会干扰用户界面响应能力。在本例中,我没有注意到很大的滞后,但最佳实践是最佳实践,因此将以上解决方案与自动释放池一起使用,而不是在主分派队列/主线程上运行该解决方案。

为了防止内存问题,只需使用主分派队列而不是创建新的队列。

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

setupCaptureSession中,更改如下:

代码语言:javascript
复制
// Configure your output.
dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
[output setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);

至:

代码语言:javascript
复制
// we want our dispatch to be on the main thread
[output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
票数 4
EN

Stack Overflow用户

发布于 2011-02-04 04:40:37

一个根本上更好的方法是使用OpenGL为您处理与映像相关的大量繁重工作(正如我所看到的,您正在尝试使用你最近的尝试)。但是,即使这样,在构建要处理的框架时也可能会出现问题。

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

也许调度信号量将允许您将新项添加到处理队列中。有关这方面的更多信息,我强烈推荐Mike的"GCD实习“文章,其中他将研究如何使用分派信号量优化I/O绑定的缩略图处理操作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4893620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档