当拍摄照片时切换AVCaptureSession预设

8

我的当前设置如下(基于来自Brad Larson的ColorTrackingCamera项目):

我正在使用一个AVCaptureSession,其设置为AVCaptureSessionPreset640x480,通过OpenGL场景作为纹理运行输出。然后由片段着色器对此纹理进行操作。

我需要这种“较低质量”的预设,因为我想在用户预览时保持高帧率。然后,当用户拍摄静态照片时,我想切换到更高质量的输出。

起初,我认为可以更改AVCaptureSession上的sessionPreset,但这会强制相机重新对焦,从而破坏了可用性。

[captureSession beginConfiguration];
captureSession.sessionPreset = AVCaptureSessionPresetPhoto;
[captureSession commitConfiguration];

目前我正在尝试向AVCaptureSession添加第二个AVCaptureStillImageOutput,但是我得到了一个空的像素缓冲区,所以我认为我有点卡住了。

这是我的会话设置代码:

...

// Add the video frame output
[captureSession beginConfiguration];

videoOutput = [[AVCaptureVideoDataOutput alloc] init];
[videoOutput setAlwaysDiscardsLateVideoFrames:YES];
[videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
[videoOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

if ([captureSession canAddOutput:videoOutput])
{
    [captureSession addOutput:videoOutput];
}
else
{
    NSLog(@"Couldn't add video output");
}

[captureSession commitConfiguration];



// Add still output
[captureSession beginConfiguration];
stillOutput = [[AVCaptureStillImageOutput alloc] init];

if([captureSession canAddOutput:stillOutput])
{
    [captureSession addOutput:stillOutput];
}
else
{
    NSLog(@"Couldn't add still output");
}

[captureSession commitConfiguration];



// Start capturing
[captureSession setSessionPreset:AVCaptureSessionPreset640x480];
if(![captureSession isRunning])
{
    [captureSession startRunning];
};

...

这是我的截取方法:

- (void)prepareForHighResolutionOutput
{
    AVCaptureConnection *videoConnection = nil;
    for (AVCaptureConnection *connection in stillOutput.connections) {
        for (AVCaptureInputPort *port in [connection inputPorts]) {
            if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
                videoConnection = connection;
                break;
            }
        }
        if (videoConnection) { break; }
    }

    [stillOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:
     ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
         CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(imageSampleBuffer);
         CVPixelBufferLockBaseAddress(pixelBuffer, 0);
         int width = CVPixelBufferGetWidth(pixelBuffer);
         int height = CVPixelBufferGetHeight(pixelBuffer);

         NSLog(@"%i x %i", width, height);
         CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
     }];
}

(widthheight都为0)

我已经阅读了AVFoundation文档,但似乎我没有掌握一些重要的内容。


你需要这个预览运行多快?使用AVCaptureStillImageOutput并运行视频预览(支持iOS 4.3+),我看到来自该视频预览的输入帧速率为20 FPS。虽然不是视频相机的完整30 FPS,但对于想要拍摄场景的预览来说已经足够了。 - Brad Larson
我几分钟前找到了一个解决方案。我现在正在使用AVCaptureStillImageOutput预设,但我必须明确设置outputSettings以避免颜色空间之间的转换。我会立即将其发布为答案。 - polyclick
1个回答

3
我找到了解决我的特定问题的方法。如果有人遇到相同的问题,希望这个解决方案能作为指南。
帧率显著下降的原因是内部像素格式转换导致的。在明确设置像素格式之后,帧率得到了提高。
在我的情况下,我使用以下方法创建BGRA纹理:
// Let Core Video create the OpenGL texture from pixelbuffer
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, videoTextureCache, pixelBuffer, NULL,
                                                            GL_TEXTURE_2D, GL_RGBA, width, height, GL_BGRA,
                                                            GL_UNSIGNED_BYTE, 0, &videoTexture);

因此,当我设置AVCaptureStillImageOutput实例时,我更改了我的代码:

// Add still output
stillOutput = [[AVCaptureStillImageOutput alloc] init];
[stillOutput setOutputSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];

if([captureSession canAddOutput:stillOutput])
{
    [captureSession addOutput:stillOutput];
}
else
{
    NSLog(@"Couldn't add still output");
}

希望这能帮助到有需要的人:)


我正在尝试您的代码,但仍然在点击640 x 480。有可能更新吗? - p0lAris
我在我的代码中遇到了类似的情况,我正在获取640x480的视频流,但是想要拍摄高分辨率照片。不幸的是,即使添加了“setOutputSettings:”参数,我仍然得到零宽度和高度。你能帮忙吗? - jowie
请告诉我,你是如何获得高质量的?你的预设是AVCaptureSessionPreset640x480... - vkalit
请提供最终代码。我不知道在哪里使用CVOpenGLESTextureCacheCreateTextureFromImage函数。 - Jaydeep Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接