通过AVFoundation框架获取摄像头数据

一、概述

从iOS4开始,AVFoundation框架增加了几个类,AVCaptureDevice、AVCaptureSession等,可以获取摄像头的数据,而不会弹出类似于ImagePicker一样的界面,我们可以将数据转为一张张的图片,然后我们可以即时显示在视图上,也可以使用FFMPEG或者其它的视频编码工具,来合成视频。

二、步骤

第一步:创建AVCaptureSession,添加输入,输出源

#import

//创建并配置一个摄像会话,并启动。
- (void)setupCaptureSession
{
    NSError *error = nil;

    //创建会话
    AVCaptureSession *session = [[AVCaptureSession alloc] init];

    //设置视频质量
    session.sessionPreset = AVCaptureSessionPresetMedium;

    //获取合适的AVCaptureDevice
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    //创建设备输入流,并增加到会话。
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device
                                                                    error:&error];
    if (!input) {
        //处理错误
    }
    [session addInput:input];

    //创建一个视频输出流,并增加到会话。
    AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
    [session addOutput:output];

    //配置输出流
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL);
    [output setSampleBufferDelegate:self queue:queue];
    dispatch_release(queue);

    //指定像素格式。
    output.videoSettings = [NSDictionary dictionaryWithObject:
      [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey];

    //设置FPS
    output.minFrameDuration = CMTimeMake(1, 15);

    //启动会话
    [session startRunning];

    //将会话与当前控制器关联
    [self setSession:session];
}

第二步:实现AVCaptureVideoDataOutputSampleBufferDelegate协议方法
 
//当采样数据被写入缓冲区时调用
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
         fromConnection:(AVCaptureConnection *)connection
{
    //抽取采样数据,合成UIImage对象
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer];
    //后续自定义处理
    xxxxxxxx
}

//抽取采样数据,合成UIImage对象
- (UIImage *)imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer
{
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    
    //锁定像素缓冲区的起始地址
    CVPixelBufferLockBaseAddress(imageBuffer,0);

    //获取每行像素的字节数
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    
    //获取像素缓冲区的宽度和高度
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);

    //创建基于设备的RGB颜色空间
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    if (!colorSpace)
    {
        NSLog(@"CGColorSpaceCreateDeviceRGB failure");
        return nil;
    }

    //获取像素缓冲区的起始地址
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
    
    //获取像素缓冲区的数据大小
    size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer);

    //使用提供的数据创建CGDataProviderRef
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, bufferSize,NULL);
    
    //通过CGDataProviderRef,创建CGImageRef
    CGImageRef cgImage =
        CGImageCreate(width,
                        height,
                        8,
                        32,
                        bytesPerRow,
                        colorSpace,
                        kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
                        provider,
                        NULL,
                        true,
                        kCGRenderingIntentDefault);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);

    //创建UIImage
    UIImage *image = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);

    //解锁像素缓冲区起始地址
    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

    return image;
}

你可能感兴趣的:(iOS大类)