從零開始寫一個發送h264的rtsp服務器(上)


轉自:http://blog.csdn.net/jychen105/article/details/47006345

 

一、什么是RTSP

通常所說的rtsp協議其實包含三個協議: rtsp協議, rtp協議, rtcp協議

各協議運作流程概要:

第一階段:rtsp協議負責溝通傳輸什么數據,傳的是圖像還是聲音,還是兩者混合?圖像的話傳是h264流,還是h265流,還是jpeg流?后續的rtp,rtcp協議是采用tcp還是udp,端口號是多少都是通過第一階段的rtsp協議確定的。

第二階段:通過rtp協議傳輸數據,rtcp進行網絡傳輸質量的監控

第三階段:通過rtsp協議中斷整個協議的傳輸

二、RTSP協議詳解

rtsp協議是個文本協議,運行於tcp協議之上,服務器默認監聽端口554,當然也可以修改成其他端口,一般不改。

協議包格式

  • 客戶端協議格式

第一行:方法名:XXX\r\n

第二行:CSeq:XXX\r\n

第N行:XXX\r\n

\r\n

  • 服務器端協議格式

第一行:RTSP/1.0 XXX\r\n

第二行:CSeq:XXX\r\n

第N行:XXX\r\n

\r\n

協議最終都是以兩個\r\n分隔

rtsp通信精簡版

步驟 客戶端 服務端 含義
1 請求OPTIONS 回應OPTIONS 查詢服務器支持哪些命令或者方法
2 請求DESCRIBE 回應DESCRIBE 查詢服務器發送流的描述信息
3 請求SETUP 回應SETUP 告訴服務器以TCP or UDP建立RTP,RTCP連接,並告訴端口號
4 請求PLAY 回應PLAY 告訴服務器可以用RTP協議發送數據過來了
最后一步 請求TEARDOWN 關閉連接 告訴服務器關閉連接

rtsp通信詳細版本

客戶端:192.168.1.109 
服務端:192.168.1.188

1. OPTIONS

客戶端請求:

OPTIONS rtsp://192.168.1.188/h264 RTSP/1.0
CSeq: 2
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)

服務端回應:

RTSP/1.0 200 OK
CSeq: 2
Date: Mon, Jul 21 2014 09:07:56 GMT
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER

需注意的點:

  • 回應的CSeq與請求的CSeq必須一致,后續rtsp命令下同。

  • PAUSE, GET_PARAMETER, SET_PARAMETER這幾個命令可無,也就是一些命令服務器可以不實現。OPTIONS, SETUP, PLAY是一定要有的,其他的未認真調查。

2. DESCRIBE

客戶端請求:

DESCRIBE rtsp://192.168.1.188/h264 RTSP/1.0
CSeq: 3
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Accept: application/sdp

服務端回應:

RTSP/1.0 200 OK
CSeq: 3
Date: Mon, Jul 21 2014 09:07:56 GMT
Content-Base: rtsp://192.168.1.188/h264/
Content-Type: application/sdp
Content-Length: 547

v=0
o=- 1405932398518315 1 IN IP4 192.168.1.188
s=Session streamed by "hua_an"
i=h264
t=0 0
a=tool:LIVE555 Streaming Media v2012.10.24
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:Session streamed by "hua_an"
a=x-qt-text-inf:h264
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:500
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=64002A;sprop-parameter-sets=J2QAKq2EBUViuKxUcQgKisVxWKjiECSFITk8nyfk/k/J8nm5s00IEkKQnJ5Pk/J/J+T5PNzZpsqAUAW6bIAAAfQAAGGocAAABbjYAAD0JBe91lA=,KP4Briw=
a=control:track1

注意的點:

  • 服務端回應了兩個協議,一個是rtsp的回應,還回應了一個sdp協議(Session Description Protocol),sdp協議最后一個只有一個\r\n。 rtsp協議是兩個\r\n結尾。

  • sdp協議中描述了發送的流為h264,采樣率為90000Hz (h264的采樣率為90000HZ,因此時間戳的單位為1(秒)/90000,因此如果當前視頻幀率為25fps,那時間戳間隔或者說增量應該為3600, 即每個naul單元的時間間隔為3600。此句話可以放在rtp協議封裝h264時理解。)

  • sprop-parameter-sets為sps跟pps的base64編碼組合。(sps,pps為h264 nalu單元的Sequence Parameter Sets (SPS) 和Picture Parameter Set (PPS), 后續會介紹)

3. SETUP

客戶端請求:

SETUP rtsp://192.168.1.188/h264/track1 RTSP/1.0
CSeq: 4
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Transport: RTP/AVP/TCP;unicast;interleaved=0-1

服務端回應:

RTSP/1.0 200 OK
CSeq: 4
Date: Mon, Jul 21 2014 09:07:56 GMT
Transport: RTP/AVP/TCP;unicast;destination=192.168.1.109;source=192.168.1.188;interleaved=0-1
Session: 5C01EACE

此處為TCP建立RTP跟RTCP。RTP,RTCP都是利用此路連接,不再建立新連接,只是數據包格式不一樣而以。 
注意interleaved=0-1, 0為傳送RTP數據,1為RTCP數據

4. PLAY

客戶端請求

PLAY rtsp://192.168.1.188/h264/ RTSP/1.0
CSeq: 5
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Session: 5C01EACE
Range: npt=0.000-

服務端回應

RTSP/1.0 200 OK
CSeq: 5
Date: Mon, Jul 21 2014 09:07:56 GMT
Range: npt=0.000-
Session: 5C01EACE
RTP-Info: url=rtsp://192.168.1.188/h264/track1;seq=28626;rtptime=98136845

播放,開始傳輸rtp數據。同時告知開始序號為28626, 開始時間戳為98136845

5. 最后一步

客戶端請求:

TEARDOWN rtsp://192.168.1.188/h264/ RTSP/1.0
CSeq: 7
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Session: 5C01EACE

服務端回應:

關閉RTSP連接

三、RTP協議

根據之前rtsp的協議,rtp即可以通過tcp,也可以通過udp傳輸。但是數據包協議格式是一樣的。

  • tcp傳輸
協議格式 ‘$’ 0 長度(=RTP協議頭長度+RTP數據長度) RTP協議頭 RTP數據
長度信息 1字節 1字節 2字節 sizeof(RTP協議頭) N
  • udp傳輸
協議格式 RTP協議頭 RTP數據
長度信息 sizeof(RTP協議頭) N

– 數據傳輸采用網絡字節序

– RTP數據長度小於MTU長度, 一般是1500, 目的是為了網絡傳輸避免分片,未深究如何避免分片的。

– 傳輸的流媒體數據就是封裝在RTP數據部分

RTP協議頭

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|  CC   |M|     PT      |       sequence number         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           synchronization source (SSRC) identifier            |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|            contributing source (CSRC) identifiers             |
|                             ....                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

//set CC = 0, so there is no CSRC

轉成c語言結構體(小端字節序):

typedef struct 
{
    /* byte 0 */
    unsigned char csrc_len:4;  /* CC expect 0 */
    unsigned char extension:1; /* X  expect 1, see RTP_OP below */
    unsigned char padding:1;   /* P  expect 0 */
    unsigned char version:2;   /* V  expect 2 */

    /* byte 1 */
    unsigned char payload:7;   /* PT  RTP_PAYLOAD_RTSP */
    unsigned char marker:1;    /* M   expect 1 */

    /* byte 2,3 */
    unsigned short seq_no;     /*sequence number*/

    /* byte 4-7 */
    unsigned  long timestamp;  /*time stamp*/

    /* byte 8-11 */
    unsigned long ssrc;        /* stream number is used here. */
} RTPHeader;/*12 bytes*/

四、RTCP

rtcp主要是用來解決網絡流控的,如果是自實現rtsp服務器傳輸實時流,可以不實現此部分。

如果是實現rtsp客戶端,建立實現一個Recvive Report包就行了,此包主要是報告丟包率,網絡延遲是多少,方便服務器端調節。 
因為發的都是實時流,簡單起見,recvive report封包時,丟包率為0,延遲也為0

五、h264是如何通過rtsp發送的

下篇


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM