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",我在无意中发现了它们所具有的相同的一些用法,先举 ...
随机推荐
- VC中如何将资源打包并释放到指定文件夹
转载请注明来源:https://www.cnblogs.com/hookjc/ 很多时候,我们可能要将某些文件打包到资源中,然后当程序执行的时候,发现缺少某些文件时,进行自我修复,以维持程序的正常执行 ...
- Vuex 状态管理的工作原理
Vuex 状态管理的工作原理 为什么要使用 Vuex 当我们使用 Vue.js 来开发一个单页应用时,经常会遇到一些组件间共享的数据或状态,或是需要通过 props 深层传递的一些数据.在应用规模较小 ...
- 用maven创建项目引入js文件位置
用maven创建项目引入js文件位置 截图如下:
- 基于XC7A100T的PCIe千兆电口以太网收发卡
一.板卡概述 本板卡采用Xilinx公司的Artix7系列的XC7A100T-2FGG484 芯片作为主处理器.包含双路千兆电口网络,双组DDR,PCIeX1 V1.1接口,板卡设计满足工业级要求. ...
- Memory Management in Rust
程序在运行时需要请求操作系统分配内存以及释放内存,因此,程序员在编写程序时,需要显式(手动)地编写分配和释放内存的代码,或者隐式(自动,由语言保证)地进行内存管理.对于前者,C/C++ 是代表语言,程 ...
- python内置模块之re模块
内容概要 re模块常用方法 findall search match re模块其他方法 split sub subn compile finditer findall 对无名分组优先展示 re实战之爬 ...
- Solution -「CF 1349D」Slime and Biscuits
\(\mathcal{Description}\) Link. 有 \(n\) 堆饼干,一开始第 \(i\) 堆有 \(a_i\) 块.每次操作从所有饼干中随机一块,将其随机丢到另外一堆.求所 ...
- 自学linux(修改中文)STEP2
登录身份 最好用普通身份登录,而不是root用户,因为root用户权限太高,容易引起安全问题. 不显示中文 安装系统后,在图形化界面设置中文还是不生效.查询资料后如下: 1. 查看 linux 系统下 ...
- 微服务从代码到k8s部署应有尽有系列(四、用户中心)
我们用一个系列来讲解从需求到上线.从代码到k8s部署.从日志到监控等各个方面的微服务完整实践. 整个项目使用了go-zero开发的微服务,基本包含了go-zero以及相关go-zero作者开发的一些中 ...
- (Unity)XML文件读写与IO文件操作类使用介绍
using System.Xml; //xml文件操作命名空间 #region 写入操作 void WriteXMLFile(string _fileName) { Xm ...