AVFoundation で FaceTime カメラからキャプチャする
今時の Macbook には FaceTime カメラがついているので,ちょっと試しました。
AVFoundationすげえよやっぱここまでは簡単だもの #Xamarin pic.twitter.com/XUHNPXct6X
— Tsubasa HIRANO (@ailen0ada) 2016年9月13日
リポジトリはこちら。
環境
プロジェクト
Xamarin.Mac Cocoa Appを作成して,Viewをひとつ追加,xib ファイルは使わないので削除。
ここでは LiveView.cs
として,このように実装。
背景色の設定などはまあどうでもよく,最低限 Layout()
をオーバーライドして内包するレイヤーの描画領域を追従させること。
Xcode
Main.storyboard を開き,適当にコントロールを配置する。
CustomView
のベースクラスを NSView
から作成しておいた LiveView
に変更し,さらに CoreAnimationLayer
の指定をしておく。
これでビュー内にレイヤーが作成されるので,このレイヤーにビデオストリームをサブレイヤーとしてパスするのが大まかな流れとなる。
ビューほか3つのボタンは ViewController.h
にアクセサを生やしておく。
ViewController
ViewWillAppear
をオーバーライドし,
- デバイスの探索と接続
- プレビュー用のレイヤーを作成
を行っていく。
デバイスの探索と接続
接続されているカメラデバイスは,
AVCaptureDevice[] device = AVCaptureDevice.DevicesWithMediaType(AVMediaType.Video)
で取得できる。これをポップアップボタンに項目として追加すれば複数接続されているときにデバイスの選択ができるが,FirstOrDefault
でお茶を濁すことに。
デバイスが見つかったら,これを入力ソースとしてセッションに設定する。
var session = new AVCaptureSession(); var input = new AVCaptureDeviceInput(device, null); session.AddInput(input);
さらに後々JPEG画像として切り出したいので,出力ソースも設定しておく。
var imageOutput = new AVCaptureStillImageOutput();
imageOutput.OutputSettings = NSDictionary.FromObjectAndKey(AVVideo.CodecJPEG, AVVideo.CodecKey);
session.AddOutput(output);
プレビューレイヤー
レイヤーは AVCaptureVideoPreviewLayer
というそのままな名前のものが存在する。これに先ほど作成したセッションを接続すればよい。
previewLayer = new AVCaptureVideoPreviewLayer(session);
previewLayer.VideoGravity = AVLayerVideoGravity.ResizeAspect;
LiveView.Layer.AddSublayer(previewLayer);
あとはボタンのクリック時に session.StartRunning()
すればプレビューが表示される。まあ簡単。
画像のキャプチャ
セッションに登録した出力ソースから AVCaptureConnection
を取り出し,スチルイメージバッファを取得すればよい。
CoreMedia.CMSampleBuffer
として取り出したバッファを,JPEGバイト列に変換するメソッドが提供されている。
まとめ
カメラからのキャプチャは非常に簡単。ではこれをどう料理するかはまた次回。