spydroid源码分析(二):spydroid运行流程

来源:互联网 发布:js的transitionend 编辑:程序博客网 时间:2024/05/29 05:03

          这几天空闲的时候在看《struts2技术内幕》这本书,作者downpour说的这句话我很赞同,忘了原文了,  学习开源项目,不是一个包一个包的阅读代码,而是通过动态运行项目,通过断点调试,来获取相关信息。 我也打算用这种方式来看spydroid源代码,但了解每个package大体的功能是必须的。

          如果spydroid已经安装到了android手机上,开启这个软件,VLC就可以通过rtsp://手机的ip:8086/访问。在这里以H264来说明spydroid的运行流程,其他类似。在这里需要吧option的encode编码设为h264.调试android源代码,可以通过logcat打印相关信息

           程序运行时,进入net.majorkernelpanic.spydroid.SpydroidActivity,该activity 运行时候,开启http server ,rtsp server。这里重点关注rtsp 服务。           

   进入  net.majorkernelpanic.networking.RtspServer

rtspserver开启后,启动一个线程RequestListenerThread,负责监听客户端(这里用VLC)的请求,public void start() throws IOException {
if (running) return;
running = true;
listenerThread = new RequestListenerThread(port,handler);
listenerThread.start();
}


当有客户端请求的时候,开启一个workerTread线程。一个线程session代表一个请求

new WorkerThread(server.accept(), handler).start();


VLC向rtsp服务器进行交互时,这里就需要用到rtsp协议的内容了,主要分为Options,Describe,Setup,play,teardown这5步骤。

下面是我进行rtsp连接,服务器与客户端请求与响应的详细信息,

 

//当来自192.168.1.26的VLC客户端向手机服务器发送rtsp://192.168.1.60:8086请求时
 
Connection from 192.168.1.26        //来自192.168.1.26的请求

//下面的C表示客户端client,S表示服务器server
C-S:OPTIONS rtsp://192.168.1.60:8086/ RTSP/1.0     //可用选项
S-C: Public: DESCRIBE,SETUP,TEARDOWN,PLAY,PAUSE        //描述信息、建立连接、关闭、播放、暂停

C-S:DESCRIBE rtsp://192.168.1.60:8086/ RTSP/1.0
S-C:
v=0
o=- 1357627796453 1357627796453 IN IP4 192.168.1.60      //1357627796453是当前的timestamp信息,timestamp =System.currentTimeMillis();
s=Unnamed
i=N/A
c=IN IP4 192.168.1.26
t=0 0            //t=0 0意味着会话是永久的
a=recvonly
m=video 5006 RTP/AVP 96    //video指明是视频信息, 5006是指客户端VLC接收视频信息的udp端口号
                          
b=RR:0
a=rtpmap:96 H264/90000          //这里的96的信息很关键,因为这个是rtp的负载类型,Payload type (PT): 7 bits。后面介绍rtp协议的时候会介绍,H264编码,90000是H264视频传输的默认视频采样频率,必须是这个值
a=fmtp:96 packetization-mode=1;profile-level-id=42c016;sprop-parameter-sets=ZOLAFukBQHsg,aM4G4g==;</             //packetization-mode=1指定rtp打包模式,有3种模式,数值只能为0,1,2,。0是单NAL单元模式 1是非交互模式 2是交互模式
    profile,sps,pps这3个数值是从mp4中提取出来的base64编码,在net.majorkernelpanic.mp4这个包      有详细介绍。a=control:trackID=0   //trackID为0

Content-Base: 192.168.1.60:8086/
Content-Type: application/sdp          //规定文件格式类型为sdp

C-S:SETUP 192.168.1.60:8086/trackID=0 RTSP/1.0
S-C:
Transport: RTP/AVP/UDP;unicast;destination=192.168.1.26;client_port=5006-5007;server_port=49749-49750;ssrc=431567f7;mode=play
Session: 1185d20035702ca        //制定基于udp协议的rtp传输,目标地址,客户端端口、服务器端口,以及ssrc的数值,这里ssrc的数值很重要,它是同步源标识,synchronization source (SSRC) identifier,在rtp传输中,会包含这个内容
Cache-Control: no-cache

C-S:  PLAY 192.168.1.60:8086/ RTSP/1.0
S-C:
RTP-Info: url=rtsp://192.168.1.60:8086/trackID=0;seq=0
Session: 1185d20035702ca       //session标识

C-S:   TEARDOWN 192.168.1.60:8086/ RTSP/1.0

 

 在上面的内容中,可以看到options请求时,发送可用的状态。
describe请求时,发送流类型,在这里是h264视频流,以及mp4 的profile,sps,pps,在不同手机上,profile,sps,pps的数值不一定相同。这个是通过提取录制的该手机上的mp4文件的内容得到的。 除了H264,这里也可以是H263视频流,或者其他audio音频流。这里重点查看generateSessionDescriptor()   方法,比如在这里,选择H264,那么就可以看看H264Stream这个类的这个方法,看看它是如何获取profile ,sps,pps的setup请求时,主要关注stream.prepare(),stream.start()方法,prepare()的时候调用初始化视频录制的参数,比如H264编码,分辨率,帧数等相关信息。而start()方法就开始通过localsocket把录制的视频以流的形式发送到本地,而H264Packetizer通过获取其输入流,然后对其rtp打包处理,发送。

 

写完后才发现排版极为糟糕,重新整理一下