TS之PCR

        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);

你可能感兴趣的:(多媒体--容器)