我的应用程序目前正在使用AVFoundation从iPhone的后置摄像头获取原始摄像头数据,并实时显示在AVCaptureVideoPreviewLayer上。
我的目标是有条不紊地将简单图像滤镜应用于预览图层。图像未保存,因此我不需要捕获输出。例如,我想切换一个设置,将预览图层中的视频转换为Black&白。
我发现了一个问题here似乎通过捕获缓冲区中的各个视频帧,应用所需的转换,然后将每个帧显示为UIImage来完成类似的事情。由于多种原因,这似乎对我的项目来说太过分了,我想避免这可能造成的任何性能问题。
这是实现目标的唯一途径吗?
正如我所提到的,我不打算捕捉任何AVCaptureSession的视频,只是预览它。
答案 0 :(得分:66)
处理此问题的最佳方式可能是使用OpenGL ES过滤和显示这些视频帧。除了在与另一个视图或图层重叠时调整其不透明度之外,您将无法直接使用AVCaptureVideoPreviewLayer。
我有一个示例应用程序here,我从相机中抓取帧并应用OpenGL ES 2.0着色器来实时处理视频以进行显示。在这个应用程序中(详细解释here),我使用基于颜色的过滤来跟踪摄像机视图中的对象,但是其他人已经修改了这段代码以做一些整洁的视频处理效果。此应用程序中显示在屏幕上的所有基于GPU的过滤器在我的iPhone 4上以60 FPS运行。
支持视频的唯一iOS设备是iPhone 3G,但没有支持OpenGL ES 2.0的GPU。如果您还需要定位该设备,则可以使用基本代码进行视频捕获和生成OpenGL ES纹理,然后使用Apple的GLImageProcessing示例应用程序中的过滤器代码。该应用程序是围绕OpenGL ES 1.1构建的,所有iOS设备都支持该应用程序。
但是,我强烈建议您考虑使用OpenGL ES 2.0,因为使用着色器可以实现比使用固定功能OpenGL ES 1.1管道更多种类的效果。
(编辑:2/13/2012)作为上述内容的更新,我现在创建了一个名为GPUImage的开源框架,它封装了这种自定义图像过滤。它还可以处理捕获视频并在过滤后将其显示在屏幕上,只需要六行代码即可设置所有这些内容。有关框架的更多信息,请阅读my more detailed announcement。
答案 1 :(得分:3)
我建议查看ios开发库中的Rosy Writer示例。 Brad Larson的GPUImage Library非常棒,但对于这个问题来说似乎有些过分。
如果您只想将OpenGL着色器(又名过滤器)添加到AVCaptureVideoPreviewLayer
,则工作流程是将捕获会话的输出发送到OpenGL视图进行渲染。
AVCaptureVideoDataOutput *videoOut = [[AVCaptureVideoDataOutput alloc] init];
videoOut.videoSettings = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(_renderer.inputPixelFormat) };
[videoOut setSampleBufferDelegate:self queue:_videoDataOutputQueue];
然后在captureOutput:
委托中将样本缓冲区发送到OpenGL渲染器
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CVPixelBufferRef sourcePixelBuffer = CMSampleBufferGetImageBuffer( sampleBuffer );
_renderer copyRenderedPixelBuffer:sourcePixelBuffer];
}
在OpenGL渲染器中,将sourcePixelBuffer
附加到纹理,您可以在OpenGL着色器中对其进行过滤。着色器是一个在perpixel基础上运行的程序。 Rosy Writer示例还显示了使用除OpenGL之外的其他过滤技术的示例。
答案 2 :(得分:0)
Apple的示例AVCamFilter 完成了所有操作