【问题标题】:AVCapture capturing and getting framebuffer at 60 fps in iOS 7AVCapture 在 iOS 7 中以 60 fps 捕获和获取帧缓冲区
【发布时间】:2013-12-02 14:04:26
【问题描述】:

我正在开发一个需要以尽可能高的 fps 捕获帧缓冲区的应用程序。我已经想出了如何强制 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

【问题讨论】:

    标签: ios iphone camera avcapturesession frame-rate


    【解决方案1】:

    在 captureOutput 中进行实时运动检测和使用 AVAssetWriter 将帧保存到视频时,我在 iPhone 5 上以 60 fps 和在 iPhone 5s 上以 120 fps 获取样本。

    您必须将 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 写入文件,还有两个注释。不要使用 pixelAdaptor,只需使用

    广告样本
    [videoWriterInput appendSampleBuffer:sampleBuffer]
    

    其次是设置assetwriter使用时

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

    sourceFormatHint 会影响写入速度。

    【讨论】:

    • 我做的完全一样(可能除了 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange 类型),但委托方法仍然只被调用了 15 次。您能否提供初始化视频输入和输出的完整源代码?
    • 我添加了视频输出代码,很标准。您没有在 captureOutput 中进行任何减慢速度的繁重计算吗?
    • 我的代码看起来一样。我想出了如何将帧速率提高到 30 fps(我之前尝试设置会话预设),但仍然不够。我有一些计算,但出于测试目的,我禁用了它们,我仍然有 30 fps。
    • 我调试了一下,发现 [videoOutput connectionWithMediaType:AVMediaTypeVideo] 返回与 minFrameRateDuration (1,30) 的连接
    • 这个iOS编程让我抓狂!我没有怀疑很多事情取决于操作顺序。我只是在格式配置之前放了[captureSession addInput:cameraInput]; 行,它就可以了!感谢您的帮助!
    【解决方案2】:

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

    // 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()
    }
    

    【讨论】:

    • 不错!但是,我的 iPhone 6 plus 报告了以下帧率 Framerates = 所以你应该在你的回答中做一个小的补充: if frameRates.maxFrameRate == 120 || frameRates.maxFrameRate == 240 {
    • 也更改为 CMTimeMake(5,1200) 然后我的相机运行在 240
    • 我编辑我的答案。 CMTimeMake(5, 1200) 让您的相机在 240 处运行,因为 1200 / 5 = 240。在 CMTimeMake 中,第一个值是分子,第二个是分母。见stackoverflow.com/questions/12902410/…
    【解决方案3】:

    遇到了同样的问题。在[AVCaptureSession addInput:cameraDeviceInput] 之后使用此功能已修复。在捕获会话开始之前,我不知何故无法更改 iPad Pro 上的帧速率。所以起初我在设备添加到捕获会话后更改了视频格式。

    - (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];
    }
    

    【讨论】:

    • 非常适合我。谢谢。
    猜你喜欢
    • 2020-07-12
    • 1970-01-01
    • 2013-09-28
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多