北京理工大学 20981 陈罡
3G眼看着就到了(虽然前途到底如何还不知道),但从手机的on-line应用已经一点点热起来的形势来看3G的到来一定会给手机软件开发行业带来一个比较大的冲击的。这就好比在大家都用56k modem拨号上网的时候,没有人能遇见到现在可以用电脑下载动辄几个G的高清电影,可以在线玩3D游戏,可以在线看电视一样。于是未雨绸缪偶先来试试,做个demo,验证一下这个传说中的手机流媒体在线播放到底有没有那么神秘,所谓的“核心技术”到底有多大的门槛。
由于偶是没有3G的网络条件的,所以只好退而求其次,使用现有的GPRS网络做做在线的流媒体了,而且接触这方面的技术时间也不长,如果有什么写的不对的地方还请各位大侠斧正。
大概看了一遍视频方面的资料,目前比较成熟的是mpeg4压缩算法,其实很多人把mp4文件格式与mpeg4压缩算法搞混了。mpeg4其实只能够对视频数据进行压缩(这里的“视频”数据是指纯的yuv格式的图像数据,不包含声音的),相关文件指出mpeg4最大压缩比可以达到200:1。mpeg4技术就跟我们平常用到的winzip, winrar一样只是一个普通的压缩算法,所不同的地方在于winzip或winrar用于常规的文件压缩,而mpeg4对于动态图像的压缩效果尤为明显,可以大大减小影像数据的存储大小。现在mpeg4算法出了个part 10,算是比较先进的压缩算法了,非官方的叫法是h.264,这个的压缩比更高,就好像pc上的7z一样。但是当然,有一利,就一定会有一弊,压缩比高了自然就是导致了运算量增大,有关数据显示h.264的运算量比mpeg4大2倍以上,尽管如此,鉴于当前的GPRS带宽有限,只好采用h.264做为首选了编解码方案了,毕竟它占用的带宽小嘛。
再来看看mp4文件格式,其实mp4文件格式与3gp文件格式一样,都是符合iso标准的文件格式。具体的格式定义可以参考文档ISO/IEC 14496-14 Mp4 file format。其实看过了这个format以后,感觉上就跟html网页差不多,只不过mp4文件里面的tag都是二进制的,而html网页都是肉眼可读的ascii码形式的,其余的就是各个tag定义的不尽相同。在mp4/3gp文件里面不再叫做tag,而是叫做“box”,盒子。mp4和3gp文件就是由一系列的装有不同音、视频数据的“盒子”所组成的,所以解码播放的时候,只需要把这些“盒子”打开取出数据,然后解码显示、播放即可。所以,如果你听到用mpeg4编码的3gp文件,一定不要惊奇,这很正常,盒子都是一样的盒子,只不过里面装的东西,可以是mpeg4编码的视频数据,也可以是h264编码的视频数据,也可以是早期手机采用的h263编码的视频数据,当然声音可以是aac也可以是amrnb或者别的什么。这些只要解码器支持,就一切ok。这就好像在html网页里面<mytag>XYZ</mytag>,两个tag之间的XYZ可以随意变化一样,反正只要复合html的规范写tag就不会出错。视频也是一样,只要box定义符合iso的标准,它才不管你里面装的是什么数据呢。
hoho,既然决定了编码器和解码器都是自己写了,那么盒子里面装的什么东西自然就可以自己说得算了,这也是为什么商用的很多codec都是配对的,有解码器就一定有对应的编码器。
对于音频的选型,也不管那么多了,压缩比越大越好,质量嘛。。。就不做那么多考虑了,这只是一个实验性质的验证而已。因此,选择了amrnb做为音频的压缩标准,目前看来似乎在低码率的条件下对声音的压缩,最理想的就是它了,而且symbian手机本身就有amr的codec的,这样省得自己花力气去写了。唉,可惜视频解码器在手机上还没有现成的可以用,强烈建议symbian公司给内置一个视频的解码器,我不需要调用第三方的应用程序,还是一个解码器来得实在。
然后就可以胡乱画一个手机上的流媒体视频框架设计图了:
从图的下面可以看到Muti-media Stream Format,就是大概设计的编码器应该编码出来的视频和音频混合在一起的流媒体文件内部的样子。然后这里的sabs和vabs分别代表了音频数据和视频数据的信息,例如总有多少帧,播放时长是多少,采用什么编码方式,理想状况下的波特率是多少,音频的信息还包括采样率,支持声道个数等信息。由于只是实验,没有必要把VBR动态码率的概念引入进来,而且手机估计处理这些也费劲,所以无论是音频还是视频,统一采用了静态码率CBR了。这样同步啥的也比较方便一些。
再往下就是具体的数据了,vdat代表装有视频数据的“盒子”,adat代表装有音频数据的“盒子”,“盒子”里面记录了音频和视频数据的大小以及同步信息,例如帧序号,nal头之类的东西。
从框架的整体来看,是由一个net engine和一个stream player engine组成的,net engine在调试阶段可以暂时换成file engine来模拟,呵呵,毕竟symbian上面网络部分调好了也不是很容易的事情。大体的工作流程就是由net engine通过GPRS从网络上下载视频流,这里我直接套用了以前在blog上贴出来的断点续传的引擎的部分代码,从http服务器上,利用断点续传技术直接下载视频数据,下载到media queue这个队列里面,如果下载满了,就暂停下载,如果media queue数据不够了,就利用断点续传,从刚刚停下来的地方开始继续下载。
然后,就进入到stream divider这个模块,这个所谓的divider是用于把音频、视频混合在一起的流数据进行分流,这可能也是通常所说的filter过滤器,把视频数据引入到h264 queue里,把音频数据引入amrnb queue里,然后由各自的解码器进行解码。
h264 codec可以采用开源的ffmpeg项目中的libavcodec。这个libavcodec过于强大了,可以经过适当裁剪后使用(这说起来是轻描淡写,呵呵,做过的朋友在此该跟偶是心有戚戚焉了:P);amr codec既可以使用手机内置的amr codec,也可以自己移植一个。hoho,偶是没有偷懒,自己移植了一个amrnb的解码器,想来这工作挺多余,但是如果想想这意味着可以在win mobile上也跑起来,那还是值得的。至于那些queue,估计看过Richard Stevens的《Unix网络编程》的朋友们自然都是不在话下的。
最后来说说这个显示问题,从libavcodec解码出来的图像都是yuv格式的,需要一个转换的程序把yuv格式转换成为rgb565的格式(其实symbian手机也是支持rgb32的,但是考虑到过日子能省则省这一点,所以还是采用了rgb565的方式)。然后就是为了加快显示速度,使用CDirectScreenAccess这个类了,不清楚的朋友可以查阅symiban 3rd的sdk help。
回过头来说声音,声音这块在symbian上还是非常方便的。系统直接提供了可以播放pcm16格式的声音接口,CMdaAudioOutputStream,这个类需要说道说道。如果要使用这个类必须实现三个纯虚函数:
void MaoscOpenComplete(TInt aError) ;
void MaoscBufferCopied(TInt aError, const TDesC8 &aBuffer) ;
void MaoscPlayComplete(TInt aError) ;
这里的MaoscBufferCopied这个函数比较重要,每次数据读取完毕了以后,手机系统会自动回调这个函数,你必须把数据给系统,否则就出错;幸好symbian提供了一个WillResumePlay()的函数,呵呵,如果回调函数回调的时候恰好没有可以用的pcm数据给它的时候(你当大家是地主啊,你要的时候就一定有),就可以调用这个函数来推掉这次请求数据,那么下次只要数据足够多了,执行一下write操作,就又会启动回调函数索取数据的机制。这就为网络状况不佳的时候重新继续播放视频成为了可能。
最后就是同步策略了,基本的思路是以音频为主,视频为辅,音频稍微有延迟就可以听出来,而对于视频而言,由于视频帧都是连续的,适当丢掉一帧两帧都是完全没有问题的。经过大概一个多星期的努力,总算实现了上述所示的整个框架,还顺手把mp3的streaming播放也搞了出来。在symbian 3rd n81平台上测试通过。
调试过程中的截图:
服务器不定时会关掉,在使用手机程序测试之前需要确定如下的url可以访问:
然后就是安装程序了,在此只提供一个没有sign过的sis包,需要测试的朋友可以自己sign一下,只使用了如下的capability :
ReadUserData WriteUserData ReadDeviceData WriteDeviceData LocalServices NetworkServices NetworkControl CommDD TrustedUI UserEnvironment
安装包下载(这里是没有sign过得sis,需要自己sign一下才行)
|
文件: |
Mp3Test_S60_3_X_v_1_0_0.rar |
大小: |
344KB |
下载: |
下载 |
|
使用方法:
(1)修改cmnet接入点名字,名字改为"INTERNET"(注意,必须全部大写)
(2)修改cmwap接入点名字,名字改为"WAP over GPRS"(注意,大小写必须一样)
这两点对不住各位了,测试的时候图省事直接把这两个写死在程序里面了。
(3)打开程序,就可以随意使用了。
(4)选择cmwap h264或者cmwap h264就会开始自动联网播放视频(cmwap的时间稍微长一点)
(5)播放过程中可以选择pause暂停播放,选择resume可以继续播放。
(6)可以从上面的链接中下载ms文件和mp3文件到手机上,利用local h264或local mp3播放。
这里的local模式的播放都是“循环”模式播放的,播放完毕后,又会从头开始播放。
(7)pause和resume同样对本地播放有效。
(8)左右方向键可以调整音量,左方向键减小音量,右方向键增大音量。
这个测试最大的好处在于服务器端部署极为方便,不需要复杂的视频服务器配置(当然复杂有复杂的好处了,可以实现更加精准的定位和控制),有一台普通的apache或者tomcat即可使用,也可以配合free wap,利用mdl或者类似的关联技术,实现在wap网页上单击某个视频,就可以直接调用播放器在线播放的效果。