Capture video full screen with AVCaptureSession - ios

I need my app to display a live preview of what the front camera is filming, and this video stream's dimensions need to match the screen size of the device.
But there are black bars appearing at the top and bottom of the preview view...
How can capture and preview video that has the dimensions of the full screen? Note I don't want to resize the video!
Below is my code:
session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetPhoto;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
[session addInput:input];
UIView *cameraPreviewView = [[UIView alloc] initWithFrame:self.view.frame] ;
[self.view addSubview:cameraPreviewView];
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
[session addOutput:output];
dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
[output setSampleBufferDelegate:self queue:queue];
AVCaptureVideoPreviewLayer *cameraPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
cameraPreviewLayer.frame = cameraPreviewView.bounds;
[cameraPreviewView.layer addSublayer:cameraPreviewLayer];
[cameraPreviewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[cameraPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
[session startRunning];

Related

AVFoundation custom video recorder audio issues

I try to learn how to create custom video recorder, everything work fine except when the audio having a lot of noisy sound. I try in the system camera, instagram or any other camera app their audio quality is very good and don't have some kind of low level sound. Beside, the recorded volume of the video also significantly lower compare to other camera app. I can't found any answer on stackoverflow which most of them having answer about AVAudioSession but not on AVCaptureSession.
Here is the code how I implement the recorder
_session = [[AVCaptureSession alloc]init];
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:[devices objectAtIndex:0] error:nil];
if ([_session canAddInput:audioInput])
[_session addInput:audioInput];
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];
if ( [_session canAddInput:deviceInput] )
[_session addInput:deviceInput];
_videoOutput = [[AVCaptureVideoDataOutput alloc] init];
_videoOutput.alwaysDiscardsLateVideoFrames = NO;
if ( [_session canAddOutput:_videoOutput] )
[_session addOutput:_videoOutput];
_audioOutput = [[AVCaptureAudioDataOutput alloc] init];
if ( [_session canAddOutput:_audioOutput] )
[_session addOutput:_audioOutput];
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = [[self view] layer];
[rootLayer setMasksToBounds:YES];
[previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height)];
[rootLayer insertSublayer:previewLayer atIndex:0];
[_session setSessionPreset:AVCaptureSessionPresetHigh];
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[_videoOutput setSampleBufferDelegate:self queue:queue];
[_audioOutput setSampleBufferDelegate:self queue:queue];
AVCaptureConnection *videoConnection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo];
[videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
[_session startRunning];
The video quality is fine and the code working, just having trouble on the audio part. So
How can I improve the audio quality when recording a video?
How can I increase the recording volume of the video?
I know how to increase it when just pure recording an audio with the code below but not when recording video.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:(AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionAllowBluetooth) error:&sessionCategoryError];
Ok I finally figure it out. After create the AVCaptureSession do the following code.
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:(AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionAllowBluetooth) error:nil];
[audioSession setActive:YES error:nil];
_session = [[AVCaptureSession alloc]init];
//the 2 line below is very important.
_session.usesApplicationAudioSession = YES;
_session.automaticallyConfiguresApplicationAudioSession = NO;
Now the ouput audio of the video is even better than the system

Remove top and bottom gray bar from AVCaptureSession

I am using AVCaptureSession to record video.I want to open camera on full screen but there is gray bar is displaying on top and bottom. I am using following code-
-(void)addCamera
{
session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = self.view.bounds;
[self.view.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
AVCaptureDevicePosition currentCameraPosition = [input device].position;
currentCameraPosition = AVCaptureDevicePositionFront;
if (!input)
{
// Handle the error appropriately.
NSLog(#"ERROR: trying to open camera: %#", error);
}
[session addInput:input];
}
I just change the frame of the captureVideoPreviewLayer and the camera is showing on full screen.

Custom camera works, live preview does not

I'm attempting to build a custom camera app.
Tasks:
Shows an live image preview.
Allows you to tap anywhere on the screen to capture an image.
Displays the resulting image above the live image preview.
Currently everything works except for task 1. The view that contains my live image preview remains it's background color (or remains transparent when no background color is selected), even though the camera is operational and an image is displayed when the screen is tapped. Any ideas? I've referred to this previous discussion and I think I'm covering all my bases: AVFoundation camera preview layer not working
What am I missing?
-(void)viewWillAppear:(BOOL)animated{
session = [[AVCaptureSession alloc] init];
[session setSessionPreset:AVCaptureSessionPresetPhoto];
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
if ([session canAddInput:deviceInput]) {
[session addInput:deviceInput];
}
AVCaptureVideoPreviewLayer *previewlayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[previewlayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = [[self view] layer];
[rootLayer setMasksToBounds:YES];
CGRect frame = self.frameforCapture.frame;
[previewlayer setFrame:frame];
[rootLayer insertSublayer:previewlayer atIndex:0];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
[session startRunning];
//....
}

How can i take a picture using AVCaptureSession

I have a code that set a camera view as a subview, what i need is when i click a button it takes a picture from this AVCaptureSession and save it in to the photo library, how can i achive this?
Heres is my code:
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureOutput *output = [[AVCaptureStillImageOutput alloc] init];
[session addOutput:output];
//Setup camera input
NSArray *possibleDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
//You could check for front or back camera here, but for simplicity just grab the first device
AVCaptureDevice *device = [possibleDevices objectAtIndex:1];
NSError *error = nil;
// create an input and add it to the session
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; //Handle errors
//set the session preset
session.sessionPreset = AVCaptureSessionPresetMedium; //Or other preset supported by the input device
[session addInput:input];
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
previewLayer.affineTransform = CGAffineTransformMakeRotation(M_PI_2);
//Set the preview layer frame
previewLayer.frame = CGRectMake(45, 55, 512, 387);
//Now you can add this layer to a view of your view controller
[self.cameraPlace.layer addSublayer:previewLayer];
[session startRunning];

Get Camera Preview to AVCaptureVideoPreviewLayer

I was trying to get the camera input to show on a preview layer view.
self.cameraPreviewView is tied to a UIView in IB
Here is my current code that I put together from the AV Foundation Programming Guide. But the preview never shows
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
NSLog(#"Couldn't create video capture device");
}
[session addInput:input];
// Create video preview layer and add it to the UI
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
UIView *view = self.cameraPreviewView;
CALayer *viewLayer = [view layer];
newCaptureVideoPreviewLayer.frame = view.bounds;
[viewLayer addSublayer:newCaptureVideoPreviewLayer];
self.cameraPreviewLayer = newCaptureVideoPreviewLayer;
[session startRunning];
So after some trial and error and looking at apple's AVCam Sample Code
I wrapped the PreviewLayer code and session startRunning into a grand central dispatch block like so and it started working.
dispatch_async(dispatch_get_main_queue(), ^{
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
UIView *view = self.cameraPreviewView;
CALayer *viewLayer = [view layer];
newCaptureVideoPreviewLayer.frame = view.bounds;
[viewLayer addSublayer:newCaptureVideoPreviewLayer];
self.cameraPreviewLayer = newCaptureVideoPreviewLayer;
[session startRunning];
});
here is my code, it works perfect for me , you can refer to it
- (void)initCapture
{
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];
if (!captureInput) {
return;
}
AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
/* captureOutput:didOutputSampleBuffer:fromConnection delegate method !*/
[captureOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[captureOutput setVideoSettings:videoSettings];
self.captureSession = [[AVCaptureSession alloc] init];
NSString* preset = 0;
if (!preset) {
preset = AVCaptureSessionPresetMedium;
}
self.captureSession.sessionPreset = preset;
if ([self.captureSession canAddInput:captureInput]) {
[self.captureSession addInput:captureInput];
}
if ([self.captureSession canAddOutput:captureOutput]) {
[self.captureSession addOutput:captureOutput];
}
//handle prevLayer
if (!self.captureVideoPreviewLayer) {
self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
}
//if you want to adjust the previewlayer frame, here!
self.captureVideoPreviewLayer.frame = self.view.bounds;
self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer: self.captureVideoPreviewLayer];
[self.captureSession startRunning];
}

Resources