摘要

  • RFC 2038 要求分组方式把 MPEG Slice 起点放在可识别的 RTP 载荷边界上,并以 B、E 位说明载荷是否从 Slice 开始、是否在 Slice 末尾结束。
  • 每个视频分组都重复当前图片的时间参考 TR、图片类型 P,以及适用于 P/B 图片的前向、后向运动向量参数;图片头或 GOP 头丢失后,接收器可在下一条 Slice 处构造有限的替代上下文。
  • 序号缺口、边界位和重复状态只能支持一个有边界的重启决定。它们不能证明此前 Slice 已收到、头字段真实、整张图片完整、参考帧可用、解码正确、播放连续、观众确实看到内容或服务质量合格。

假设分组 9201 到达,9202 消失,9203 的 B 位为一。9203 还带着时间参考 17、P 图片类型和一组前向运动向量参数。接收器由此知道,它不用把未知的中间字节硬塞给解码器;它可以丢弃受损延续,在这个声明的 Slice 起点重新进入 MPEG 处理。

但屏幕上的图片可能仍然裂开。

丢失分组或许含有不可替代的宏块,P 图片所依赖的参考图片或许已经损坏,发送端也可能错误设置了 B 位。即便语法可接受,接收器用默认值重建的图片头也未必与原头相同。RFC 2038 的价值并非消除这些风险,而是把恢复单位和最少上下文显式带到分组层,让错误不必无限传播。

恢复单位被带到了分组表面

MPEG 压缩流不是任意字节都能重新进入的独立块集合。图片之间可能有时间预测,图片内部也有空间依赖;丢掉一段数据,会让仍然到达的后续数据失去解释前提。与此同时,一张压缩图片又可能大于网络通常允许的单个分组。

RFC 2038 因而规定了若干明确的放置规则。Video Sequence Header 必须从 RTP 载荷开头出现;GOP Header 必须位于载荷开头或紧随 Sequence Header;Picture Header 必须位于载荷开头或紧随 GOP Header。这些基本码流头都必须完整地装进一个分组,不能横跨分组。

更关键的规则针对 Slice。RFC 把 Slice 视为丢失或损坏后的预期恢复单位。Slice 起点可以是载荷中的第一段数据,也可以出现在允许的 MPEG 头之后,或出现在同一载荷中若干完整 Slice 之后。Slice 本身仍可跨越多个 RTP 分组,因此“一个分组等于一个 Slice”从来不是这项设计的承诺。

这个约束省掉了一项危险工作:丢包后的接收器无需盲扫所有载荷字节寻找 Slice start code。分组器已经把可供重新进入的点摆到可声明的边界上。编解码器决定哪里有恢复意义,RTP 专用头负责把该位置暴露出来;后者并没有获得证明 MPEG 内容正确的权力。

B 与 E 描述的是对齐形状

每个视频分组在 RTP 固定头之后带有一个 32 位专用头。B=1 表示载荷从 Slice start code 开始,之前至多只有允许的 Sequence、GOP 或 Picture Header。E=1 表示载荷最后一个字节也是一条 Slice 的末尾。

两位组合能区分四类载荷:从 Slice 开始并结束于 Slice;从 Slice 开始但延续到后续分组;承接前一分组并结束 Slice;以及仅携带一段中间碎片。接收器甚至无需先解析压缩负载,就能决定这段数据处于什么边界形状。

这仍只是发送端声明。B=1 不会认证其后的 start code,E=1 也不会列举同一 Slice 的其他分片。两位都为一的分组可以完整对齐,但 RTP 序号缺口仍说明别处有内容未到达。两位都为零的分组也可能逐字节完好,只是它所依赖的开头已经丢失。

所以证据表达必须窄而准确:B/E 证明分组头携带了某种边界声明;要确认真实起始码、合法语法和完整 Slice,仍需检查载荷并观察解码器。

每个分组都带着一份缩小的图片档案

边界信息之外,RFC 2038 还在每个视频分组中重复图片状态。十位 TR 是当前图片在 GOP 内的 Temporal Reference,同一图片的所有 RTP 分组应保持相同。三位 P 标明 I、P、B 或 D 图片,同样在整张图片内不变。

余下四个字段来自最近的 Picture Header,记录前向与后向运动向量的 full-pel 标志和 f-code。组合依图片类型而定:I 图片不使用运动向量字段,全部置零;P 图片只使用前向一对;B 图片可以使用四项。它们不是原始图片头的完整副本,更不是图片副本,而是一份足以支持有限重建的小档案。

这种重复切断了一个脆弱依赖。如果唯一的 Picture Header 随某个分组消失,后面的 Slice 即使边界清楚,解码器也可能不知道它进入何种图片、如何解释运动向量。把关键值放进每个分组,就让下一条可用 Slice 同时带来恢复输入。

重复值还形成一致性线索。TR 或 P 在意外位置变化,可能意味着 GOP Header 或 Picture Header 丢失。RFC 附录提出维护参考图片与依赖图片的计数,并把预期进度同分组声明的 Temporal Reference 比较。两者不符能说明接收器的预期与当前声明发生断裂,却不能恢复已丢头字段的原始内容,也不能单独解释断裂为何发生。

“重建”是可见的近似,不是找回原件

RFC 2038 给出了继续处理的建议。GOP Header 丢失时,可以用空时间码、前一个 GOP 的 closed_gop 值和设为一的 broken_link 构造替代头。Picture Header 丢失时,可在下一次 B=1 处依据 P、TR、四项运动向量字段和依赖具体码流的默认值重建。

这里的重建并非逐字节找回。空时间码不是发送端遗失的时间码;沿用旧 closed_gop 不是对新 GOP 的独立观测;默认值更是接收器假设。broken_link=1 反而诚实地保留了断裂:它告诉解码器不能信任跨越该处的预测关系。

这种设计允许系统继续工作,同时没有把缺失历史伪装成已知事实。它提供的是一次解码尝试的条件,不是参考依赖已经满足的证书。

序号缺口触发止损,而非作出终局判断

附录描述的操作顺序很直接:RTP 序号出现缺口后,接收器可以丢弃后续分组,直到遇到 B=1。在那个 Slice 边界,它拥有足以重新开始 MPEG 处理的有限状态;若 GOP 或 Picture Header 被判定缺失,则先构造替代头。

RTP 序号递增,有助于恢复发送顺序和发现接收侧缺口,但 RTP 本身不保证交付、顺序、时限或服务质量。一个接收器观察到的缺口,不能仅凭序号区分物理丢包、乱序、采集不完整或中间设备行为,也不能说明缺失分组里究竟是什么。

因此“丢弃直到 B”是一项损害控制政策。它宁可舍弃一些或许完好的字节,也不把失去开头的延续片段提交给解码器。它把可恢复性建立在承认未知之上。

七类回执不能压成一个“已恢复”

审计这类系统时,应至少分开记录七层观察:RTP 序号连续性、B/E 声明、解析出的 MPEG 边界语法、TR/P/向量重复状态、所需参考图片的存在与完整性、解码器输出及错误隐藏行为、定时播放与观众侧观察。

前一层证据可以触发收集下一层,却不能替代下一层。整齐的 B/E 模式不证明图片完整;合理的 TR/P 不证明丢失头的原值;语法解析成功不证明预测参考正确;得到一个输出帧不证明按时播放;播放器事件更不证明真人看到或接受了结果。

RFC 2038 在 1996 年 10 月以 Proposed Standard 发布,1998 年 1 月被 RFC 2250 取代。IANA 当前 RTP 参数表把静态载荷类型 32 记为 90 kHz 的 MPV,引用的是 RFC 2250。这个注册项证明参数获得分配,不证明今天某个网络正在使用它,也不证明实现质量。

短暂标准留下的长期教训是:把压缩格式真正的恢复单位显式放到分组边界,并在附近重复最少必要状态,能够限制错误传播。但元数据必须保持正确层级。Slice 边界允许系统重新尝试,不会让边界前后的图片自动变得完整。

资料来源