2013年11月3日 星期日

iOS-AVSession(1)

今天工作的時候又再一次遇到從iPhone的後鏡頭動態抓取影片,看來動態抓取未來還會再遇到,再網誌備分一下

話說上次寫從"影像抓取每張影像的照片"時連delegate是啥都矇矇懂懂的,上次花了兩個禮拜才完成,今天一個下午就完成惹XD超爽。回到正題,要動態抓取影片最重要的概念應該是要有input和output這兩個部分,然後還需要一個可以連接input和output的一個API,所以總結一下連續影像截取片段的方式如下:

  1. import <AVFoundation/AVFoundation.h>
  2. import <CoreVideo/CoreVideo.h>
  3. set input source
  4. create session
  5. set output

1. set input source:(以後置鏡頭為例)

- (void)setCaptureInput{

    captureSession = [[AVCaptureSession alloc]init];
    NSArray *devices = [AVCaptureDevice devices];
    
    NSError *error = nil;
    for(AVCaptureDevice *device in devices){
        if([device position] == AVCaptureDevicePositionBack){
            AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device
                                                                                      error:&error];
            if(!error){
                [captureSession addInput:deviceInput];
                NSLog(@"add input");
            }
        }
    }
}

上面這段code是利用

NSArray *devices = [AVCaptureDevice devices];

來獲得目前所有的device,然後用回圈搜尋是否為後置鏡頭,然後把它加入一個AVCatpureSession中

2. set output:

videoDataOutput = [[AVCaptureVideoDataOutput alloc]init];
videoDataOutput.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
                                                            forKey:(id)kCVPixelBufferPixelFormatTypeKey];
[videoDataOutput setAlwaysDiscardsLateVideoFrames:YES];
[videoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
[captureSession addOutput:videoDataOutput];

上面這段code是把用後置鏡頭抓取到的影像作為output到我們app,注意是output到我們app,借由設定好輸出端的輸出格式與輸出的type(videoDataOutput),我們就可以因此借由把自己設定為output的delegate來獲得image,當設定好delegate為該物件後,只需要時做以下method即可獲得image buffer

// Drop late image
- (void)captureOutput:(AVCaptureOutput *)captureOutput didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

// Get capture image
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

另外如果要把抓取到的影像顯示在某個viewController的view中的話需要設定AVCaptureVideoPreviewLayer這個物件,實作方式如下:

- (void)setVideoPreviewLayer{

    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    
    previewLayer.frame = self.view.frame;
    [self.view.layer addSublayer:previewLayer];
    
}

如此我們便可以看到影像在我們的view中。

從上面的code大概可以看出如果要動態的截取影像,比較重要的物件有三個


// Setting Output
AVCaptureVideoDataOutput *videoDataOutput;
// Setting captureSession
AVCaptureSession *captureSession;
// Setting preview layer(purpose for see capture result)
AVCaptureVideoPreviewLayer *previewLayer;

以及一個獲得Device的方法

NSArray *devices = [AVCaptureDevice devices];

藉由上面的物件因此就可以達成連續影像截取片段XD,最後不要忘惹將抓取影像的thread打開

[captureSession startRunning];

Reference:

  1. 透過 AVCaptureVideoDataOutput 做連續影像片段的擷取
  2. 透過 AVCaptureStillImageOutput 做靜態影像的擷取

沒有留言:

張貼留言