CMSampleBufferRef have always same video resolution? - ios

I' trying to capture video by AVAssetWriter and AVCaptureOutput
You can find sample project here.
The video should be in portrait mode with any resolution. The main problem that it should be in portrait mode.
I'm trying to set different setting, but in the end, video is rotated and scaled to size (1920x1080) on iPhone SE.
Is it possible to control this resolution? Or at least orientation?

Video resolution is determined by the AVCaptureSession sessionPreset. You're setting that to medium, so you're getting the resolution that comes with that. If you want a different resolution, pass a different session preset, or use AVCaptureDevice to set a specific capture format. (For a good overview of capture session presets vs device formats, go back to this WWDC13 video.)
Per this Apple Developer Q&A, you need to set an orientation on the capture connection after you start the capture session in order to get "physically" rotated frame buffers (at a capture performance cost), or set the transform property on your asset writer (so that buffers are recorded in the sensor's native orientation, but clients display it in your intended orientation).

Related

How to configure AVCaptureSession for high res still images and low res (video) preview?

I'd like to capture high resolution still images using AVCaptureSession. Therefore AVCaptureSession preset is set to Photo.
This is working well so far. On an iPhone 4 the final still image resolution is at its maximum of 2448x3264 pixels and the preview (video) resolution is 852x640 pixels.
Now, because the preview frames are analyzed to detect objects in the scene, I'd like to lower their resolution. How can this be done?
I've tried to set AVVideoSettings with a lower width/height to AVCaptureVideoDataOutput, but this leads to the following error message:
AVCaptureVideoDataOutput setVideoSettings:] - videoSettings dictionary contains one or more unsupported (ignored) keys: (AVVideoHeightKey, AVVideoWidthKey
So it seems this is not the right approach to configure the size of the preview frames received by AVCaptureVideoDataOutput / AVCaptureVideoDataOutputSampleBufferDelegate. Do you have any ideas how the resolution of the preview frames can be configured?
Any advise is welcome,
Thank you.
If you want to specify the settings manually, you need to set activeFormat on the AVCaptureDevice. This will be implicitly set the session preset to AVCaptureSessionPresetInputPriority.
The activeFormat takes a AVCaptureDeviceFormat but you can only take one from the list of AVCaptureDevice.formats. You'll need to go through the list and find one that fits your needs. Specifically, check that highResolutionStillImageDimensions is high enough for desired still capture and formatDescription (which needs to be inspected with CMFormatDescription* functions, e.g., CMVideoFormatDescriptionGetDimensions) matches your desired preview settings.
Just for the records: I ended up configuring AVCaptureSession in preset Low while aiming the camera. As soon as the shutter is triggered, the app switches to preset Photo, performs a focus run and takes the picture. This way it takes between 1 and 2.5 seconds to take a picture, which isn't that great, but it's at least a workaround.
To lower the size of the output of AVCaptureVideoDataOutput you can set the bitrate to be lower thus producing a small sample size.
commonly used keys for AVCaptureVideoDataOutput are:
AVVideoAverageBitRateKey
AVVideoProfileLevelKey
AVVideoExpectedSourceFrameRateKey
AVVideoMaxKeyFrameIntervalKey
For example:
private static let videoCompressionOptionsMedium = [AVVideoAverageBitRateKey : 1750000,
AVVideoProfileLevelKey : AVVideoProfileLevelH264BaselineAutoLevel,
AVVideoExpectedSourceFrameRateKey : Int(30),
AVVideoMaxKeyFrameIntervalKey : Int(30)]

Can AVCaptureSession use custom resolution

I'm using AVCaptureSession to capture and record a video.
I need to record the video at a 4:3 ratio, and with a good resolution.
Is there a way to specify a custom resolution when capturing using AVCaptureSession?
I tried using the native presets but the problem is that I need to capture at a 4:3 ratio, and almost all of the presets are 16:9. and the ones that are 4:3 has very low resolution.
I can't fide any other way to change the preset to a custom one, what if I need to capture a 4:3 video with better resolution? Any ideas?
AVCaptureSession presets cover only a small subset of the capabilities of a device camera (the ones most apps want quick, easy access to). For more fine-grained control — such as to select a capture resolution not provided by a session preset — you need to use capture formats instead.
Look at the capture device's formats property, an array of AVCaptureDeviceFormat objects. Enumerate through that array until you find one whose dimensions are what you want. To get the dimensions, look at the format's underlying CMFormatDescription:
let fdesc = format.formatDescription
let dims = CMVideoFormatDescriptionGetDimensions(fdesc)
NSLog("%d x %d", dims.width, dims.height)
Once you've found the format you want, lock the device for configuration and set its activeFormat:
if try device.lockForConfiguration() {
device.activeFormat = myChosenFormat
// set up other things like activeVideoMinFrameDuration if you want
device.unlockForConfiguration()
}
You can find out more about configuring a capture session via AVCaptureDeviceFormat in Apple's programming guide and the WWDC2013 session that introduced device formats back in iOS 7.0. (Most of what you'll find about this topic is aimed at slow-motion video, taking high-res stills during video, and other things that you can't do with session presets, but those aren't the only things you can do with capture formats.)
Just record at the given aspect ratio and use an AVMutableComposition to crop the output video to the required aspect ratio: If you adjust the preview layer to mask to 4:3 this will appear seamless to the user.

Retrieve iOS videocamera resolution

I need to retrieve the resolution in pixels of a movie captured by iOS camera of the iPhone...
Is there a library like UIDevice that check which type of device I'm using, also for the camera information?
Everything depends in which mode you'll start capturing video.
According to this link: https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html#//apple_ref/doc/uid/TP40010188-CH5-SW30
You can try to capture video with AVCaptureSessionPresetHigh preset, and than check what's the size of captured image.
This should give you highest video resolution in recording mode.

iOS Camera Programming - How to get maximum resolution images in the didOutputSampleBuffer callback

I have this camera App where I'd like to get the max resolution image in the didOutputSampleBuffer callback. Right now all the frames I receive in the callback are 852 x 640 (I am using an iPhone 4 for testing). Only when I request for a still image capture (via captureStillImageAsynchronouslyFromConnection) do I get one - and only one - frame corresponding to the actual image captured in the highest resolution of the device - 2592x1936.
Is it possible to set things up so that I constantly receive frames of resolution - 2592x1936 in didOutputSampleBuffer? Then I would like to save some of these frames as images in the callback without having to go through captureStillImageAsynchronouslyFromConnection to capture an image.
Video output can't support the full resolution that you see when capturing still images. Look at the table given in Use Capture Outputs to Get Output from a Session for a list of supported resolutions.
If you want to change the resolution set the appropriate setting on your camera session like so:
cameraSession.sessionPreset = AVCaptureSessionPresetHigh;
Note that AVCaptureSessionPresetPhoto isn't possible with video capture.

iOS AVFoundation Video Capture Orientation Options

I have an app that I would like to have video capture for the front-facing camera only. That's no problem. But I would like the video capture to always be in landscape, even when the phone is being held in portrait.
I have a working implementation based on the AVCamDemo code that Apple published. And borrowing from the information in this tech note, I am able to specify the orientation. There's just one trick: while the video frame is oriented correctly, the contents still appear as though shot in portrait:
I'm wondering if I'm just getting boned by the physical constraints of the hardware: is the image sensor just oriented this way? The referenced tech note above makes this note:
Important: Setting the orientation on a still image output and movie
file output doesn't physically rotate the buffers. For the movie file
output, it applies a track transform (matrix) to the video track so
that the movie is rotated on playback, and for the still image output
it inserts exif metadata that image viewers use to rotate the image
properly when viewing later.
But my playback of that video suggests otherwise. Any insight or suggestions would be appreciated!
Thanks,
Aaron.
To answer your question, yes, the image sensor is just oriented that way. The video camera is an approx 1-megapixel "1080p" camera that has a fixed orientation. The 5MP (or 8MP for 4S, etc) still camera also has a fixed orientation. The lenses themselves don't rotate nor do any of the other camera bits, and hence the feed itself has a fixed orientation.
"But wait!", you say, "pictures I take with the camera app (or API) get rotated correctly. Why is that?" That's cuz iOS takes a look at the orientation of the phone when a picture is taken and stores that information with the picture (as an Exif attachment). Yet video isn't so flagged -- and each frame would have to be individually flagged, and then there's issues about what to do when the user rotates the phone during video....
So, no, you can't ask a video stream or a still image what orientation the phone was in when the video was captured. You can, however, directly ask the phone what orientation it is in now:
UIDeviceOrientation currentOrientation = [UIDevice currentDevice].orientation;
If you do that at the start of video capture (or when you grab a still image from a video feed) you can then use that information to do your own rotation of playback.

Resources