15
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

How to get movie with AVFoundation

Last updated at Posted at 2013-03-13

iPhoneのアプリを作成していてカメラから取得した動画を表示したい。
その時に方法。

必要なFramework

  • AVFoundation
  • CoreMedia
  • CoreMovie

sessionの取得

カメラから動画を取得するにはsessionというものを作成する必要がある。Unixとかでいうstreamみたいなものだと思っている。sessionにはカメラからのInput、ユーザアプリケーションへのOutputの2つの口がある。この2つを弄って、アプリを作ることになる。まず自分の任意のクラスに以下のようにしてsessionをもたせる

@interface VideoCameraViewController (){
    AVCaptureSession *_session;
}

このクラスの初期化の際に以下のようにしてsessionを作成する。

-(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.videoSettings = settings;
    [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
    
    // セッションの作成
    _session = [[AVCaptureSession alloc] init];
    [_session addInput:deviceInput];
    [_session addOutput:dataOutput];
    
    // セッションの開始
    // ここから撮影が始まる感じ
    [_session startRunning];
}

delegateメソッドの実装

AVCaptureSessionを使うならAVCaptureAudioDataOutputSampleBufferDelegateプロトコルを実装する必要がある。そしてデータがsessionから送られるたびに呼び出されるのが- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection

  • captureOutput: さっきのOutputのインスタンス
  • sampleBuffer: キャプチャされたデータが入っている
  • connection: セッションの状態

さてこのメソッドは好きなように実装して大丈夫だけれど、簡単に画面にUIImageとして表示させたい場合は以下のようになる。

    // イメージバッファの取得
    CVImageBufferRef    buffer;
    buffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    
    // イメージバッファのロック
	// これをしないbufferがカメラから送られてくるデータが書き換えられていってしまう
    CVPixelBufferLockBaseAddress(buffer, 0);
    
    // イメージバッファ情報の取得
	// 画像の情報を取得する。これが得られればCoreGraphicsを使ってUIImageに変換することができる。
    uint8_t*    base;
    size_t      width, height, bytesPerRow;
    base = CVPixelBufferGetBaseAddress(buffer);
    width = CVPixelBufferGetWidth(buffer);
    height = CVPixelBufferGetHeight(buffer);
    bytesPerRow = CVPixelBufferGetBytesPerRow(buffer);
    
    // ビットマップコンテキストの作成
    CGColorSpaceRef colorSpace;
    CGContextRef    cgContext;
    colorSpace = CGColorSpaceCreateDeviceRGB();
    cgContext = CGBitmapContextCreate(
                                      base, width, height, 8, bytesPerRow, colorSpace,
                                      kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);
    
    // 画像の作成
    CGImageRef  cgImage;
    UIImage*    image;
    cgImage = CGBitmapContextCreateImage(cgContext);
    image = [UIImage imageWithCGImage:cgImage scale:1.0f
                          orientation:UIImageOrientationRight];
    CGImageRelease(cgImage);
    CGContextRelease(cgContext);
    
    // イメージバッファのアンロック
	// カメラからまた送られてくるようにするため、忘れずに
    CVPixelBufferUnlockBaseAddress(buffer, 0);
    
    // 画像の表示
	// 適当に貼っつけたUIImageViewで表示
    imageView.image = image;

これでカメラを通した動画をリアルタイムにみることができる。

15
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?