1
votes

I am trying to implement video capture in my app using AVFoundation. I have the following code under viewDidLoad:

session = [[AVCaptureSession alloc] init];
movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
videoInputDevice = [[AVCaptureDeviceInput alloc] init];
AVCaptureDevice *videoDevice = [self frontFacingCameraIfAvailable];

if (videoDevice)
{
    NSError *error;

    videoInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];

    if (!error)
    {
        if ([session canAddInput:videoInputDevice])
            [session addInput:videoInputDevice];
        else 
            NSLog (@"Couldn't add input.");
    }

}


AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
NSError *audioError = nil;
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&audioError];

if (audioInput)
{
    [session addInput:audioInput];
}

movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];

Float64 TotalSeconds = 35;          //Total seconds
int32_t preferredTimeScale = 30;    //Frames per second
CMTime maxDuration = CMTimeMakeWithSeconds(TotalSeconds, preferredTimeScale);   
movieFileOutput.maxRecordedDuration = maxDuration;

movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024;                        

if ([session canAddOutput:movieFileOutput])
    [session addOutput:movieFileOutput];

[session setSessionPreset:AVCaptureSessionPresetMedium];
if ([session canSetSessionPreset:AVCaptureSessionPreset640x480])        //Check size based configs are supported before setting them
    [session setSessionPreset:AVCaptureSessionPreset640x480];

[self cameraSetOutputProperties];


[session startRunning];

This code is in the implementation for a button that is to start the capture, among other things:

NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:outputPath])
{
    NSError *error;
    if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
    {
        //Error - handle if requried
    }
}
[outputPath release];
//Start recording
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
[outputURL release];

When I try to run it on a device, it crashes when I try to load the view that all of this is supposed to happen on. Xcode gives me a "Thread 1: EXC_BAD_ACCESS (code=1, address=0x4) at:

AVFoundation`-[AVCaptureDeviceInput _setDevice:]:
(stuff)
0x3793f608:  ldr    r0, [r1, r0]

The error is given at that last line. I assume this has something to do with the AVCaptureDeviceInput somewhere, but I am blanking on what it could be. Does anyone have any idea what I am missing here? Thanks.

Edit: After fiddling with breakpoints, I've figured out that the crash happens at this line:

AVCaptureDevice *videoDevice = [self frontFacingCameraIfAvailable];

So something to do with that method? Here's the implementation file that I have for it, maybe something is wrong there.

NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *captureDevice = nil;
for (AVCaptureDevice *device in videoDevices)
{
    if (device.position == AVCaptureDevicePositionFront)
    {
        captureDevice = device;
        break;
    }
}

//  couldn't find one on the front, so just get the default video device.
if ( ! captureDevice)
{
    captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}

return captureDevice;

Edit 2: Could it maybe be that I am using

AVCaptureDevice *videoDevice = [self frontFacingCameraIfAvailable];

and the 'self' is throwing a wrench in it somehow? I know that when creating a CALayer it is possible to do

CALayer *aLayer = [CALayer layer];

but I don't know the AVCaptureDevice equivalent of this, if there is one. I am not sure what else it could be, by all accounts my code seems fine and I've tried cleaning the project, restarting Xcode, restarting the computer, etc.

2
when you say the last line, what line are you specifically talking about? The last line of code in your post is a release.Dima
sorry, I meant the last line of the last code block, the 0x3793f608. that's the only place I get any sort of error.lunadiviner

2 Answers

1
votes

I'm pretty sure the problem is that you're running the program on the simulator. The simulator can't use those resources.

0
votes

Managed to fix this (maybe).

Added

@property (nonatomic, retain) AVCaptureDeviceInput *videoInputDevice; 

to the interface, synthesized it in the implementation, and used these methods to get the front facing camera:

- (AVCaptureDevice *) cameraWithPosition:(AVCaptureDevicePosition) position
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) {
    if ([device position] == position) {
        return device;
    }
}
return nil;
}

-(AVCaptureDevice *)frontFacingCamera
{
return [self cameraWithPosition:AVCaptureDevicePositionFront];

Then assigned it with

videoInputDevice = [AVCaptureDeviceInput deviceInputWithDevice:[self frontFacingCamera] error:&error];

Not 100% sure if it works yet because now it's having trouble saving, but it's not crashing anymore. Will come back and update this when I know for sure if it works or not.