How to solve the problem while recording video at 60 frames per second using iphone 4s, ipad 2?

Shortly speaking:

Get an exception when trying to record at 59 frames per second. How to solve it?

2014-09-16 15: 16: 27.740 RosyWriter [2294: 60b] ** Completion of the application to exclude the exception "NSInvalidArgumentException", reason: "activeVideoMaxFrameDuration is not supported by the active format of the receiver. Use -activeFormat.videoSupportedFrameRateRanges to detect valid ranges.

My question is in the details:

What am I trying to do?

Trying to record video at 30+ frames per second (60 frames per second or more fps ).

What have i tried so far?

  • Initially using the AVCaptureConnection property below , and then realized that the properties used were impaired.

AVCaptureConnection *conn = [output connectionWithMediaType:AVMediaTypeVideo];

CMTimeShow(conn.videoMinFrameDuration);
CMTimeShow(conn.videoMaxFrameDuration);

if (conn.isVideoMinFrameDurationSupported)
    conn.videoMinFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
if (conn.isVideoMaxFrameDurationSupported)
    conn.videoMaxFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);

reference: According to the header file (AVCaptureSession.h),

This property is deprecated on iOS, where the minimum and maximum frame rate adjustments are applied exclusively to AVCaptureDevice using the activeVideoMinFrameDuration and activeVideoMaxFrameDuration properties.

  1. Then I tried using "AVCaptureDevice" as shown below:

    -(void)setupCaptureSession
    {
        if ( _captureSession ) {
            return;
        }
    
        _captureSession = [[AVCaptureSession alloc] init];  
    
        AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
      ....................................
      ....................................
    
    _videoConnection = [videoOut connectionWithMediaType:AVMediaTypeVideo];
    
    int frameRate;
    NSString *sessionPreset = AVCaptureSessionPreset640x480;
    CMTime frameDuration = kCMTimeInvalid;
    // For single core systems like iPhone 4 and iPod Touch 4th Generation wI 
    //use a lower resolution and framerate to maintain real-time performance.
    if ( [[NSProcessInfo processInfo] processorCount] == 1 )
    {
        if ( [_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720] ) {
            sessionPreset = AVCaptureSessionPreset1280x720;
        }
        frameRate = 59;
    }
    else
    {
        // USE_GPU_RENDERER is set in the project build settings
     #if ! use_gpu_renderer
        // When using the CPU renderer we lower the resolution to 720p so that all devices can maintain real-time performance (this is primarily for A5 based devices like iPhone 4s and iPod Touch 5th Generation).
        if ( [_captureSession canSetSessionPreset:AVCaptureSessionPreset640x480] ) {
            sessionPreset = AVCaptureSessionPreset640x480;
        }
     #endif // ! use_gpu_renderer
    
        frameRate = 59;
    }
    
    _captureSession.sessionPreset = sessionPreset;
    
    frameDuration = CMTimeMake( 1, frameRate );
    
    
    
    NSError *error = nil;
    
    if ( [videoDevice lockForConfiguration:&error] ) {
        videoDevice.activeFormat = bestFormat;
        [**videoDevice setActiveVideoMaxFrameDuration:frameDuration];
        [videoDevice setActiveVideoMinFrameDuration:frameDuration**];
        [videoDevice unlockForConfiguration];
    }
    else {
        NSLog(@"videoDevice lockForConfiguration returned error %@", error);
    }
    
    self.videoOrientation = [_videoConnection videoOrientation];
    
    [videoOut release];
    
    return;
    

    }

    My problem:

    • I got an exception

2014-09-16 15:16:27.740 RosyWriter[2294:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The activeVideoMaxFrameDuration passed is not supported by the receiver active format.  Use -activeFormat.videoSupportedFrameRateRanges to discover valid ranges.'
        *** First throw call stack:
        (0x2da2ff83 0x385d2ccf 0x2c919e4f 0xb4c7d 0xb4317 0x38aba81f 0x38ac07cb 0xb42b1 0xb2539 0x302676df 0x30258e89 0x3025864d 0x302584bf 0x30257fe5 0x30255827 0x302bf33d 0x302bbfad 0x302b656b 0x302526e9 0x30251851 0x302b5ca9 0x3288baed 0x3288b6d7 0x2d9faa67 0x2d9faa03 0x2d9f91d7 0x2d963ebf 0x2d963ca3 0x302b4ed1 0x302b014d 0xb1b4d 0x38adfab7)
        libc++abi.dylib: terminating with uncaught exception of type NSException

Am I doing something wrong here?

  1. I later changed the code as


      AVCaptureDeviceFormat *bestFormat = nil;
      AVFrameRateRange *bestFrameRateRange = nil;
      for ( AVCaptureDeviceFormat *format in [videoDevice formats] ) {
        for ( AVFrameRateRange *range in format.videoSupportedFrameRateRanges ) {
            if ( range.maxFrameRate > bestFrameRateRange.maxFrameRate ) {
                bestFormat = format;
                bestFrameRateRange = range;
            }
        }
    }
    NSError *error = nil;
    
    if ( bestFormat ) {
    if ( [videoDevice lockForConfiguration:&error] ) {
        videoDevice.activeFormat = bestFormat;
        videoDevice.activeVideoMinFrameDuration = bestFrameRateRange.minFrameDuration;
        videoDevice.activeVideoMaxFrameDuration = bestFrameRateRange.maxFrameDuration;
        [videoDevice unlockForConfiguration];
        }}
    

But I get a video that is recorded at 30 frames per second using bestFrameRateRange, but not at 59 frames per second.

+4
1

:

.

float maxFrameRate = 0.0;
int maxIndex = 0;
for(int i=0;i<_videoCaptureDevice.formats.count;i++) {
    AVCaptureDeviceFormat *format = [_videoCaptureDevice.formats objectAtIndex:i];
    AVFrameRateRange *frameRateRange = [format.videoSupportedFrameRateRanges firstObject];
//You can add hard coded checking for specific format like if(frameRateRange.maxFrameRate == 240) etc I am using the max one
    if(maxFrameRate<frameRateRange.maxFrameRate) {
        maxFrameRate = frameRateRange.maxFrameRate;
        maxIndex = i;
    }
}

AVCaptureDeviceFormat *format = [_videoCaptureDevice.formats objectAtIndex:maxIndex];
AVFrameRateRange *frameRateRange = [format.videoSupportedFrameRateRanges firstObject];
[self.videoCaptureDevice lockForConfiguration:nil];
self.videoCaptureDevice.activeFormat = format;
self.videoCaptureDevice.activeVideoMinFrameDuration = frameRateRange.minFrameDuration;
self.videoCaptureDevice.activeVideoMaxFrameDuration = frameRateRange.maxFrameDuration;
[self.videoCaptureDevice  unlockForConfiguration];

if(YourFrameRate<=frameRateRange.maxFrameRate && YourFrameRate>=frameRateRange.minFrameRate) {
    if([device lockForConfiguration:&error]) {
        [device setActiveVideoMinFrameDuration:CMTimeMake(1, YourFrameRate)];
        [device setActiveVideoMaxFrameDuration:CMTimeMake(1, YourFrameRate)];
        [device unlockForConfiguration];
    } else {
        [self passError:error];
    }
}

0

All Articles