AVCapture przechwytywanie i uzyskiwanie bufora ramek przy 60 klatkach na sekundę w systemie iOS 7

Rozwijam aplikację, która wymaga przechwytywania bufora ramek z jak największą ilością klatek na sekundę. Już wiem, jak zmusić iphone ' a do przechwytywania przy 60 fps, ale

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

Metoda jest wywoływana tylko 15 razy na sekundę, co oznacza, że iPhone obniża wydajność przechwytywania do 15 klatek na sekundę.

Czy ktoś miał taki problem? Czy istnieje możliwość zwiększenia liczby klatek na sekundę?

Update mój kod:

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

Wziąłem configureCameraForHighestFrameRate metodę tutaj https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVCaptureDevice_Class/Reference/Reference.html

Author: Alexander Taraymovich, 2013-12-02

3 answers

[3]}pobieram próbki z prędkością 60 fps na iPhonie 5 i 120 fps na iPhonie 5s, zarówno podczas detekcji ruchu w czasie rzeczywistym w captureOutput, jak i podczas zapisywania klatek na wideo za pomocą AVAssetWriter.

Musisz ustawić AVCaptureSession na format obsługujący 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];
}

Dwa inne komentarze, jeśli chcesz napisać do pliku za pomocą AVAssetWriter. Nie używaj pixelAdaptor, po prostu reklamuj próbki za pomocą

[videoWriterInput appendSampleBuffer:sampleBuffer]

Po drugie przy zakładaniu assetwritera użycie

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

SourceFormatHint robi różnicę w szybkości zapisu.

 20
Author: Sten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-12 08:41:47

Opracowałem tę samą funkcję dla Swift 2.0. Zamieszczam tutaj kod dla tych, którzy mogą go potrzebować:

// 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()
}
 3
Author: Adda_25,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-09 09:28:46

Miałem ten sam problem. Fixed by using this function after [AVCaptureSession addInput:cameraDeviceInput]. Jakoś nie mogłem zmienić liczby klatek na moim iPadzie pro przed rozpoczęciem sesji przechwytywania. Więc na początku zmieniłem format wideo po dodaniu urządzenia do sesji przechwytywania.

- (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];
}
 1
Author: Martijn Mellens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-01 12:23:35