Posted at

AVFoundationでカメラを表示するとても短いサンプル

More than 5 years have passed since last update.

AVFoundationでカメラアプリを作るほうが、UIImagePickerControllerを使うより拡張性が高いということで、さくっと表示させるサンプルを用意しました。


準備

プロジェクトに以下を追加。

* AVFoundation.framework

* CoreVideo.framework

* CoreMedia.framework

* QuartzCore.framework

* MobileCoreService.framework


画像のキャプチャ

まず以下をヘッダファイルに追記。

ただし、別にここに書かなくとも良いけども。


ViewController.h


#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface ViewController : UIViewController<AVCaptureVideoDataOutputSampleBufferDelegate>
@property (nonatomic, strong) AVCaptureSession* session;
@property (nonatomic, strong) IBOutlet UIImageView* imageView;
@end


次に、ViewController.xibにUImageViewを追加して、ヘッダファイルのimageViewとリンクしておくこと。

AVFoundationは、


  • AVCaptureSessionを作る

  • sessionをスタートさせる

  • delegateで取得したデータを受け取る

の流れでとりあえず画像を取得できます。

まず、captureSessionを作り、スタートさせる。


ViewController.m


- (void)viewDidLoad
{
[super viewDidLoad];
//デバイス取得
AVCaptureDevice* device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//入力作成
AVCaptureDeviceInput* deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];

//ビデオデータ出力作成
NSDictionary* settings = @{(id)kCVPixelBufferPixelFormatTypeKey:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]};
AVCaptureVideoDataOutput* dataOutput = [[AVCaptureVideoDataOutput alloc] init];
dataOutput.videoSettings = settings;
[dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

//セッション作成
self.session = [[AVCaptureSession alloc] init];
[self.session addInput:deviceInput];
[self.session addOutput:dataOutput];
self.session.sessionPreset = AVCaptureSessionPresetHigh;

AVCaptureConnection *videoConnection = NULL;

// カメラの向きなどを設定する
[self.session beginConfiguration];

for ( AVCaptureConnection *connection in [dataOutput connections] )
{
for ( AVCaptureInputPort *port in [connection inputPorts] )
{
if ( [[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;

}
}
}
if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false**
{
[videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
}

[self.session commitConfiguration];
// セッションをスタートする
[self.session startRunning];
}


その後、delegateメソッドを実装し、その中でCMSampleBufferRefをUIImageに変換する。


ViewController.m


//delegateメソッド。各フレームにおける処理
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
// 画像の表示
self.imageView.image = [self imageFromSampleBufferRef:sampleBuffer];
}

// CMSampleBufferRefをUIImageへ
- (UIImage *)imageFromSampleBufferRef:(CMSampleBufferRef)sampleBuffer
{
// イメージバッファの取得
CVImageBufferRef buffer;
buffer = CMSampleBufferGetImageBuffer(sampleBuffer);

// イメージバッファのロック
CVPixelBufferLockBaseAddress(buffer, 0);
// イメージバッファ情報の取得
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:UIImageOrientationUp];
CGImageRelease(cgImage);
CGContextRelease(cgContext);

// イメージバッファのアンロック
CVPixelBufferUnlockBaseAddress(buffer, 0);
return image;
}


参考:

https://developer.apple.com/jp/devcenter/ios/library/documentation/AVFoundationPG.pdf

http://news.mynavi.jp/column/iphone/040/index.html