diff --git "a/src/\345\214\205\345\244\264\345\216\213\347\274\251.md" "b/src/\345\214\205\345\244\264\345\216\213\347\274\251.md" index 4fe3bda..f948597 100644 --- "a/src/\345\214\205\345\244\264\345\216\213\347\274\251.md" +++ "b/src/\345\214\205\345\244\264\345\216\213\347\274\251.md" @@ -68,11 +68,8 @@ RTP 包头压缩使用了很多相同的技术,观察表明,尽管每个数 上下文包含以下状态信息,这些信息将在收到完整的包头包时进行初始化: - 传送的最后一个数据包的完整 IP,UDP 和 RTP 包头,可能包括 CSRC 列表 - - 当接收到一个完整的包头时,将会把 IPv4 的 ID 字段的一阶差分初始化为 1。(当 RTP-over-UDP/IPv6 被压缩时,不需要此信息,因为 IPv6 没有 ID 字段) - - 当接收到一个完整的包头时,RTP 的 timestamp 字段 的一阶差分初始化为 0。 - - CRTP 序列号(4bit)的最后一个值,用于检测压缩链路丢包。 有了这些上下文信息,接收端就可以解码收到的每个连续数据包。尽管可能需要使用每个数据包更新存储在上下文中的状态,但不再需要额外的其他状态。 @@ -96,15 +93,10 @@ RTP 包头压缩使用了很多相同的技术,观察表明,尽管每个数 你可以通过采用先前存储在上下文中的报头来重构 RTP 包头,按如下所述进行修改: - 如果所有 M,S,T 和 I 都为 1,则数据包包含 CC 字段和 CSRC 列表以及 M‘,S’,T‘,I’。在这种情况下,M,S,T,I 字段用于预测标记位,序列号,时间戳和 IPv4 ID。CC 字段和 CSRC 列表基于压缩的 RTP 包被更新。否则,CC 和 CSRC 列表将基于先前的数据包进行重建。 - - M 位被压缩 RTP 包中的 M(或 M’)位所代替。 - - 如果压缩 RTP 包中的 S 或 S‘位为 1,则 RTP 序列号将增加由压缩 RTP 包中的 delta RTP sequence 指示的值。否则 RTP 序列号自增 1。 - - 如果压缩 RTP 包中设置了 T 或 T’位,则将 RTP 时间戳增加压缩 RTP 数据包中的 delta RTP timestamp 字段指示的值,并更新上下文中存储的时间戳的一阶差分值。否则,RTP 时间戳会根据上下文中存储的一阶差分值递增。 - - 如果上下文中设置了 X 位,将从压缩 RTP 中恢复 header extension 字段。 - - 如果上下文中设置了 P 位,将从压缩 RTP 中恢复 padding 字段。 上下文以及任何对 IPv4 ID,RTP 时间戳 的一阶差分和链路层序列号的更新将使用新接收到的包头来进行更新。然后,将重构的包头和负载数据传递到 IP 栈,以常规方式进行处理。 @@ -136,9 +128,7 @@ CRTP 的另一个限制因素是数据包重排序。如果数据包在压缩链 观察媒体流包头字段的变化,可以发现这些字段分为三类: 1. 有些字段或者大部分字段都是静态不变的。比如 RTP,SSRC,UDP 端口号和 IP 地址。这些字段在连接建立时发送一次,它们或者从不改变,或者变化不频繁。 - 2. 有些字段随着数据包的发送以可预测的方式变化,但偶尔会突然变化。比如 RTP 时间戳,序列号,以及 IPv4 ID 字段。在这些字段可预测期间,它们通常有一个恒定的关系。当突然变化时,通常只有一个字段发生了不可预期的变化。 - 3. 有些字段是不可预测的,基本上是随机的,必须按原样进行通信,不能进行压缩。主要是 UDP 校验和。 ROHC 通过在 RTP 序列号和其他可预测字段之间建立映射函数(mapping functions)进行操作,然后可靠的传输 RTP 序列号和不可预测的包头字段。这些静态函数与在启动或当这些字段更改时传递的静态字段一起构成了压缩上下文的一部分。 @@ -150,9 +140,7 @@ ROHC 和 CRTP 的主要差别在它们处理第二类字段(通常以可预测 ROHC 具有三种运行状态,具体取决于传输的上下文量: 1. 系统以初始化和刷新状态启动,非常类似于 CRTP 的完整包头模式。 此状态传达了建立上下文的必要信息,使系统能够进入一阶或二阶压缩状态。 - 2. 一阶压缩状态使系统有效地传播媒体流中的不规范信息(上下文的变化),同时仍然保持很高的压缩效率。在这种状态下,只传输 RTP 序列号的压缩表示以及上下文标识符和更改字段的简化表示。 - 3. 当根据 RTP 序列号和存储的上下文可以预测整个包头时,二阶状态是最高的压缩级别。包中只包含 RTP 序列号的压缩表示(可能是隐式的)和上下文标识符,给出的包头可以小到只有一个八位组。 如果存在任何不可预测的字段(如 UDP 校验和),则一阶和二阶压缩方案都会不变的传递这些字段。如预期那样,造成的结果是压缩效率显著降低。为了简单起见,这个描述省略了对它们的进一步提及,尽管它们总会被传递。 @@ -162,9 +150,7 @@ ROHC 具有三种运行状态,具体取决于传输的上下文量: 系统可以以三种模式之一运行:单向,双向乐观(bidirectional optimistic),双向可靠(bidirectional reliable)。根据选择的模式,编码器将根据超时或确认从初始化和刷新状态转换到一阶或二阶压缩状态: 1. 单向模式。有可能没有反馈,编码器会在发送预定数量的数据包之后,转换到一阶或二阶状态。 - 2. 双向乐观模式。与单向模式一样,编码器在发送了预定数量的数据包之后,或收到确认时将转换为一阶或二阶状态。 - 3. 双向可靠模式。编码器在收到确认后转换为一阶或二阶状态。 单向或双向反馈模式的选择取决于编码器和解码器之间链路的特性。一些网络链路可能不支持(对其不友好)反馈消息的反向通道,从而迫使运行于单向模式。但是,在大多数情况下,可以使用双向模式之一,从而使接收端可以将其状态传达给发送端。 @@ -191,12 +177,9 @@ ROHC 具有三种运行状态,具体取决于传输的上下文量: 可解释区间是 _Vref_ 偏移参数 _p_ 后,周围 _2k_ 范围内的值,从 _Vref - p_ 到 _Vref + 2k -1 - p_ 。参数*p* 是基于初始化期间被传输并传送到解码器的字段的特性来选择的,从而构成上下文的一部分。可能的选择包括: -- 如果字段的值期望被增加,则 _p = -1_。 - +- 果字段的值期望被增加,则 _p = -1_。 - 如果字段的值期望被增加或保持不变,则 _p = 0_。 - - 如果字段的值期望与固定值不同,则 _p = 2(k-1) + 1_。 - - 如果字段的值期望经历小的负变化和大的正变化(如使用 B 帧的视频流的 RTP 时间戳),则 _p = 2(k-2) - 1_。 序列号传输示例。假定,最后传输的值 _Vref = 984_ ,_k = 4_(表示 4 个最低有效位作为编码格式传输)。假设 _p = -1_,计算出可解释区间为 985 到 1000,如图 11.5 所示。下一个发送的值是 985(二进制:1111011001)被编码为 9(二进制:1001,985 的 4 个最低有效位)。收到编码后的值后,解码器获取到 _Vref_,然后使用接收到的数据替换其 _k_ 个最低有效位,来恢复原始值。 diff --git "a/src/\345\252\222\344\275\223\351\207\207\351\233\206\343\200\201\346\222\255\346\224\276\345\222\214\346\227\266\345\272\217.md" "b/src/\345\252\222\344\275\223\351\207\207\351\233\206\343\200\201\346\222\255\346\224\276\345\222\214\346\227\266\345\272\217.md" index ea1c387..4f74beb 100644 --- "a/src/\345\252\222\344\275\223\351\207\207\351\233\206\343\200\201\346\222\255\346\224\276\345\222\214\346\227\266\345\272\217.md" +++ "b/src/\345\252\222\344\275\223\351\207\207\351\233\206\343\200\201\346\222\255\346\224\276\345\222\214\346\227\266\345\272\217.md" @@ -227,7 +227,7 @@ RTCP的发送者/接收者报告主要用于应用程序监视其发送的流的 播放缓冲区需要在保真度和延迟之间做权衡:应用程序必须确定可以接受的最大播放延迟。为交互式系统 -- 例如,视频会议或电话 -- 必须尽量减少播放延迟,因为它无法承受缓冲带来的延迟。对人类感知能力的研究表明,互动的最大可容忍的往返时间限制在 300ms 左右。如果系统是对称的,则该限制意味着只有 150 毫秒的端到端延迟,包括网络传输时间和缓冲延迟。然而,非交互式的系统,如流视频、电视或广播,可能允许播放的缓冲区增长到几秒,从而使非交互式系统能更好的处理包到达的时间。 -#### 播放时序的计算 +#### 计算播放时序 设计 RTP 播放缓冲区的最大难点是确定播放延迟,在播放之前,数据包应该在缓冲区中停留多长时间?答案取决于多种因素: @@ -237,17 +237,17 @@ RTCP的发送者/接收者报告主要用于应用程序监视其发送的流的 - 发送者和接收者之间的相对时钟偏移(skew) - 应用程序的端到端之间延迟预测,以及接收质量和延迟的相对重要性。 -受应用程序控制的因素,包括帧中数据包的间隔以及媒体数据和任何纠错数据包之间的延迟,而这两者均由发送者控制。这些因素对延迟计算的影响将在本章后面的发送者行为补偿一节中讨论。 +发送端可以控制帧内数据包之间的延迟,以及数据包和纠错包之间的延迟。这些因素对播放延迟计算的影响在本章后面的“发送方行为的HTU补偿”一节中有详细讨论。 -应用程序无法控制网络的行为,以及发送者和接收者时钟的准确性和稳定性。以图 6.9 为例,它显示了追踪 RTP 音频包的包传输时间和接收时间之间的关系。发送时钟和接收时钟的运行速度是一样的,这张图的斜率应该正好是 45 度。在实践中,发送者和接收者时钟通常是不同步的,以略微差异的速率运行。对于图 6.9 中,发送者时钟的运行速度快于接收者时钟,因此图中的斜率小于 45 度(图 6.9 是一个极端的例子,为了更容易看到效果,坡度通常更接近 45 度)。本章后面的“对时钟倾斜的补偿”一节解释了如何对不同的时钟进行校正。 +应用程序无法控制的因素包括网络的行为以及发送方和接收方时钟的准确性和稳定性。以图6.9为例,该图显示了一组RTP音频数据包的传输时间和接收时间之间的关系。如果发送方和接收方的时钟以相同的速率运行,就如期望的那样,这个图的斜率应该恰好为45度。但实际上,发送方和接收方的时钟通常无法同步,运行速率也会略有差异。在图6.9中,发送方的时钟比接收方的时钟运行得更快,因此图的斜率小于45度(这个图是为了更容易看到效果而极端化的例子;通常情况下,斜率会更接近45度)。本章后面的“时钟偏差的补偿”一节将详细解释如何纠正不同步的时钟。 ![图6.9 时钟偏斜的说明,包发送时间与接收时间的对比](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.9.png) -如果包网络传输时间恒定,图 6.9 中将生成一条直线。然后由于排队延迟的变化,数据包间通常会在的间隔中引起一些网络抖动,这在图中可以看出是与直线图的偏差。该图还显示了不连续性,这是由于网络传输时间的阶跃变化而引起的,很可能是由于网络中的路由变化所导致的。第二章《分组网络上的音视频通信》中,更详细的讨论了抖动的影响,本章后面“抖动补偿”一节解释了如何纠正这些问题。在路由变化补偿和包重排序部分讨论了对更极端变化的校正。 +如果数据包具有恒定的网络传输时间,图6.9中将呈现出完全直线。然而,通常由于排队延迟的变化,网络会引入一些抖动,导致数据包之间的间隔波动,这在图中可以看到,呈现出与直线图的偏离。图中还显示了一个不连续点,这是由于网络传输时间发生了突变,很可能是由于网络中的路由变化引起的。HTU第2章《数据包网络上的语音和视频通信》详细讨论了这些影响,本章后面的“抖动的HTU补偿”一节解释了如何纠正这些问题。如何纠正更极端的变化在“路由变化的HTU补偿”和“数据包重排序的HTU补偿”这两节中进行了讨论。 -最后考虑的是应用程序的端到端延迟预估。这主要是个人因素问题:应用程序的用户可接受的最大端到端延迟是多少?在去除网络传输时间之后,还需要多长时间才能平滑播放缓冲区?正如预期的那样,缓冲可用的时间量,确实会影响播放缓冲区的设计。标题为《抖动补偿》的部分进一步讨论了这个主题。 +最后需要考虑的是端到端延迟的容忍阈值。这主要取决于个人因素:对于用户来说,他们能够接受的最大端到端延迟是多少?在网络传输时间被排除后,用于平滑播放缓冲的剩余时间是多少?显然,可用于缓冲的时间会影响播放缓冲的设计。本章后面的"抖动的补偿"一节进一步讨论了这个问题。 -在决定每一帧的播放时间的时候,接收者应该考虑这些因素。对播放的计算步骤如下: +在决定每一帧的播放时间的时候,接收者应该上面的因素。所以对播放的计算步骤如下: 1. 发送者的时间轴映射到本地播放时间轴,以补偿发送者和接收者时钟之间的相对偏移,以导出播放时间计算的基准时间(请参考本章后面的映射到本地时间轴)。 2. 如果有必要,接受者可以通过添加一个偏移补偿偏移来补偿相对发送者的时钟,该偏移会定期校准基准时间(参见时钟偏移补偿)。 @@ -255,7 +255,7 @@ RTCP的发送者/接收者报告主要用于应用程序监视其发送的流的 4. 如果路由发生了变化(参见路由变化的补偿),如果包被重新排序(参见排序的补偿),如果选择的播放延迟导致帧重叠,或者相应媒体中其他的变化(参见调整播放点),则会调整播放延迟。 5. 最后,将播放延迟添加到基准时间中,以获得帧的实际播放时间。 -图 6.10 说明了计算的过程,并记录了此过程的步骤。下面部分给出了每个阶段的详细信息。 +图 6.10 说明了计算的过程,并记录了此过程。下面给出了每个阶段的详细信息。 ![图6.10 播放的计算](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.10.png) @@ -285,39 +285,40 @@ RTCP的发送者/接收者报告主要用于应用程序监视其发送的流的 #### 时钟偏移(skew)补偿 -RTP 有效负载格式定义了媒体流的标准时钟速率,但是对时钟的稳定性和准确性没有任何要求。发送者和接收者的时钟通常以稍微不同的速率运行,从而迫使接收者对变化进行补偿。数据包的传输时间与接收时间的关系图,如图 6.9 所示。如果曲线的斜率正好是 45 度,那么时钟的频率是一样的,偏移是由发送者和接收者之间的时钟倾斜造成的。 +RTP 有效负载格式定义了媒体流的标准时钟速率,但是对时钟的稳定性和准确性没有任何要求。发送者和接收者的运行速率通常稍微不同,迫使接收者对需要变化进行补偿。数据包的传输时间与接收时间的关系图,如图 6.9 所示。如果曲线的斜率正好是 45 度,那么时钟的频率是一样的,偏移是由发送者和接收者之间的时钟倾斜造成的。 -接收者必须检测时钟偏移的存在,预估其大小,并调整播放点进行补偿。补偿策略有两种,一种是调整接收时钟以匹配发送时钟,另一种是定期调整播放缓冲区占用率,用以做重新校准。 +接收方需要检测时钟偏差是否存在,并估计其大小,然后通过调整播放点进行补偿。有两种可能的补偿策略:一种是调整接收方时钟以与发送方时钟匹配,另一种是定期调整播放缓冲区的重新对齐。 -后一种方法接受偏移,并通过插入或删除数据来定期重新对齐播出缓冲区。 如果发送者速度更快,则接收者最终将不得不丢弃一些数据以使时钟对齐,否则其播出缓冲区将溢出。如果发送者速度较慢,则接收者最终将用尽所有媒体来播放,并且必须合成一些数据以填补剩余的空白。时钟偏移的大小决定了播放点调整的频率,因此会导致质量下降。 +后一种方法不调整受时钟偏差,而是通过插入或删除数据来周期性地重新对齐播放缓冲区。如果发送方的速度更快,接收方最终需要丢弃保持对齐时钟,否则播放缓冲区将溢出。如果发送方的速度较慢,接收方将用完可播放的媒体内容,必须合成一些数据来填补剩余的空白。时钟偏差的大小决定了播放点调整的频率,从而决定了体验下降程度。 -或者,如果接收者时钟速率比较容易调整,则有可能将其速率调整为与发送器速率完全匹配,而无需重新设置播放缓冲区。这种方法可以提供更高的质量,因为永远不会由于时钟偏移而丢弃数据,但是它可能需要不常见的硬件支持(使用音频的系统可能能够使用软件重新采样以匹配所需的速率)。 +如果接收方的时钟频率可以进行精确调节,可以调整速率以完全匹配发送方的速率,从而避免了对播放缓冲区进行重新对齐。这种方法可以提供更高的质量,因为数据不会因为时钟偏差而被丢弃,但可能需要硬件支持,这种硬件并不常见(音频系统可以用软件的方法重新采样来匹配所需的速率)。 -预估时钟偏移的大小,最初看起来是一个简单的问题,观察发送者时钟的速率 -- RTP 时间戳 -- 并与本地时钟进行比较。如果![公式10](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_10.png)是接收到的第 n 个数据包的 RTP 时间戳,![公式11](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_11.png)是当时的本地时钟的值,那么时钟偏移的预估如下: +估计初始时钟偏差看起来似乎很简单:观察发送方时钟的速率,即RTP时间戳,然后与本地时钟进行比较。如果![公式10](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_10.png)是接收到的第 n 个数据包的 RTP 时间戳,![公式11](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_11.png)是当时的本地时钟的值,那么时钟偏移的预估如下: ![公式12](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_12.png) -偏移小于 1 表示发送者比接收者慢,而偏移大于 1 表示发送者时钟比接收者快。不幸的是,网络定时抖动的存在意味着这种简单的估计是不够的。它会直接受抖动引起的数据包间隔变化的影响。接收者必须查看数据包到达速率的长期变化,以得出潜在时钟偏移的估计值,从而消除抖动的影响。 +偏移小于 1 表示发送者比接收者慢,而偏移大于 1 表示发送者时钟比接收者快。然而不幸的是,因为网络时序抖动的存在, 这种估算是存在不足的;网络时序抖动回影响到达时间。为了估算更准确时钟偏差,接收方必须观察数据包到达时间长期变化,剔除时序抖动的影响。 -根据所需的准确性和对抖动的敏感性,有许多可能的算法可用于管理时钟偏移。在下面的讨论中,我将介绍一种简单的方法来预估和补偿时钟偏移,这种方法已被证明适用于 VOIP,并且给出了针对要求更高的应用的算法的指南。 +准确性和对抖动的敏感性是时钟偏移管理中的重要考虑因素,有多种算法可用于处理这些问题。在下面的讨论中,我将介绍一种简单的方法来估计和补偿时钟偏移,这种方法已被证明适用于VOIP,并提供了适用于对准确性要求更高的应用的算法的指南。 -对时钟偏移的管理方法是,持续监控平均网络传输延迟,并将其与主动延迟预估进行比较。有效延迟预估和测得的平均延迟之间的差距越大,越表示了时钟倾斜的存在,这最终将导致接收者调整播放。当每个包到达时,接受方根据包的接收时间以及其 RTP 时间戳计算 n 个数据包![公式13](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_13.png)的瞬时单向延迟: +对时钟偏移的管理方法是,持续监控平均网络传输延迟,并将其与主动延迟预估进行比较。有效延迟预估和测得的平均延迟之间的差距越大,越表示了时钟倾斜存在,这最终将导致接收者调整播放。当每个包到达时,接受方根据包的接收时间以及其 RTP 时间戳计算 n 个数据包![公式13](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_13.png)的瞬时单向延迟: ![公式14](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_14.png) -在接收到第一个数据包时,接收者设置活动延迟为 E = d0,预估平均延迟为 D0 = d0。对于每个后续的数据包,平均延迟预估的值 Dn 将通过指数加权移动平均值(exponentially weighted moving average)进行更新: +在接收到第一个数据包时,接收者设置延迟为 E = d0,预估平均延迟为 D0 = d0。对于每个后续的数据包,平均延迟预估的值 Dn 将通过指数加权移动平均值(exponentially weighted moving average)进行更新: ![公式15](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_15.png) -该因子控制平均过程,数值接近于 1,从而使平均值对短期的波动不那么敏感。注意,此计算类似于预估抖动的计算,但是,它保留了变化的符号(sign of the variation),并使用选择的时间常数,来采集长期变化和减少对短期抖动的响应。 -将平均单向延迟 Dn 与主动延迟预估 E 进行比较,以用来预估自上次预估以来的差异: +31/32 这个因子控制了平均过程,数值越接近单位 1,平均值对传输时间的短期波动越不敏感。需要注意的是,这个计算类似于估计抖动的计算;但是它保留了变化的符号,并且使用了一个经过选择的时间常数来捕捉长期变化并减小对短期抖动的反应。 + +将平均单向延迟 Dn 与主动延迟预估 E 进行比较,用来预估自上次预估以来的差异: ![公式16](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_16.png) -如果发送者时钟和接收者时钟同步,则差异(divergence)将趋近于 0,只会由于网络抖动而产生很小的变化。如果时钟是偏移的,那么它的差异将增加或者减少,直到超过预定的阀值,从而使接收者采取补偿措施。这个阈值,取决于抖动以及编码器和一组可能的适配点(possible adaptation points)。它必须足够大,以避免由于抖动而造成的错误调整,并且应选择适当的位置,使得调整所能引起的不连续性很容易被掩盖。通常单个帧间隔是合适的,这意味着插入或删除整个编解码器的帧。 +如果发送者时钟和接收者时钟保持同步,那么它们之间的差异(divergence)将接近于零,只会因为网络抖动而产生微小的变化。如果时钟存在偏移,那么差异将会增加或减少,直到超过预定的阈值,从而促使接收者采取补偿措施。该阈值的选择取决于抖动的程度,以及编码器。阈值必须足够大,以避免由于抖动引起的错误调整,并且选择调整的时机需要慎重选择,避免播放不连续。通常情况下,合适的时间点是在帧间隔,这意味着可以插入或删除整个帧。 -补偿包括增加或减少播放缓冲区,如本章后面的“自适应播放点”一节所述。播放点可以根据 RTP 时间戳单元的差异做变化(对于音频,差异通常给出要添加或删除的样本数量)。在补偿偏移之后,接收者将活动预估值 E,重置为等于当前延迟预估的值 Dn,在此过程中差异(divergence)重置为 0(此时还将重置 base_play-out_time(n) 的预估值). +补偿包括增加或减少播放缓冲区,如本章后面的“自适应播放点”一节所述。播放点可以根据 RTP 时间戳单元的差异做变化(对于音频,差异通常给出要添加或删除的样本数量)。在补偿偏移之后,接收者将活动预估值 E,重置为当前延迟预估的值 Dn,在此过程中差异(divergence)重置为 0(此时还将重置 base_play-out_time(n) 的预估值). 在类 C 的伪代码中,当接收到每个包时,执行的算法是这样的: @@ -350,49 +351,49 @@ RTP 有效负载格式定义了媒体流的标准时钟速率,但是对时钟 } ``` -该算法假设抖动分布是对称的,任何系统偏差都是由时钟偏移引起的。如果偏移值的分布是由时钟偏移以外的原因而不对称的,那么这种算法将导致伪偏移自适应。网络传输时间的短期波动也可能使算法无法描述真正的抖动,接收者将网络抖动视为时钟偏移并调整其播放点。偏移补偿算法最终会自我纠正,不能如何,我们都需要适配网络抖动。 +该算法的假设是抖动分布是对称的,并且任何系统性偏差都是由于时钟偏差引起的。如果偏差值的分布非对称,原因并非时钟偏差,那么该算法会得出错误的偏差。此外,网络传输时间的显著短期波动也可能导致算法失灵,接收方会将网络抖动误认为时钟偏差,调整播放点。然而,这些问题都不能带来实际的问题:偏差补偿算法最终会自我纠正,而任何调整步骤都可能需要来适应这些波动。 -这里描述的偏移补偿的另一个假设是,希望对播放点进行逐步调整 -- 例如,一次添加或删除一个完整的帧 -- 同时隐藏不连续的,就好像丢失了一个包一样。许多编解码器 -- 特别是基于帧的语音编解码器 -- 这是适当的行为,因为编解码器经过优化以隐藏丢失的帧,而偏移补偿可以利用这种能力,只要小心地添加或删除不重要的、通常是低能量(low-energy)的帧。然而,在某些情况下,更平滑地自适应是可取的,可能一次插入一个样本。 +另一个偏移补偿的假设是对播放点进行逐步调整,例如逐次添加或删除一个完整的帧,同时隐藏不连续性,就好像丢失了一个包一样。这对许多编解码器(尤其是基于帧的语音编解码器)是适当的行为,因为它们经过优化以隐藏丢失的帧。偏移补偿可以利用这种能力,只需小心地添加或删除不重要的、通常是低能量的帧。然而,在某些情况下,更平滑地自适应是可取的,可能一次插入一个样本。 -如果需要更平滑的自适应,Moon 等人的算法可能更合适,虽然它更复杂,对状态维护的要求也相应更高。他们的方法的基础是在观测到的单向延迟与时间的关系图上使用线性规划,以尽可能在所有数据点下拟合一条最接近数据点的线。一种等效的方法是在图 6.9 所示的数据点下获得一条最佳的拟合直线,并使用它来预估直线的斜率,从而预估时钟的倾斜。如果偏差是恒定的,则这个算法会更准确,但是显然具有更高的开销,因为它要求接收者保持点的历史记录,并执行昂贵的线性拟合算法。但是,如果有足够长的测量间隔,它可以获得非常精确的偏移测量。 +如果需要更平滑的自适应,Moon等人提出的算法可能更合适,尽管它更加复杂,对状态维护的要求也更高。他们的方法基于观测到的单向延迟与时间之间的关系图,使用线性规划来拟合一条最接近所有数据点的线。一种等效的方法是在图6.9所示的数据点上获得最佳拟合直线,并使用它来估计时钟的倾斜。如果偏移是恒定的,那么这个算法将更准确,但显然会有更高的成本,因为它需要接收者记录点的历史数据,并执行昂贵的线性拟合算法。然而,如果延迟测量采样间隔足够长,该算法可以获得高精度的偏移估计。 -长时间运行的应用程序应考虑到偏移是不稳定的,并且其会根据外部的影响而变化。例如,温度的变化会影响晶振的频率,并导致时钟频率的变化以及发送者和接收者之间的偏移。非平稳时钟偏移可能会使使用长期测量的某些算法(例如 Moon 等人的算法)感到困惑。 其他算法,例如前面描述的 Hodson 等人的算法,则在较短的时间尺度上工作并定期重新计算偏移,因此它们对变化具有鲁棒性。 +对于长期运行的应用程序来说,应考虑时钟偏移的不稳定性,它会受外界影响而随时间变化。例如,温度变化会影响振荡器的频率,从而导致时钟频率和发送方与接收方之间偏移的变化。非稳定的时钟偏差可能会影响依赖于长期观测的数据的一些算法(如Moon等人提出的算法)的效果。其他一些算法,例如前文提到的Hodson等人的算法,由于它们在较短时间内工作并定期重新计算偏差,因此对时钟变化具有较强的鲁棒性。 -在选择时钟偏移估计算法时,重要的是考虑播出点将如何变化,并选择具有适当准确度的估计器。例如,使用基于帧的音频编解码器的应用程序,可以通过添加或删除单个帧来进行自适应,因此,测量到最近样本的偏移的估计器可能会过大。本章后面的标题为《适应播放点》的部分将更详细地讨论此问题。 +在选择时钟偏差估算算法时,关键是考虑播出时间点可能的变化规律,并选择一个具有适当精度的估算器。例如,基于帧的音频编解码应用可以通过添加或删除单个帧实现自适应,因此直接基于最近样本测量得到的偏差估算可能会过大。本章后续部分"适应播放点"将更深入地探讨此问题。 > 虽然它们超出了本书的范围,但是 NTP 的算法可能也会引起读者的兴趣。对于那些对时钟同步和偏移补偿感兴趣的人,推荐阅读 PFC 1305(PDF 版本,可以从 RFC 编辑器的网站http://www.rfc-editor.org获得,比纯文本的版本可读性要强很多)。 #### 发送者补偿 -发送者数据包生成过程的方式,可能影响接收者的播放时间计算,从而导致播放缓冲延迟增加。 +发送者数据包生成方式,可能影响接收者的计算播放时间,从而导致播放缓冲延迟增加。 + +如果发送者将组成一帧视频发送时间扩展到整个帧间隔,则帧的第一个和最后一个数据包之间将存在延迟,接收者必须缓冲数据包,直到接收到整个帧为止 。 图 6.11 显示了附加的播放延迟 Td 的插入,以确保接收者在所有片段到达之前都不会尝试播放该帧。 -如果发送者将组成一帧视频的数据包扩展到整个帧间隔,则帧的第一个和最后一个数据包之间将存在延迟,接收者必须缓冲数据包,直到接收到整个帧为止 。 图 6.11 显示了附加的播放延迟 Td 的插入,以确保接收者在所有片段到达之前都不会尝试播放该帧。 ![图6.11 延迟缓冲,将数据包分组为帧](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.11.png) -如果知道帧间时序和每帧的数据包数量,则插入额外的延迟很简单。 假设发送者发送数据包的间隔是均匀的,则调整如下: +如果我们知道帧之间的时间间隔和每帧的数据包数量,那么插入额外的延迟就会变得很简单。假设发送者发送数据包的间隔是均匀的,那么我们可以进行以下调整: ```c++ adjustment_due_to_fragmentation = (packets_per_frame – 1) x (interframe_time / packets_per_frame) ``` -不幸的是,接收者并不总是事先知道这些。 例如,在会话建立期间,可能未用声明发送帧率;在会话期间可能会改变帧速率,或改变每帧的数据包数量。 这种变化可能会导致难以排序播放时间,因为尚不清楚需要添加多少延迟才能允许所有分段到达。接收者必须估计所需的播出延迟,并在估计结果不正确时进行调整。 +不幸的是,接收者并不能总是提前知道这些变量。例如,在会话设置期间可能没有信令告知帧率,会话期间帧速率可能会变化,或者会话期间每帧的数据包数量可能会变化。这种变化可能会使得调度播放变得困难,因为不清楚需要添加多少延迟才能让所有片段到达。接收方必须估计所需的播放延迟,并在估计不准确时做出适应。 -预估的播放补偿可以通过特殊用途的例程来计算,该例程查看分段的到达时间以计算平均分段延迟。幸运的是,这不是必须的。抖动计算起着相同的作用。一个帧的所有包都具有相同的时间戳 -- 表示帧的时间,而不是发送包的时间 -- 因此分段化的帧会导致抖动的出现(接收者无法区分网络中延迟的包和发送者延迟的包)。因此,下一节中讨论的抖动补偿策略可用于预估补偿碎片所需的缓冲延迟量,并且无需考虑播放延迟的主机分量中的分段。 +一个专门的模块复杂计算播放延时补偿,根据分片的到达时间来计算平均片片延迟。幸运的是,这不是唯一的计算方式,抖动计算可以起到同样的作用。一个帧的所有数据包具有相同的时间戳,表示帧的采集时间,而不是数据包发送的时间,因此分割的帧会导致接收抖动的出现(接收方无法区分在网络中延迟的数据包还是因为发送方延迟的数据包)。因此,下一节将讨论的抖动补偿策略可以用来估算必需的缓冲延迟来弥补分片带来的影响,而不需要在播放延迟机制中考虑分片问题。 -如果发送者使用第 9 章中描述的纠错技术,也会出现类似的问题。为了使纠错包有用,必须延迟播放,以便纠错包及时到达才能使用。 在会话建立期间用信号通知纠错包的存在,并且该信令可以包括足够的信息以允许接收者正确地调整播放缓冲器的大小。 或者,必须从媒体流中推断出正确的播放延迟。 所需的补偿延迟取决于所采用的纠错类型。 三种常见的纠错类型是奇偶校验 FEC(前向纠错)、音频冗余和重传。 -第九章讨论的奇偶校验 FEC 方案不修改数据包,并在单独的 RTP 流中发送纠错数据包。纠错包在其 FEC 报头中包含一个位掩码,以标识其保护的包的序号。通过观察掩码,接收者可以确定在数据包中添加的延迟。如果包间隔是恒定的,那么这个延迟就转换为一个时间偏移量,以添加到播放计算中。如果包间隔不是恒定的,接收者必须使用保守的间隔来获得所需的播放延迟。 +如果发送方使用第9章中描述的纠错技术,就会出现类似的问题。为了让纠错包发挥作用,需要延迟播放,以便纠错包能够及时到达并被使用。纠错包的存在会在会话设置期间进行信令,并且信令可能包含足够的信息,使接收方能够正确调整播放缓冲区的大小。或者,正确的播放延迟必须从媒体流中推断出来。所需的补偿延迟取决于所采用的纠错类型。常见的三种纠错类型是奇偶FEC(前向纠错)、音频冗余和重传。 -音频冗余方案在第九章《错误恢复》中讨论,包括冗余包中的时间偏移,该偏移可用于调整播放缓冲区的大小。在通话开始时,冗余音频可在两种模式下使用:发送初始包时不使用冗余头,或使用零长度冗余块发送。如图 6.12 所示,如果初始包中包含零长度冗余块,则调整播放缓冲区的大小会更容易。不幸的是,规范中并没有强制包含这些块,而且实现中可能必须猜测,是否存在适当的播放延迟(单个数据包偏移是最常见的情况,在没有其他信息的情况下进行合理的预估)。一旦确定媒体流使用冗余,就应该将偏移量应用于该流中的所有包,包括在通话开始时发送的没有冗余的包。如果接收到完整的通话开始期(talk spurts)数据而没有冗余,则可以假定发送者已停止冗余传输,并且将来的通话开始期(talk spurts)可以无延迟的播放。 +在第9章中讨论的错误纠正中,音频冗余方案包括在冗余数据包中使用时间偏移量,该偏移量可以用于确定播放缓冲区的大小。在对话开始时,冗余音频可以有两种方式:初始数据包可以不带冗余标头发送,或者可以带有零长度的冗余块。如图6.12所示,如果对话的初始数据包包含零长度的冗余块,可以更方便确定播放缓冲区的大小。然而,标准没有强制要求包含这些块,如果没有,可能需要估算出适当的播放延迟。在信息不足的情况下,常用方法是利用单个数据包的偏移值进行一个合理的估算。一旦确定了媒体流是否使用冗余,就应将偏移量应用于该流中的所有数据包,包括在对话开始时没有冗余的数据包。如果收到了完整的对话段而没有冗余,可以假设发送方已停止发送冗余数据包,未来的对话段可以无延迟播放。 ![图6.12 音频冗余编码对播放缓冲区的影响](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.12.png) -奇偶校验 FEC 或冗余的接收者接收器最初应该选择一个大的播放延迟,以确保到达的任何数据包都被缓冲。当第一个错误恢复包到达时,它将导致接受方减少它的播放延迟,重新安排时间,并播放当前缓冲的包。这个过程避免了由于缓冲延迟的增加而导致的播放间隙,代价是初始包会稍微延迟。 +如果使用了奇偶校验 FEC 或冗余,接收者最初应该选择一个大的播放延迟,以确保到达的任何数据包都进入缓冲区。当第一个错误恢复包到达时,它将导致接受方减少它的播放延迟,重新安排时间,并播放当前缓冲的包。这个过程避免了由于缓冲延迟的增加而导致的播放间隙,代价是初始包会稍微延迟。 -当使用包重传时,播放缓冲区的大小,必须大于发送者和接收者之间的往返时间,以便允许重传请求返回发送者并得到服务。接收者无法知道往返时间,只能发送重传请求并测量相应时间。这并不影响大多数实现,因为重传通常用于非交互应用程序,在这种应用程序中,播放缓冲延迟大于往返时间,但是如果往返时间很大,则可能会出现问题。 +当使用包重传机制时,播放缓冲区的大小必须大于发送方和接收方之间的往返时延,以支持重传请求的往返和服务。接收方无法获知往返时延,只能通过发送重传请求来估测它。这对大多数实施没有影响,因为重传通常用于非交互应用,在这类应用中,播放缓冲延迟一般大于往返时延。但如果往返时延过大,可能会引起问题。 -无论采用何种纠错方案,发送者都可能产生过量的纠错数据。例如,在发送到多播组(multicast group)时,发送者可能会根据最坏情况的接收者,选择错误恢复码,这对于其他接收者来说太过分了。正如 roseno-berg 等人指出的那样,仅使用错误恢复数据的子集,就可能修复部分损失。在这种情况下,接收者可以选择比所有纠错数据所需的播放延迟更小的播放延迟,而不是等待足够长的时间来修复它所选择的损失。忽略某些纠错数据的决定,完全是由接收者根据其对传输质量的看法做出的。 +无论采用何种纠错方案,发送者都可能产生超量的纠错数据。例如,在向多播组发送数据时,发送端可能根据最差条件下的接收端选择错误纠错码,这对其他接收端来说可能过于保守。如Roseno-Berg等研究人员指出,仅利用部分错误纠错数据就可能修复部分数据丢失。在这种情况下,接收端可以选择比完全利用所有纠错数据需要的延迟更小的播放延迟,而不是等待足够长时间来修复其选择修复的损失部分。忽略某些纠错数据的决定,完全是由接收者根据其对传输质量的看法做出的。 最后,如果发送者使用了交织媒体流 -- 如第八章所述,错误隐藏 -- 接收者必须在播放计算中考虑这一点,这样才能将交织的数据包按照播放顺序排序。交织参数通常在会话设置期间发出信令,允许接收者选择适当的缓冲延迟。例如,AMR 有效负载格式定义了一个交织参数,该参数可以在 SDP a = fmtp:行中发出信令,表示每个交织组数据包的数量(因此应该插入到播放缓冲区中进行补偿的数据包数量方面的延迟量)。其他支持交织的编解码器应该提供类似的参数。 @@ -400,42 +401,40 @@ adjustment_due_to_fragmentation = (packets_per_frame – 1) x (interframe_time / #### 抖动补偿 -当 RTP 数据包流经真实 IP 网络时,数据包间时序的变化是不可避免的。 这种网络抖动可能很大,接收者必须通过在其播出缓冲区中插入延迟来进行补偿,以便可以处理网络延迟的数据包。延迟过大的数据包在其播放时间过去之后到达,并被丢弃; 选择适当的播出算法后,这种情况很少发生。图 6.13 显示了抖动补偿过程。 +当 RTP 数据包流经真实 IP 网络时,数据包间时序的变化是不可避免的。 这种网络抖动可能很大,接收者必须通过在播出缓冲区中插入延迟补偿,以便可以处理网络延迟的数据包。延迟过大的数据包在其播放时间过去之后到达,会被丢弃; 选择适当的播出算法后,这种情况很少发生。图 6.13 显示了抖动补偿过程。 ![图6.13 网络抖动对接收时间的影响,并如何在播放缓冲中做修正](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.13.png) -抖动补偿延迟的计算,没有标准算法;大多数应用程序都希望自适应的计算播放延迟,并可以根据应用程序类型和网络条件使用不同的算法。为非交互式场景设计的应用程序可以选择一个远远大于预期抖动的补偿延迟;一个适当的值可能是几秒钟。更复杂的是交互情况,在这种情况下,应用程序希望保持输出延迟尽可能小(考虑到特定的网络和分组延迟,数十毫秒的值也是可能的)。为了使播放延迟最小化,有必要研究抖动的特性,并利用这些特性获得最小的适当播放延迟。 +抖动补偿延迟的计算,没有标准算法;大多数应用程序都希望自适应的计算播放延迟,可以根据应用程序类型和网络条件使用不同的算法。为非交互式场景设计的应用程序可以选择一个远远大于预期抖动的补偿延迟,甚至几秒都是合适的。更复杂的是交互情况下,应用程序希望保持输出延迟尽可能小(考虑到特定的网络和分组延迟,数十毫秒的值也是可能的)。为了使播放延迟最小化,有必要研究抖动的特性,并利用这些特性获得最小的适当播放延迟。 -在许多情况下,网络引起的抖动基本上是随机的。在这种情况下,包间到达时间(interpacket arrival time)与出现频率(frequency of occurrence)的关系图与图 6.14 的高斯分布有点儿类似。大多数数据包仅受到网络抖动的轻微影响,但是某些异常值则明显延迟或与相邻的数据包粘包(neighboring packet); +大多数情况,网络引起的抖动基本上是随机的。包间到达时间(interpacket arrival time)与出现频率(frequency of occurrence)的关系图如图 6.14 的高斯分布有点儿类似。大多数数据包仅受到网络抖动的轻微影响,但是某些异常值则明显延迟或与相邻的数据包粘包(neighboring packet); ![图6.14 网络抖动的分布](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.14.png) -这个近似值有多精确呢?当然,这取决于网络的路径,但是我和 Moon 等人进行的测量表明,在许多情况下,这种方案是近似合理的,尽管现实世界中的数据通常会偏向较大的到达时间,并且具有急剧的最小截止值(如图 6.14 的“实际分布”所示)。这种差异通常不是关键的,因为丢弃区域中的数据包数据量很少。 +这个近似值有多精确取决于网络的路径,但是我和 Moon 等人进行的测量表明,在许多情况下,这种方案是近似合理的,尽管现实世界中的数据通常会偏向较大的到达时间,并且具有急剧的最小截止值(如图 6.14 的“实际分布”所示)。这种差异通常不是关键的,因为丢弃区域中的数据包数据量很少。 -如果可以假设抖动分布近似于高斯正态分布,那么就很容易推导出合适的播放延迟。抖动的标准差是计算出来的,根据概率论,我们知道 99%以上的正态分布在均值(平均值)标准差的三倍以内。一个实现可能会选择一个等于到达间隔时间标准偏差的三倍的播放延迟,并希望由于延迟到达而丢弃少于 0.5%的数据包。如果此延迟过长,则使用延迟时间为标准差的两倍时,由于延迟到达产生的预期的丢弃率将会少于 2.5%,这也是基于概率论。 +如果可以假设抖动分布近似于高斯正态分布,那么就很容易推导出合适的播放延迟。抖动的标准差是计算出来的。根据概率论,我们知道 99%以上的正态分布在均值(平均值)标准差的三倍以内。一个实现可能会选择一个等于到达间隔时间标准偏差的三倍的播放延迟,并希望由于延迟到达而丢弃少于 0.5%的数据包。如果此延迟过长,则使用延迟时间为标准差的两倍时,由于延迟到达产生的预期的丢弃率将会少于 2.5%,这也是基于概率论。 -我们如何测量标准差?计算用于插入 RTCP 接收者报告的抖动值,跟踪网络传输时间的平均变化,该变化可用于近似标准偏差。根据这些近似值,可以将补偿网络抖动所需的播放延迟预估为特定源 RTCP 抖动预估的三倍。新一帧的播放延迟可以设置为: +我们如何测量标准差?计算用于插入 RTCP 接收者报告的抖动值,跟踪网络传输时间的平均变化,该变化可以当作近似标准偏差。根据这些近似值,可以将补偿网络抖动所需的播放延迟预估为源 RTCP 抖动的三倍。新一帧的播放延迟可以设置为: ![公式17](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/Formula_17.png) -其中 J 为对当前抖动的预估,如第五章 RTP 控制协议所述。Tplayout 的值可以以一种依赖于媒体的方式进行修改,稍后对此讨论。使用此值做为其播放计算的实现,已在一系列实际条件下显示出了良好的性能。 - -> 尽管 RTCP 抖动预估提供了一个方便的值,可以用于播放计算中,但如果证明为播出时间提供了可靠的基础,则实现也可以使用备用抖动预估(仍必须在 RTCP RR 中计算并返回标准抖动宇预估)。特别是,有人提出,相位抖动(数据包到达时间与预期时间之间的差值)是对网络时间的更精准的度量,尽管这尚未在广泛部署的实现中进行测试。准确预估交互播放缓冲的抖动是一个难题,与当前的算法相比,还有改进的空间。 +其中 J 为对当前抖动的预估,如第五章 RTP 控制协议所述。playout的值可以按照媒体类型进行相应的修改,如后面所讨论的。真实世界里,使用该值作为播放计算的基础表现出了良好的性能。 -抖动分布即取决于流量通过网络时的路径,也取决于共享该路径的其他流量。抖动的主要原因是与其他流量竞争,导致中间路由器的排队时延不同。显然,其他流量中的变化也会影响接收者看到的抖动。因此,接收者应该定期重新计算它们使用的播放缓冲延迟的数量,以防止网络行为发生变化,必要时可以进行调整。接收者应何时调整?这不是一个无关紧要的问题,因为媒体播放时播放延迟的任何变化都会中断播放,导致没有播放内容的间隙,或者迫使接收者丢弃一些数据来弥补丢失的时间。因此,接收者试图限制它们调整其播放点的次数。有以下几个因素可以作为调整的触发因素: +抖动分布既取决于流量在网络中的传输路径,也取决于与其共享该路径的其他流量。抖动的主要原因是与其他流量的竞争,导致中间路由器的排队延迟不断变化;显然,其他流量的变化也会影响接收方所感知到的抖动。因此,接收方应定期重新计算所使用的播放缓冲延迟,以适应网络行为的变化,并在必要时进行调整。接收方应该在何时进行适应?这并不是一个简单的问题,因为在媒体播放时改变播放延迟会打断播放,导致要么出现中断,要么迫使接收方丢弃一些数据来弥补时间损失。因此,接收方尽量限制调整播放点的次数。有几个因素可以触发适应: - 由于延迟而丢弃的数据包的比例显著变化 -- 接收几个连续的必须因为延迟到达而被丢弃的包(三个连续的数据包是一个合适的阀值) +- 接收几个连续的必须而被丢弃的包,原因是延迟到达(三个连续的数据包是一个合适的阀值) - 接收到来自长时间不活跃发送者的信息包(10 秒是合适的阀值) - 网络传输延迟出现尖峰 -除了网络传输延迟的峰值外,这些因素应该是不言自明的。如第二章第 2 节的图 2.12 所示,当几个数据包被延迟并突发时,网络有时会导致传输延迟中出现“尖峰”信号。这样的峰值很容易使抖动预估值产生偏差,导致应用程序选择比要求的更大的播放延迟。在许多应用程序中,这种播放延迟的增加是可以接受的,应用程序应该将尖峰视为任何其他形式的抖动,并增加它们的播放延迟来进行补偿。然后,一些应用程序更喜欢增加丢包而不是增加延迟。这些应用程序应该检测延迟尖峰的开始,并在计算播放延迟时,忽略尖峰中的包。 +除了网络传输延迟的峰值外,这些因素应该是不言自明的。如第二章第 2 节的图 2.12 所示,当几个数据包被延迟并突发时,网络有时会导致传输延迟中出现“尖峰”信号。这样的峰值很容易使抖动预估值产生偏差,导致应用程序选择比要求的更大的播放延迟。在许多应用程序中,这种播放延迟的增加是可以接受的,应用程序应该将尖峰视为其他形式的抖动,并增加播放延迟来进行补偿。然后,一些应用程序更喜欢增加丢包而不是增加延迟。这些应用程序应该检测延迟尖峰的开始,并在计算播放延迟时,忽略尖峰中的包。 检测延迟尖峰的开始很简单:如果连续数据包之间的延迟突然增加,就可能发送了延迟尖峰。“突然增加”的规模可以有一些解释:Ramjee 等人认为,到达间隔时间统计方差的两倍加上 100 毫秒是一个合适的阈值;我熟悉的另一个实现,用了 375 毫秒的固定阈值(都是使用 8KHz 语音的 ip 语音系统)。 > 某些媒体事件还会导致连续包之间的延迟增加,不应将其与延迟峰值开始混淆在一起。例如,音频静音抑制将导致在一个通话突发中的最后一个数据包,与下一个通话突发中的第一个数据包之间出现间隙。同样,视频帧速率的变化也会导致包的时序发生变化。在假定数据包间延迟的变化,就意味着出现了一个尖峰之前,应该先检查此类事件。 -一旦检测到延迟脉冲,实现时就应该暂停正常的抖动调整,直到脉冲结束。结果,几个包可能会因为延迟到达而被丢弃,但是假设应用程序有严格的延迟边界,且相比于增加播放延迟更倾向于这个结果。 +一旦检测到延迟脉冲,应该暂停正常的抖动调整,直到脉冲结束。这个操作的结果就是几个包可能会因为延迟到达而被丢弃,但是假设应用程序有严格的延迟边界,那么相比于增加播放延迟,这个结果是可接受的。 定位一个尖峰的末端比探测它的开始要困难。延迟尖峰的一个关键特征是,在尖峰之后,在发送者均匀间隔的数据包将以突发的形式到达,这意味着每个数据包的传输延迟将逐渐减小,如图 6.15 所示: @@ -501,43 +500,41 @@ adjustment_due_to_fragmentation = (packets_per_frame – 1) x (interframe_time / } ``` -关键的一点是,抖动补偿在延迟尖峰期间暂停,只有在发生重大事件时,实际播放的时间才会改变。在其他时候,需要将 desired_playout_offset 存储以在特定于媒体的时间恢复(参见标题“调整播出点”的章节)。 +关键点是在延迟峰值期间,抖动补偿被暂停,而实际的播放时间只在发生重要事件时才会改变。在其他时间,desired_playout_offset被存储,以在特定时间(参见标题为"调整播放点"的部分)恢复。 #### 路由变更补偿 -虽然很少发生,但是,由于链路故障或者拓扑结构发生改变,路由更改就会出现在网络中。如果 RTP 包所采取的的路由发生了变化,它将表现为网络传输时间的突然变化。此更改将会中断播放缓冲区,因为要么数据包到达得太晚而无法播放,要么它们将提前到达并与之前的数据包重叠。 +虽然很少发生,但是,由于链路故障或者拓扑结构发生改变,路由更改就会出现在网络中。如果 RTP 包所传输的的路由发生了变化,将表现为网络传输时间的突然变化。这个变化将会打乱播放缓冲区,因为要么数据包到达得太晚而无法播放,要么它们将提前到达并与之前的数据包重叠。 -抖动和延迟尖峰补偿算法,应该检测延迟的变化,并调整播放结果对其补偿,但是这种方法可能不是最优的。如果接收者直接观察网络传输时间,并根据较大的变化调整播放时延,就可以进行更快的自适应。例如,如果传输延迟的变化超过当前抖动预估的五倍,则实现时可能调整播放延迟。相对网络传输时间用作抖动计算的一部分,因此这种观察很简单。 +抖动和延迟峰值补偟算法应检测延迟变化,调整播放进行补偿,但这可能不是最优方法。如果接收端直接观测网络传输时延并根据较大变化调整播放延迟,就可以实现更快的自适应。例如,如果传输延迟变化超过当前抖动估计值的5倍,则调整播放延迟。因为网络传输时延用于部分抖动计算,所以这种观测很简单。 #### 对包重新排序的补偿 在极端的情况下,抖动或者路由的更改,可能导致网络中的包被重排序。正如第二章“分组网络上的音视频通信”中所讨论的,这种情况通常很少发生,但是这种情况发生的频度足够引起重视,实现时需要能够补偿它的影响,并平稳的处理包含乱序包的媒体流。 -对于正确设计的接收者来说,重新排序应该不是问题,数据包根据它们的 RTP 时间戳插入到播放缓冲区,而不考虑它们到达的顺序。如果播放延迟足够大,则按正确的顺序播放。否则,它们将像任何其他延迟的包一样被丢弃。如果许多包由于重新排序和延迟到达而被丢弃,标准的抖动补偿算法将负责调整播放延迟。 +对于设计正确的接收者来说,重新排序应该不是问题,数据包根据它们的 RTP 时间戳插入到播放缓冲区,而不考虑它们到达的顺序。如果播放延迟足够大,则按正确的顺序播放。否则,它们将像其他延迟的包一样被丢弃。如果许多包由于重新排序和延迟到达而被丢弃,抖动补偿算法将负责调整播放延迟。 #### 播放点自适应 -这是调整播放点的两种基本方法:接收者可以稍微调整每个帧的播放时间,对播放点进行连续的小调整,或者可以从媒体流中插入或删除完整的帧,从而减少播放次数,在必要时在进行少量的大调整。无论如何调整,媒体流都会受到一定程度的干扰。调整的目的是尽量减少这种干扰,这需要了解媒体流方面的知识。我们将分别讨论音频和视频的播放调整策略。 +调整播放点的方法有两种基本方式:接收方可以对每帧的播放时间进行微调,持续进行小幅度的调整;或者可以在媒体流中插入或删除完整的帧,根据需要进行较少次数的大幅度调整。无论采用哪种方式进行调整,媒体流都会在某种程度上受到干扰。适应的目标是最大程度地减少这种干扰,这需要对媒体流有深入的了解;因此,音频和视频的播放适应策略需要单独进行讨论。 #### 用静音抑制调整音频播放 -音频是一种连续的媒体格式,即每个音频帧占用一定的时间,下一帧在完成后立即开始。除非使用静音抑制,否则帧之间是没有间隙的,因此没有合适的时间来适应播放延迟。因此,静音抑制的存在对播放缓冲算法的设计有着重要的影响。 +音频是一种连续的媒体格式,每个音频帧都占用一定的时间,下一个音频帧会在前一个帧完成后立即开始。除非使用了静音抑制技术,否则帧之间不会有间隔,因此没有合适的时机来调整播放延迟。正因为如此,静音抑制对音频播放缓冲算法的设计具有重要影响。 -音频是一种连续的媒体格式,这意味着每个音频帧都占用一定的时间,并且下一个音频帧计划在完成后立即开始。 除非使用静音抑制,否则帧之间没有间隙,因此没有合适的时间来适应播放延迟。 因此,静音抑制的存在对音频播放缓冲区算法的设计有重要影响。 - -对于会话性的语音信号,一个活跃的讲话者将产生持续的几百毫秒的通话尖峰(talk spurts),中间用静音时间隔开。图 6.16 显示了语音信号中语音通话尖峰(talk spurts)的出现以及它们之间的间隙。发送者检测代表了静默期的帧,并对它们进行抑制,否则它们将封装 RTP 数据包。结果是一个带有连续序列号但时间戳跳跃的数据包序列,RTP 时间戳中的跳跃取决于静默期的长度。 +在对话性语音信号中,发言人的说话会间隔几百毫秒,间隙期间为静默期。图6.16展示了语音信号中说话间隔及其间隙的存在。发送方会检测到表示静默期的帧,并抑制为这些帧产生的RTP数据包。结果,数据包序列号连续,但RTP时间戳会根据静默期长度发生跳跃。 ![图6.16 通话期的语音信号](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.16.png) -在通话期间使用播放点调整,将在输出中引起可以听见的干扰,但是在通话期之间的静默时段的长度微小变化,将不会被注意到。这是在设计音频工具的播放算法时要记住的关键点:如果可能,只在静默期调整播放点。 +在说话间隔期间调整播放点会在输出中产生明显的故障声,但是在说话间隔之间的静默期长度发生微小变化是不会被注意到的。这是在设计音频工具的播放算法时需要牢记的关键要点:如果可以的话,只在静默期间调整播放点。 -接收者通常很容易检测到通话期的开始,因为发送者需要在静默期之后设置第一个数据包上的标记位,以便明确的指示通话期的开始。然后,有时候,在一次通话期时,第一个信息包丢失了。通常仍然可以检测到一个新的通话期已经开始,因为序列号/时间戳的关系会发生改变,如图 6.17 所示,提供了一个关于通话期开始的隐式指示。 +通常情况下,接收方能够很容易地检测到说话间隔的开始,因为发送方在静默期后的第一个数据包上会设置标记位,明确表示说话间隔的开始。有时在说话间隔起始时,第一个数据包可能会丢失。通过序列号和时间戳的变化通常还是可以判断新的说话间隔开始,如图6.17所示,这提供了判断标准。 ![图6.17 通话期的隐式开始](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.17.png) -一旦确定了对话的开始,你可以通过稍微改变静音时间的长度来调整播放点。然而,对于通话期中的所有数据包,播放延迟保持不变。在假定条件不太可能发生显著变化的情况下,计算每次通话期间适当的播放延迟,用于调整后续通话期(talk spurt)的播放点。 +一旦确定了说话间隔的开始,你可以通过微调静默期的长度来调整播放点。然后,在整个说话间隔中,播放延迟保持不变。在每个说话间隔期间计算出适当的播放延迟,并用于调整接下来的说话间隔的播放点,这是基于一个假设:在说话间隔之间,网络情况不太可能发生显著变化。 -一些语音编解码器在静音期间发送低速率的舒适噪声帧,以便接收者可以播放适当的背景噪声,以获得更愉快的收听体验。接收到一个舒适的噪声包表明一个谈话的结束,和一个适当的时间来调整播放延迟。舒适噪声周期的长度可以改变,但对音频质量没有显著影响。RTP 有效负载类型通常不会标识出舒适噪声帧,因此,有必要检查媒体数据,以检测它们的存在。不具有支持本机舒适噪声编解码功能的较旧的编解码器,可以将 RTP 有效负载格式用于舒适噪声,这由 RTP 负载类型 13 来标识。 +一些语音编解码器在静音期间发送低速率的舒适噪声帧,以便接收者可以播放适当的背景噪声,以获得更愉快的收听体验。接收到一个舒适的噪声包表明一个谈话的结束,和一个适当的时间来调整播放延迟时机的开始。舒适噪声周期的长度可以改变,但对音频质量没有显著影响。RTP 有效负载类型通常不会标识出舒适噪声帧,因此,有必要通过检查媒体数据判断是否是舒适噪音。对于不支持本地舒适噪声的旧编解码器,可能会使用RTP有效负载格式来传输舒适噪声,其RTP有效负载类型为13。 在特殊情况下,可能有必要在通话尖峰期进行调整 -- 例如,如果多个数据包由于延迟到达而被丢弃。这些情况预计会很罕见,因为通话尖峰相对较短,网络条件通常变化缓慢。 @@ -570,35 +567,33 @@ adjustment_due_to_fragmentation = (packets_per_frame – 1) x (interframe_time / } ``` -变量 contdrop 是计算由于不适当的播放时间而丢弃的连续数据包的数量。例如,如果路由更改导致数据包到达时间太晚而无法播放。CONSECUTIVE_DROP_THRESHOLDT 一个合适的值是三个数据包。 - -如果函数 should_playout()返回了 TRUE,则接收者要么处于静默期,要么错误的计算了播放点。如果计算的播放点偏离了当前使用的值,那么它应该通过更改计划的播放时间来调整未来包的播放点。不需要生成填充数据,只需要继续播放静音/舒适的噪音,直到下一个包被调度(即使调整是由多个连续的数据包丢弃触发的,也是如此,因为这表明播放已停止)。 +变量 contdrop 是由于不在适当的播放时间而丢弃的连续数据包的数量。例如,如果路由更改导致数据包到达时间太晚而无法播放。连续丢包阈值CONSECUTIVE_DROP_THRESHOLD 的一个合适值是三个数据包。如果should_playout()返回TRUE,接收端要么处于静音期,要么错误计算了播放点。如果计算的播放点偏离当前值,应通过调整计划播放时间来调整未来包的播放点。无需生成填充数据,直接播放静音或舒适噪音,直到下个数据包调度播放。 -当播放延迟正在减少时,需要注意,因为条件的重大变化,可能会使下一个讲话的突然开始时间提前到,与一个讲话突然结束的时间重叠。由于不希望限制通话期的开始,因此可执行的调整量会受到限制。 +当播放延迟正在减少时,需要注意,因为条件的重大变化,可能会使下一个讲话的突然开始时间提前到,与一个讲话突然结束的时间重叠。由于不希望限制通话期的开始,因此可执行的调整量会受到限制 #### **音频无静音抑制的播放调整** -当接收到在没有静音抑制情况下传输的音频时,接收者必须在音频播放的同时调整播放点。最理想的调整方法是调整本地媒体时钟,使其与发送者的时钟相匹配,以便直接播放数据。如果这是不可能的,那就是因为缺少必要的硬件支持,接收者将不得不通过生成要插入到媒体流中的填充数据,或从播放缓冲区中删除一些媒体数据来改变播放点。这两种方法都不可避免的会对播出产生一些干扰,重要的是要隐藏调整的影响,以确保不会干扰听众。 +当接收到没有静默抑制的音频时,接收方必须在音频播放过程中调整播放点。最理想的适应方式是调整本地媒体时钟以与发送方保持一致,这样数据就可以直接播放出来。如果由于缺乏必要的硬件支持而无法实现这一目标,接收方将不得不通过生成填充数据插入到媒体流中,或者从播放缓冲区中删除一些媒体数据来变化播放点。无论采用哪种方法,都不可避免地会对播放造成一些干扰,因此重要的是要隐藏适应的效果,以确保不会干扰听众。 根据输出设备的性质和接收者的资源,有几种可能的自适应算法: -- 音频可以在软件中重采样,以匹配输出设备的速率。标准信号处理教程提供了各种算法,这取决于所需的质量和资源的权衡。这是一个很好的通用解决方案。 +- 音频可以在软件重采样,以匹配输出设备的速率。标准信号处理教程提供了各种算法,这取决于所需的质量和资源之间的权衡。这是一个很好的通用解决方案。 - 根据对媒体的了解,可以对播放延迟进行逐个样本的调整。例如,Hodson 等人使用模式匹配算法来检测语音中的音调周期,这些音调周期会被删除或复制以适应播放效果(音调周期比完整帧要短得多,因此这种方法可以实现细粒度的适应)。与重采样相比,此方法可以执行得更好,但是它是特定于内容的。 - 完整的帧可以插入或者删除,就像数据包丢失或重复一样。这种算法质量通常不高,但是,如果使用了专为同步网络而设计的硬件解码器,则可能需要这种算法。 -在没有静音抑制的情况下,没有明显的时间来调整播放点。 尽管如此,接收者仍然可以通过在错误隐藏更有效的时间(例如,在相对安静的时间段或信号高度重复的时间段内)更改播放(取决于编解码器和错误隐藏算法)来做出有关播放调整的明智选择。第八章《错误隐藏》中详细介绍了丢包隐藏策略。 +在没有静音抑制的情况下,调整播放点的时机并不明显。然而,接收方仍然可以根据情况做出明智的选择,根据编解码器和错误隐藏算法,在相对安静或信号高度重复的时期进行自适应播放。关于错误隐藏的策略,可以在第8章的错误隐藏一章中找到详细的描述。 #### **视频播放自适应** -视频是一种离散的媒体格式,在这种格式中,每一帧都在特定的时间点采样,帧与帧之间的间隔不会被记录。视频的离散特性,为播放算法提供了灵活性,可以允许接收者通过稍微改变帧间计时来自适应播放。不幸的是,显示设备通常以固定的速率运行并限制可能的显示时间。视频播放变成了一个最小化预期和可能的帧表示之间的偏差的问题。 +视频是一种离散的媒体格式,在这种格式中,每一帧都在特定的时间点采样,帧与帧之间的间隔不会被记录。视频的离散特性,为播放算法提供了灵活性,可以允许接收者通过稍微改变帧间计时来自适应播放。不幸的是,显示设备通常以固定的速率运行,视频不能在任意时间显示。因此,视频播放成为了一个问题,即如何尽量减小期望的帧呈现瞬间与可能的帧呈现瞬间之间的偏差。 -举个例子,考虑一下在刷新率为 85Hz 的监视器上显示每秒 50 帧的视频剪辑的问题。在这种情况下,监视器刷新时间将与视频播放时间不匹配,这将不可避免的导致帧呈现给用户的时间发生变化,如图 6.18 所示。只有改变采集设备的帧速率或者显示的刷新率才能解决这个问题。在实践中,这个问题目前是无解的,因为视频采集和回放设备通常对可能的速率有硬件限制。即使采集和回放设备,在名义上具备相同的速率,也可能需要根据抖动或者时钟偏移的影响调整播放。 +举个例子,考虑一下在刷新率为 85Hz 的监视器上显示每秒 50 帧的视频的问题。在这种情况下,监视器刷新时间将与视频播放时间不匹配,这将不可避免的导致帧呈现给用户的时间发生变化,如图 6.18 所示。只有改变采集设备的帧速率或者显示的刷新率才能解决这个问题。在实践中,这个问题目前是无解的,因为视频采集和回放设备通常对可能的速率有硬件限制。即使采集和回放设备,在名义上具备相同的速率,也可能需要根据抖动或者时钟偏移的影响播放。 ![图6.18 媒体帧时间和输出设备时序之间不匹配](https://raw.githubusercontent.com/milzero/RTP-Audio-and-Video-for-the-Internet-Chinese-Version/img/image/6.18.png) 存在三种可能的调整情况:(1)当显示设备的帧率高于采集设备时;(2)当显示设备的帧率低于采集设备时;(3)当显示和采集设备以相同帧率运行时。 -如果显示设备的帧速率高于采集设备的帧速率,则可能的显示时间将围绕所需时间,并且每个帧都可以映射到唯一的显示刷新间隔。 最简单的方法是以最接近其播放时间的刷新间隔显示帧。可以通过朝任何所需的播放调整方向移动帧来获得更好的结果:如果接收者时钟相对较快,则在其播放时间之后的刷新间隔显示帧,如果接收者时钟较慢则以较早的间隔显示帧。当没有从发送者收到新帧时,可以通过重复前一帧来填充中间刷新间隔。 +如果显示设备的帧率高于采集设备的帧速率,则可能的显示时间将围绕所需时间,并且每个帧都可以映射到唯一的显示刷新间隔。 最简单的方法是以最接近其播放时间的刷新间隔显示帧。可以通过朝任何所需的播放调整方向移动帧来获得更好的结果:如果接收者时钟相对较快,则在其播放时间之后的刷新间隔显示帧,如果接收者时钟较慢则以较早的间隔显示帧。当没有从发送者收到新帧时,可以通过重复前一帧来填充中间刷新间隔。 如果显示设备的帧率低于采集设备,则不可能显示所有帧,并且接收者必须丢弃一些数据。例如,接收者可以计算帧播放时间和显示时间之间的差异,并选择显示最接近可能显示时间的帧子集。 diff --git "a/src/\345\256\211\345\205\250\350\200\203\350\231\221.md" "b/src/\345\256\211\345\205\250\350\200\203\350\231\221.md" index 821b2d7..01a22b9 100644 --- "a/src/\345\256\211\345\205\250\350\200\203\350\231\221.md" +++ "b/src/\345\256\211\345\205\250\350\200\203\350\231\221.md" @@ -92,7 +92,6 @@ RTP 头以及任何头扩展都是在不加密的情况下发送的。假如 RTP 加密过程包括两个步骤: 1. 系统通过一个非基于 RTP 的密钥交换协议提供一个或多个主密钥。每个会话密钥是一个伪随机函数的采样,在发送了一定数量的数据包后,以主密钥、数据包索引和密钥产生速率作为输入进行重新绘制。根据加密上下文中的密钥产生速率,会话密钥可能会针对发送的每个数据包进行更改。密钥管理协议可以使用主密钥标识符来指示要使用哪个预交换的主密钥,从而允许同步主密钥中的更改。 - 2. 通过基于包索引和会话密钥生成密钥流,然后利用 RTP 包的有效负载部分计算该密钥流的逐位异或(XOR),以对包进行加密。 在这两个步骤中,包索引是 32bit 扩展的 RTP 序列号。如何生成密钥流的细节取决于加密算法和操作模式。