近两年一直从事视频行业的开发, 加班也比较严重, 好久没有写文章了, 最近稍微有些时间, 前来写点文章, 记录一些开发中遇到的问题, 和解决方法!
做视频会议项目, 当然是离不开音视频啦, 也常常和WebRTC打交道, 包括编译WebRTC, 修改源码, 还有C++和OC的混编开发, JS交互, 也尝试过RN的开发来避开一些问题等等, 东西很多, 路也很不好走, 通宵加班也是家常便饭, 不过现在项目基本稳定,已经上线, 用户反馈也都很不错! 回头看看走过的路, 虽然坎坎坷坷, 但是也是收获满满呀!
进入正题, 项目中有共享的功能, 屏幕共享使用的ReplayKit, 但是应用外的屏幕共享时是使用的Broadcast Extension, 而该扩展是另外的独立进程, 涉及到宿主App和扩展App的信令之间的交互, 好在有比较有好的第三方使用, 省了不少事, 最终完成了屏幕共享! 如果有朋友涉及到这方面的知识的话, 可以一起交流沟通哈!
除屏幕共享外, 我们要有网页共享, 网页共享, 开始一脸懵逼! 后来的解决方案是, 共享人端使用WKWebView, 观看端看的是视频流! OK, 那么问题来了, 如何把一个UIView 的渲染数据采集成为Buffer呢, 头大, 最初考路过使用应用内的录屏, 这样是可以解决, 但是, 录屏的话吧整个屏幕上的内容全都采集出来, 不是很友好, 用户只想共享这个网页, 其他的不想让观看者看到! 确实挺麻烦的, 查了很多资料, 也没有特别合适的!
经过多方面研究和资料的查阅, 最终的解决方案是, 创建CVPixelBufferRef pxbuffer, 然后获取像素基本地址

void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
然后在创建上下文以pxdata 所指向的内存作为上下文数据存贮的容器, 最后 渲染 上下文[self.webView.layer renderInContext:context];
这样就将 webView 视图上的渲染数据转成了一帧 CVPixelBufferRef 数据, 然后根据帧率设置定时器, 去不停的获取webView的渲染数据转换成需要像素缓冲数据!

具体的代码如下

- (CVPixelBufferRef)CVPixelBufferRef {

    CGSize size = self.frame.size;
NSDictionary *options = @{(NSString*)kCVPixelBufferCGImageCompatibilityKey : @YES,
(NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES,
(NSString*)kCVPixelBufferIOSurfacePropertiesKey: [NSDictionary dictionary]};
CVPixelBufferRef pxbuffer = NULL; CGFloat frameWidth = size.width;
CGFloat frameHeight = size.height; CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
frameWidth,
frameHeight,
kCVPixelFormatType_32ARGB,
(__bridge CFDictionaryRef) options,
&pxbuffer); NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
NSParameterAssert(pxdata != NULL); CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(pxdata, size.width, size.height, 8, CVPixelBufferGetBytesPerRow(pxbuffer), rgbColorSpace, kCGImageAlphaPremultipliedFirst); NSParameterAssert(context); CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGAffineTransform flipVertical = CGAffineTransformMake( 1, 0, 0, -1, 0, frameHeight);
CGContextConcatCTM(context, flipVertical); // CGAffineTransform flipHorizontal = CGAffineTransformMake( -1.0, 0.0, 0.0, 1.0, frameWidth, 0.0 );
// CGContextConcatCTM(context, flipHorizontal); [self.webView.layer renderInContext:context]; CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0); return pxbuffer;
}

这或许不是最好的方法, 但目前确实解决了燃眉之急, 分享出来, 为有同样需求的小伙伴提供一条方案, 或者小伙伴有更好的方法, 分享出来, 大家可以学习交流一下

或者上我的简书

iOS 视图渲染数据转CVPixelBuffer的更多相关文章

  1. iOS 视图,动画渲染机制探究

    腾讯Bugly特约作者:陈向文 终端的开发,首当其冲的就是视图.动画的渲染,切换等等.用户使用 App 时最直接的体验就是这个界面好不好看,动画炫不炫,滑动流不流畅.UI就是 App 的门面,它的体验 ...

  2. iOS 图像渲染原理

    http://chuquan.me/2018/09/25/ios-graphics-render-principle/ 通过 图形渲染原理 一文,大致能够了解图形渲染过程中硬件相关的原理.本文将进一步 ...

  3. iOS开发系列--数据存取

    概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation框架的文章中提到归档.plist文件存储, ...

  4. Rails :布局和视图渲染

    原文地址: http://guides.ruby-china.org/layouts_and_rendering.html Rails 布局和视图渲染 本文介绍 Action Controller 和 ...

  5. iOS 视图控制器转场详解

    iOS 视图控制器转场详解 前言的前言 唐巧前辈在微信公众号「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各项指标有了大幅度的增长,多谢唐巧前辈的推荐.有些人问我相关的问题 ...

  6. Laravel 5 多个视图共享数据的方法

    我们都知道模板一般会用到继承,导航栏就是一个很好的例子,但是导航栏的数据如何共享,比如有个导航的文件叫在view/navigation.blade.php 为了简单一点,文件里只有设置了一个变量 {{ ...

  7. SpringMVC核心——视图渲染(包含视图解析)问题

    一.本来想说的是返回值处理问题,但在 SpringMVC 中,返回值处理问题的核心就是视图渲染.所以这里标题叫视图渲染问题. 本来想在上一篇文章中对视图解析进行说明的,但是通过源码发现,它应该算到视图 ...

  8. 【转】iOS开发系列--数据存取

    原文: http://www.cnblogs.com/kenshincui/p/4077833.html#SQLite 概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储 ...

  9. 微信小程序教学第四章第二节(含视频):小程序中级实战教程:详情-视图渲染

    § 详情 - 数据渲染 本文配套视频地址: https://v.qq.com/x/page/x055550lrvd.html 开始前请把 ch4-2 分支中的 code/ 目录导入微信开发工具 这一节 ...

随机推荐

  1. JS系列1---节流,去抖(防抖)应用场景:intput请求优化,页面监听

    在项目开发过程中经常遇到在input的change事件中发起请求,将用户最新输入的字符作为data传给后台,但是如果用户的输入频率过高,或者用户输入的字符还未拼成一个完整的字词,这时候发起请求会浪费网 ...

  2. CSS画出三角形(利用Border)

    画出三角形的原理是调整border(边框)的四个方向的宽度,线条样式以及颜色. 如果你将宽度调的足够大,改变不同方向的颜色,你就可以发现盒模型的border是四个梯形一样的线条. div{ width ...

  3. 在Ubuntu中安装Docker和docker的使用

    1.在Ubuntu中安装Docker 更新ubuntu的apt源索引 sudo apt-get update 安装包允许apt通过HTTPS使用仓库 sudo apt-get install \ ap ...

  4. 准备开始,选好第一个C#的封装库

    如今C#做工业图像处理和开发,最多资料和例子的就是Emgu.不过现在人家开始商业收费了,对于我们这些小企业就不是很好了.这里,我要介绍和推荐的是另外一个也同样牛逼的C#封装Opnecv的库,叫做Ope ...

  5. Pinyin4j简单使用教程

    Pinyin4j是一个流行的Java库,支持中文字符和拼音之间的转换,拼音输出格式可以定制,在项目中经常会遇到需求用户输入汉字后转换为拼音的场景,这时候Pinyin4j就可以派上用场 有自己私服的可以 ...

  6. lr参数化

    为什么做参数化? 数据库校验:注册用户时会看数据库有没有这个账号 应用程序校验:pc端qq登陆,一个账号只能登陆一台电脑 1.数据库或应用程序提交值的唯一性校验 数据库查询过程: 1.语法检查.语义检 ...

  7. layui上传Excel更新数据并下载

    前言: 最近做项目遇到了一个需求,上传Excel获取数据更新Excel文档,并直接返回更新完的Excel到前端下载:其实需求并没有什么问题,关键是前端用到的是layui上传组件(layui.uploa ...

  8. 脱壳系列_2_IAT加密壳_详细版_解法1_包含脚本

    1 查看壳程序信息 使用ExeInfoPe 分析: 发现这个壳的类型没有被识别出来,Vc 6.0倒是识别出来了,Vc 6.0的特征是 入口函数先调用GetVersion() 2 用OD找OEP 拖进O ...

  9. python多进程详解

    目录 python多进程 序.multiprocessing 一.Process process介绍 例1.1:创建函数并将其作为单个进程 例1.2:创建函数并将其作为多个进程 例1.3:将进程定义为 ...

  10. Android Studio 设置/更改 SDK 路径

    网上看到有人说需要重启 Android Studio,感觉麻烦,就自己试了试其他方法,果然还是有的! 很简单,只需打开 File 菜单下的 Project Structure 就可以设置了,如图所示: