In my OSX application I'm using code below to show preview from camera.
[[self session] beginConfiguration];
NSError *error = nil;
AVCaptureDeviceInput *newVideoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (captureDevice != nil) {
[[self session] removeInput: [self videoDeviceInput]];
if([[self session] canAddInput: newVideoDeviceInput]) {
[[self session] addInput:newVideoDeviceInput];
[self setVideoDeviceInput:newVideoDeviceInput];
} else {
DLog(@"WTF?");
}
}
[[self session] commitConfiguration];
Yet, I need to detect the exact time when the preview from the camera becomes available.
In other words I'm trying to detect the same moment like in Facetime under OSX, where animation starts once the camera provides the preview.
What is the best way to achieve this?
I know this question is really old, but I stumbled upon it too when I was looking for this same question, and I have found answers so here goes.
For starters, AVFoundation is too high level, you'll need to drop down to a lower level, CoreMediaIO. There's not a lot of documentation on this, but basically you need to perform a couple queries.
To do this, we'll use a combination of calls. First,
CMIOObjectGetPropertyDataSize
lets us get the size of the data we'll query for next, which we can then use when we callCMIOObjectGetPropertyData
. To set up the get property data size call, we need to start at the top, using this property address:Next, we'll set up some variables to keep the data we'll need:
From this point on, we'll need to wait until we get some data out, so let's busy loop:
Once we get past this point in our execution,
devices
will point to potentially many devices. We need to loop through them, somewhat like this:Finally, clean up
devices
Now at this point, you'll want to use that object ID you saved above to make another query. We need a new property address:
This tells CoreMediaIO that we want to know if the device is currently running somewhere (read: in any app), wildcarding the rest of the fields. Next we get to the meat of the query,
camera
below corresponds to the ID you saved before:With the above code samples you should have enough to test whether or not the camera is in use. You only need to get the device once (the first part of the answer); the check for if it's in use however, you'll have to do at any time you want this information. As an extra exercise, consider playing with
CMIOObjectAddPropertyListenerBlock
to be notified on event changes for the in use property address we used above.While this answer is nearly 3 years too late for the OP, I hope it helps someone in the future. Examples here are given with Swift 3.0.
The previous answer from the user jer is definitely the correct answer, but I just wanted to add one additional important information.
If a listener block is registered with
CMIOObjectAddPropertyListenerBlock
, the current run loop must be run, otherwise no event will be received and the listener block will never fire.