视频流网络透传分析

最近在翻看以前写的文档,把这篇word文档复制下来,保留一下。


 

序号

版本

作者

描述

1

V0.1

YJ.Yan

初始版本

2

V0.2

YJ.Yan

添加方案细节描述以及可参考方案

 

 

 

 

 

1.      基本概念

a)       NAT

网络地址转换(NAT,Network AddressTranslation)属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术,它被广泛应用于各种类型Internet接入方式和各种类型的网络中。原因很简单,NAT不仅完美地解决了IP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。

家庭用路由器就是采用这种技术。NAT还分4种类型:

(1)       Full Cone

这种NAT内部的机器A连接过外网机器C后,NAT会打开一个端口.然后外网的任何发到这个打开的端口的UDP数据报都可以到达A。不管是不是C发过来的。如图所示:

视频流网络透传分析_第1张图片

(2)       Address Restricted Cone

这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口。然后C可以用任何端口和A通信。其他的外网机器不行。如图:

视频流网络透传分析_第2张图片

(3)       Port Restricted Cone

这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口。然后C可以用原来的端口和A通信,其他的外网机器不行。如图:

视频流网络透传分析_第3张图片

(4)       Symmetric(对称形)

对于这种NAT。连接不同的外部Server,NAT打开的端口会变化。也就是内部机器A连接外网机器B时,NAT会打开一个端口,连接外网机器C时又会打开另外一个端口。

b)       打洞(穿越)

如上面NAT类型的描述,因为只有A主动连接了C,C才可以透过NAT发送数据到A。如果两个处在NAT环境中的主机要相互连接并传输数据(透传)的时候,就需要一个中间人的角色:Server。所以打洞的过程如图所示:

视频流网络透传分析_第4张图片

       主要流程是这样的:

(1)如果A想与B通信;

(2)A首先连接C,C得到A的外网NAT A的地址和端口;

(3)B也要连接C,C得到B的外网NAT B的地址和端口;

(4)A告诉C说我要和B通讯;

(5)C通过NAT B发信息给B,告诉B A的外网NAT A的地址和端口;

(6)B向NAT A发数据包(肯定会被NAT A丢弃,因为NAT A上并没有 A->NAT B 的合法session),但是NAT B上就建立了有B->NAT A的合法session了;

(7)B发数据包给C,让 C 通知 A,我已经把洞打好了;

(8)A接受到通知后向 B 的外网发NB数据包,这样就不会被丢弃掉了。因为对于NAT B来说,它看到的是A的外网NAT A的地址,而通过第6步,B已经让NAT A成为NAT B的合法通信对象了。所以当NAT A发数据包给NAT B时,NAT B就会接收并转发给B;

c)       STUN

STUN的全称是Simple Traversal of UDP Through NAT,即UDP对NAT的简单穿越方式。应用程序(即STUN CLIENT)向NAT外的STUN SERVER通过UDP发送请求STUN 消息询问自身的转换后地址,STUN SERVER收到请求消息,产生响应消息,响应消息中携带请求消息的源端口,即STUN CLIENT在NAT上对应的外部端口。然后响应消息通过NAT发送给STUN CLIENT,STUN CLIENT通过响应消息体中的内容得知其在NAT上对应的外部地址,并且将其填入以后呼叫协议的UDP负载中,告知对端,同时还可以在终端注册时直接注册这个转换后的公有IP地址,这样就解决了穿越NAT的通信建立问题以及作为被叫时的问题。本端的接收地址和端口号为NAT外的地址和端口号。由于通过STUN协议已在NAT上预先建立媒体流的NAT映射表项,故媒体流可顺利穿越NAT。

PS:从RFC5389开始,STUN不再是RFC3489那样作为一个NAT穿越的完全解决方案了。

STUN is not a NAT traversal solution by itself. Rather, it is a tool to be used in the context of a NAT traversal solution. This is an important change from the previous version of this specification (RFC3489), which presented STUN as a complete solution.

d)       TURN

TURN方式解决NAT问题的思路与STUN相似,也是私网中的客户端通过某种机制预先得公网上的服务地址,不同的地方在于:STUN方式得到的地址为出口NAT上外部地址,TURN方式得到地址为TURN Server上的公网地址,然后在报文净载中所要求的地址信息就直接填写该公网地址。

TURN的全称为Traversal Using Relay NAT,即通过Relay方式穿越NAT。TURN解决了STUN应用无法穿透对称NAT(Symmetric NAT)的问题,但是所有报文都必须经过TURN Server转发,所以又增大了包的延迟和丢包的可能性。

视频流网络透传分析_第5张图片

2.      天猫魔盒家庭监控APK分析

a)       抓包分析

天猫魔盒的IP为:


抓包过程为:启动家庭监控——>关闭家庭监控

此时手机端和天猫魔盒不属于同一个网段。

网络包的靠前部分为:

视频流网络透传分析_第6张图片

除去TCP的握手过程,可以清晰的看到STUN协议的包,经过查询42.156.208.7是阿里巴巴的服务器IP,所以可以断定该服务器是STUN服务器。

视频流网络透传分析_第7张图片

再仔细观察这个包,其中的NONCE字段,表明了他们采用了RFC5389的STUN协议,而CHANNEL-NUMBER则进一步表明了他们使用的是TURN协议来进行网络透传的。

              接下去让我们再继续看传输视频流的包:

视频流网络透传分析_第8张图片

所有的ChannelData包都是以0x2080开头的,通过和手机端的抓包(这里不再贴图)对比,发现0x2080就是他们视频流的网络封包。所以,这里可以断定他们是使用TURN协议来进行网络透传的。

虽然有经过服务器中转,但是视频的实时性还是不错的,实际测试中,延时大概在1S左右。

 

我们再来看一看手机端和天猫魔盒属于同一网段时候,手机端的抓包:

视频流网络透传分析_第9张图片

魔盒的IP是131,手机的是134,如上可以看出,当两者处于同一网段的时候,他们不再通过TURN中转,而是直接以UDP点对点的方式进行视频流传输,视频流网络包也是以0x2080开头,从而验证了上面所说的0x2080包头属于视频流的猜想。

 

综上所述:对于天猫魔盒和阿里TV助手配合实现的家庭监控方案,我们得到了如下分析:

1NAT穿透方面,采用的是STUN+TURN的方式,对于视频流采用服务器中转。

2)内网直接采用UDP方式进行视频流传输。

b)       APK反编译分析

使用apktool对阿里TV助手(Remote.apk)进行反编译之后,有如下文件:

      视频流网络透传分析_第10张图片

在AndroidManifest.xml中,关于家庭监控有如下内容:


       其中safehome与家庭监控模块的有关,所以我们先开始查看与safehome相关的smali目录“smali\com\yunos\safehome”(smali是apktool反编译出来的伪代码):

视频流网络透传分析_第11张图片

       在monitor/ VideoMonitorActivity.smali的伪代码中,有如下片段:

视频流网络透传分析_第12张图片


       其中可以发现,视频方面是采用mmpc/avengine/video/目录中的方法。

       接下去让我们看看mmpc中的内容:

视频流网络透传分析_第13张图片

       从这个目录中,我们不难看出,avengine与视频相关,netengine与网络相关。现在分别贴出avengine和netengine的目录结构:

视频流网络透传分析_第14张图片

                 

目录结构已经验证了我们的猜想。在VideoEngine.smali以及P2PConnector.smali中,我们都看到这么一句伪代码:


       在mmp/util/LoadLibraryUtil的LoadMmpc()函数中,我们又可以看到如下伪代码:

视频流网络透传分析_第15张图片

所以,我们可以推断,libmmpc.so是这些模块的关键库,接下去,我们就将libs/libmmpc.so通过nm命令将其中的函数打印出来。

其中我们可以看到很多关于RTP/RTCP、VideoEngine、P2PTransport等等与网络传输以及视频编解码相关的函数名。

综上所述,我们可以推出天猫手机端APK的几个技术点:

1)采用RTP传输视频流

2)采用so库进行视频编解码和NAT穿透

3)对STUN/TURN协议的实现是自己组包的

3.      初定方案

(1)实时视频流采集

方案一:在Camera中对setPreviewCallback实现onPreviewFrame接口,实时截取每一帧视频流数据。

    通过试验,传输一帧数据比较大,对网络质量要求高。

方案二:使用MediaRecorder,在SetoutputFile函数中绑定LocalSocket实现

    使用LocalSocket可以获取硬件编码后的视频流,但是不是实时视频流,需要在视频流中添加SPS和PPS重新编码并通过RTP打包发送出去。

方案三:流媒体服务器方式,利用ffmpeg或GetStreamer等获取Camera视频

(2)压缩编码

方案一:不编码,直接通过Socket传输原始YUV420SP视频帧

方案二:JPEG编码,将原始YUV420SP视频帧压缩转换为JPEG格式,JPEG传输

方案三:H.264/AVC.将原始YUV420SP视频帧压缩成H.264再传输

方案四:MPEG4.将原始YUV420SP视频帧压缩成MPEG4再传输

(3)数据传输

方案一:Socket传输

方案二:HTTP传输

方案三:RTP/RTSP传输

方案四:流媒体服务器方式,如live555等

    Live555可以将已有的视频文件编码成可播放的RTP视频流,但是对于实时视频流的编码是否支持还未知。

(4)NAT穿透

方案一:使用STUN+TURN方式进行NAT穿透(可以使用restund开源方案搭建STUN/TURN服务器)

(5)解码与播放

方案一:使用VLC/JAVACV等第三方库解码后使用SurfaceView进行播放。

方案二:直接使用MediaPlayer(需要底层芯片支持解码)

4.      可参考开源方案以及第三方库

(1)DroidIPCam(采用了libjingle库)

    http://code.google.com/p/ipcamera-for-android/

(2)spydroid-ipcamera

    http://code.google.com/p/spydroid-ipcamera/

(3)libjingle

https://code.google.com/p/webrtc/source/browse/#svn%2Ftrunk%2Ftalk


你可能感兴趣的:(移动应用)