几年前,我开始从事于完全用JavaScript编写的MPEG1视频解码器上。现在,我终于找到了清理该库的时间,改善其性能、使其具有更高的错误恢复能力和模块化能力,并添加MP2音频解码器和MPEG-TS解析器。这使得该库不仅仅是一个MPEG解码器,而是一个完整的视频播放器。在本篇博文中,我想谈一谈我在开发这个库时遇到的挑战和各种有趣的事情。
JSMpeg的重构
最近,我需要为一位客户在JSMpeg中实现音频流传输,然后我才意识到该库处于一种多么可怜的状态。从其首次发布以来,它已经有很多发展了。在过去的几年里,WebGL渲染器、WebSocket客户端、渐进式加载、基准测试设备等等已被加入。但所有这些都保存在一个单一的、庞大的类中,条件判断随处可见。
我决定首先通过分离它的逻辑组件来梳理清楚其中的混乱。我还总结了完成实现需要哪些:解复用器、MP2解码器和音频输出:
•
源代码(Sources):AJAX,渐进式AJAX和WebSocket
•
解复用器(Demuxer):MPEG-TS(TransportStream)
•
解码器(Decoder):MPEG1视频&MP2音频
•
渲染器(Render):Canvas2D&WebGL
•
音频输出:WebAudio
加上一些辅助类:
•
一个位缓存(BitBuffer),用于管理原始数据
•
一个播放器(Player),整合其他组件
每个组件(除了Sources之外)都有一个.write(buffer)方法来为其提供数据。这些组件可以“连接”到接收处理结果的目标组件上。流经该库的完整流程如下所示:
640?wx_fmt=png
JSMpeg的Source实现
JSMpeg目前有3种不同的Source实现(AJAX\AJAX渐进式和WebSocket),还有2种不同的渲染器(Canvas2D和WebGL)。该库的其他部分对这此并不了解-即视频解码器不关心渲染器内部逻辑。采用这种方法可以轻松添加新的组件:更多的Source,解复用器,解码器或输出。
我对这些连接在库中的工作方式并不完全满意。每个组件只能有一个目标组件(除了多路解复用器,每个流有都有一个目标组件)。这是一个折衷。最后,我觉得:其他部分会因为没有充分的理由而过度工程设计并使得库过于复杂化。
总之,JSMpeg给大家简单的介绍了一些,希望大家多看看。