iOS学习:AVFoundation 视频流处理

本文通过一个具体的项目实例,详细介绍了如何使用AVFoundation框架进行二维码的实时扫描与解析。包括创建Session、设置输入输出设备、配置输出类型及处理代理方法等关键步骤。

框架

首先我们从整体对所需框架做个初步了解。

AVFoundation在相关框架栈中的的位置:

1.jpg

为了捕捉视频,我们需要这样几种类(与其它的子类)。

  • AVCaptureDevice 代表了输入设备,例如摄像头与麦克风。

  • AVCaptureInput 代表了输入数据源

  • AVCaptureOutput 代表了输出数据源

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

并且还有AVCaptureVideoPreviewLayer提供摄像头的预览功能

可以用这样一幅图来概述: 

2.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

3.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];
}

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

也就是

  1. 创建session

  2. 创建device

  3. 创建input

  4. 创建output。

    这里是与捕捉视频流所不一致的地方。我们捕捉视频流需要的是AVCaptureVideoDataOutput,而在这里我们需要捕捉的是二维码信息。因此我们需要AVCaptureMetadataOutput。并且我们需要指定捕捉的metadataObject类型。在这里我们指定的是AVMetadataObjectTypeQRCode,我们还可以指定其他类型,例如PDF417条码类型。

    完整的可指定列表可以在这里找到。

    然后我们还要指定处理这些信息的delegate与队列。

  5. 开始录制

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能够做得更多。能够进行剪辑,处理音轨等功能。如果我们需要对视频与音频相关的事务进行处理,不妨在着手处理,寻找第三方解决方案前,看看这个苹果公司为我们带来的强大模块。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值