2013-03-20 83 views
4

我正在使用AV Foundation来处理来自摄像机(iPhone 4s,iOS 6.1.2)的帧。我正在根据AV Foundation编程指南设置AVCaptureSession,AVCaptureDeviceInput,AVCaptureVideoDataOutput。一切都按预期工作,我可以在captureOutput:didOutputSampleBuffer:fromConnection:代表中接收帧。AV Foundation:AVCaptureVideoPreviewLayer和帧持续时间

我也有这样设置的预览层:

AVCaptureVideoPreviewLayer *videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession]; 
[videoPreviewLayer setFrame:self.view.bounds]; 
videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
[self.view.layer insertSublayer:videoPreviewLayer atIndex:0]; 

事情是,我不需要每秒30帧的帧我处理,我不能够处理他们这么快呢。所以我使用此代码来限制帧持续时间:

// videoOutput is AVCaptureVideoDataOutput set earlier 
AVCaptureConnection *conn = [videoOutput connectionWithMediaType:AVMediaTypeVideo]; 
[conn setVideoMinFrameDuration:CMTimeMake(1, 10)]; 
[conn setVideoMaxFrameDuration:CMTimeMake(1, 2)]; 

这工作得很好,并限制由captureOutput代表收到的帧。

但是,这也限制了预览图层上的每秒帧数,预览视频变得无法响应。

我从文档中了解到,帧持续时间是在连接上独立设置的,预览层的确有不同的AVCaptureConnection。在[videoPreviewLayer connection]上检查混合/最大帧持续时间显示它确实设置为默认值(1/30和1/24),并且不同于连接AVCaptureVideoDataOutput时设置的持续时间。

那么,是否有可能仅限于帧捕捉输出限制帧持续时间,并且仍然在预览视频上看到1/24-1/30帧持续时间?怎么样?

谢谢。

回答

4

虽然您确定有两个AVCaptureConnection s,但这并不意味着它们可以独立设置最小和最大帧持续时间。这是因为他们共享相同的物理硬件

如果连接#1以5帧/秒的速率(例如)以1/5秒的帧持续时间激活卷帘快门,则存在不可能连接#2可以同时激活快门30次/秒,帧持续时间为1/30秒。

要获得您想要的效果,需要两个摄像头!

接近你想要的东西的唯一方法就是沿着3月22日回答中Kaelin Colclasure概述的方法。

可以选择在该方法中稍微复杂一点,但是。例如,您可以使用计数器来决定丢弃哪些帧,而不是让线程休眠。您可以让该计数器响应实际帧速率(您可以通过captureOutput:didOutputSampleBuffer:fromConnection:委托人的元数据以及图像数据获得该帧数,也可以通过手动计算帧来计算)。你甚至可以通过合成框架来合理模仿更长时间的曝光,而不是将它们合并 - 就像App Store中的一些“慢速快门”应用一样(留下细节 - 例如不同的滚动快门文物 - 没有真正的在1/5秒扫描的一帧和1/25秒扫描的五帧之间差别很大,然后粘在一起)。

是的,这是一项工作,但您试图使一台摄像机的实时行为像两个一样 - 并且这从来都不会轻松。

+0

“这并不容易。”夸张的 – aleclarson 2014-05-30 20:34:42

+0

嗨@Wildaker你能帮忙解释一下帧持续时间以及在这个问题中使用不同值的含义吗?谢谢! http://stackoverflow.com/questions/34937008/exporting-videos-on-ios-understanding-and-setting-frame-duration-property – Crashalot 2016-01-22 00:36:21

+0

对不起,但没有试验,我真的不能说,@Crashalot。这不是我所做的。 – Wildaker 2016-01-23 09:36:11

1

我对我的Cocoa(Mac OS X)应用程序有同样的问题。以下是我如何解决它:

首先,请确保在单独的调度队列上处理捕获的帧。还要确保你没有准备处理的任何帧都被丢弃;这是默认设置,但我将下面的标记设置为只是为了证明我依赖它。

videoQueue = dispatch_queue_create("com.ohmware.LabCam.videoQueue", DISPATCH_QUEUE_SERIAL); 
    videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 
    [videoOutput setAlwaysDiscardsLateVideoFrames:YES]; 
    [videoOutput setSampleBufferDelegate:self 
            queue:videoQueue]; 
    [session addOutput:videoOutput]; 

然后,当处理委托中的帧时,您可以简单地让线程休眠所需的时间间隔。委托人未醒来处理的帧被悄悄丢弃。我实现了用于计数丢失帧的可选方法,只是作为完整性检查;我的应用程序从不记录使用这种技术丢弃任何帧。

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
    didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection; 
{ 
    OSAtomicAdd64(1, &videoSampleBufferDropCount); 
} 

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection; 
{ 
    int64_t savedSampleBufferDropCount = videoSampleBufferDropCount; 
    if (savedSampleBufferDropCount && OSAtomicCompareAndSwap64(savedSampleBufferDropCount, 0, &videoSampleBufferDropCount)) { 
     NSLog(@"Dropped %lld video sample buffers!!!", savedSampleBufferDropCount); 
    } 
    // NSLog(@"%s", __func__); 
    @autoreleasepool { 
     CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
     CIImage * cameraImage = [CIImage imageWithCVImageBuffer:imageBuffer]; 
     CIImage * faceImage = [self faceImage:cameraImage]; 
     dispatch_sync(dispatch_get_main_queue(),^{ 
      [_imageView setCIImage:faceImage]; 
     }); 
    } 
    [NSThread sleepForTimeInterval:0.5]; // Only want ~2 frames/sec. 
} 

希望这会有所帮助。

+0

谢谢,但我想我不想这样做,只是丢帧。当您限制帧持续时间时,AV框架将在低照度条件下增加每帧的曝光量,如果您丢帧,则不会获得此优势。此外,每帧的处理时间会有所不同,当您限制最小/最大帧持续时间时,您可以让框架适应您。我不认为我想要自己计算间隔。 – danielv 2013-03-22 16:44:41

2

想想这样: 您可以让捕捉设备限制帧持续时间,以便您获得更好的曝光。 好。 你想以更高的帧率预览。 如果您要以更高的速率进行预览,那么捕捉设备(相机)将没有足够的时间来曝光相框,以便在捕捉的帧处获得更好的曝光。 这就像要求在预览中看到不同的帧比捕获的帧。

我认为,如果可能的话,这也会是一种负面的用户体验。

+0

你的意思很有道理。但是,如果您阅读“AV Foundation编程指南”和“AVCaptureConnection类参考”的文档,您会发现预览图层和实际输出设备具有不同的AVCaptureConnection。最小/最大帧持续时间参数在AVCaptureConnection对象上独立设置,实际上预览的连接和捕捉输出连接具有不同的值。这并不奇怪,苹果公司有误导性的文档和不一致的API,但你可以理解为什么这可以完全抛弃一个... – danielv 2013-03-28 13:13:06

+1

我还没有测试过它,但应该可以有其他的方式:低fps上预览图层和更高的捕获帧。这可能就是你获得独立捕获连接的原因。 – gWiz 2013-03-28 13:26:40

+0

嗨@gWiz你能帮忙解释一下帧持续时间以及在这个问题中使用不同值的含义吗?谢谢! http://stackoverflow.com/questions/34937008/exporting-videos-on-ios-understanding-and-setting-frame-duration-property – Crashalot 2016-01-22 00:37:03