Knowing resolution of AVCaptureSession's session presets
Solution 1
According to Apple, there's no API for that. It stinks, I've had the same problem.
Solution 2
I am no AVFoundation pro, but I think the way to go is:
captureSession.sessionPreset = AVCaptureSessionPresetMedium;
AVCaptureInput *input = [captureSession.inputs objectAtIndex:0]; // maybe search the input in array
AVCaptureInputPort *port = [input.ports objectAtIndex:0];
CMFormatDescriptionRef formatDescription = port.formatDescription;
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
I'm not sure about the last step and I didn't try it myself. Just found that in the documentation and think it should work.
Searching for CMVideoDimensions
in Xcode you'll find the RosyWriter example project. Have a look at that code (I don't have time to do that now).
Solution 3
You can programmatically get the resolution from activeFormat
before capture begins, though not before adding inputs and outputs: https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVCaptureDevice_Class/index.html#//apple_ref/occ/instp/AVCaptureDevice/activeFormat
private func getCaptureResolution() -> CGSize {
// Define default resolution
var resolution = CGSize(width: 0, height: 0)
// Get cur video device
let curVideoDevice = useBackCamera ? backCameraDevice : frontCameraDevice
// Set if video portrait orientation
let portraitOrientation = orientation == .Portrait || orientation == .PortraitUpsideDown
// Get video dimensions
if let formatDescription = curVideoDevice?.activeFormat.formatDescription {
let dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription)
resolution = CGSize(width: CGFloat(dimensions.width), height: CGFloat(dimensions.height))
if (portraitOrientation) {
resolution = CGSize(width: resolution.height, height: resolution.width)
}
}
// Return resolution
return resolution
}
Solution 4
FYI, I attach here an official reply from Apple.
This is a follow-up to Bug ID# 13201137.
Engineering has determined that this issue behaves as intended based on the following information:
There are several problems with the included code:
1) The AVCaptureSession has no inputs. 2) The AVCaptureSession has no outputs.
Without at least one input (added to the session using [AVCaptureSession addInput:]) and a compatible output (added using [AVCaptureSession addOutput:]), there will be no active connections, therefore, the session won't actually run in the input device. It doesn't need to -- there are no outputs to which to deliver any camera data.
3) The JAViewController class assumes that the video port's -formatDescription property will be non nil as soon as [AVCaptureSession startRunning] returns.
There is no guarantee that the format description will be updated with the new camera format as soon as startRunning returns. -startRunning starts up the camera and returns when it is completely up and running, but doesn't wait for video frames to be actively flowing through the capture pipeline, which is when the format description would be updated.
You're just querying too fast. If you waited a few milliseconds more, it would be there. But the right way to do this is to listen for the AVCaptureInputPortFormatDescriptionDidChangeNotification.
4) Your JAViewController class creates a PVCameraInfo object in retrieveCameraInfo: and asks it a question, then lets it fall out of scope, where it is released and dealloc'ed.
Therefore, the session doesn't have long enough to run to satisfy your dimensions request. You stop the camera too quickly.
We consider this issue closed. If you have any questions or concern regarding this issue, please update your report directly (http://bugreport.apple.com).
Thank you for taking the time to notify us of this issue.
Best Regards,
Developer Bug Reporting Team Apple Worldwide Developer Relations
Solution 5
May be you can provide a list of all posible preset resolutions for every iPhone model and check which device model the app is running on? - using something like this...
[[UIDevice currentDevice] platformType] // ex: UIDevice4GiPhone
[[UIDevice currentDevice] platformString] // ex: @"iPhone 4G"
However, you have to update the list for each newer device model. Hope this helps :)
Related videos on Youtube
Francisco Ryan Tolmasky I
Updated on June 04, 2022Comments
-
Francisco Ryan Tolmasky I almost 2 years
I'm accessing the camera in iOS and using session presets as so:
captureSession.sessionPreset = AVCaptureSessionPresetMedium;
Pretty standard stuff. However, I'd like to know ahead of time the resolution of the video I'll be getting due to this preset (especially because depending on the device it'll be different). I know there are tables online you can look this up (such as here: http://cmgresearch.blogspot.com/2010/10/augmented-reality-on-iphone-with-ios40.html ). But I'd like to be able to get this programmatically so that I'm not just relying on magic numbers.
So, something like this (theoretically):
[captureSession resolutionForPreset:AVCaptureSessionPresetMedium];
which might return a CGSize of { width: 360, height: 480}. I have not been able to find any such API, so far I've had to resort to waiting to get my first captured image and querying it then (which for other reasons in my program flow is not good).
-
Francisco Ryan Tolmasky I over 12 yearsUnfortunately this is only set after the video starts shooting, so still no good (gave you a point though).
-
Christian Beer over 12 yearsYeah, I didn't try. That's a pity there is no such API, though. Thanks for the point :)
-
JongAm Park over 11 years@Dex I did call "startRunning", but the CMVideoFormatDescriptionGetDimensions() keeps giving me { 0, 0} I called them while an app is being launched. Will that matter?
-
Dex over 11 years@JongAmPark It's been a while since I've messed with this but I think you must wait for it to spool up completely and actually capture a frame via the
captureOutput
method. It's very annoying and caused me many headaches when writing my app. -
JongAm Park about 11 years@Dex Thank you, Dex. I got an official answer from Apple. It's simply saying that I had to wait more until the video pipeline is ready and working. Also, the commenter told that even output should be connected. Currently, the bugreport site is down. When it's up, let me copy & paste their comment here.
-
spring about 11 yearsThe code above worked for me - calling it after
[capSession commitConfiguration]
, it works when switching between front and back cameras. What a silly info scavenger hunt! -
Brad Moore over 10 yearsI was thinking about doing this, but the apple docs only list up until the iPhone 4.
-
mahboudz over 9 yearsbest to use AVCaptureInputPortFormatDescriptionDidChangeNotification as the place where you get the formatDescription and dimensions.
-
Peter Lapisu over 9 yearsiOS8 see here stackoverflow.com/questions/25902122/…
-
Crashalot about 8 yearsThere's no API, but there is a way to programmatically discover the video resolution before capture begins. Answer here: stackoverflow.com/a/35470937/144088
-
Rajat Mishra almost 4 years@Crashalot I was thinking then how snapchat does it? Because in snapchat, the camera is in full screen with no stretching/zommed issue. And when I saved a story to Gallery, then the image/video dimensions (for iPhone X) was 1122x2208. Thanks
-
Iskeraet about 3 yearsThis can be shortened to just let formatDescription = <cameraGoesHere>.activeFormat.formatDescription let dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription) print(dimensions)