AVFoundation的使用

2013-05-03 14:50:21|  分类: iphone_dev_note|举报|字号 订阅

 
 
 
 
相机相关应用一般会用到AVFoundation. 这里简单做个整理。
 
1. session
AVFoundation是基于session(会话)概念的。 一个session用于控制数据从input设备到output设备的流向。
 
声明一个session:
AVCaptureSession *session = [[AVCaptureSession alloc] init];
 
session允许定义音频视频录制的质量。
[session setSessionPreset:AVCaptureSessionPresetLow];
 
2. capture device
定义好session后,就该定义session所使用的设备了。(使用AVMediaTypeVideo 来支持视频和图片)
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
 
3. capture device input
有了capture device, 然后就获取其input capture device, 并将该input device加到session上。
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if ( [session canAddInput:deviceInput] )
    [session addInput:deviceInput];
 
4. preview
在定义output device之前,我们可以先使用preview layer来显示一下camera buffer中的内容。这也将是相机的“取景器”。
AVCaptureVideoPreviewLayer可以用来快速呈现相机(摄像头)所收集到的原始数据。
我们使用第一步中定义的session来创建preview layer, 并将其添加到main view layer上。
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
 
CALayer *rootLayer = [[self view] layer];
[rootLayer setMasksToBounds:YES];
[previewLayer setFrame:CGRectMake(-70, 0, rootLayer.bounds.size.height, rootLayer.bounds.size.height)];
[rootLayer insertSublayer:previewLayer atIndex:0];
 
5. start Run
最后需要start the session.
[session startRunning];
 
 
==============以下内容为“对视频进行实时处理”部分================
 
6. the output buffer
如果向对视频进行实时处理,则需要直接对camera buffer中的视频流进行处理。
首先我们定义一个视频数据输出(AVCaptureVideoDataOutput), 并将其添加到session上。
AVCaptureVideoDataOutput *dataOutput = [AVCaptureVideoDataOutput new];
dataOutput.videoSettings = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey];
[dataOutput setAlwaysDiscardsLateVideoFrames:YES];
 
if ( [captureSession canAddOutput:dataOutput]
    [captureSession addOutput:dataOutput];
 
 
7. the destination layer
若要显示实时处理后的视频效果,则需要自己创建一个layer(不能用AVCaptureVideoPreviewLayer),并将该labor添加到view.layer上。
CALayer *customPreviewLayer = [CALayer layer];
customPreviewLayer.bounds = CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width);
customPreviewLayer.position = CGPointMake(self.view.frame.size.width/2., self.view.frame.size.height/2.);
customPreviewLayer.affineTransform = CGAffineTransformMakeRotation(M_PI/2);
[self.view.layer addSublayer:customPreviewLayer];
 
 
8. 设置sampleBuffer的代理
设置我们自己的controller作为视频数据输出缓冲区(sample buffer)的代理
dispatch_queue_t queue = dispatch_queue_create("VideoQueue", DISPATCH_QUEUE_SERIAL);
[dataOutput setSampleBufferDelegate:self queue:queue];
 
 
9. 视频显示
因为已经将我们的view controller作为capture video data output的代理,所以需要在view controller中实现其代理方法:
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
        fromConnection:(AVCaptureConnection *)connection
这样,当数据缓冲区(data buffer)一有数据时,AVFoundation就调用该方法。
在该代理方法中,我们可以获取视频帧、处理视频帧、显示视频帧(在第七步中创建的layer中显示)了。
 
在该代理方法中,sampleBuffer是一个Core Media对象,可以引入Core Video供使用。
CVImageBufferRef imageBuffer =  CMSampleBufferGetImageBuffer(sampleBuffer);
 
锁住缓冲区基地址:
CVPixelBufferLockBaseAddress(imageBuffer, 0);
 
然后提取一些有用的图片信息:
size_t width = CVPixelBufferGetWidthOfPlane(imageBuffer, 0);
size_t height = CVPixelBufferGetHeightOfPlane(imageBuffer, 0);
size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0);
 
视频缓冲区中是YUV格式的,要从缓冲区中提取luma部分:
Pixel_8 *lumaBuffer = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
 
然后我们将该缓冲区的数据显示(渲染)到layer上。(为此需要 创建color space, 创建 graphic context, 使用color space将buffer渲染到graphic context)
CGColorSpaceRef grayColorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(lumaBuffer, width, height, 8, bytesPerRow, grayColorSpace, kCGImageAlphaNone);
CGImageRef dstImage = CGBitmapContextCreateImage(context);
 
这里dstImage是core graphics image, 由captured buffer中创建而来。 最后我们将该image渲染到layer上。
dispatch_sync(dispatch_get_main_queue(), ^{
    customPreviewLayer.contents = (__bridge id)dstImage;
});
 
接下来做一些清理工作就OK了。
CGImageRelease(dstImage);
CGContextRelease(context);
CGColorSpaceRelease(grayColorSpace);
 
这样取景器上的实时图像就显示出来了。(这里仅仅是对视频做提取与渲染,没有对视频做处理)
有关对imageBuffer进行处理,需要用到GPU相关知识。

AVFoundation的使用的更多相关文章

  1. 用AVFoundation自定义相机拍照

    自定义拍照或者录视频的功能,就需要用到AVFoundation框架,目前我只用到了拍照,所以记录下自定义拍照用法,视频用法等用上了再补充,应该是大同小异 demo在这里:https://github. ...

  2. iOS开发--AVFoundation自定义相机

    首先导入一个头文件 #import <AVFoundation/AVFoundation.h> 由于后面我们需要将拍摄好的照片写入系统相册中,所以我们在这里还需要导入一个相册需要的头文件 ...

  3. 使用AVFoundation仅仅生成缩略图,不进行播放视频(本地和网络文件都可以创建视频缩略图)

    使用MPMoviePlayerController来生成缩略图足够简单,但是如果仅仅是是为了生成缩略图而不进行视频播放的话,此刻使用 MPMoviePlayerController就有点大材小用了.其 ...

  4. iOS使用AVFoundation实现二维码扫描(ios7以上)——转载

    关于二维码扫描有不少优秀第三方库: ZBar SDK 里面有详细的文档,相应介绍也非常多,如:http://rdcworld-iphone.blogspot.in/2013/03/how-to-use ...

  5. iOS使用AVFoundation实现二维码扫描

    原文:http://strivingboy.github.io/blog/2014/11/08/scan-qrcode/ 关于二维码扫描有不少优秀第三方库如: ZBar SDK 里面有详细的文档,相应 ...

  6. AVFoundation视频流处理

    框架 首先我们从整体对所需框架做个初步了解. AVFoundation在相关框架栈中的的位置: 为了捕捉视频,我们需要这样几种类(与其它的子类). AVCaptureDevice 代表了输入设备,例如 ...

  7. AVFoundation 初识

    AVFoundation是苹果 OS X系统和 iOS系统中用于处理基于时间的媒体数据的高级Objective-C框架. iOS中 AVFoundation 在整个体系中所处的角色

  8. 音频播放AVFoundation框架

    一.系统声音 ios应用中的提醒声音.游戏背景音乐等.可以播放的格式有CAF.AIF.WAV. 系统声音服务提供了一个API,但是没有操作声音和控制音量的功能,因此如果为多媒体或者游戏创建专门的声音, ...

  9. 【转】 iOS使用AVFoundation实现二维码扫描

    原文:http://strivingboy.github.io/blog/2014/11/08/scan-qrcode/ 关于二维码扫描有不少优秀第三方库如: ZBar SDK 里面有详细的文档,相应 ...

随机推荐

  1. WordPress 主题开发 - (十二) Search模板与Page模板 待翻译

    The Search Template and The Page Template are vital to any complete WordPress Theme. And they're bot ...

  2. 一,U盘安装 CentOS 6.5 minimal

    U盘安装盘: CentOS-6.5的版本有四个,分别是: 1.CentOS-6.5-i386-netinstall.iso 通过网络安装的,需要联网 2.CentOS-6.5-i386-minimal ...

  3. LinkedList存储一副扑克牌,实现洗牌功能。

    package cd.itcast.runble; import java.util.LinkedList; import java.util.Random; /** * LinkedList存储一副 ...

  4. DataTable使用总结

    1.DataTable数据去重 static void Main(string[] args) { DataTable dt = new DataTable();//创建表 DataColumn dc ...

  5. USB总线介绍

    •USB 1.0出现在1996年的,速度只有1.5Mb/s1998年升级为USB 1.1,速度也提升到12Mb/s,称之为”full speed” •USB2.0规范是由USB1.1规范演变而来的.它 ...

  6. 使用 Attribute +反射 来对两个类之间动态赋值

    看同事使用的 一个ORM 框架 中 有这样一个功能  通过特性(附加属性)的功能来 实现的两个类对象之间动态赋值的 功能 觉得这个功能不错,但是同事使用的 ORM 并不是我使用的  Dapper  所 ...

  7. delphi 博客地址收藏

    博客地址: Delphi XE5 for Android系列,值得入门者一读http://www.cnblogs.com/ChinaEHR/p/3346867.html http://hi.baidu ...

  8. 排序 选择排序&&堆排序

    选择排序&&堆排序 1.选择排序: 介绍:选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理如下.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始 ...

  9. 10 款提高开发效率的 jQuery/CSS3 组件

    前端开发是一项十分繁琐而又耗体力的工作,如何更有效率的开发我们的应用,很多人会选择适当地使用一些jQuery插件.今天就要给大家分享10款可以提高开发效率的jQuery/CSS3组件.部分插件可以下载 ...

  10. hdu 1885 Key Task

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1885 Key Task Description The Czech Technical Univers ...