iOS学习:AVFoundation 视频流处理

转载:http://www.cocoachina.com/ios/20150528/11966.html

框架
首先我们从整体对所需框架做个初步了解。
AVFoundation在相关框架栈中的的位置:

1432777169283241.jpg

为了捕捉视频,我们需要这样几种类(与其它的子类)。
AVCaptureDevice 代表了输入设备,例如摄像头与麦克风。

AVCaptureInput 代表了输入数据源

AVCaptureOutput 代表了输出数据源

AVCaptureSession 用于协调输入与输出之间的数据流

并且还有AVCaptureVideoPreviewLayer提供摄像头的预览功能
可以用这样一幅图来概述:

1432777184186186.jpg

例子
实际应用AVFoundation来捕捉视频流并不复杂。
Talk is Cheap,Show me the Code.
我们用代码简单地描述用AVFoundation捕捉视频的过程,其他捕捉音频,静态图像的过程也是大同小异的。
1.创建AVCaputureSession。
作为协调输入与输出的中心,我们第一步需要创建一个Session
1

AVCaptureSession *session = [[AVCaptureSession alloc] init];

2.创建AVCaptureDevice
创建一个AVCaptureDevice代表代表输入设备。在这里我们制定设备用于摄像。
1

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

3.创建AVCaptureDeviceInput,并添加到Session中
我们需要使用AVCaptureDeviceInput来让设备添加到session中, AVCaptureDeviceInput负责管理设备端口。我们可以理解它为设备的抽象。一个设备可能可以同时提供视频和音频的捕捉。我们可以分别用AVCaptureDeviceInput来代表视频输入和音频输入。
1
2
3

NSError *error;

AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

[session addInput:input];

4.创建AVCaptureOutput
为了从session中取得数据,我们需要创建一个AVCaptureOutput
1

AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc]init];

5.设置output delegate,将output添加至session,在代理方法中分析视频流
为了分析视频流,我们需要为output设置delegate,并且指定delegate方法在哪个线程被调用。需要主要的是,线程必须是串行的,确保视频帧按序到达。
1
2
3

videoDataOutputQueue = dispatch_queue_create(
"VideoDataOutputQueue"
, DISPATCH_QUEUE_SERIAL);

[videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue];

[session addOutput:videoDataOutput];

我们可以在delegate方法中分析视频流。
1

captureOutput:didOutputSampleBuffer:fromConnection:,

6.开始捕捉
1

[session startRunning];

通过上面的简单例子,我么可以看出使用AVFoundation来捕捉视频流并不是十分复杂。重点是使用的过程需要了解配置的细节,还有性能问题。
实战
学习基础知识过后,让我们用个具体例子来进行阐明。
我们来做一个基于AVFoundation二维码识别应用:QRCatcher

1432777448102553.jpg

应用已经上架AppStore 并且完整开源
项目架构:
1
2
3
4
5
6
7
8
9
10
11

|- Model

|- URLEntity

|- View

|- QRURLTableViewCell

|- QRTabBar

|- Controller

|- QRCatchViewController

|- QRURLViewController

|- Tools

|- NSString+Tools

|- NSObject+Macro

项目并不复杂。典型的MVC架构.
Model层只有一个URLEntity用于存储捕捉到的URL信息。 这次项目也顺便学习了一下CoreData。感觉良好,配合NSFetchedResultsController工作很幸福。

View层则是一个TableViewCell和Tabbar,继承Tabbar主要用于改变tabbar高度。

Controller层中QRCatchViewController负责捕捉与存储二维码信息, QRURLViewController负责展示与管理收集到的URL信息。

Tools则是一些辅助方便开发的类。出自我自己平时使用收集编写维护的一个工具库 (开源链接)在这个项目中主要用以检查URL是否合法,判断设备类型等。

介绍完基本的架构后,我们把精力放回AVFoundation模块上来。在这个项目中, AVFoundation主要负责二维码的扫描与解析。
我们直接来看QRCatchViewController中涉及的代码。
对于我们这个应用来说,只需两步核心步骤即可。
1.设置AVFoundation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

  • (void)setupAVFoundation

{

//session

self.session = [[AVCaptureSession alloc] init];

//device

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

NSError *error = nil;

//input

AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

if
(input) {

[self.session addInput:input];

}
else
{

NSLog(@
"%@"
, error);

return
;

}

//output

AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];

[self.session addOutput:output];

[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];

[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

//add preview layer

self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];

[self.preview.layer addSublayer:self.previewLayer];

//start

[self.session startRunning];

}

在这里我们可以看到和上面创建捕捉视频流的步骤基本是一致的。
也就是
创建session

创建device

创建input

创建output。
这里是与捕捉视频流所不一致的地方。我们捕捉视频流需要的是AVCaptureVideoDataOutput,而在这里我们需要捕捉的是二维码信息。因此我们需要AVCaptureMetadataOutput。并且我们需要指定捕捉的metadataObject类型。在这里我们指定的是AVMetadataObjectTypeQRCode,我们还可以指定其他类型,例如PDF417条码类型。
完整的可指定列表可以在这里找到。
然后我们还要指定处理这些信息的delegate与队列。

开始录制

2.实现代理方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

  • (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection

{

for
(AVMetadataMachineReadableCodeObject *metadata
in
metadataObjects) {

if
([metadata.type isEqualToString:AVMetadataObjectTypeQRCode]) {

self.borderView.hidden = NO;

if
([metadata.stringValue isURL])

{

[[UIApplication sharedApplication] openURL:[NSString HTTPURLFromString:metadata.stringValue]];

[self insertURLEntityWithURL:metadata.stringValue];

self.stringLabel.text = metadata.stringValue;

}

else

{

self.stringLabel.text = metadata.stringValue;

}

}

}

}

我们需要在代理方法里面接收数据,并根据自己的需求进行处理。在这里我简单地进行了URL的测试,如果是的话则打开safari进行浏览。
总结
在这里仅仅是通过一个二维码的应用来展示AVFoundation处理视频流能力。事实上,AVFoundation能够做得更多。能够进行剪辑,处理音轨等功能。如果我们需要对视频与音频相关的事务进行处理,不妨在着手处理,寻找第三方解决方案前,看看这个苹果公司为我们带来的强大模块。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容