iOS 视图渲染数据转CVPixelBuffer
程序员文章站
2022-05-24 13:09:55
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);然后在创建上下文以pxdata 所指向的内存作为上下文数据存贮的容器, 最后 渲染 上下文[self.webView.layer renderInContext:context];这样就将 we ......
近两年一直从事视频行业的开发, 加班也比较严重, 好久没有写文章了, 最近稍微有些时间, 前来写点文章, 记录一些开发中遇到的问题, 和解决方法!
做视频会议项目, 当然是离不开音视频啦, 也常常和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;
}
这或许不是最好的方法, 但目前确实解决了燃眉之急, 分享出来, 为有同样需求的小伙伴提供一条方案, 或者小伙伴有更好的方法, 分享出来, 大家可以学习交流一下
或者上我的简书
上一篇: 如何安装Eclipse WTP插件
推荐阅读
-
iOS对象指针和基础数据类型的强转详解
-
iOS 视图渲染数据转CVPixelBuffer
-
ios应用数据存储方式(XML属性列表-plist) - 转
-
iOS项目中的socket应用/IPV6 转换/域名转IP/解析socket接受的数据/心跳包
-
微信小程序_文档_03_框架_视图层_WXML_数据绑定_列表渲染_事件处理
-
在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图 3DJavaScript前端3D渲染
-
iOS 视图渲染数据转CVPixelBuffer
-
iOS项目中的socket应用/IPV6 转换/域名转IP/解析socket接受的数据/心跳包
-
ios应用数据存储方式(XML属性列表-plist) - 转
-
创建控制器、视图、路由文件,数据渲染到视图,@include使用-11月4号作业