Upload
tomoya-onishi
View
5.259
Download
0
Embed Size (px)
DESCRIPTION
http://tomoyaonishi.hatenablog.jp/entry/2014/06/29/024010
Citation preview
Capturing with AVFoundation
2014/03/12 iOS_LT #8 @Tomoya_Onishi
自己紹介
• iOS開発歴約3年
• ツイート専用アプリ「FasPos」:累計5万DL
• その他位置情報ログアプリなどいくつか
AVFoundation@import AVFoundation;
音声、画像、動画 の再生や作成の細かい作業を行うための 超強力な低レベルObjective-C API
今回はキャプチャ機能を かなりざっくりと
AVCaptureSession
入力と出力を管理する
カメラ
マイク
静止画
音声データ
動画
メタデータ
AVCaptureDeviceInput
AVCaptureDevice
AVCaptureOutput
…
AVCaptureSession• デバイスからの入力と出力を管理するクラス
@property(nonatomic, copy) NSString *sessionPreset;キャプチャクオリティの調整
AVCaptureSessionPresetPhoto AVCaptureSessionPresetHigh AVCaptureSessionPresetMedium …
self.session = [[AVCaptureSession alloc] init];
AVCaptureDevice• デバイスそのものを表現するクラス
self.camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
@property(nonatomic) AVCaptureFocusMode focusMode;
@property(nonatomic) CGPoint focusPointOfInterest;
…
@property(nonatomic, readonly) AVCaptureDevicePosition position;@property(nonatomic) AVCaptureExposureMode exposureMode;
@property(nonatomic) AVCaptureWhiteBalanceMode whiteBalanceMode;
AVCaptureDeviceInput• 指定したデバイスをセッションに入力する時に使うクラス
self.cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.camera error:NULL];
[self.session addInput:self.cameraInput];
セッションにカメラが入力機器として接続された状態
AVCaptureOutput• AVCaptureStillImageOutput(静止画)
• AVCaptureMovieFileOutput(動画)
• AVCaptureVideoDataOutput(ビデオデータ)
• AVCaptureAudioDataOutput(音声データ)
• AVCaptureMetadataOutput(顔、QRコードなど)
[self.session addOutput:self.output];
セッションへの入力を特定の方法で出力できる状態
AVCaptureStillImageOutput• カメラから入力されたデータを静止画として出力するクラス
self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
@property(nonatomic) BOOL automaticallyEnablesStillImageStabilizationWhenAvailable NS_AVAILABLE_IOS(7_0)
手ぶれ補正ON
[self.session addOutput:self.stillImageOutput];
静止画のキャプチャ準備完了
- (void)captureStillImageAsynchronouslyFromConnection:(AVCaptureConnection *)connection completionHandler: (void (^)(CMSampleBufferRef imageDataSampleBuffer, NSError *error))handler;
+ (NSData *)jpegStillImageNSDataRepresentation:(CMSampleBufferRef)jpegSampleBuffer;
JPEG画像がNSDataで取得できる
このメソッドを呼ぶと自動でシャッター音が鳴る
Exifなどのメタデータも含まれる
非同期で静止画をキャプチャ
CoreMediaのままではUIKitで使いづらいので変換
AVCaptureMovieFileOutput• 動画を簡単にキャプチャできるクラス
self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
self.movieFileOutput.maxRecordedDuration = CMTimeMake(10 * 30, 30);
最大10秒キャプチャする
[self.session addOutput:self.movieFileOutput];
動画のキャプチャ準備完了
キャプチャ開始[self.movieFileOutput startRecordingToOutputFileURL:self.movieURL recordingDelegate:self];
キャプチャ終了self.movieFileOutput stopRecording];
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections
AVCaptureFileOutputRecordingDelegate
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections error:(NSError *)error
AVCaptureFileOutputRecordingDelegate
outputFileURLに動画が保存されている
AVCaptureVideoDataOutput• 映像の各フレームをそのまま取得できるクラス
self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
self.videoDataOutput.videoSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) };
self.videoDataQueue = dispatch_queue_create("jp.co.xxx.videoDataQueue", DISPATCH_QUEUE_SERIAL);
[self.videoDataOutput setSampleBufferDelegate:self queue:self.videoDataQueue];
[self.session addOutput:self.videoDataOutput];
映像フレームのキャプチャ準備完了
AVCaptureVideoDataOutputSampleBufferDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
sampleBufferがフレーム
1秒に何十回も呼ばれるので重い処理はしないように
各フレームの取得
プレビュー
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; previewLayer.frame = self.view.bounds;
セッションからレイヤーを生成して画面に貼り付けるだけ
盗撮防止のため?renderInContextが効かないようになっている
セッションを動かす
入出力をセッションに接続した状態で呼ぶ実際に入力データがセッションに入って、出力できるようになる
[self.session startRunning];
[self.session stopRunning];
止める
Tips• AVCaptureSession startRunning
• AVCaptureVideoPreviewLayerの生成が遅い
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session]; [self.session startRunning]; ! dispatch_async(dispatch_get_main_queue(), ^{ previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; previewLayer.frame = frame; }); ! });
非同期で
その他
• QRコードのキャプチャ及び生成AVCaptureMetadataOutput, CIFilter
• 動画の再構成や画像との合成などAVMutableComposition, AVVideoCompositionCoreAnimationTool
• 動画変換AVAssetExportSession
• フレームから動画構築AVAssetWriter
参考
• https://developer.apple.com/jp/devcenter/ios/library/documentation/AVFoundationPG.pdf#search='AVFoundation'
• https://developer.apple.com/library/ios/navigation/
• ヘッダーファイル