21
Capturing with AVFoundation 2014/03/12 iOS_LT #8 @Tomoya_Onishi

AVFoundationを使ったキャプチャ機能

Embed Size (px)

DESCRIPTION

http://tomoyaonishi.hatenablog.jp/entry/2014/06/29/024010

Citation preview

Page 1: AVFoundationを使ったキャプチャ機能

Capturing with AVFoundation

2014/03/12 iOS_LT #8 @Tomoya_Onishi

Page 2: AVFoundationを使ったキャプチャ機能

自己紹介

• iOS開発歴約3年

• ツイート専用アプリ「FasPos」:累計5万DL

• その他位置情報ログアプリなどいくつか

Page 3: AVFoundationを使ったキャプチャ機能

AVFoundation@import AVFoundation;

Page 4: AVFoundationを使ったキャプチャ機能

音声、画像、動画 の再生や作成の細かい作業を行うための 超強力な低レベルObjective-C API

Page 5: AVFoundationを使ったキャプチャ機能

今回はキャプチャ機能を かなりざっくりと

Page 6: AVFoundationを使ったキャプチャ機能

AVCaptureSession

入力と出力を管理する

カメラ

マイク

静止画

音声データ

動画

メタデータ

AVCaptureDeviceInput

AVCaptureDevice

AVCaptureOutput

Page 7: AVFoundationを使ったキャプチャ機能

AVCaptureSession• デバイスからの入力と出力を管理するクラス

@property(nonatomic, copy) NSString *sessionPreset;キャプチャクオリティの調整

AVCaptureSessionPresetPhoto AVCaptureSessionPresetHigh AVCaptureSessionPresetMedium …

self.session = [[AVCaptureSession alloc] init];

Page 8: AVFoundationを使ったキャプチャ機能

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;

Page 9: AVFoundationを使ったキャプチャ機能

AVCaptureDeviceInput• 指定したデバイスをセッションに入力する時に使うクラス

self.cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.camera error:NULL];

[self.session addInput:self.cameraInput];

セッションにカメラが入力機器として接続された状態

Page 10: AVFoundationを使ったキャプチャ機能

AVCaptureOutput• AVCaptureStillImageOutput(静止画)

• AVCaptureMovieFileOutput(動画)

• AVCaptureVideoDataOutput(ビデオデータ)

• AVCaptureAudioDataOutput(音声データ)

• AVCaptureMetadataOutput(顔、QRコードなど)

[self.session addOutput:self.output];

セッションへの入力を特定の方法で出力できる状態

Page 11: AVFoundationを使ったキャプチャ機能

AVCaptureStillImageOutput• カメラから入力されたデータを静止画として出力するクラス

self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];

@property(nonatomic) BOOL automaticallyEnablesStillImageStabilizationWhenAvailable                              NS_AVAILABLE_IOS(7_0)

手ぶれ補正ON

[self.session addOutput:self.stillImageOutput];

静止画のキャプチャ準備完了

Page 12: AVFoundationを使ったキャプチャ機能

- (void)captureStillImageAsynchronouslyFromConnection:(AVCaptureConnection *)connection                       completionHandler:        (void (^)(CMSampleBufferRef imageDataSampleBuffer, NSError *error))handler;

+ (NSData *)jpegStillImageNSDataRepresentation:(CMSampleBufferRef)jpegSampleBuffer;

JPEG画像がNSDataで取得できる

このメソッドを呼ぶと自動でシャッター音が鳴る

Exifなどのメタデータも含まれる

非同期で静止画をキャプチャ

CoreMediaのままではUIKitで使いづらいので変換

Page 13: AVFoundationを使ったキャプチャ機能

AVCaptureMovieFileOutput• 動画を簡単にキャプチャできるクラス

self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];

self.movieFileOutput.maxRecordedDuration = CMTimeMake(10 * 30, 30);

最大10秒キャプチャする

[self.session addOutput:self.movieFileOutput];

動画のキャプチャ準備完了

Page 14: AVFoundationを使ったキャプチャ機能

キャプチャ開始[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に動画が保存されている

Page 15: AVFoundationを使ったキャプチャ機能

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];

映像フレームのキャプチャ準備完了

Page 16: AVFoundationを使ったキャプチャ機能

AVCaptureVideoDataOutputSampleBufferDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

sampleBufferがフレーム

1秒に何十回も呼ばれるので重い処理はしないように

各フレームの取得

Page 17: AVFoundationを使ったキャプチャ機能

プレビュー

AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];

previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; previewLayer.frame = self.view.bounds;

セッションからレイヤーを生成して画面に貼り付けるだけ

盗撮防止のため?renderInContextが効かないようになっている

Page 18: AVFoundationを使ったキャプチャ機能

セッションを動かす

入出力をセッションに接続した状態で呼ぶ実際に入力データがセッションに入って、出力できるようになる

[self.session startRunning];

[self.session stopRunning];

止める

Page 19: AVFoundationを使ったキャプチャ機能

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; }); ! });

非同期で

Page 20: AVFoundationを使ったキャプチャ機能

その他

• QRコードのキャプチャ及び生成AVCaptureMetadataOutput, CIFilter

• 動画の再構成や画像との合成などAVMutableComposition, AVVideoCompositionCoreAnimationTool

• 動画変換AVAssetExportSession

• フレームから動画構築AVAssetWriter

Page 21: AVFoundationを使ったキャプチャ機能

参考

• https://developer.apple.com/jp/devcenter/ios/library/documentation/AVFoundationPG.pdf#search='AVFoundation'

• https://developer.apple.com/library/ios/navigation/

• ヘッダーファイル