You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MPEG2传输流PCR计算问询:基于PTS/DTS的推导与实现问题

关于MPEG-TS中PCR的计算与推导方案

核心认知:PCR与PTS/DTS的本质区别

PCR(Program Clock Reference)是用于同步解码器系统时钟(STC)的基准信号,它对应的是TS包到达解码器的时间点,时钟基准为90kHz(扩展部分为27MHz);而PTS/DTS是帧的显示/解码时间,属于媒体内容的时间戳。两者没有固定的推导公式,PCR的计算需要结合传输码率和解码器缓冲需求两个核心因素。

对现有两种计算方式的分析

  1. 基于包数量与码率的计算
    你提到的这段代码:

    (int64_t) ((8.0 * (packetsWritten * TS_PACKET_LENGTH + offset) / tsMuxrate) * TS_CLOCK + 0.5) + pcrStart
    

    逻辑上是正确的——通过已发送的字节数、码率计算对应传输时间,再转换为90kHz的PCR值。但和ffmpeg输出不符的原因大概率是细节误差:

    • tsMuxrate需精确到bps(如10Mbps要写10000000而非10);
    • offset必须指向PCR字段在TS包中的具体字节位置(PCR是指该字节到达解码器的时间,不是包起始位置);
    • pcrStart的初始值未和ffmpeg的起始PCR对齐。
  2. 硬编码100ms延迟的方法

    base = (int64_t) packet->dts - (int64_t) (SYSTEM_CLOCK_FREQ_90kHz * 0.1);
    

    这种方式能快速跑通,但100ms是经验值,无法适配不同码率、不同解码器的缓冲需求,属于临时方案。

合理的PCR计算实现方案

方案1:结合传输时间与媒体时间戳约束

PCR的计算需要满足两个核心规则:

  • PCR的增长速率严格匹配90kHz时钟,且和TS流码率对应(每个TS包的发送间隔对应固定的PCR增量);
  • 对于承载视频PES的TS包,PCR必须早于该PES中首帧的DTS(提前几十到几百ms,保证解码器STC在帧到达时已准备好解码)。

具体实现步骤:

  1. 初始化全局PCR计数器:取第一个视频帧的DTS,减去一个可配置的缓冲时间(如50-200ms,对应90kHz时钟周期为缓冲时间(ms)*90),作为初始PCR值;
  2. 每发送一个TS包,计算该包对应的PCR增量:
    // 避免浮点运算误差,用整数计算:增量 = (包字节数*8*90000)/码率
    int64_t pcr_increment = (TS_PACKET_LENGTH * 8LL * 90000) / tsMuxrate;
    current_pcr += pcr_increment;
    
  3. 当发送包含视频PES头的TS包时,检查当前PCR是否小于当前帧DTS - 缓冲时间,如果是则将PCR调整到该值,避免PCR落后于解码时间。

方案2:对齐ffmpeg的实现逻辑

ffmpeg在libavformat/mpegtsenc.c中的PCR计算逻辑可参考:

  • 维护last_pcr变量记录上一次写入的PCR值;
  • 通过已发送字节数计算传输时间对应的PCR:current_pcr = start_pcr + (bytes_written * 8LL * 90000) / bit_rate;
  • 对视频流强制保证PCR至少比当前帧DTS提前pcr_delay(默认100ms,对应9000个90kHz时钟周期),若计算出的current_pcr小于DTS - pcr_delay,则用后者作为当前PCR。

额外注意事项

  • PCR的插入间隔:MPEG标准要求每100ms至少插入一次PCR,通常在视频PES的适配字段中插入;
  • 精度要求:PCR包含33位的90kHz基准和9位的27MHz扩展部分,若追求严格标准,需完整计算扩展部分(将90kHz基准乘以300,加上对应27MHz的增量)。

内容的提问来源于stack exchange,提问作者Tomislav Timic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:22:20