现开源一个项目 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. Luogu_1080_国王游戏

    题目描述 恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这n位大臣排成一排,国王站在队伍的最前面.排好队 ...

  2. RxJava学习笔记(操作符)

    前言 上一篇文章介绍了RxJava的基础知识和简单实现,篇幅已经比较多了,所以把操作符(Operators)相关的内容放在这一篇.有了上一篇文章的基础,相信会比较容易理解操作符相关的内容了. 操作符( ...

  3. Tornado 简述

    前言 python 旗下,群英荟萃,豪杰并起.单是用于 web 开发的,就有 webpy.web2py.bottle.pyramid.zope2.flask.tornado.django 等等,不一而 ...

  4. Blind Estimation and Detection of Space-Time Trellis Coded Transmissions over the Rayleigh Fading MIMO Channel

    目录 文章来源 摘要 基本概念 粒子滤波 时间序列模型 系统模型 通信系统 经典状态空间表示 论文所提出的状态空间表示 借鉴之处 文章来源 IEEE TRANSACTIONS ON COMMUNICA ...

  5. 如何优雅地删除 Linux 中的垃圾文件

    不知道大家是否也跟我一样,是一只要把的自己电脑文件安排的条理有序,把没用的文件会及时删掉的程序猿呢?如果是的话,那么我们可以愉快地探讨下文章的内容.如果不是的话,你也可以留下来凑凑热闹嘛(>-& ...

  6. 从头认识js-js中的继承

    要彻底弄明白js中的继承,我们首先要弄清楚js中的一个很重要的概念那就是原型链. 1.什么是原型链? 我们知道每个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针,而实例都包含一个指向原型 ...

  7. Slog62_项目上线之ArthurSlog个人网站上线1

    ArthurSlog SLog-62 Year·1 Guangzhou·China September 9th 2018 GitHub NPM Package Page ArthurSlog Page ...

  8. 牛客网剑指offer第34题——找到第一个只出现一次的字符

    题目如下: 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写). 先上代码: class ...

  9. 关于Java序列化的问题你真的会吗?

    引言 在持久化数据对象的时候我们很少使用Java序列化,而是使用数据库等方式来实现.但是在我看来,Java 序列化是一个很重要的内容,序列化不仅可以保存对象到磁盘进行持久化,还可以通过网络传输.在平时 ...

  10. Ubuntu系统下环境安装遇到依赖冲突问题

    问题场景:在ubuntu系统下使用docker拉了一个python3.6的镜像,要在该容器中安装vim结果总是报已安装某些依赖的版本不满足要求 解决方法: 1.安装aptitude apt-get i ...