直播预览层(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协同编辑平台的架构与实现历程
大家好,又见面了. 在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件在线预览.在线编辑.多人协同编辑等种种能力的诉求. 对于人力不是特别充裕.或者项目投入预期规划不是特别大的公司或 ...
随机推荐
- 如何使用强化学习算法解决贪吃蛇问题(Neural Network Learns to Play Snake)
相关: Neural Network Learns to Play Snake https://github.com/greerviau/SnakeAI/ RL算法是有很多baseline算法的,算法 ...
- 第二篇:低功耗模组Air724UG硬件设计手册
接着上篇,继续分享. 3.5 串口 模块提供了五个通用异步收发器:主串口 UART1.校准串口 UART2.通用串口 UART3.调试串口 HOST UART 和 ZSP UART. 3.5.1 ...
- 2023NOIP A层联测32 T3 sakuya
2023NOIP A层联测32 T3 sakuya 虚伪的期望,彬彬赛时都能 A 的数学题. 思路 考虑算出来总的花费,再除以 \(m!\) 求期望. 对于某个排列的花费为:\(\sum\limits ...
- go build tags使用
转载请注明出处: 在 Go 语言中,构建标签(Build Tags)是一种用于条件编译的机制,可以帮助开发者根据不同的条件选择性地编译特定的代码块.它们在处理多平台和多环境的代码时特别有用,例如为不同 ...
- 德承工控机DX-1200 成功适配2024年6月6日发布的国产开源系统OpenEuler 24.03 LTS
基础软件双子星:欧拉系统(OpenEuler)& 鸿蒙系统(OpenHarmony),鸿蒙系统常应用在华为的手机和平板电脑上,大众也较为熟悉,是面向消费电子产品领域的系统:而欧拉系统则是面向服 ...
- Flutter枚举
Flutter枚举 Enum Extension 在Dart2.7版本,Dart新增了扩展函数,使枚举相关的代码定义.调用更加简洁 通过扩展枚举定义方法 定义一个元素枚举 enum Element { ...
- django静态文件、form表单和request对象
目录 一.静态文件 1.静态文件概念 2.资源访问 3.静态文件资源访问 二.静态文件相关配置 1.接口前缀 2.接口前缀动态匹配 三.form表单 action属性 method属性 四.reque ...
- Anaconda功能、优点、安装步骤(安装视频)
目录 介绍 功能(包和环境的管理器) 优点(省时省心) 下载地址 安装教程 要点 conda 的常见命令 查询完整帮助文件 管理conda和anaconda 管理环境 包管理 其他 介绍 Anac ...
- 【bug记录】AttributeError: 'CollectReport' object has no attribute 'description'
问题截图 问题原因 有完全重复用例,因为写用例的时候,为了图方便,直接复制的,还没来得及改,然后,用pytest运行的时候,就报这个错误了. 问题解决 去掉重复就行了
- logback高级特性使用(二) 自定义Pattern模板
原文链接:https://blog.csdn.net/chenjie2000/article/details/8892764 创建自定义格式转换符有两步: 1.写一个转换器类,继承ClassicCon ...