现开源一个项目 OEIP 项目实现的功能Demo展示

  

  这个项目演示了在UE4中,接入摄像机通过OEIP直接输出到UE4纹理上,并直接把UE4里的RenderTarget当做输入源通过OEIP里GPU管线处理后推流出去,而另一边Unity3D也是把RenderTarget当做输入,用OEIP处理后推流,经过OEIP封装signalR技术的直播SDK通知,二边各自拉另一边的流并通过OEIP相应管线直接输出到Texture2D并显示出来。演示的机器配置是i5-7500,8G内存,有二个推1080P,拉1080P流的处理,再加上生成截屏视频和yolov3-tiny神经网络识别,所以CPU有点吃不消。

  这是我个人验证一些技术所搭建的DEMO级方案,接入了基本的普通摄像头处理,也没有提供稳定的直播供应商的实现,一些基本的图像处理,推拉流也只支持422P/420P格式。但是我自己还是花了大量业余时间在这方案上,并以及大热情来完善,不过业余时间毕竟有限,测试不完善,加上本人C++不是太熟悉,所以肯定有很多隐藏问题,欢迎指出问题,更欢迎提交修改。

  本项目重点主要在图像处理并与游戏引擎的对接上,主要实现与游戏引擎对接更少的性能消耗,方便引入各种图像处理,包括相关神经网络图像处理,余下处理都是结合网上代码加上测试完善逻辑。毕竟这个项目开始只是想验证DX11比CUDA的GPGPU计算资源占用高是不是因为线程组的分配方式,后来想着用神经网络层的做法来搭建相关逻辑,方便用来做测试一些算法。双十一腾讯的云服务器打折,一时手痒就买了台,现在不是直播很火吗,再加上对云游戏的概念感兴趣,本人在工作过程也接入过二个商业的直播SDK,通过接入SDK自己思考下流程,发现做一个技术验证性的DEMO还是比较容易的,所以也就有了这个项目。  

  本项目暂时只考虑WIN平台,但是框架从开始就考虑从多平台扩展,后面熟悉别的平台相关知识后,会把相应功能补起。

特点:

  • 1 与游戏引擎UE4/Unity3D方便接入,引擎里的纹理可以直接传入传出。
  • 2 图像处理现支持CUDA/DX11,图像处理管线可以直接输入输出DX11纹理,可以做到不需要CPU/内存做图像中转,提高效率。
  • 3 图像处理管线类似神经网络框架的图像处理层设计,并且可以动态打开与关闭某层,方便组合。
  • 4 方便接入各种神经网络框架处理,项目上面集成darknet,可以方便对比别的神经网络框架接入。
  • 5 使用Media Foundation采集图像设备,WASAPI采集麦与声卡。
  • 6 用signalR搭建直播SDK,配合nginx管理推拉流,使用ffmpeg编码解码推流拉流,设计支持多推流多拉流。
  • 7 有一些同学找我要过我原来写的CUDA grabcut实现,我是感觉效果不好也没有商用价值,这次也集成在上面,要的可以去找相应实现自己改进。
  • 8 结合后面5G,有4K,8K图像处理的,这种所有计算都用GPGPU来完成的应该有更多可能。

大致内容如下。

  • 1 OEIP框架设计
  • 2 GPGPU图像处理
  • 3 采集音视频数据
  • 4 FFmpeg编解码与推拉流
  • 5 直播服务器设计
  • 6 Unity3D插件
  • 7 UE4插件

OEIP框架设计

  和一般直播SDK类似,分为设备采集,图像/音频处理,编码,推流,服务器通知与分发,拉流,解码,图像显示这几步。

  方案中,核心项目oeip定义上面模块的各个功能接口,插件模块化,图像处理层的设计。

  图像处理层采用类神经网络实现,层之间可以互相结合,层支持多输入与多输出,可以方便扩展成别的GPGPU方案,现在主要是CUDA与DX11实现,CUDA模版添加与神经网络Darknet的集成,后续会引入别的神经网络框架集成图像处理。

  关联项目:oeip

GPGPU图像处理

  在游戏引擎里,想设计各种图像处理说方便也方便,说麻烦也很麻烦,说方便就是因为如果你想实现的功能在这个框架下,那很简单,嗯,UE4下如果要集成自己的Compute shader还是有点麻烦,复杂点我想引入抠图相关算法,会发现各种麻烦,以及如果想引入 神经网络框架的处理更是复杂,由此我想实现一个能支持CPU数据输入,也支持引擎里GPU数据直接输入,支持CPU数据输出,也支持直接把处理的GPU显存结果返回给游戏引擎,脱离实际游戏环境,只关注本身的逻辑实现。

  最开始,并没有输入层与输出层的设计,但是有几个问题,如在DX11中,让所有层以纹理流通,而传入与传出的CPU数据与纹理长度不一定对应是其一,其二封装内存/显存处理,显存外部上下文与Oeip处理的上下文不同线程切换等,三是并不好处理多输入与多输出,中间层输出等各种问题,所以加入输入与输出层,这二层本身并没任何逻辑,专门用来解决上面的问题。

  在GPU算法中,一是善用一些多线程的算法,如跨线程组步长的循环,以及线程组内二分操作,尽可以同时多利用线程组内所有线程。二是多利用共享显存,注意这个大小有限制,如果你把太多数据放进去,可能会起反作用。三是GPGPU线程组的划分也比较重要,如果出现几个线程同时访问或是读取某个显存地址,不管需要同步不,都不算太好的方式,情愿一个线程读写多个显存地址。四是可以在CPU确认判断可以先编译成不同GPU代码,如HLSL可以通过加入宏定义编译,而CUDA可以利用模版。五减少与CPU的数据交互,如1080P的数据下,上传与下载到显存的时间大约是你做一次基本图像处理的十倍左右,我认为的理想方法,要么是从CPU数据读入,然后所有处理在GPU,并通过引擎显示,或是数据就在GPU上,图像处理最后一步交给CPU传输用,或是从GPU来,GPU处理后再还给GPU,中间但凡出现多次CPU-GPU的交互不如考虑方案的合理性。

  关联项目:oeip-win,oeip-win-cuda,oeip-win-dx11

  CUDA版Grabcut的实现 整合Yolov3到UE4/Unity3D

采集音视频数据

  这个没什么好说的,采集图像视频用的是Media Foundation技术,大约有几点,一是读不管异步还是同步,数据读取都应该放在非主线程中,用异步读自己不需要开,用同步自己管理线程,但是需要注意设备关闭时,确保相应数据流线程最好同步调用线程关闭,免的数据状态不正确。二是避免CPU处理数据,直接读取设备所支持的原生格式,如NV12(YUV420SP),YUV422I,我们在GPGPU图像处理层里有相应的YUV/RGB层,层里采集设备常用的NV12,YUV420I,BGR,YUV422I等都支持,当然传输用的YUV422P,YUV420P也是支持的,相应的CUDA/HLSL代码都有.三是我以前采过的坑,采集设备就是采集数据,他本身不应该和数据处理绑在一起。

  音频采集用的WASAPI技术,处理没用Media Foundation,重采样,混音用的FFmpeg,音频采集主要是麦与声卡这二部分,麦还好,声卡处理需要注意静音的处理,别的跟着网上的代码来就行。

  关联项目:oeip-win-mf,oeip-ffmpeg

FFmpeg编解码与推拉流

  现在直播相关比较火,并且结合现在网络情况可以做很多原来想不到的事情,云游戏这种原概念产品感觉有完善的可能了,我今年也学了些FFmpeg相关知识用来储备。

  推流前,数据处理后需要编码,主要用来压缩数据,可以说是超强的压缩率,在这只结合网上代码完善了H264与AAC这二种视频与音频编码方式,推拉流使用RTMP协议。

  而拉流就是把上来的拉到的H264/AAC数据解码得到YUV/PCM固定格式后固定大小的数据,然后自己处理。

  主要代码都是参照网上部分,然后整合,其中感觉主要是FFmpeg各种资源的销毁比较麻烦,比如要动态更新编码格式,重采样混音都有FFmpeg中间重用的资源,结合std::unique_ptr可以自定义销毁函数与模板,写出C#的感觉,省了我不少脑力与代码。

  关联项目:oeip-ffmpeg

直播服务器设计

  直播服务器简单来说,就是通知一组成员之间消息流通,比如张三李四王五,张三上来了,李四推流了,王五关闭推流了等等这些消息,都需要及时通知这组里的所有成员,每个成员根据需求来对各种消息做各种处理。

  直播服务器通信方案我选择的signarR,我对C#相关的技术熟悉点。

  这只是一个非常简单的设计,主要分为三方,一是SDK调用方,也就是上面的张三李四王五他们,二是直播服务器,管理上面的各种通知,三是媒体服务器,管理推拉流的音视频数据。三方是可以分开放的,不过现没有丢桢方案,SDK调用方最好和媒体服务器在同一局域网效果会比较好。

  相关流程简单来说,先打开直播服务器,然后打开媒体服务器,这样直播服务器就知道了所有的媒体服务器,然后SDK调用方连接直播服务器后,直播服务器返回给SDK调用方相应的媒体服务器地址,这样SDK调用方推流后就知道向那个媒体服务器的地址推流并记录下来,然后别的用户进来,就通知别的用户已经有别的用户推流了,并返回相应的推流地址,然后就可以拉流的,当然这个用户推流了,也需要返回相应推流地址给前一个用户。

  注意事项,signalR 现在也是类似ASP net core里的一个中间件,在这为了直播服务器是否成功打开,我也写了个简单的中间件验证是否能成功连接服务器,打开服务器就会返回结果,在这中间件处理的是每个请求,每次请求都会生成一个HUB对象,这样导致相应的HUB里面绑定事件话,会累加,所以并不是一个好的选择,可以用GlobalHost返回这个HUB逻辑上的所有链接用户。

  SDK调用方,我最开始找的是signalR的C++实现,可惜,一个是老版概念signalR 实现的,几年没更新了,最新的在asp net core下有份C++ 实现,这个还没BATA版,故客户端SDK调用方与直播服务器通信用C#完成,我们知道,与播服务器通信主要是二个部分,一个是我们主动提交的信息,如我们登陆了,我们推流了,还有一个是直播服务器的通知,比如通知你别的用户上线,别的用户推流了。第一个部分我们主动发起通知,表现就是我们从C++调用相关C#的实现,而第二部分是服务器通知回调,需要从C#端通知到C++端,这个算是不常用调用方法,综合考虑了下,把相应的C#客户端封装成COM接口,方便一是C++调用相关C#的实现,二是把相应的C++接口实现传入到C#环境中去执行。需要注意的,这个C++客户端事实上包含相应的CLI环境,所以如果销毁资源,如unity3D/UE4里的每次play/endplay间,要确认引用的C++DLL所关联的CLI环境已经清理干净,我反正是在对应销毁时调用GC.WaitForPendingFinalizers()才搞定关闭时不挂起的现象。

  需要注意的是,客户端C#使用COM封装,那么每台机器需要注册相应的COM组件,如果你是用的VS,直接开管理员,编译相应的OeipLiveCom项目就行。

  当然这个等asp net core signalR的C++实现完善后,会把相应C#+COM/C++调用方案改成全C++低层实现。

  关联项目:OeipLiveServer,OeipLiveMedia,OeipLiveCom,oeip-live,oeip-live-ffmpeg

Unity3D插件

  因为在验证各项功能前,我已经用WinForm+SharpDx做了验证项目,包含DX11纹理的传入传出验证,Unity3D的大部分代码和这部分共用,注意事项就一点,在Unity3D C#中我们拿不到DX11设备与上下文,我们需要编写一个Unity3D的非托管插件,在这插件里我们能拿到Unity3D的DX11设备与上下文,结合OEIP原来接口再封装一层。

  注意事项,更新Unity3D的RHI资源,需要用到Unity3D的非托管插件特定的写法,保证在渲染线程中更新资源,而OEIP回调大部分在非主线程中,所以回调里要用到Unity3D游戏线程里的资源里,请转到游戏线程去执行。

  关联项目:oeip-unity3d,OeipWrapper,OeipUnity3D

  更详细说明请看 UE4/Unity3D中同时捕获多高清摄像头的高效插件

UE4插件

  基本和Unity3D插件思路一样,相应数据处理编写相应管线,设备数据处理管线,拉流管线,推流管线,直播SDK的再封装都是差不多的,就连注意事项也是差不多,回调里用到UE4资源的,请转到游戏线程,用到RHI资源的,请转到渲染线程。

  关联项目:OeipUE4

  更详细说明请看 UE4/Unity3D中同时捕获多高清摄像头的高效插件

最后说下项目编译相关  

  我主要环境在VS2017上开发。

  第三方库:

  CUDA 10.1安裝:https://developer.nvidia.com/cuda-downloads

  CUDNN 10.1安裝:https://developer.nvidia.com/cudnn

  下载https://github.com/xxxzhou/oeip-thridparty在Oeip项目下,新建一个ThirdParty文件夹,把oeip-thridparty里的文件全部复制到这。 二种引用DLL方式。 一是把相应的DLL复制到对应oeip dll目录下。 二是在环境变量里把上面的几个文件夹的BIN目录写入,推荐第二种。(1 ThirdParty\cuda 2 ThirdParty\FFmpeg\dll 3 ThirdParty\opencv4\bin 4 ThirdParty\pthread\dll).

  直播SDK环境配置:

  • 1 先启动直播服务器 OeipLiveServer
  • 2 启动媒体服务器 OeipLiveMedia
  • 3 本机注册OeipLiveCom这个COM组件,然后就可以用了。

  相应UE4/Unity3D里神经网络加载用的的绝对路径,请自己修改相应路径。

  其主要只考虑了64位,相应编译的环境只有64位配置了,32位需要自己配置。

开源项目OEIP 游戏引擎与音视频多媒体(UE4/Unity3D)的更多相关文章

  1. 采用EasyDSS视频点播服务器搭建企业私有化的音视频多媒体、短视频、视频服务网站与管理后台

    最近有越来越多的用户咨询关于视频点播的功能,主要需求就是集中于如何搭建专属的私有化视频点播平台: 实现的功能类似于,对应自身拥有的视频文件,需要发布到一个网站,其他用户都可以实现点播观看. 针对于类似 ...

  2. 了不起的WebRTC:生态日趋完善,或将实时音视频技术白菜化

    本文原文由声网WebRTC技术专家毛玉杰分享. 1.前言 有人说 2017 年是 WebRTC 的转折之年,2018 年将是 WebRTC 的爆发之年,这并非没有根据.就在去年(2017年),WebR ...

  3. 《Genesis-3D开源游戏引擎-FQA常见问题解答》2014年01月10号版本

    1.Genesis-3D开源游戏引擎主要面向哪些用户人群?有限制吗? 1.我们的引擎没有限制,只要您想了解和使用我们的引擎,就可以加入Genesis-3D的大家庭.2.我们的主要用户群是各个相关的企业 ...

  4. Genesis-3D开源游戏引擎简介!

    Genesis-3D由搜狐畅游公司超百人引擎研发团队历时数年耗费巨资自主研发,是国内外首款商业开源的3D游戏引擎平台.它包括跨平台渲染引擎.2D引擎.物理引擎.音效系统.粒子系统.动画系统.服务器引擎 ...

  5. 记录一下八款开源 Android 游戏引擎

    记录一下八款开源 Android 游戏引擎 虽然android学了点点,然后现在又没学了(我为啥这么没有恒心呢大哭).以后有时间还是要继续学android的,一定要啊!虽然现在没学android游戏编 ...

  6. 八款开源 Android 游戏引擎[转]

    记录一下,以备不时之需~~~~~ 虽然android学了点点,然后现在又没学了(我为啥这么没有恒心呢大哭).以后有时间还是要继续学android的,一定要啊!虽然现在没学android游戏编程,不过还 ...

  7. 开源HTML5游戏引擎Kiwi.js 1.0正式发布

    Kiwi.js是由GameLab开发的一款全新的开源HTML5 JavaScript游戏引擎.在经过一年多的开发和测试之后,终于在日前正式发布了Kiwi.js 1.0版本. 其创始人Dan Milwa ...

  8. 开源项目大全 >> ...

    http://www.isenhao.com/xueke/jisuanji/kaiyuan.php   监控系统-Nagios 网络流量监测图形分析工具-Cacti 分布式系统监视-zabbix 系统 ...

  9. 20款最受欢迎的HTML5游戏引擎收集

    在“最火HTML5 JavaScript游戏引擎”系列文章国外篇(一)中,我们盘点了当下备受开发者推崇的非国产HTML5和JavaScript游戏引擎.在各种2D小游戏逆袭的今天,用HTML5和Jav ...

随机推荐

  1. Ubuntu和window10 安装双系统

    先安装window10,然后空出一部分储存空间,我空出来了103G. 然后安装ubuntu分区的时候注意: 刚开始安装的时候:出现安装类型的时候:选择其他选项: 在分区的时候:单击127117(这里是 ...

  2. js 函数的防抖(debounce)与节流(throttle)

    原文:函数防抖和节流: 序言: 我们在平时开发的时候,会有很多场景会频繁触发事件,比如说搜索框实时发请求,onmousemove, resize, onscroll等等,有些时候,我们并不能或者不想频 ...

  3. P6跨级晋升P8再到P10,我的11年成长之路

    来自:语雀,作者:玉伯 链接:https://www.yuque.com/yubo/morning/grow-up-at-alibaba 注:这是在阿里内部前端大学的一个分享,整理了一份对外的版本,希 ...

  4. Java WebSocket实现简易聊天室

    一.Socket简介 Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求.Socket的英文原义是“孔”或“插座”,作为UNI ...

  5. CentOS卸载旧版本内核

    CentOS卸载旧版本内核 查看正在使用的内核 uname -a 查看系统中的全部内核 rpm -qa | grep kernel 卸载多余内核 yum remove kernel-x.xx.x

  6. History of AI

    人工智能的历史源远流长.在古代的神话传说中,技艺高超的工匠可以制作人造人,并为其赋予智能或意识.[1]现代意义上的AI始于古典哲学家用机械符号处理的观点解释人类思考过程的尝试.20世纪40年代基于抽象 ...

  7. 测试LFI WITH PHPINO过程中的一些记录

    原理:以往LFI漏洞都是需要满足两个条件:1.攻击者上传一个含PHP代码的的文件,后缀名任意,没有后缀名也可以:2.需要知道上传后的文件路径及文件名,然后包含之. 后来有国外研究者发现了新的攻击方式, ...

  8. 事务以及Spring的事务管理

    一.什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行 二.事务的特性(ACID) 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用: 一致性 ...

  9. PHP创建缓存文件

    文件操作类 <?php /** 文件操作类 */ class FileIO { /** * 读取目录 * @param string $dirPath dir名称 * @return array ...

  10. sql -- 获取连续签到的用户列表

    签到表: 需求:统计连续签到的 用户 1.根据用户和日期分组 select user_name, sign_date from user_sign group by user_name, sign_d ...