第二讲:时间戳体系——PTS、DTS、STC 的三角关系
各位同学好,我是老张。今天咱们聊聊机顶盒里最绕不开的一个话题——时间戳体系。
说实话,我刚入行那会儿,也被 PTS、DTS、STC 这三个缩写搞得晕头转向。后来在项目里踩过坑,才真正理解了它们的关系。今天我把这些经验分享给你。
1. 为什么需要时间戳?
你想想看,机顶盒播放视频时,视频流和音频流是分开传输的。如果没有统一的时间基准,画面和声音就会「各说各话」。
我见过一个项目,因为时间戳没处理好,视频播到一半,声音还在放上一段的内容。用户投诉说「这机顶盒是不是坏了?」——其实不是硬件问题,就是时间戳乱了。
所以,时间戳的核心作用就两个:
- 同步:让音视频在正确的时间点播放
- 排序:告诉解码器数据包的先后顺序
2. PTS——显示时间戳
PTS 全称是 Presentation Time Stamp,说白了就是「这个画面/声音应该在什么时候显示出来」。
举个例子:
- 视频帧 A 的 PTS = 1000ms,表示它应该在 1 秒时显示
- 音频帧 B 的 PTS = 1000ms,表示它应该在 1 秒时播放
当这两个 PTS 对齐时,画面和声音就同步了。
重要概念:PTS 是相对于系统时钟 STC 的。不是绝对时间,而是相对时间。
我在项目中遇到过一个问题:某个码流里视频 PTS 是 33 位计数器,音频 PTS 是 27 位计数器。两者精度不同,直接比较会出错。后来我统一做了归一化处理才解决。
3. DTS——解码时间戳
DTS 全称是 Decoding Time Stamp,表示「这个数据包应该在什么时候开始解码」。
你可能会问:为什么需要 DTS?PTS 不是已经告诉什么时候显示了吗?
嗯,这里要注意。视频编码时,有些帧是参考帧(I 帧),有些是预测帧(P 帧、B 帧)。B 帧需要依赖后面的帧才能解码,所以解码顺序和显示顺序不一样。
举个例子:
- 显示顺序:I1 → P2 → B3 → P4
- 解码顺序:I1 → P2 → P4 → B3
你看,B3 虽然显示在 P2 之后,但解码时它需要等 P4 解码完才能解。所以 DTS 和 PTS 就分开了。
我的经验:对于没有 B 帧的码流(比如某些低延迟场景),DTS 和 PTS 是相等的。但只要有 B 帧,两者一定不同。
4. STC——系统时钟
STC 全称是 System Time Clock,它是机顶盒内部的「心跳」。
所有的时间戳都要跟 STC 比较。比如:
- 当 PTS == STC 时,显示这一帧
- 当 DTS == STC 时,开始解码
STC 是怎么来的?通常有两种方式:
- 本地晶振:机顶盒自己产生 27MHz 时钟
- PCR 恢复:从传输流中提取 PCR(节目时钟基准),同步到本地
我建议优先使用 PCR 恢复的方式。因为发送端和接收端的时钟如果不一致,时间长了就会累积误差。我曾经在一个项目中,本地晶振偏差了 50ppm,播了 2 小时后音视频差了 300ms——用户直接投诉了。
5. 时间戳的生成与传递
时间戳的生成通常发生在编码端。编码器在压缩音视频时,会记录每个数据包的 PTS 和 DTS。
传递过程是这样的:
- 编码器生成 PTS/DTS,写入码流
- 解复用器从码流中提取时间戳
- 解码器根据 DTS 调度解码
- 显示模块根据 PTS 调度显示
这里有个关键点:时间戳的精度。MPEG-2 标准中,PTS 用 33 位表示,精度是 90kHz 时钟(约 11.1μs)。
| 参数 | 值 |
|---|---|
| 时钟频率 | 90 kHz |
| PTS 位数 | 33 位 |
| 最大可表示时间 | 约 26.5 小时 |
| 精度 | 约 11.1 μs |
注意:PTS 只有 33 位,大约 26.5 小时会回绕一次。如果你的机顶盒需要长时间运行,必须处理回绕问题。我见过一个 DVR 项目,因为没处理回绕,录了 30 小时的节目,后半段全部不同步。
6. 实战中的时间戳处理
在实际代码中,我们经常需要比较两个 PTS 的大小。但因为有回绕,不能直接比较。
我常用的方法是:
// 判断 pts1 是否早于 pts2(考虑回绕)
bool is_pts_earlier(uint32_t pts1, uint32_t pts2) {
uint32_t diff = pts2 - pts1;
// 如果差值小于 2^31,说明 pts1 早于 pts2
return (diff & 0x80000000) == 0;
}
这个技巧在嵌入式系统里很实用。因为 32 位无符号整数的减法,天然处理了回绕。
我的习惯:在项目中,我会把 PTS 统一转换成 64 位整数,避免回绕问题。虽然多占点内存,但省心很多。
7. 常见问题与避坑指南
最后,我总结几个常见问题:
- PTS 抖动:编码器生成的时间戳可能不均匀,需要做平滑处理
- PCR 抖动:传输过程中 PCR 可能被干扰,需要滤波
- 音视频 PTS 不匹配:可能是解复用器解析错误,也可能是编码器问题
我曾经遇到一个坑:某个码流的音频 PTS 比视频 PTS 慢了 40ms,但用户说「感觉声音滞后」。后来发现是音频解码器内部有缓冲,导致实际播放延迟。最后我们在音频输出路径上做了补偿才解决。
好了,这一讲的内容就到这里。时间戳体系是音视频同步的基石,理解透了,后面的算法实现就水到渠成了。
下一讲,我们会深入音视频同步的三种主流算法,到时候见。