簡體   English   中英

AVCapture在iOS 7中以60 fps捕獲和獲取幀緩沖

[英]AVCapture capturing and getting framebuffer at 60 fps in iOS 7

我正在開發一個應用程序,它需要盡可能多地捕獲幀緩沖區。 我已經想出如何強制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將幀保存到視頻時。

您必須將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]

其次在設置資產編寫者時使用

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

sourceFormatHint在寫入速度方面有所不同。

我為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()
}

有同樣的問題。 [AVCaptureSession addInput:cameraDeviceInput]之后使用此函數修復。 不知何故,我無法在捕獲會話開始之前更改我的iPad專業版的幀速率。 因此,首先我將設備添加到捕獲會話后更改了視頻格式。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM