18

I believe this used to be done with captureOutput.minFrameDuration. However, this is deprecated in iOS 5.

Instead I apparently need to use AVCaptureConnection's video.minFrameDuration. So I have my input, my output, I add them both the the capture session - where can I get access to the capture connection? I think it is created for me by the session, but where?

I could try adding the I/O using addInputWithNoConnections and addOutputWithNoConnections and then maybe creating the connection manually. But this seems like a bit of hassle just to set a maximum frame rate. Plus, Xcode complains that these methods don't exist.

makes
  • 6,438
  • 3
  • 40
  • 58
chris838
  • 5,148
  • 6
  • 23
  • 27

4 Answers4

28

Chris, I think I have solved this problem:

(Edit -- See Tomas Camin's comment below on correct way of checking whether videoMinFrameDuration videoMaxFrameDuration are supported, although below code worked fine when posted)

The line below gives access to the AVCaptureConnection object associated with the AVCaptureVideoDataOutput object:

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

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

If you're using (as I am), the didOutputSampleBuffer delegate, you can confirm that the video frame rate in the fromConnection AVCaptureConnection * value passed in to the delegate has been correctly set and "remembered" by the above code.

Note that you need to set both videoMinFrameDuration and videoMaxFrameDuration to the same value to successfully clamp the frame rate -- setting min on its own did not seem to work when testing on an iPhone 4s. This doesn't seem to be documented.

Josh

Andrew
  • 567
  • 2
  • 5
  • 18
Josh Greifer
  • 3,151
  • 24
  • 25
  • Awesome! Thanks Josh. And I'm also finding that both videoMinFrameDuration and videoMaxFrameDuration need to be set on iPhone 4 and 4S. – chris838 Nov 22 '11 at 09:33
  • I wish I could give you 10 points for this! The old deprecated method use to work fine in 4.3, and I wasted a lot of time before finding this thread! I'm just a bug report on this if anyone wants to dup it: Bug ID# 10524664. – David H Dec 04 '11 at 14:23
  • Note that the correct way to check if `videoMinFrameDuration` and `videoMinFrameDuration` are supported is to use `[AVCaptureConnection isVideoMinFrameDurationSupported]` and `[AVCaptureConnection isVideoMaxFrameDurationSupported]` – Tomas Camin May 12 '12 at 09:13
  • 2
    I'm working with iOS SDK 5.1: `[AVCaptureConnection isVideoMinFrameDurationSupported]` and `[AVCaptureConnection isVideoMaxFrameDurationSupported]` do not exist, instead they are properties `conn.isVideoMinFrameDurationSupported` and `conn.isVideoMaxFrameDurationSupported`. – Andrew Jul 04 '12 at 22:49
  • Also note that setting `activeVideoMinFrameDuration` and `activeVideoMaxFrameDuration` must be done _after_ adding it to your session. See https://stackoverflow.com/a/34720352/1271826. – Rob May 31 '22 at 17:48
5

AVCaptureConnection videoMinFrameDuration is deprecated. Use AVCaptureDevice activeVideoMinFrameDuration/activeVideoMaxFrameDuration. First code snippet in AVCaptureDevice class reference answers the question.

kiranpradeep
  • 10,859
  • 4
  • 50
  • 82
  • AVCaptureConnection videoMinFrameDuration works fine without warnings on OS X 10.9. – kareman May 21 '14 at 11:59
  • @KareMorstol This question is both titled and tagged ios. Not osx. Hence the ios specific answer. More at this [SO](http://stackoverflow.com/q/19168970/1180117) question. – kiranpradeep May 21 '14 at 14:09
2

Assume the following members.

AVCaptureConnection         *videoConnection;
AVCaptureVideoDataOutput    *videoOutput;
AVCaptureDeviceInput        *videoInput;

Then you would do something like the following. I have not tested this. This is just a guess from reading the docs.

AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];   

if ( videoDevice ) {
    NSError *error;
    videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; 

    [captureSession addInput:videoInput];   
}

videoOutput = [[AVCaptureVideoDataOutput alloc] init];
//setup video options
if ([captureSession canAddOutput:videoOutput])
    [captureSession addOutput:videoOutput];

videoConnection = [[AVCaptureConnection alloc] initWithInputPorts:captureSession.inputs output:videoOutput];
videoConnection.videoMinFrameDuration = CMTimeMake(1, frameRate);

[captureSession addConnection:videoConnection];

I have not converted my own code over to this yet. I will respond back with working code when I do the conversion. If you have multiple inputs added to the captureSession then you may need to explicitly load the one you want into an array. e.g.

ports = [NSArray arrayWithObject:videoInput];

Then pass this into the initializer for the AVCaptureConnection.

Steve McFarlin
  • 3,576
  • 1
  • 25
  • 24
  • Thanks Steve, my compiler is complaining about initWithInputPorts for AVCaptureConnection? – chris838 Nov 16 '11 at 14:01
  • I am not sure why. I am referencing the [AVCaptureConnection](http://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVCaptureConnection_Class/Reference/Reference.html) docs. As I said I did not test this code. I wrote it 'blind' by just looking at the docs. joshgreifer looks to have a cleaner solution. **AVCaptureVideoDataOutput** inherits from **AVCaptureOutput** which has the **connectionWithMediaType** message. – Steve McFarlin Nov 22 '11 at 01:49
  • 1
    @chris838 it's complaining about `initWithInputPorts` because the method is only available in Mac OS X v10.7 and later. – Tomas Camin May 12 '12 at 08:13
0

As mentioned by Kiran, AVCaptureConnection videoMinFrameDuration is deprecated since iOS 7.

Just to be more specific, 'updating' Apple's example:

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

AVCaptureDeviceInput *input = ... // Following the example

// ** Create and Configure the Video Data Output **
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];

[session addOutput:output];

output.videoSettings = @{
                             (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)
                             };

device.activeVideoMinFrameDuration = CMTimeMake(1, 15);
bauerMusic
  • 5,470
  • 5
  • 38
  • 53