分析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)底层实现的更多相关文章

  1. 微信开发中使用微信JSSDK和使用URL.createObjectURL上传预览图片的不同处理对比

    在做微信公众号或者企业微信开发业务应用的时候,我们常常会涉及到图片预览.上传等的处理,往往业务需求不止一张图片,因此相对来说,需要考虑的全面一些,用户还需要对图片进行预览和相应的处理,在开始的时候我使 ...

  2. Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)

    Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView) 分类: Android开发 Androi ...

  3. Mantis的附件图片实现预览/弹出层动画效果预览图片(LightBox2)的完美解决方案[Z]

    方法1: 在Mantis的配置文件中,加入此句,将这个值设的很大,就可以直接看到图片 1 $g_preview_attachments_inline_max_size=1000000; 效果如图 这个 ...

  4. 深入浅出Docker(一):Docker核心技术预览

    Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上, 基于Go语言开发并遵从Apache 2.0协议开源.Docker提供了一种在安全.可 ...

  5. WebRTC 源码分析(二):安卓预览

    有过一定相机开发经验的朋友可能会疑惑,预览还有什么好分析的,不是直接 camera.setPreviewDisplay 或者 camera.setPreviewTexture 就能在 SurfaceV ...

  6. Windows 10 开发人员预览版中的新增功能(转自 IT之家)

    Windows 10 开发人员预览版中的新增功能 在Win10预览版中安装工具与SDK后,即可着手创建Windows通用应用或先浏览目前的环境与此前相比都发生了什么变化. 应用建模 文件资源管理器: ...

  7. avalon1.3的新特性预览

    avalon1.2的性能优化风暴很快就告一段落,入职也快一个月了,许多乱七八糟的事也少了下来,估计未来一个月会有许多好东呈现给大家. 首先是一个性能检测工具.由于MVVM是将原本由人脑干的事,转到各种 ...

  8. Dubbo 3.0 预览版解读,6到飞起~

    , false).start(); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new St ...

  9. Java的虚拟线程(协程)特性开启预览阶段,多线程开发的难度将大大降低

    高并发.多线程一直是Java编程中的难点,也是面试题中的要点.Java开发者也一直在尝试使用多线程来解决应用服务器的并发问题.但是多线程并不容易,为此一个新的技术出现了,这就是虚拟线程. 传统多线程的 ...

  10. 基于开源方案构建统一的文件在线预览与office协同编辑平台的架构与实现历程

    大家好,又见面了. 在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件在线预览.在线编辑.多人协同编辑等种种能力的诉求. 对于人力不是特别充裕.或者项目投入预期规划不是特别大的公司或 ...

随机推荐

  1. 支持国产3A游戏大作 ——《黑神话:悟空》

  2. [NOIP2022] 比赛 随机排列 部分分

    看到最大值,考虑使用单调栈搞出 \([la_i, ra_i], [lb_i, rb_i]\) 表示这一段区间 \(i\) 是 \(a, b\) 的最大值.预处理是简单的. inline void in ...

  3. NZOJ 模拟赛5

    T1 逃离遗迹 根据外星人的回信,在遗迹中有分布着三样道具.当三样道具都拿走后,遗迹就很快自动毁灭,所以必须要在最短时间内离开.遗迹可以看作是由N个房间(编号1..N)和N-1条长度不等通道所组成,并 ...

  4. python3的json数据库-TinyDB效率篇

    安装了这个TinyDB库后,我突然想到一般来说python执行的速度并不算高,那这个库写文件速度如何呢? 测试代码如下: from tinydb import TinyDB import time # ...

  5. golang定时器之timer+ticker

    转载: https://juejin.cn/post/7327157426298011663 Timer 是一个一次性的定时器,用于在未来的某一时刻执行一次操作. 基本使用 创建 Timer 定时器的 ...

  6. AtCoder Beginner Contest 152

    Flatten 给定\(n\)个正整数\(a_i\),,现在让你求出\(n\)个整数\(b_i\),使得任取\(1\le i < j \le n\),\(a_ib_i=a_jb_j\)始终成立, ...

  7. PTA-1002

    原先主要错误: 没有考虑到有关0的相关情况 观看的大佬代码 整理思路 无非就是在相同的指数的情况下,系数相加 因为最后是要从大到小输出来. 注意 要对最后的结果进行四舍五入: PTA的英语题对英语不好 ...

  8. Python3 print不输出回车符

    Python3 print的函数原型: print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) objects ---- 输出 ...

  9. nodejs安装和环境配置

    nodejs安装和环境配置 1.下载安装node.js 官方下载地址: https://nodejs.org/en/ 下载LTS版本(长期稳定版本) 安装可以更改安装路径(我的更改是D:\Progra ...

  10. Debian 11 (bullseye) 国内软件源

      本文整理了Debian 11在国内的几个软件源. 1.使用说明 一般情况下,将/etc/apt/sources.list文件中Debian默认的软件仓库地址和安全更新仓库地址修改为国内的镜像地址即 ...