iOS/iPhone照片连拍模式API

7

我正在尝试在iPhone 5s上以最高分辨率(AVCaptureSessionPresetPhoto)捕获多张照片。我尝试使用以下代码:

    dispatch_semaphore_t sync = dispatch_semaphore_create(0);
while( [self isBurstModeEnabled] == YES )
                {
        [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
                             {

                                 if (imageSampleBuffer != NULL)
                                 {
                                     NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
                                     NSString *videoThumbPath = [NSString
                                                                 stringWithFormat:@"%@/img%d.png",
                                                                 burstFolderPath,
                                                                 index];

                                     [imageData writeToFile:videoThumbPath atomically:YES];
                                     if( 0 == index )
                                     {
                                         [self NSLogPrint:[NSString stringWithFormat:@"Created photo at %@",videoThumbPath]];
                                     }
                                 }
                                 dispatch_semaphore_signal(sync);
                             }];
    dispatch_semaphore_wait(sync, DISPATCH_TIME_FOREVER);
}

使用这段代码,我每秒大约能获取2张照片,远远达不到本机相机应用的连拍模式的性能。我做错了什么?此外,我尝试使用上面的代码而没有使用信号量,但在这种情况下我遇到了一些奇怪的行为,有些照片会缺失(img0.png、img1.png和img3.png存在,但img2.png缺失)。使用第二种方法性能会更好,但仍然达不到本机应用的表现(在我的测试中,相机应用每秒大约可以拍摄8.4张照片)。
2个回答

16

captureStillImageAsynchronouslyFromConnection:completionHandler: 我认为并不是苹果用于其连拍模式的方法。

相反,苹果正在以全分辨率(5s支持)抓取视频帧。做法如下:

AVCaptureDevice 将其activeFormat设置为全传感器分辨率,然后您从AVCaptureVideoDataOutputSampleBufferDelegatecaptureOutput:didOutputSampleBuffer:fromConnection:中获取和处理每秒10帧,每次获取一帧时发出快门声音。

对于不支持全传感器大小分辨率的设备(和/或如果您想支持早于iOS 7.x的任何设备),您需要一个备用方案(低分辨率图像或更慢的连拍模式)。

请注意,如果同时使用多个captureStillImageAsynchronouslyFromConnection:completionHandler:,结果可能会非常出乎意料。这就是为什么您应该从上一个completionHandler调用每个迭代的原因(本质上,这就是您的信号量正在做的事情)。此外,您可能希望将文件格式从PNG切换为连拍拍摄的格式 - 保存PNG速度非常慢且需要大量系统资源 - 堆叠15或20个PNG可能会导致严重的问题!

它可能正在这样做,因为它可能使用私有API来实现相同的最终结果。


我并不是在寻找那个具体的问题,但我一直在想为什么有些捕获格式是“全屏”,而有些则有不同的比例(4:3 vs 16:9)...这似乎与图像稳定有关,这也解释了为什么AVCaptureSessionPresetPhoto没有这个问题。(https://www.iphonelife.com/blog/87/why-you-may-want-disable-image-stabilization-during-video-recording)。在连拍模式下,逻辑上看来也不会使用图像稳定... - Vinzzz
唯一的16:9格式是高清格式,根据定义,它是16:9格式。其他都是全幅画面,如果我没记错的话。AVCaptureSessionPresetPhoto不能用于拍摄视频,但是在适当的硬件上,您可以通过手动设置activeFormat而不使用预设来以相同的分辨率拍摄视频。在iOS 7.x中,预设非常可选。 - Wildaker
这句话的另一种表达方式是:传感器是4:3,因此任何不是4:3的输出格式实际上都会从传感器中裁剪数据。在16:9格式的情况下,可以使用传感器的额外像素来进行图像稳定,并且此功能(AVCaptureConnection enablesVideoStabilizationWhenAvailable)实际上仅适用于16:9格式。关于activeFormat,您手动设置的格式必须是-AVcaptureDevice formats之一。 - Vinzzz

1

在iOS 8及以上版本中,可使用此方法进行爆发模式:

- (void)captureStillImageBracketAsynchronouslyFromConnection:(AVCaptureConnection *)connection withSettingsArray:(NSArray *)settings completionHandler:(void (^)(CMSampleBufferRef sampleBuffer, AVCaptureBracketedStillImageSettings *stillImageSettings, NSError *error))handler NS_AVAILABLE_IOS(8_0);

{{链接1:文档}}


这是曝光括号,而不是爆发捕捉。参见http://www.digital-photo-secrets.com/tip/2111/what-is-exposure-bracketing/ 了解曝光括号的简介。 - pjh68
如果您不更改设置,则可以为每张照片使用相同的设置,这是推荐的方式。 - d0n13

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