在数字电视传输码流中。节目时钟基准 (PCR) 也是一种重要的包头信息,
1. pcr 能表示的时间范围
它由 33bit 基值 (Base) 和 9bit 扩展值 (Extension) 组成。
#define PCR_TIME_BASE 27000000
pcr 为1 代表1/27M 时间,
pcr 的最大表示时间为(2^33*300+299)/27000000=95443.7177秒
95443.7177/3600=26.512小时
2. pcr 的内存存储
节目时钟是27M 为基准单位,在内存中存储占用6个bytes, 如下代码所示.:
static int write_pcr_bits(uint8_t *buf, int64_t pcr)
{
int64_t pcr_low = pcr % 300, pcr_high = pcr / 300;
*buf++ = pcr_high >> 25;
*buf++ = pcr_high >> 17;
*buf++ = pcr_high >> 9;
*buf++ = pcr_high >> 1;
*buf++ = pcr_high << 7 | pcr_low >> 8 | 0x7e;
*buf++ = pcr_low;
return 6;
}
3. pcr 的数值生成
#define PCR_TIME_BASE 27000000
static int64_t get_pcr(const MpegTSWrite *ts)
{
return av_rescale(ts->total_size + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
ts->first_pcr;
}
1秒钟,pcr要走27M, 所以pcr 计算是 时间*27M
时间=(发送的总大小*8/mux_rate)
用函数表示: rescale(total_size,8*27M,mux_rate), 再加一个原始偏移,代码即理解了.
可见pcr 值决定于发送的数据量.
4. pcr 应用
在mpegtsenc.c第1600行, 有
if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
要求传来的dts 不能小于pcr/300, 否则会有一个warning 警告! 不过后面它该干的都干了.
何时write_pcr?
考察,cbr 模式, 此时mux_rate 为有效.
1.
if (pcr >= ts->next_pcr) { write_pcr=1;}
当发送的数据量足够多了(当前pcr),多于下一个next_pcr, 就要插入一个pcr包
next_pcr 的计算:
next_pcr = FFMIN(next_pcr, ts_st2->last_pcr + ts_st2->pcr_period);
当dts 与pcr/300 差距大于delay 时,要插入pcr 或者空包
if ((dts - pcr / 300) > delay) {
/* pcr insert gets priority over null packet insert */
if (write_pcr)
mpegts_insert_pcr_only(s, st);
else
mpegts_insert_null_packet(s);
/* recalculate write_pcr and possibly retransmit si_info */
continue;
}
dts 被重新计算过.