Rtsp交互流程,RTP 打包流程

xiaoxiao2021-02-28  131

http://blog.csdn.net/smilestone_322/article/details/7574253

1. 网络抽象层单元类型 (NALU)

NALU 头由一个字节组成, 它的语法如下:

      +---------------+       |0|1|2|3|4|5|6|7|       +-+-+-+-+-+-+-+-+       |F|NRI| Type   |       +---------------+

F: 1 个比特. forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.

NRI: 2 个比特. nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性,如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心。

这个属性.

Type: 5 个比特. nal_unit_type. 这个 NALU 单元的类型. 简述如下:

0     没有定义 1-23 NAL单元 单个 NAL 单元包. 24    STAP-A   单一时间的组合包 25    STAP-B   单一时间的组合包 26    MTAP16   多个时间的组合包 27    MTAP24   多个时间的组合包 28    FU-A     分片的单元 29    FU-B     分片的单元 30-31 没有定义

2. 打包模式

下面是 RFC 3550 中规定的 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             |       |                             ....                              |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

负载类型 Payload type (PT): 7 bits 序列号 Sequence number (SN): 16 bits 时间戳 Timestamp: 32 bits

H.264 Payload 格式定义了三种不同的基本的负载(Payload)结构接收端可能通过 RTP Payload的第一个字节来识别它们这一个字节类似 NALU 头的格式而这个头结构的 NAL 单元类型字段则指出了代表的是哪一种结构。

 

这个字节的结构如下, 可以看出它和 H.264 的 NALU 头结构是一样的.       +---------------+       |0|1|2|3|4|5|6|7|       +-+-+-+-+-+-+-+-+       |F|NRI| Type   |       +---------------+ 字段 Type: 这个 RTP payload 中 NAL 单元的类型. 这个字段和 H.264 中类型字段的区别是, 当 type 的值为 24 ~ 31 表示这是一个特别格式的 NAL 单元, 而 H.264 中, 只取 1~23 是有效的值.    24    STAP-A   单一时间的组合包 25    STAP-B   单一时间的组合包 26    MTAP16   多个时间的组合包 27    MTAP24   多个时间的组合包 28    FU-A     分片的单元 29    FU-B     分片的单元 30-31 没有定义

可能的结构类型分别有:

1. 单一 NAL 单元模式      即一个 RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264的 NALU 头类型字段是一样的.

2. 组合封包模式     即可能是由多个 NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24. 那么这里的类型值分别是 24, 25, 26 以及 27.

3. 分片封包模式     用于把一个 NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29.

2.1 单一 NAL 单元模式

对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式. 对于一个原始的 H.264 NALU 单元常由 [Start Code] [NALU Header] [NALU Payload] 三部分组成, 其中 Start Code 用于标示这是一个

NALU 单元的开始, 必须是 "00 00 00 01" 或 "00 00 01", NALU 头仅一个字节, 其后都是 NALU 单元内容. 打包时去除 "00 00 01" 或 "00 00 00 01" 的开始码, 把其他数据封包的 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       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |F|NRI| type   |                                               |       +-+-+-+-+-+-+-+-+                                               |       |                                                               |       |               Bytes 2..n of a Single NAL unit                 |       |                                                               |       |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |                               :...OPTIONAL RTP padding        |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

如有一个 H.264 的 NALU 是这样的:

[00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]

这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 是 NALU , 42 开始的数据是 NALU 内容.

封装成 RTP 包将如下:

[ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

即只要去掉 4 个字节的开始码就可以了.

 

2.2 组合封包模式

其次, 当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 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       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |                          RTP Header                           |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |STAP-A NAL HDR |         NALU 1 Size           | NALU 1 HDR    |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |                         NALU 1 Data                           |       :                                                               :       +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |               | NALU 2 Size                   | NALU 2 HDR    |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |                         NALU 2 Data                           |       :                                                               :       |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |                               :...OPTIONAL RTP padding        |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

举例:

如有一个 H.264 的 NALU 是这样的:  [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]  [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]  这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 是 NALU 头, 42 开始的数据是 NALU 内容.  封装成 RTP 包可能如下:  [ RTP Header ] [78, STAP-A NAL HDR, 一个字节 ] [长度, 两个字节] [ 67 42 A0 1E 23 56 0E 2F ...] [长度, 两个字节] [ 67 42 A0 1E 23 56 0E 2F... ]

 

2.3 Fragmentation Units (FUs).

而当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs).        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       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       | FU indicator |   FU header   |                               |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |       |                                                               |       |                         FU payload                            |       |                                                               |       |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+       |                               :...OPTIONAL RTP padding        |       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      Figure 14. RTP payload format for FU-A

   The FU indicator octet has the following format:

      +---------------+       |0|1|2|3|4|5|6|7|       +-+-+-+-+-+-+-+-+       |F|NRI| Type   |       +---------------+

   The FU header has the following format:

      +---------------+       |0|1|2|3|4|5|6|7|       +-+-+-+-+-+-+-+-+       |S|E|R| Type   |       +---------------+

 

举例如下:

int GEPlayback::SendNaluPacket( BYTE* sliceData, int sliceSize, BOOL isEnd,  BOOL isVideo, int type, time_t pts, INT64 timestamp )  {  // NALU 小于最大 RTP 包大小的情况  if (sliceSize < 1350) {  return SendPacket(sliceData, sliceSize, isEnd, TRUE, type, pts, timestamp);  }  // 如果一个 NALU 大于最大的 RTP 包的大小, 则需要把它进行分片后打包发送  BYTE buffer[1500];  BYTE nalHeader = sliceData[0]; // NALU 头  BYTE* data = sliceData + 1;  int leftover = sliceSize - 1;  BOOL isStart = TRUE;  while (leftover > 0) {  int size = MIN(1350, leftover);  isEnd = (size == leftover);  // 构建 FU 头  buffer[0] = (nalHeader & 0x60) | 28; // FU indicator  buffer[1] = (nalHeader & 0x1f); // FU header  if (isStart) {  buffer[1] |= 0x80;  }  if (isEnd) {  buffer[1] |= 0x40;  }  memcpy(buffer + 2, data, size);  SendPacket(buffer, size + 2, isEnd, TRUE, type, pts, timestamp);  leftover -= size;  data += size;  isStart = FALSE;  }  return sliceSize;  }

Rtsp交互流程

http://blog.csdn.net/smilestone_322/article/details/7570066

简单的RTSP交互过程: C表示RTSP客户端,S表示RTSP服务端 1.C->S:OPTIONS request    //询问S有哪些方法可用 1.S->C:OPTIONS response   //S回应信息中包括提供的所有可用方法 2.C->S:DESCRIBE request   //要求得到S提供的媒体初始化描述信息 2.S->C:DESCRIBE response  //S回应媒体初始化描述信息,主要是sdp   3.C->S:SETUP request      //设置会话的属性,以及传输模式,提醒S建立会话 3.S->C:SETUP response     //S建立会话,返回会话标识符,以及会话相关信息   4.C->S:PLAY request       //C请求播放 4.S->C:PLAY response      //S回应该请求的信息   S->C:发送流媒体数据 5.C->S:TEARDOWN request   //C请求关闭会话 5.S->C:TEARDOWN response  //S回应该请求

 

转载一篇文件,对rtsp建立流程有详细的解答:

http://hi.baidu.com/yg_110/item/6ad422ebd6ae72b72e140b23

 

内容如下:

 

关于RTSP的理解和例子说明

rtsp是real time streaming protocol,按照我的理解为流媒体控制协议,协议双方的的编码类型和地址,以及对stream media的控制(play,pause,record).注意这里不要与RTCP协议搞混,rtcp是用来控制rtp的.

下面通过介绍RTSP的几种方法来说明协议 1:options  这个通常由client发送server,询问服务器所支持的方法种类,当然在应用中也可以用来作为心跳,因为它是状态无关的.例如: C->S:       OPTIONS * RTSP/1.0             CSeq: 1             Require: implicit-play             Proxy-Require: gzipped-messages

S->C:       RTSP/1.0 200 OK             CSeq: 1             Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE 服务端发送的200ok里表明服务端支持describe,setup,teardown,play,pause. 在这里可以看到请求和响应的cseq相同,对应后面所有的消息,请求和响应的cseq都是相同的.

2:describe 按照字面意思,就是描述,描述什么呢?当然是流媒体的信息呢,在返回的应答中包含SDP.举个例子 DESCRIBE rtsp://server.address:port/object.sdp RTSP/1.0\r\n CSeq: 1\r\n \r\n

----------------------------------------------------------------------- RTSP/1.0 200 OK\n Server: QTSS(IFI)/v88\n Cseq: 1\n Content-Type: application/sdp\n Content-Base: rtsp://bildeus.ifi.uio.no:8000/12.sdp/\n Content-length: 785\n \n n=2236805513 2236805513 932036356 224.2.127.254 9875 127 trusted\n v=0\n o=yozo 3138827440 3138828177 IN IP4 aohakobe.ipc.chiba-u.ac.jp\n s=Places all over the world\n i=Low bandwidth video (10kb/s) with views from all over the world. Audio is primarily for feedback for the senders of video. (looks like there's some problem for the session announcement from sweden distributes to the whole MBone, I'm repeating the announcement from japan. -- yozo.)\n e=Yozo TODA at IPC, Chiba University, JAPAN < p=+81-43-290-3539\n c=IN IP4 224.2.213.113/127\n t=3138827400 3141246600\n a=tool:sdr v2.6.1\n a=type:test\n m=audio 20154 RTP/AVP 0\n c=IN IP4 224.2.213.113/127\n a=ptime:40\n a=control:trackID=1\n m=video 51482 RTP/AVP 31\n c=IN IP4 224.2.172.238/127\n a=control:trackID=2\n

在应答中, 我们重点关注SDP字段.在SDP中,我们看到了流媒体包含了2个资源(m行):audio和video,其中a行是m(media)的属性描述.在m行中,中间的数字为服务端推荐客户端接收的端口,如果服务端不想这样做,可以将port置为0.在sdp中,还有a=control字段,在rfc2326中,对其的解释如下:

   The "a=control:" attribute is used to convey the control URL. This    attribute is used both for the session and media descriptions. If    used for individual media, it indicates the URL to be used for    controlling that particular media stream. If found at the session    level, the attribute indicates the URL for aggregate control.

   Example:      a=control:rtsp://example.com/foo

   This attribute may contain either relative and absolute URLs,    following the rules and conventions set out in RFC 1808 [25].    Implementations should look for a base URL in the following order:

   1.     The RTSP Content-Base field    2.     The RTSP Content-Location field    3.     The RTSP request URL

   If this attribute contains only an asterisk (*), then the URL is    treated as if it were an empty embedded URL, and thus inherits the    entire base URL.

    这里我们对集合控制(aggregate control)进行说明.当服务端支持集合控制,比如对一个音频视频流,它就不需要建立2个session,集合成一个session就ok,如果不支持就得分别建立2个session.我的理解a=control即是对媒体的标识:比如track1表示视频,track2表示音频.在后续的setup中可以看到这点. 通过SDP这些参数我们就可以知道流媒体的编码格式.

3:setup 建立会话,如果支持集合控制,在setup中会包含session字段.下面的消息是支持集合操作的例子.

SETUP rtsp://server.address:port/object.sdp/trackID=1 RTSP/1.0\r\n CSeq: 2\r\n Transport: RTP/AVP;unicast;client_port=9000-9001\r\n \r\n -------------------------------------------------------------------------

RTSP/1.0 200 OK\n Server: QTSS(IFI)/v88\n Cseq: 2\n Session: 1234567890;timeout=60 Transport: rtp/avp;source=129.240.65.208;server_port=9000-9001;client_port=9000-9001\n \n -------------------------------------------------------------------------- SETUP rtsp://server.address:port/object.sdp/trackID=2 RTSP/1.0\r\n CSeq: 3\r\n Session: 1234567890\r\n Transport: RTP/AVP;unicast;client_port=9000-9001\r\n \r\n

在例子中我们看到,通过setup的响应,即建立了流媒体的会话.后续的setup必须带上session字段,通过上面的消息我们看到客户端发送了2次setup,分别是代表video的track1和audio的track2.如果服务端不支持集合操作,那么setup里带上session字段则是非法的.在消息中,我们看到了transport字段,在这里表明了客户端接收流媒体的端口,以及编码格式.在本例中采用的是udp方式传送RTP,如果采用TCP的方式传送RTP,则可能transport 字段为:Transport: RTP/AVP/TCP;unicast;interleaved=0-1 ,这里解释下interleaved,因为采用TCP方式传送,所以传送的RTP,RTCP包都在同一个链路上,需要区分,所以有了interleaved,0表示是RTP的通道,1表示是RTCP的通道.体现在包上面就是在RTP,RTCP包上封装了一层interleaved frame,格式如下: Magic:0x24 Channel:0x01(表示RTCP) Length:84

4:play play 即对流媒体的播放指令: PLAY rtsp://server.address:port/object.sdp RTSP/1.0\r\n CSeq: 4\r\n Session: 1234567890\r\n \r\n 通常在play中有range字段,但不是必需的.这个字段表示播放的流媒体的范围.

5:teardown teardown指令即对流媒体的结束 在teardown中是否必须带有session,我们曾经进行过讨论.如果一个session对应一个链路,则可以不需要对应session,但是在我们遇到的应用中,teardown基本都是携带了teardown.谈到这里,我们说下RTSP的几种连接类型: * persistent transport connections used for several request-response transactions * one connection per request/response transaction; * connectionless mode.

对几种基本的消息的介绍就到这里了,我们现在来谈谈RTSP的状态机.其实RTSP的状态机很简单,不像sip协议那么复杂.对应很多消息,是状态无关的.现在这里只介绍与服务器相关的状态机:      state           message received     next state      Init             SETUP                    Ready                          TEARDOWN          Init      Ready           PLAY              Playing                      SETUP             Ready                      TEARDOWN          Init                      RECORD            Recording      Playing         PLAY              Playing                      PAUSE             Ready                      TEARDOWN          Init                      SETUP             Playing      Recording       RECORD            Recording                      PAUSE             Ready                      TEARDOWN          Init                      SETUP             Recording 通过上面的表,我们就可以知道消息的发送必须是有序的,比如还没有发送setup,就不能发送play.还有连续2次的pause肯定是错误的.在这个状态机中,是没有结束的,我们通常teardown后一个会话就会结束,甚至会关闭链路.但是在上图中又回到了init状态,我对此有些迷惑,这里又要提到了上面我们讨论的话题:teardown是否该带session,在这个状态机中,在任何阶段都可以接收teardown,比如init阶段,这个阶段是没有session的.

PS:这篇是在DR的最后一个项目(全球眼)结束后写的一篇总结。如今看来,却有部分连自己都不懂了。

转载请注明原文地址: https://www.6miu.com/read-20880.html

最新回复(0)