Android实现RTSP


RTSP和SIP有些类似,只是起到媒体协商的作用,并不关心媒体流的手法,具体来讲,在协商过程中,采用TCP协议进行一系列交互

具体流程:

-------------------------------
C--->S:     DESCRIBE
S--->C:     DESCRIBE/SDP

C--->S:     SETUP
S--->C:     SETUP

C--->S:     PLAY
S--->C:     PLAY

媒体流传输

C--->S:     TEARDOWN
-------------------------------

研究RTSP协议的最好方法 :

  • 先去下载一个live555的开源流媒体服务器,手机端则用videoview控件做客户端
  • 用wireshark抓取videoview和live555通信时的包,分析live555 response的格式
  • 细节不懂的地方参照协议RFC 2326

DESCRIBE

具体到程序里是,客户端采用videoview,需要setVideoURI(rtsp://192.168.2.103:1234/path/stream.sdp); 这里这个uri是说向192.168.2.103端口为1234的rtsp服务器发送播放流媒体文件请求,流媒体文件路径为path,文件为stream.sdp 此时videoview会向server发送两个tcp包, 如下:

第一个包用于连接,第二个包发送的是DESCRIBE,内容如下:

0000   44 45 53 43 52 49 42 45 20 72 74 73 70 3a 2f 2f  DESCRIBE rtsp://
0010   31 39 32 2e 31 36 38 2e 32 2e 31 30 33 3a 31 32  192.168.2.103:12
0020   33 34 2f 73 74 72 65 61 6d 2e 73 64 70 20 52 54  34/stream.sdp RT
0030   53 50 2f 31 2e 30 0d 0a 43 53 65 71 3a 20 31 0d  SP/1.0..CSeq: 1.
0040   0a 41 63 63 65 70 74 3a 20 61 70 70 6c 69 63 61  .Accept: applica
0050   74 69 6f 6e 2f 73 64 70 0d 0a 41 63 63 65 70 74  tion/sdp..Accept
0060   2d 45 6e 63 6f 64 69 6e 67 3a 20 69 64 65 6e 74  -Encoding: ident
0070   69 74 79 0d 0a 43 6f 6e 74 65 6e 74 2d 45 6e 63  ity..Content-Enc
0080   6f 64 69 6e 67 3a 20 69 64 65 6e 74 69 74 79 0d  oding: identity.
0090   0a 43 6f 6e 74 65 6e 74 2d 4c 61 6e 67 75 61 67  .Content-Languag
00a0   65 3a 20 65 6e 2d 55 53 0d 0a 42 61 6e 64 77 69  e: en-US..Bandwi
00b0   64 74 68 3a 20 31 31 30 30 30 30 30 30 0d 0a 55  dth: 11000000..U
00c0   73 65 72 2d 41 67 65 6e 74 3a 20 48 54 43 20 53  ser-Agent: HTC S
00d0   74 72 65 61 6d 69 6e 67 20 50 6c 61 79 65 72 20  treaming Player
00e0   68 74 63 5f 61 73 69 61 5f 77 77 65 20 2f 20 31  htc_asia_wwe / 1
00f0   2e 30 20 2f 20 68 74 63 5f 73 61 67 61 20 2f 20  .0 / htc_saga /
0100   32 2e 33 2e 33 0d 0a 78 2d 6e 65 74 77 6f 72 6b  2.3.3..x-network
0110   2d 74 79 70 65 3a 20 57 49 46 49 0d 0a 78 2d 77  -type: WIFI..x-w
0120   61 70 2d 70 72 6f 66 69 6c 65 3a 20 68 74 74 70  ap-profile: http
0130   3a 2f 2f 77 77 77 2e 68 74 63 6d 6d 73 2e 63 6f  ://www.htcmms.co
0140   6d 2e 74 77 2f 41 6e 64 72 6f 69 64 2f 43 6f 6d  m.tw/Android/Com
0150   6d 6f 6e 2f 50 47 38 38 2f 75 61 2d 70 72 6f 66  mon/PG88/ua-prof
0160   69 6c 65 2e 78 6d 6c 0d 0a 0d 0a                      ile.xml....

按照rfc2326的标准格式:

image

写response时注意几点:

  • RTSP版本号要一致
  • CSeq要一致
  • content-type一般是sdp
  • content-lengthsdp长度
  • 一定要把control这个属性加上,否则videoview解析不出来
  • 一定要注意每个消息头部结尾时的"\r\n\r\n",不写或写错会导致videoview死循环,后面的消息同理

代码如下:

String describe_content = "v=0\r\n"+
"o=- 1234567899876543 1 IN IP4 192.168.1.102\r\n"+
"a=range:npt=0-\r\n"+
"m=video 0 RTP/AVP 96\r\n"+
"c=IN IP4 0.0.0.0\r\n"+
"b=AS:500\r\n"+
"a=rtpmap:96 H264/90000\r\n"+                                                       
"a=control:track1";
                                               
String descirbe_header = "RTSP/1.0 200 OK\r\n"+
"CSeq: 1\r\n"+
"Date: Fri,12 Aug 2011 18:43:59 GMT\r\n"+
"Content-Base: rtsp://192.168.1.102:554/newStream264.264\r\n"+
"Content-Type: application/sdp\r\n"+
"Content-Length: "+describe_content.length()+"\r\n\r\n";

注意几点:

  1. 一定要确保 "a=control:track1"
  2. 对于三星手机下面参数一定要写,具体含义参见RFC3984,其含义是:指定RTP的传输通道是track1,具体含义参考sdp协议
a=fmtp:96 packetization-mode=1;
profile-level-id=42000B;
sprop-parameter-sets=Z0IAC41oLE5A,aM4G8g==

SETUP

此时videoview会发来SETUP请求,同样要给予应答,代码如下:

String setup_header = "RTSP/1.0 200 OK\r\n"+
"CSeq: 2\r\n"+
"Date: Fri,12 Aug 2011 18:43:59 GMT\r\n"+
"Transport: RTP/AVP;unicast;mode=play;destination=192.168.1.101;source:192.168.1.102;" +
"client_port="+port1+"-"+port2+";server_port=6970-6971\r\n"+
"Session: 00004E61\r\n\r\n";

注意文本格式,尤其是空格的位置需要特别注意

PLAY

vidoview收到SETUP回复后会发送PLAY消息,同样要给予应答,代码如下:

String play_header = "RTSP/1.0 200 OK\r\n"+
              "CSeq: 3\r\n"+
              "Date: Fri,12 Aug 2011 18:43:59 GMT\r\n"+
              "Range: npt=0.000-\r\n"+
              "Session: 00004E61\r\n"+
              "RTP-Info: url=rtsp://192.168.1.102/newStream264.264/track1;seq=1000;rtptime=27000\r\n\r\n";                 

其中Session的标识符要与SETUP的一致,seq指定了RTP包的起始值,rtptime指定了时间戳的起始值