关于Jet的一些想法

来到快网之后一直在搞流媒体,在以前的公司也是大部分时间搞音视频,看来这很可能就是我的路吧,是时候沉下心来,踏踏实实做点东西了。再加上新公司给提供的环境还可以,周围有一些牛人,不算太忙的节奏,还有主要就是在这可以深度学习挖掘一些东西,而不是像以前那样绝大部分时间都是在实现业务逻辑。

在公司做的产品就是流媒体CDN服务器。要求很简单:稳定,性能。其实互联网行业要求支持的协议不是太多,初期对性能也没什么要求,难点还是在稳定性和快速实现客户业务需求上。刚到公司时,我被分配的任务是和另外4个同事实现RTMP协议的直播转发。不知道为什么,明明知道以后肯定要支持多种协议之间的互相转换,可项目还是被拆成了2个,分2拨人去搞。我认为当初的这个决定肯定会导致以后的合并会把项目搞的越来越乱,现在看来还是有这个趋势的,不再多表。

随着公司项目的进展,我也逐渐了解了这个行业,了解了许多相关的商业的、开源的产品或项目,了解了客户的需求以及未来可能会有的需求,于是脑海中一个自己设计的项目渐渐清晰开来。我的计划是实现一个流媒体框架,类似Gstreamer,VLC那样的,可以通过插件轻松扩展。客户可以基于这个框架快速实现服务器或客户端。首先如何让客户做到快速实现?我认为这是最重要的,客户需要做的其实只有实现他自己的业务逻辑,其他一切都不需要关心:性能,流媒体协议,编解码,缓存等等。这个实现必须具有很低的学习成本,因此开发语言就很重要了,C/C++肯定不是最好的,拿它们来写业务纯粹是自虐,我的想法是给客户提供多种语言,如Lua,JavaScript等。Lua的特点是很小的footprint,高性能首选,嵌入式必选,所以它适合各种应用场景:服务器,嵌入式(智能手机,智能硬件,工控设备)都是很完美的。JavaScript则是针对很多人有很小的学习成本,看Node.JS和Github就知道了。以后可能还会考虑Java,因为Java是企业大中型项目的首选,而且wowza就提供了Java的API,所以可能会考虑支持,而我们的引擎因为是C写的,因此又会比wowza有一些性能优势。除了选择一门合适的语言,生态也是很重要的,因此我计划Lua的API参考openresty来设计,尽量做到完全兼容(应该无法做到完全兼容,区别还是很大的),JavaScript的API完全按照Node.JS设计,确保Node.js的模块可以直接运行在我的引擎上,使用了libuv的C++模块可能会兼容不了,不过这种模块应该也不是很多。

框架的实现,我计划基于coroutine来做,因为用coroutine写非阻塞IO实在是酸爽,直接甩callback几条街。还有就是看看Go,Rust就知道了。state thread这个库是我从SRS中得知的,很不错的一个库,该做的他基本都做了,不该做的他也没多做。而且有SRS这个很棒的项目一直在用,我就不用担心坑了。st没有实现异步文件IO,没有支持Windows IOCP,这些都是我以后需要添加的。异步文件IO可以按libuv那种方式设计。

框架的设计,我选择了Gstreamer,因为我认为这个框架设计的不错(虽然实现的有点不是那么追求完美),层次分明,官方积累了很多插件,基本全方位覆盖音视频各种协议和编解码,还有就是以前搞TI的Davinci的时候,官方只提供了Gstreamer的插件,所以感觉这个适用面更广一些,用户基数更大一些。虽然后来随着对Gstreamer越来越熟悉就越感觉好多地方写得不是很好(毕竟它只是被拿来做客户端的,不需要考虑太多),但是我还是认为架构设计的很不错。Gstreamer的作者说他是参照DirectShow来设计的,我也认可这一点,而且更坚定了我选择它的决心。微软下一代的多媒体框架是Media Foundation,我也会参考进来。

整个框架全部纯C开发,使用GObject实现OO,以及完成和业务层开发语言的对接。需要深度优化Gstreamer,话说看到那些lock/unlock我就很无语,而且还那么多!这方面Nginx是个典范,幸好在公司做项目对Nginx还算一般熟。网络IO肯定是使用各OS上性能最高的API:epoll,kqueue,IOCP。多线程架构,线程间使用MQ通信,需要参考ZeroMQ基于st写一套MQ库。集群的支持也可以使用这个MQ,可以参考的有云风的skynet。硬件支持计划的有x86,x64,ARM,以后可能会考虑NPU。OS支持肯定会有3大主流OS,以后可能会考虑支持一些RTOS如VxWorks,TI-RTOS等。

业务层开发语言。Lua本身支持coroutine,但是不能在C中yield,所以采用了Lua 5.1.5,打了luajit coco的补丁,然后仿照openresty,添加了可以统一调度的thread API,Lua的coroutine因为是非对称coroutine,所以无法用于非阻塞IO,只能用新加的thread API。我说的无法用的意思是openresty里的那种用法:同步方式写但是异步方式执行。JavaScript的话需要让st实现回调触发的功能,同时也要支持Lua的那种写法:同步写异步执行,可以参考的有孢子响马开源的fibjs项目,但是我的可以直接利用Node.js的生态。

应用场景想了好多好多,例如软交换,互联网行业流媒体服务器,客户端播放器,客户端播放插件,安防行业信令/转发等服务器,互联网流媒体SaaS提供商,HTPC,电视盒子等等,当然其中有很多甚至全部是不怎么靠谱的,但是当有一天我把框架做出来了,也许应用自然就有了,总之现在的当务之急就是先把它做出来。

代码会开源托管在Github,使用travis-ci做build和unit test,目前还是在heavy develop,代码还没提交,欢迎follow和star。代码提交首个版本后应该会做一个简单的页面放在Github Pages上。

关于开源,因为核心是基于GStreamer的,GStreamer遵循LGPL协议,因此整个核心也只能是LGPL协议并开源,但是插件是使用动态链接的方式,因此可以避开开源的问题。开源对该项目肯定是利大于弊的,产品的价值最终还是要体现在业务和服务上,我做的只是给大家提供一个高质量的二次开发的平台而已,当然这个大家也包括我自己。