AVCaptureSession部分用法
AVCaptureSession阻塞主线程问题
前阵子程序中出现了一个奇怪的 bug,在 iOS 系统上,页面弹出的时候会卡很久,相机始终黑屏,大概6-7秒钟,跟踪具体每个步骤花费时间的时候发现在viewWillDisappear:中开销最大,这其中只调用了一个相机关闭的代码:
if ([[self.avCameraManager session] isRunning]) {
[[self.avCameraManager session] stopRunning];
}
仔细看了文档之后,发现问题出在stopRunning这里,
苹果文档描述如下:
Clients invoke -stopRunning to stop the flow of data from inputs to outputs connected to
the AVCaptureSession instance. This call blocks until the session object has completely
stopped.
重点是这个函数在 session 完全停止下来之前会始终阻塞线程, 同样的,在startRunning中:
Clients invoke -startRunning to start the flow of data from inputs to outputs connected to
the AVCaptureSession instance. This call blocks until the session object has completely
started up or failed. A failure to start running is reported through the AVCaptureSessionRuntimeErrorNotification
mechanism.
因此这里必须放在后台线程中处理,否则,就会导致界面不响应,iOS8之后应该在这里做了优化,即使放在主线程做也没有很卡顿的现象,但 iOS7中,尤其是测试设备为4s,界面卡死问题很严重。
开启和关闭相机部分代码改为:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
DDLogDebug(@"Function: %s,line : %d 开启相机",__FUNCTION__,__LINE__);
[[self.avCameraManager session] startRunning];
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
DDLogDebug(@"Function: %s,line : %d 关闭相机",__FUNCTION__,__LINE__);
if ([[self.avCameraManager session] isRunning]) {
[[self.avCameraManager session] stopRunning];
}
});
这里除了使用系统提供的队列以外还可以自己创建 FIFO 类型后台线程进行管理,包括切换前后摄像头、改变闪光灯模式、切换拍照和录像等,都可以放入子线程操作。
相机前后台切换问题
另一个问题与前后台切花相关,项目中在程序进入后台时有这么一段代码:
[self performSelector:@selector(startRunningSession) withObject:nil afterDelay:0.5];
当时我很奇怪,这里为什么要加延时呢?进入到前台时不是应该直接开启相机吗?于是我直接把这里改成了:
[self startRunningSession];
没过多久,问题出现了,多次切换前后台之后发现,相机始终黑屏,这时,进入后台再回来,问题解决了,仔细加了 log 之后发现,出现黑屏的时候,确实也正确调用了启动 session,但是并没有收到系统相机启动成功的消息,反而收到了两次相机关闭的通知。
那么之前代码中加了0.5秒延时的原因也就清楚了,是为了等待系统关闭相机之后,再调用开启相机,以免相机启动失败,但这种方式真的合理吗?其实并没有解决本质问题,如果0.5秒钟的时间并没有完全关闭系统相机呢?这里仍然会出现黑屏问题。
于是继续查看系统文档,发现系统的 sampleCode AVCam-iOS中并没有专门用于前后台处理的逻辑,原来这里并不需要我们自己手动管理相机,系统会自动根据程序状态来判断是否需要关闭或者开启相机,如果按 home 进入UIApplicationStateBackground 状态,那么系统自动关闭相机并在进入UIApplicationStateActive状态时开启相机;如果是进入UIApplicationStateInactive状态,例如,双击 home 调出任务管理器,这时,相机并没有被关闭,仍然能够看到 preview 画面。
我们在程序切换前后台时,仅需要捕获相继开启或者关闭的通知来刷新界面即可,否则可能会由于快速开启切换前后台导致系统相机执行命令错乱,无法正确启动相机。
总结
- AVCaptureSession 中绝大部分操作需要在后台线程完成,最好使用一个 FIFO 的队列来进行操作
- 前后台切换时,无需手动管理 CaptureSession
AVCaptureSession部分用法的更多相关文章
- EditText 基本用法
title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...
- jquery插件的用法之cookie 插件
一.使用cookie 插件 插件官方网站下载地址:http://plugins.jquery.com/cookie/ cookie 插件的用法比较简单,直接粘贴下面代码示例: //生成一个cookie ...
- Java中的Socket的用法
Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...
- [转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法
一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBo ...
- python enumerate 用法
A new built-in function, enumerate() , will make certain loops a bit clearer. enumerate(thing) , whe ...
- [转载]Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
本文对Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法进行了详细的总结,需要的朋友可以参考下,希望对大家有所帮助. 详细解读Jquery各Ajax函数: ...
- 【JavaScript】innerHTML、innerText和outerHTML的用法区别
用法: <div id="test"> <span style="color:red">test1</span> tes ...
- chattr用法
[root@localhost tmp]# umask 0022 一.chattr用法 1.创建空文件attrtest,然后删除,提示无法删除,因为有隐藏文件 [root@localhost tmp] ...
- 萌新笔记——vim命令“=”、“d”、“y”的用法(结合光标移动命令,一些场合会非常方便)
vim有许多命令,网上搜有一堆贴子.文章列举出各种功能的命令. 对于"="."d"."y",我在无意中发现了它们所具有的相同的一些用法,先举 ...
随机推荐
- c语言中数组的定义和java中数组定义的一些区别
感谢原文:https://blog.csdn.net/gzwdz778/article/details/79799408 一维情况下: c中,数组的声明需要给出数组的维数,比如: int arr[5] ...
- NSMutableString练习
从要求讲3个520it拼接在一起 会生成很多新的字符串 NSString *res = @""; NSString *subStr = @"520"; // 1 ...
- Redis主从复制、读写分离
一.Redis的主从复制是什么 主机数据更新后根据配置和策略,自行同步到备机的master/slave机制,Master以写为主,Slave以读为主. 二.Redis的主从复制能干什么 读写分离 容灾 ...
- CocoaPods使用专题 by h.l
cocoaPods安装 CocoaPods安装和使用教程(code4app) cocoapods使用问题解决 cocoapods慢如何解决? CocoaPods停在Analyzing dependen ...
- 打印流(printStream)
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.Pri ...
- LVS负载均衡群集部署——NAT模式
LVS负载均衡群集部署--NAT模式 1.群集应用概述 2.NAT模式LVS负载均衡群集部署 1.群集应用概述: 存在的问题: 互联网应用中,随着站点对硬件性能.响应速度.服务稳定性.数据可靠性等要求 ...
- Shell数组以及排序算法(冒泡、直接选择、反转)
Shell数组以及排序算法(冒泡.直接选择.反转) 目录 Shell数组以及排序算法(冒泡.直接选择.反转) 一.数组概述 1. 数组的定义 2. 下标的定义 3. 数组的特点 4. 数组定义的方法 ...
- 测试人员学Java入门指南
目标读者 本指南特别适合有Python基础的同学学习Java入门,对于没有任何编程经验的同学可能会存在困难. 为什么测试人员要学Java 选择Java,应该不错.TesterHome测试论坛知名大佬基 ...
- springboot自动扫描添加的BeanDefinition源码解析
1. springboot启动过程中,首先会收集需要加载的bean的定义,作为BeanDefinition对象,添加到BeanFactory中去. 由于BeanFactory中只有getBean之类获 ...
- log4j的替换方案
去年12月份,随着log4j暴露出高危漏洞,对于 Java 开发人员来说不是一个好消息,对于 Ops 来说更是如此.前者必须使用固定的 Log4J 版本重新打包他们的应用程序,而后者必须重新部署.但对 ...