在iOS 7中,AVCapture捕获帧速率为60fps

我正在开发一个应用程序,需要尽可能多地捕捉framebuffer。 我已经想出了如何强制iPhone以60 fps捕捉,但是

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 

方法每秒仅调用15次,这意味着iPhone会将捕捉输出降级到15 fps。

有没有人遇到这样的问题? 有没有可能增加捕捉帧率?

更新我的代码:

 camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if([camera isTorchModeSupported:AVCaptureTorchModeOn]) { [camera lockForConfiguration:nil]; camera.torchMode=AVCaptureTorchModeOn; [camera unlockForConfiguration]; } [self configureCameraForHighestFrameRate:camera]; // Create a AVCaptureInput with the camera device NSError *error=nil; AVCaptureInput* cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error]; if (cameraInput == nil) { NSLog(@"Error to create camera capture:%@",error); } // Set the output AVCaptureVideoDataOutput* videoOutput = [[AVCaptureVideoDataOutput alloc] init]; // create a queue to run the capture on dispatch_queue_t captureQueue=dispatch_queue_create("captureQueue", NULL); // setup our delegate [videoOutput setSampleBufferDelegate:self queue:captureQueue]; // configure the pixel format videoOutput.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey, nil]; // Add the input and output [captureSession addInput:cameraInput]; [captureSession addOutput:videoOutput]; 

我在这里采取了configureCameraForHighestFrameRate方法https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVCaptureDevice_Class/Reference/Reference.html

我在iPhone 5上以60 fps的速度采集样本,在iPhone 5s上采集120 fps的样本,在captureOutput中进行实时运动检测时以及使用AVAssetWriter将帧保存到video时都是如此。

您必须将AVCaptureSession设置为支持60 fps的格式:

 AVsession = [[AVCaptureSession alloc] init]; AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDeviceInput *capInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; if (capInput) [AVsession addInput:capInput]; for(AVCaptureDeviceFormat *vFormat in [videoDevice formats] ) { CMFormatDescriptionRef description= vFormat.formatDescription; float maxrate=((AVFrameRateRange*)[vFormat.videoSupportedFrameRateRanges objectAtIndex:0]).maxFrameRate; if(maxrate>59 && CMFormatDescriptionGetMediaSubType(description)==kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) { if ( YES == [videoDevice lockForConfiguration:NULL] ) { videoDevice.activeFormat = vFormat; [videoDevice setActiveVideoMinFrameDuration:CMTimeMake(10,600)]; [videoDevice setActiveVideoMaxFrameDuration:CMTimeMake(10,600)]; [videoDevice unlockForConfiguration]; NSLog(@"formats %@ %@ %@",vFormat.mediaType,vFormat.formatDescription,vFormat.videoSupportedFrameRateRanges); } } } prevLayer = [AVCaptureVideoPreviewLayer layerWithSession: AVsession]; prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; [self.view.layer addSublayer: prevLayer]; AVCaptureVideoDataOutput *videoOut = [[AVCaptureVideoDataOutput alloc] init]; dispatch_queue_t videoQueue = dispatch_queue_create("videoQueue", NULL); [videoOut setSampleBufferDelegate:self queue:videoQueue]; videoOut.videoSettings = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; videoOut.alwaysDiscardsLateVideoFrames=YES; if (videoOut) { [AVsession addOutput:videoOut]; videoConnection = [videoOut connectionWithMediaType:AVMediaTypeVideo]; } 

如果您想使用AVAssetWriter写入文件,还有两点意见。 不要使用像素适配器,只是用样品做广告

 [videoWriterInput appendSampleBuffer:sampleBuffer] 

其次在设置维护者使用

 [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings sourceFormatHint:formatDescription]; 

sourceFormatHint在写入速度上有所不同。

我为Swift 2.0开发了相同的function。 我在这里发布谁可能需要它的代码:

 // Set your desired frame rate func setupCamera(maxFpsDesired: Double = 120) { var captureSession = AVCaptureSession() captureSession.sessionPreset = AVCaptureSessionPreset1920x1080 let backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) do{ let input = try AVCaptureDeviceInput(device: backCamera) captureSession.addInput(input) } catch { print("Error: can't access camera") return } do { var finalFormat = AVCaptureDeviceFormat() var maxFps: Double = 0 for vFormat in backCamera!.formats { var ranges = vFormat.videoSupportedFrameRateRanges as! [AVFrameRateRange] let frameRates = ranges[0] /* "frameRates.maxFrameRate >= maxFps" select the video format desired with the highest resolution available, because the camera formats are ordered; else "frameRates.maxFrameRate > maxFps" select the first format available with the desired fps */ if frameRates.maxFrameRate >= maxFps && frameRates.maxFrameRate <= maxFpsDesired { maxFps = frameRates.maxFrameRate finalFormat = vFormat as! AVCaptureDeviceFormat } } if maxFps != 0 { let timeValue = Int64(1200.0 / maxFps) let timeScale: Int64 = 1200 try backCamera!.lockForConfiguration() backCamera!.activeFormat = finalFormat backCamera!.activeVideoMinFrameDuration = CMTimeMake(timeValue, timeScale) backCamera!.activeVideoMaxFrameDuration = CMTimeMake(timeValue, timeScale) backCamera!.focusMode = AVCaptureFocusMode.AutoFocus backCamera!.unlockForConfiguration() } } catch { print("Something was wrong") } let videoOutput = AVCaptureVideoDataOutput() videoOutput.alwaysDiscardsLateVideoFrames = true videoOutput.videoSettings = NSDictionary(object: Int(kCVPixelFormatType_32BGRA), forKey: kCVPixelBufferPixelFormatTypeKey as String) as [NSObject : AnyObject] videoOutput.setSampleBufferDelegate(self, queue: dispatch_queue_create("sample buffer delegate", DISPATCH_QUEUE_SERIAL)) if captureSession.canAddOutput(videoOutput){ captureSession.addOutput(videoOutput) } let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) view.layer.addSublayer(previewLayer) previewLayer.transform = CATransform3DMakeRotation(-1.5708, 0, 0, 1); previewLayer.frame = self.view.bounds previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; self.view.layer.addSublayer(previewLayer) captureSession.startRunning() } 

有同样的问题。 在[AVCaptureSession addInput:cameraDeviceInput]之后使用此函数修复。 不知何故,在捕捉会话开始之前,我无法更改iPad专业版的帧速率。 所以起初我在设备被添加到捕获会话后改变了video格式。

 - (void)switchFormatWithDesiredFPS:(CGFloat)desiredFPS { BOOL isRunning = _captureSession.isRunning; if (isRunning) [_captureSession stopRunning]; AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDeviceFormat *selectedFormat = nil; int32_t maxWidth = 0; AVFrameRateRange *frameRateRange = nil; for (AVCaptureDeviceFormat *format in [videoDevice formats]) { for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) { CMFormatDescriptionRef desc = format.formatDescription; CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(desc); int32_t width = dimensions.width; if (range.minFrameRate <= desiredFPS && desiredFPS <= range.maxFrameRate && width >= maxWidth) { selectedFormat = format; frameRateRange = range; maxWidth = width; } } } if (selectedFormat) { if ([videoDevice lockForConfiguration:nil]) { NSLog(@"selected format:%@", selectedFormat); videoDevice.activeFormat = selectedFormat; videoDevice.activeVideoMinFrameDuration = CMTimeMake(1, (int32_t)desiredFPS); videoDevice.activeVideoMaxFrameDuration = CMTimeMake(1, (int32_t)desiredFPS); [videoDevice unlockForConfiguration]; } } if (isRunning) [_captureSession startRunning]; }