先日、Appleによる開発者の祭典WWDC 2011が開催された。基調講演では予告通り、iOS 5の新機能の発表が行われた。開発者としては、追加/変更される1,500のAPIに期待が膨らむだろう。

本連載でも、iOS 5が正式にリリースされたら、その新機能を活用するアプリ開発事例を積極的に説明していきたいと思う。

メディアのキャプチャ

さて、今回から取り上げるのはビデオカメラアプリの作り方だ。iPhoneのカメラデバイスを使うアプリとしては、本連載の第一回でカメラアプリの作り方を取り上げた。あのときは、カメラで写真として撮影した静的な画像を取り込み、それにエフェクトをかけた。今回は、カメラからの映像を動的に取り扱う方法を説明しよう。以前のカメラがスチルカメラなら、今回はビデオカメラと言えるだろう。

連載の第一回で説明したときは、UIImagePickerControllerクラスを使ってカメラ機能にアクセスした。このクラスはカメラの起動、撮影、UIImageへの変換までやってくれる便利なものだが、今回はこれは使わない。使うのは、メディアキャプチャと呼ばれる機能である。

メディアキャプチャは、iOS 4から導入された機能で、AV Foundationフレームワークが提供する。名前が、「AVCapture」で始まるクラス群がそれにあたる。オーディオやビデオといったメディアデータを、直接取り扱う事のできる機能だ。プリミティブなデータにそのままアクセスできるので、AV Foundationだけでなく、Core MediaやCore Videoといった多くのフレームワークを横断的に利用する事になる。

メディアキャプチャの概念を紹介しよう。中心となるのは、セッションと呼ばれる概念だ。メディアのキャプチャは、セッションを作る事から始まる。セッションを表すクラスは、AVCaptureSessionだ。

キャプチャを行うには、セッションにインプットとアウトプットをつなげてやる。インプットは、カメラやマイクといったデバイスからの入力となる。カメラならばビデオメディアの入力、マイクならばオーディオメディアの入力となるだろう。アウトプットは、メディアデータの書き出し先となる。ファイルに書き込む出力もあれば、生のデータをバッファを経由して受け取ってプログラム中で処理するという出力もある。

インプットを表すクラスはAVCaptureInput、アウトプットのクラスはAVCaptureOutputとなる。それぞれ、デバイスやメディアに応じて、様々なサブクラスが用意されている。

セッション、インプット、アウトプットの関係を図で表すと、次のようになる。この図で表しているように、1つのセッションに複数のインプットおよびアウトプットを指定する事が可能だ。

セッションの作成

では、セッションを作成してみよう。ここでは、インプットとしてビデオカメラデバイス、アウトプットとしてビデオデータを直接受け取るものを指定しよう。これから紹介するサンプルアプリは、カメラが搭載されたiOSデバイスでないと動かないので注意してほしい。シミュレータでは動作確認はできない。

ソースコードを書くためにXcodeで新たなプロジェクトを作る事になると思うが、そのときに使用するフレームワークを追加する事になる。以下のものを追加してほしい。

  • AVFoundation
  • CoreVideo
  • CoreMedia

準備ができたら、早速書いてみよう。まず、クラスのインスタンス変数として、AVCaptureSession型の変数を用意しておく。

List 1.

@interface VideoCameraViewController : UIViewController
{
    AVCaptureSession*   _session;
}

@end

作成したAVCaptureSessionクラスは、ここに代入しておく。

AVCaptureSessionクラスのインスタンス化は、次のようになる。

List 2.

- (void)viewDidLoad
{
    // ビデオキャプチャデバイスの取得
    AVCaptureDevice*    device;
    device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    // デバイス入力の取得
    AVCaptureDeviceInput*   deviceInput;
    deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];

    // ビデオデータ出力の作成
    NSMutableDictionary*        settings;
    AVCaptureVideoDataOutput*   dataOutput;
    settings = [NSMutableDictionary dictionary];
    [settings setObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
            forKey:(id)kCVPixelBufferPixelFormatTypeKey];
    dataOutput = [[AVCaptureVideoDataOutput alloc] init];
    [dataOutput autorelease];
    dataOutput.videoSettings = settings;
    [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

    // セッションの作成
    _session = [[AVCaptureSession alloc] init];
    [_session addInput:deviceInput];
    [_session addOutput:dataOutput];

    // セッションの開始
    [_session startRunning];
}

まず、ビデオカメラデバイスを取得する。これには、AVCaptureDeviceというクラスを使う。このクラスが提供するdefaultDeviceWithMediaType:というメソッドを使えば、指定したメディアに対するデバイスを取得する事ができる。このメソッドはデフォルトデバイスを取得するので、返ってくるデバイスはただ1つに決まる。iPhone 4のように、表と裏で2つのカメラを持っている場合、その両方を取得するためのデバイスも別途用意されている。

次に、インプットを作成する。ここではAVCaptureDeviceInputというサブクラスを使う。先ほど取得したAVCaptureDeviceを指定して、インスタンスを作成する。

次はアウトプットの作成だ。AVCaptureVideoDataOutputというクラスを使う。ビデオデータを生のまま受け取るために使うクラスだ。設定として、ピクセルフォーマットを指定してやる。

最後に、セッションを作成する。AVCaptureSessionをインスタンス化する。そして、addInput:メソッドを使ってインプットを追加、addOutput:メソッドでアウトプットを追加する。

これで準備完了だ。startRunningメソッドを呼び出す事で、メディアキャプチャの開始となる。

次回は、キャプチャしたビデオデータにアクセスし、画面に表示するところまでを紹介しよう。