Camera Tutorial, Part 4: Connect to the camera in Objective-C

Opt In Image
Early bird offer on the ANE eBooks

 

Buy any Easy Native Extensions 2nd Edition package and get our $99 iOS + Android ANE Template completely free before the end of June 2015.

 

 

  • step-by-step guide to making your iOS extension in under an hour
  • library for data conversion between ActionScript and native code
  • tutorials
  • infographics
  • code included

At the end of this tutorial you will have

An iOS library which connects with the camera, sets it up and starts it.

Time

15-20 minutes

Wait, have you done these first?

If you are here just to see how to use AVFoundation to connect with the camera on iOS, that’s OK too – you can whizz through this part of the tutorial and ignore the prerequisites. (That’s what I’d do.)

Step 1: Find out how to capture frames from the camera

Your objective is to capture frames from the iPhone or iPad cameras and send them off to ActionScript to be displayed in a client app. Some digging in Apple’s developer library reveals that one way to do that is to implement the AVCaptureVideoDataOutputSampleBufferDelegate protocol:

This protocol defines an interface for delegates of an AVCaptureVideoDataOutput object to receive captured video sample buffers and be notified of video frames that were dropped.

You will also need an instance of AVCaptureSession, in order to connect to the camera and control it.

Step 2: Implement AVCaptureVideoDataOutputSampleBufferDelegate

Fair enough, let’s do that.

Add a new class to your Xcode project: File > New > File… In the dialog that appears under iOS select Cocoa Touch and on the left select Objective-C class:

New Objective-C Class for the AVCaptureVideoDataOutputSampleBufferDelegate protocol

In the next step name your class CameraDelegate and make it a subclass of NSObject, then save it.

Xcode creates CameraDelegate.h and CameraDelegate.m for you:

CameraDelegate classLet’s make CameraDelegate an implementor of the protocol that will let you capture video frames. Open CameraDelegate.h and modify it like this:

Step 3: Add a capture session

You will use the capture session to set up, start and stop the camera, so you’ll need an instance of it to be around most of the time. Let’s make that a private member of the CameraDelegate class. Open CameraDelegate.m and modify it as follows:

Step 4: Choose a camera

Most of the new iOS devices have two cameras: front and back camera. Add a private Boolean method that lets you choose one of the cameras and returns true on success or false, if the camera you requested was not found.

In CameraDelegate.m add this to your imports:

Next, add a private member (inside the @private section you declared above) that will keep a pointer to the camera:

Then add the following private method between @implementation CameraDelegate and @end:

Step 5: Attach the camera to the capture session

To attach the camera to the capture session, you’ll need an instance of AVCaptureDeviceInput – add one as a private member.

In CameraDelegate.m add this to your imports:

Then add this to CameraDelegate‘s private members:

And add the private method that will get the input from the camera and attach it to the capture session:

Step 6: Create output for capturing frames

In CameraDelegate.m add this to your imports:

Then add this to CameraDelegate‘s private members:

And add another private method to set up the video data output and attach it to the capture session:

Step 7: Add a callback for capturing video frames

This is a method of AVCaptureVideoDataOutputSampleBufferDelegate which you need to implement. It will be called, usually on a separate thread, every time a video frame has been captured, giving you the opportunity to display it in the client app. The callback has a specific signature – add the following as a private method:

Step 8: Add a placeholder for copying video frames

How you manage the arriving video frames will be the subject of Part 6: Grab frames from iOS camera. For now add a placeholder for dealing with them. Add this private method:

Step 9: Add a ‘camera has started’ callback

When you set everything up and pull the trigger on the capture session to start the camera, you won’t yet know whether the camera has started successfully or not. This happens asynchronously, so to get notified, you’ll need to set up a callback that takes NSNotification. Add this as a private method to CameraDelegate:

Did you notice the sendMessage() call there? This calls the auxiliary function you added in Part 2 for sending events to ActionScript. How forward-thinking of you!

For CameraDelegate.m to see sendMessage() however, you need to declare it as an external function at the top of the file (right underneath all of your #import directives):

Step 10: Initialize thy members

It’s pedantic. It’s important. It will save you hours of debugging, when you discover that the compiler is nice to you and initializes all of your pointers in the debug build, but is nice to you in a different way in release builds and doesn’t bother with initialization there.

Add an init() function to CameraDelegate and initialize all members you have added so far:

Step 11: Start the camera already!

It’s time to put all of the ingredients together and add a method that will stat the camera. Phew!

This will be a public method, as we’ll want to call it from the ActionScript interface you added to CameraLibiOS.m in Part 2, so first declare it in CameraDelegate.h:

Then add the definition to CameraDelegate.m:

What’s next?

 

Wait, want more features and Android support?

Check out the DiaDraw Camera Driver ANE.

Trackbacks

  1. […] And just for the record, this is not an entirely new concept. Easy Native Extensions has an iOS camera tutorial dedicated to funneling camera frames into Adobe AIR (ActionScript). […]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">