1.
本文的目的是描述 MPEG4 Video ES 在 RTP 中的传输格式,本文的主要内容参考了 RFC-3016 和 RFC-3640 ,写作本文是为了帮助理解这两篇 RFC 的内容。如果描述有与这两篇 RFC 不一致的地方,应该以 RFC 为准。
2.
在 RFC-3016 和 RFC-3640 中,建议 MPEG4 ES 的信息描述遵循 MIME 的格式,关于 MIME 格式的详细信息,请参考 RFC-2045 和 RFC-2046 。
3.
(1)
+---------+-----------+-----------+---------------+
| RTP | AU Header | Auxiliary | Access Unit |
| Header | Section | Section | Data Section |
+---------+-----------+-----------+---------------+
从 MPEG4 Encoder 输出的每个 Packet , 被称为 Access Unit , 简写成 AU , AU Header 就是描述 AU 信息的标准格式。
Auxiliary Section 是用来描述一些辅助信息的,在 RFC 中, 这个结构没有被定义,可以由用户来自定义这块内容,也可以完全忽略。
Access Unit Data Section 就是 MPEG Encoder 的输出内容
(2)
Payload Type (PT)
Marker Bit (M) 如果 RTP Payload 是完整的 1 个或多个 AU ,M = 1 ; 如果 RTP Payload 是 AU 的碎片 ( Fragment , 意指一个 AU 被分割成多个 RTP Packet 的 Payload ) , 只有最后一个 碎片的 M = 1, 其他碎片的 M = 0 。
(3)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+
|AU-h-length|AU-header|AU-header| |AU-header|padding|
| | (1) | (2) | | (n) | bits |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+
AU-h_length就是 AU-Header_Length , specifies the length in bits
of the immediately following AU-headers, excluding the padding bits.
AU Header, 每个AU Header 是与 Access Unit( 或者是 AU Fragment) 相对应的。
Padding Bits 是为了让 AU Header Section 的长度(bits) 是 8 的整数倍
(4)
+---------------------------------------+
| AU-size |
+---------------------------------------+
| AU-Index / AU-Index-delta |
+---------------------------------------+
| CTS-flag |
+---------------------------------------+
| CTS-delta |
+---------------------------------------+
| DTS-flag |
+---------------------------------------+
| DTS-delta |
+---------------------------------------+
| RAP-flag |
+---------------------------------------+
| Stream-state |
+---------------------------------------+
AU-Size : 就是指 与 AU Header 对应的那个 Access Unit 的长度 , in octets 。
如果在 RTP 包中的 Payload 是 AU Fragment , AU-Size 也应该是完整的 AU 的长度,
不应该是 Fragment 的长度,在接受段, 可以看接受到的 AU 的长度是不是跟 AU Header 中定义的 AU-Size 一致, 来判断这个 AU 是一个完整的单元 还是只是碎片。并且可以通过这个字段来判断接受到 Access Unit 是不是完整。
AU-Index : 就是 Access Unit 或者 AU Fragment 的 serial number 。相邻的两个 AU ( Fragment ) , 应该是 AU-Index[n+1] = AU-Index[n] + 1 。
如果一个 RTP Packet 中包含多个 Access Unit , 那第一个 AU Header 必须有 AU-Index 字段,接下来的几个 AU-Header 则不允许有 AU-Index 字段,而是用 AU-Index-Delta 字段来取代。
AU-Index-Delta : AU-Index-Delta 是根据上一个 AU-Index 的值来计算当前的 AU-Index 。计算公式为 AU-Index[n+1] = AU-Index[n] + AU-Index-Delta + 1 , 所以通常情况下 , AU-Index-Delta 应该是零, 如果 AU-Index-Delta 的值不是零,则说明在 RTP Packet 封装的时候使用了 Interleave 模式, 关于 Interleave 模式, 我们以后再来解释。
CTS-Flag : 1 表示接下来的数据是 CTS , 0 表示没有 CTS
CTS : the composition time stamp 。
DTS-Flag : 1 表示接下来的数据是DTS , 0 表示没有DTS
DTS:the decoding time stamp
RAP-Flag:1 表示对应的 Access Unit 是一个 Random Access Unit , 也就是所谓的 key-packet 。
如果 对应的是 Access Unit Fragment , 那么只有第一个Fragment 的RAP-Flag 的值是1, 其他Fragment 的值应该是 0 。
Stream-state :表示编码器状态。如果编码器状态改变,这个值+1 。
RFC 中没有明确说明这个状态指那些内容, 我估计应该是resolution , fps, bps 等参数的改变吧 。
(5)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+
| auxiliary-data-size | auxiliary-data |padding bits |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+
这部分内容没有定义, 如果有用户数据 , 可以考虑把用户数据放入 Auxiliary Section 。
(6)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+
| AU(1) | AU(2) | AU(3) | … | AU(n)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+
4.
RTP Payload 允许装载 1 个或多个完整的 Access Unit
也允许装载 1 个 Access Unit Fragment
禁止把完整的 Access Unit 和 Access Unit Fragment 封装在同一个 RTP Packet 中。 禁止把多个 Access Unit Fragment 封装在 RTP Packet 中 。
通常来说 , RTP Packet 的顺序应该跟 Access Unit 的顺序一致 , 除非是 Interleave 模式下 。 关于 Interleave 模式请参看 相关的 RFC , 这里就不多做阐述了 。
[1] RFC-3016
[2] RFC-3640
[3] ISO/IEC 14496 Part 2
[4] RFC-2045
[5] RFC-2046
[6] RFC-1889
[7] RFC-3550
附注: 这是我在07年的一篇旧文, 最早发在volvet.blogbus.com上, 但是blogbus发生严重事故, 我的文字大部分都丢失了. 所幸这篇文字有人转载, 从网上找回, 发到优快云.