直播预览层(AVCaptureVideoPreviewLayer)底层实现
分析sampleBuffer(帧数据)
- 通过设置AVCaptureVideoDataOutput的代理,就能获取捕获到一帧一帧数据
[videoOutput setSampleBufferDelegate:self queue:videoQue];
- 拿到这一帧一帧数据(sampleBuffer)怎么显示到屏幕上了
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
sampleBuffer(帧数据)
视频本质是由很多帧图片组成
表示一帧视频/音频数据
通过sampleBuffer可以获取当前帧信息
CVImageBufferRef(CMSampleBufferGetImageBuffer):编码前,解码后,图片信息
CMSampleBufferGetDuration获取当前帧播放时间:用于记录视频播放时间
CMSampleBufferGetPresentationTimeStamp获取当前帧开始时间(PTS):用于做音视频同步
- PTS:Presentation Time Stamp。PTS主要用于度量解码后的视频帧什么时候被显示出来
- DTS:Decode Time Stamp。DTS主要是标识读入内存中的比特流在什么时候开始送入解码器中进行解码
(CMVideoFormatDescription)CMSampleBufferGetFormatDescription:视频编码,解码格式描述信息,通过它能获取sps,pps,编码成H264,就会生成一段NALU,这里面就包含sps,pps。
(CMBlockBuffer)CMSampleBufferGetDataBuffer:编码后,图像数据;
视频帧的格式,可以在采集端的AVCaptureVideoDataOutput配置
// RGB
videoOutput.videoSettings = @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) } // YUV(Full)
[videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; // YUV
[videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
显示原理
预览层实现原理:
- 取出捕获到的帧(CMSampleBufferRef) -> 获取帧里面图片信息(CVImageBufferRef) -> 转换成UIImage -> 设置为UIImageView的image就能实时显示捕获的画面.
- 因为是连续采集,每一帧都会变成图片显示出来,就相当于一串连贯的图片在播放,就形成视频了。
CVImageBufferRef 如何转换成 UIImage
- 使用CoreImage框架,前提CVImageBufferRef是RGB格式
- CVImageBufferRef -> CIImage -> UIImage
注意点:设置UIImageView一定要放在主线程,默认接收到CMSampleBufferRef的代理方法不在主线程
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
if (_videoConnection == connection) {
// 获取图片信息
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// 转换为CIImage
CIImage *ciImage = [CIImage imageWithCVImageBuffer:imageBuffer];
// 转换UIImage
UIImage *image = [UIImage imageWithCIImage:ciImage];
// 回到主线程更新UI
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
}
- 注意点二:CIImage和UIView坐标系是反的,需要设置UIImageView宽度为屏幕高度,长度为屏幕宽度,在旋转90度,还得设置锚点,自己画图就知道怎么旋转了
- (UIImageView *)imageView
{
if (_imageView == nil) {
_imageView = [[UIImageView alloc] init];
_imageView.bounds = CGRectMake(0, 0, self.view.bounds.size.height, self.view.bounds.size.width);
_imageView.layer.anchorPoint = CGPointMake(0, 0);
_imageView.layer.position = CGPointMake(self.view.bounds.size.width, 0);
_imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
[self.view addSubview:_imageView];
}
return _imageView;
}
YUV与RGB视频格式讲解
- YUV:流媒体的常用编码方式, 对于图像每一点,Y确定其亮度,UV确认其彩度.
- 为什么流媒体需要用到YUV,相对于RGB24(RGB三个分量各8个字节)的编码格式,只需要一半的存储容量。在流数据传输时降低了带宽压力。
- YUV存储方式主要分为两种:Packeted 和 Planar。
- Packeted方式类似RGB的存储方式,以像素矩阵为存储方式。
- Planar方式将YUV分量分别存储到矩阵,每一个分量矩阵称为一个平面。
- YUV420即以平面方式存储,色度抽样为4:2:0的色彩编码格式。其中YUV420P为三平面存储,YUV420SP为两平面存储。
- RGB:在渲染时,不管是OpenGL还是iOS,都不支持直接渲染YUV数据,底层都是转为RGB,所以在显示到屏幕,必须用RGB.
直播预览层(AVCaptureVideoPreviewLayer)底层实现的更多相关文章
- 微信开发中使用微信JSSDK和使用URL.createObjectURL上传预览图片的不同处理对比
在做微信公众号或者企业微信开发业务应用的时候,我们常常会涉及到图片预览.上传等的处理,往往业务需求不止一张图片,因此相对来说,需要考虑的全面一些,用户还需要对图片进行预览和相应的处理,在开始的时候我使 ...
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)
Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView) 分类: Android开发 Androi ...
- Mantis的附件图片实现预览/弹出层动画效果预览图片(LightBox2)的完美解决方案[Z]
方法1: 在Mantis的配置文件中,加入此句,将这个值设的很大,就可以直接看到图片 1 $g_preview_attachments_inline_max_size=1000000; 效果如图 这个 ...
- 深入浅出Docker(一):Docker核心技术预览
Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上, 基于Go语言开发并遵从Apache 2.0协议开源.Docker提供了一种在安全.可 ...
- WebRTC 源码分析(二):安卓预览
有过一定相机开发经验的朋友可能会疑惑,预览还有什么好分析的,不是直接 camera.setPreviewDisplay 或者 camera.setPreviewTexture 就能在 SurfaceV ...
- Windows 10 开发人员预览版中的新增功能(转自 IT之家)
Windows 10 开发人员预览版中的新增功能 在Win10预览版中安装工具与SDK后,即可着手创建Windows通用应用或先浏览目前的环境与此前相比都发生了什么变化. 应用建模 文件资源管理器: ...
- avalon1.3的新特性预览
avalon1.2的性能优化风暴很快就告一段落,入职也快一个月了,许多乱七八糟的事也少了下来,估计未来一个月会有许多好东呈现给大家. 首先是一个性能检测工具.由于MVVM是将原本由人脑干的事,转到各种 ...
- Dubbo 3.0 预览版解读,6到飞起~
, false).start(); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new St ...
- Java的虚拟线程(协程)特性开启预览阶段,多线程开发的难度将大大降低
高并发.多线程一直是Java编程中的难点,也是面试题中的要点.Java开发者也一直在尝试使用多线程来解决应用服务器的并发问题.但是多线程并不容易,为此一个新的技术出现了,这就是虚拟线程. 传统多线程的 ...
- 基于开源方案构建统一的文件在线预览与office协同编辑平台的架构与实现历程
大家好,又见面了. 在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件在线预览.在线编辑.多人协同编辑等种种能力的诉求. 对于人力不是特别充裕.或者项目投入预期规划不是特别大的公司或 ...
随机推荐
- 3.5 Linux命令行下如何识别文件类型?
对于第一次使用 Linux 命令行的用户,可能真的搞不清楚哪个是文件,哪个是目录,究其原因是很难直接通过名字看出来目录和文件的区别. 虽然从名称上不容易分辨,但是可以从颜色上进行区分.一般情况下,Li ...
- 2.14 Linux文件目录结构一览表
学习 Linux,不仅限于学习各种命令,了解整个 Linux 文件系统的目录结构以及各个目录的功能同样至关重要. 使用 Linux 时,通过命令行输入 ls -l / 可以看到,在 Linux 根目录 ...
- delphi Image32 图形处理 图层
图形图层处理是Image32的主要功能,矢量图形,分层类似 Photoshop看人图层,直接上代码效果. unit uFrmLayer; interface uses Winapi.Windows, ...
- The 2024 ICPC Asia East Continent Online Contest (I) C
Link: Permutation Counting 4 我的评价是神题,给出两种做法. 方法一 利用线代技巧. 设法构造矩阵 \(A\), 其中 \(A_{ij} = [j \in [l_i, r_ ...
- 没有MAC电脑,如何申请苹果开发证书、上架APP Store?
[引言] 使用uni-app进行跨平台APP开发时,苹果ios平台最终还是要通过APP Store渠道发布,调试时uni-app基座也必须使用开发者证书签名后才能安装.对于使用MAC电脑的开发者,倒也 ...
- 三剑客-grep-awk-sed
三剑客-grep-awk-sed grep 格式: grep 参数 过滤文件内容 文件名称 cat file|grep '过滤的内容' 参数: -v 取反 -E 支持扩展正则 | 或者 egr ...
- ibatis源码学习(一)整体设计和核心流程
本文主要从ibatis框架的基本代码骨架进行切入,理解ibatis框架的整体设计思路,各组件的实现细节将在后文进行分析. 背景 介绍ibatis实现之前,先来看一段jdbc代码: Class.fo ...
- SQL 语法解释器jsqlparser
是用java 开发的解析器, 可以生成java类层次结构. 主页地址: http://jsqlparser.sourceforge.net 可以完美解析 表的 增删查改等操作. 展开它的源码你会发现. ...
- vue3 中屏蔽控制台中的警告信息
main.js中 const app = Vue.createApp({}); // 屏蔽错误信息 app.config.errorHandler = () => null; // 屏蔽警告信息 ...
- Astro v5 x DevNow
先介绍下 DevNow DevNow Github 体验网站 DevNow 是一个精简的开源技术博客项目模版,支持 Vercel 一键部署,支持评论.搜索等功能,欢迎大家体验.同时也支持 Follow ...