PCR用来同步前端编码器和后端机顶盒的时钟(即前端编码器实时编码或视频服务器实时播出,后端机顶盒实时接收的情况)。对DVD机这类从文件中取TS流的设备PCR没有意义。

MPEG2系统用于视音频同步以及系统时钟恢复的时间标签分别在ES,PES和TS这3个层次中。

在TS 层, TS头信息包含了节目时钟参考PCR(Program Clock Reference),用于恢复出与编码端一致的系统时序时钟STC(System Time Clock)。     

在PES层, 在PES头信息里包含有表示时间戳PTS(Presentation Time Stamp)和解码时间戳DTS(Decoding Time Stamp);

在ES 层, 与同步有关的主要是视频缓冲验证VBV(Video Buffer Verifier),用以防止解码器的缓冲器出现上溢或者下溢;

标准规定在原始音频和视频流中,PTS的间隔不能超过0.7s,出现在TS包头的PCR间隔不能超过0.1s,PCR最大值为26:30:43。

 

在TS的传输过程中,一般DTS和PCR差值会在一个合适的范围,这个差值就是要设置的视音频Buffer的大小,一般情况下视频DTS和PCR的差值在700ms~1200ms之间,音频差值在200ms-700ms之间。

PCR(i) = PCR_base(i)*300 + PCR_ext(i) 
PCR_base 33 位,最大值:0x1FFFFFFFF 
PCR_ext 9 位,根据定义,取值 0-299 
因此PCR最大值为:0x1FFFFFFFF*300 + 299 
可表示的小时数:(0x1FFFFFFFF*300 + 299) / 27000000 / 3600 约为 26.5 小时 
以前认为是两天多,大概是这样算的,PCR一共42位,把2的42次方作为PCR最大值,算出来大约是1.8天。 

PCR分两部分编码:一个以系统时钟频率的 1/300 为单位,称为PCR_base,共33bit;另一个以系统时钟频率为单位,称为PCR_ext,共9bit,共42bit。 
具体规定如下: 
PCR_base(i) = ((系统时钟频率 x t(i)) div 300) % 2^33 
PCR_ext(i) = ((系统时钟频率 x t(i)) div 1) % 300 

PCR(i) = PCR_base(i) x 300 + PCR_ext(i)

例如:
  时间"03:02:29.012"的PCR计算如下:
  03:02:29.012 = ((3 * 60) + 2) * 60 + 29.012 = 10949.012s
  PCR_base = ((27 000 000 * 10949.012) / 300) % 2^33 = 98 541 080
  PCR_ext   = ((27 000 000 * 10949.012) / 1  ) % 300  = 0 
  PCR = 98 541 080 * 300 + 0 = 295 623 324 000
PCR-base的作用:
  a. 与PTS和DTS作比较, 当二者相同时, 相应的单元被显示或者解码.
  b. 在解码器切换节目时,提供对解码器PCR计数器的初始值,
     以让该PCR值与PTS、DTS最大可能地达到相同的时间起点.
PCR-ext的作用:
  通过解码器端的锁相环路修正解码器的系统时钟, 使其达到和编码器一致的27MHz.

        随机进入压缩的码流:在视频码流中存在I帧,B帧,P帧三种编码帧类型,只有I帧编码数据可以独立进行解码。在节目调谐或节目更换时需要随时进入音频或视频,随机进入应该是I帧,在I帧前面的视频序列的头部应该有一个随机进入点,随机进入指标就是表明随机进入点的位置。 
在电视广播中,常需要进行本地节目和广告的插入,在MPEG-2传送系统中,使用TS包适配域中的一些标志来支持。插入节目的PCR值与插入前节目的PCR值是不同的,因此通知解码器,要尽快与插入节目建立同步关系。 
        PCR的插入必须在PCR字段的最后离开复用器的那一时刻,同时把27MHz系统时钟的采样瞬时值作为PCR字段插入到相应的PCR域。它是放在TS包头的自适应区中传送。 

代码: 
递增的PCR,head_pts为开始pts,head_pcr为开始pcr。
先求ptsspan。
uint64_t ptsspan = 0;
if (pts >= head_pts) {
ptsspan = pts - head_pts;
} else {
ptsspan = pts + 0x1FFFFFFFF - head_pts;
}
再求新的pcr。
uint64_t pcr_base;
uint64_t pcr_ext ;
uint64_t pcr;
pcr_base = pcr_ext = pcr = 0;
pcr = head_pcr + ptsspan*300; //300为27MHZ除以90k(h264的采样率为90000HZ)。
if(pcr > 0x1FFFFFFFF*300)
{
pcr -= 0x1FFFFFFFF*300;
}
pcr_base = pcr/300;
set_pcr(p,pcr_base);
set_pcrext(p,0);
递减的pcr, end_pts为结束pts,end_pcr为结束pcr。
先求ptsspan。
uint64_t ptsspan = 0;
if(end_pts > pts)
{
ptsspan = end_pts - pts;
}else{
ptsspan = (end_pts + 0x1FFFFFFFF) - pts;
}
再求新的pcr。
uint64_t pcr = 0;
if(end_pcr > ptsspan*300)
{
pcr = end_pcr -ptsspan*300;
}else{
pcr = end_pcr + 0x1FFFFFFFF*300 -ptsspan*300;
}
uint64_t pcr_base = pcr/300;
set_pcr(p, pcr_base);
set_pcrext(p,0);