1. 主流商用视频通讯方案
下面列举了三种主流视频通讯方案,其中WebRTC是用来取代Google talk的,Google在收购了GIPS后开源了此部分的代码。
Skype
音频:G.729与SVOPC,自Skype 4.0以后开始使用自己研发的SILK音频编码,采样率为8/12/16/24khz,比特率为5~40kbps。
视频:版本5.7以后使用VP8(Google)为标准视频编码640x480,而720p与1080p使用H264编码。
STUN和TURN检测NAT及防火墙环境。
基于P2P,通讯协议不公开,通讯内容加密。
FaceTime
音频:AAC
视频:H264,最高可至720p。
STUN+TURN+ICE检测NAT及防火墙。
RTP/SRTP传输。
WebRTC[1]
音频:iSAC(16/24/32khz, 10~52kbps)/iLBC(8khz, 13.3/15.2kbps)
视频:VP8
基于P2P,RTP/SRTP传输,STUN+TURN+ICE检测NAT及防火墙。
2. AMR与多种音频编码格式比较
| AMR | AAC | SILK | iSAC |
Algorithm | ACELP(自适应多码率) | LTP | Transform coding | |
Sample Rate | 8kHz | 8~192kHz | 8, 12, 16, 24 kHz | 16 , 32 kHz |
Bit Rate | 4.75, 5.15, 5.90, 6.70, 7.40, 7.95, 10.20, 12.20 kbit/s | 8 ~ 529 kbit/s (stereo) 注:理论上可以是任意比特率 | 6 ~40 kbit/s | 10 ~52 kbit/s |
CBR | yes | yes | yes | yes |
VBR | yes | yes | ? | yes |
Stereo | no | yes | ? | no |
Multichannel | no | 48 channels | ? | no |
表2-1
AMR算法复杂度为5[2],支持自适应多码率调整,相比较G.711是1,G.729a是15。
目前我尚未找到这几种音频编码方案的横向对比,一般AMR多与G.7xx相比,而AAC多与MP3相比。
3. 方案选择
根据需求把数据流的方向分为上行和下行。
l 下行数据为两路RTP数据流进来,合成TS文件供live555 server调用;
l 上行数据把MediaRecorder录制成的MP4文件打包成两路RTP外发;
3.1 下行方案
3.1.1 下行方案数据流程图
由数据流程图3-1我们可以看出:
l 对RTP包先做demux再做mux,再做成TS RTP包存在着一定的效率损失;
l 对两路音视频流做TS mux,目前嵌入式平台的主流方案都是由硬件来做,如果软件来做,CPU占有率及功耗均有待测试,特别是针对V2版本1080p camera捕捉方案(我们的AP选用的是高通的方案,是否可以看一下有硬件TS MUX?);
l live555在嵌入式平台的performance也需要评估一下,目前就我观察到的资料,live555如果原生代码不做更改的话,CPU的占用率似乎不低,需要移植到EP680上缓冲一个ts文件做测试?
l live555从pipe读取TS文件后,可以抛出一个标准的rtsp地址,接着走stagefright rtsp流程,也可供第三方APK来访问;
有可能提供改善的地方,两路RTP包进来后,直接作为源提供给stagefright框架,数据传递的效率可得到一定的改善,但也带来了一些问题。
l 开发工作量会上升很多,涉及到缓存读取等;
l 需要修改原有frameworks内libstagefright的代码(C/C++),如果要移植到Android新版本,每次都需要修改这层的代码,破坏了代码的原生性;
l 第三方APK将无法通过标准途径获取RTP数据;
3.1.2 编码方案
方案一(H264+AMR)
AMR并不是TS支持的标准codec[3](见表3-1),即使在private方法里也未有列出(private可用format_identifier或是stream_type=0x06然后去找descriptor来标识),所以第三方播放器无法知道AMR在private streams里的16进制标识,除非是端到端的约定,通用性并不是很好(如调试过程中做TS dump)。
如果坚持要在TS中封装AMR并被第三方播放器所识别,则需要向SMPTE[4]注册MPEG-2格式标识符,具体资格要求不详。
| Video codec | Audio codec |
MPEG transport stream TS(.ts) | MPEG-1, MPEG-2 Part2, MPEG-4 ASP, H.264, other formats in private streams: VC-1, Dirac | MPEG-1 Layers 1, 2, 3(mp3), AAC, other formats in private streams: AC-3, LPCM, DTS |
表3-1
结论:目前不会有一款通用型的TS muxer来帮助封装音频codec为AMR的TS文件(除非有另一端定制,双方私有),所以该方案可行性较小。
方案二(H264+AAC)
这两种编码目前使用较多,在MPEGTSWrite.cpp里有代码,可做一定的参考。
3.2 上行方案
3.2.1 上行方案数据流程图
由数据流程图3-2我们可以看出:
l 反复的进行mux和demux,效率的损失还是比较明显的;
l MP4是MediaRecorder所支持音视频封装输出格式之一(另一个是3GP),在输出的时候MediaRecorder已经帮我们做好了PTS的同步,这正是我们选用MediaRecorderv录制成文件的原因;
有可能提供改善的地方:
l 如果从Video source和Audio source传上来的经过编码后的数据带pts,我们是否可以直接打包成两路RTP?这块需要验证;
l 如果从Video source和Audio source传上来的经过编码后的数据不带pts,我们是否可以根据帧率算出帧时间,然后主动给帧加上pts?再做打包成RTP,同样需要验证;
l Android 2.3官方版本对应的API level 是10,尽管MediaRecorder在官方网站的MediaRecorder.OutputFormat只有MPEG_4与THREE_GPP(包含音视频),但我在2.3的代码里发现还支持如下格式,这块有待进一步验证,无论哪一种可以实现,应该都可以一定量的减轻工作量,同时live555可能要求做成多线程模式?需要验证。
OUTPUT_FORMAT_RTP_AVP = 7, /* Stream over a socket, limited to a single stream */
OUTPUT_FORMAT_MPEG2TS = 8, /* H.264/AAC data encapsulated in MPEG2/TS */
3.2.2 编码方案
MP4支持封装H264, AMR, AAC这三种codec,目前测试了三种主流视频播放器,vlc,kmplayer能正常播放,但WMP不支持AMR类型的编码,有图像无声音,需要额外的插件来解码。
4. 总结
l 目前初步确定的上行/下行数据方案在效率上有一定的改善空间,尤其是TS MUX的效率及功耗需要做一下测试。
l AMR这种编码方式在下行数据(封装成TS)的可行性方面需要做进一步的评估。
l 如果采用既定方案,codec略做调整(AMR换做AAC),数据流程中效率和功耗会有一些损失,和上文中所提及的改善方案差异较大,后期(V3?)如果想进行性能优化,可能需要重写代码,时间上会有损失。
l 如果直接采用上文中提及的改善方案,代码改动量太大,时间根本无法保证。
l 无论上面采用哪种方案,在既定时间(2013.2.25)完成所有代码编写的难度太大。
l 由于经验所限,某些理解难免片面,若有偏差,望能指正,谢谢!
参考文献
[1] http://www.webrtc.org/
[2] http://en.wikipedia.org/wiki/Adaptive_Multi-Rate_audio_codec
[3] http://en.wikipedia.org/wiki/Comparison_of_container_formats
[4] http://smpte-ra.org/mpegreg/mpeg.html