TS流中的PTS,DTS与timeus(微秒)的相互转化

TS协议概念及传输流程
TS协议之PAT(节目关联表)
TS协议之PMT(节目映射表)
TS协议之PES(ES数据包)

PTS,DTS转化为timeus(微秒)

在TS协议流中PTS和DTS都是由五个字节表示,想要将五字节的时间戳数据转化为微秒就需要了解这五个字节时间信息的构成:

根据IOS13818-1协议可知:

PTS:

'0010'       4bit
PTS[32.30]    3bit
标记位        1bit
PTS[29.15]    15bit
标记位        1bit
PTS[14.0]    15bit
标记位        1bit

DTS:

'0001'        4bit
DTS[32.30]    3bit
标记位        1bit
DTS[29.15]    15bit
标记位        1bit
DTS[14.0]    15bit
标记位        1bit

由此可见,在五字节中真正表示时间戳的也只有33字节。其中标记位为1bit,值为1.因此要想获得pts和dts的微妙值只需要将代表时间戳的33bit拼起来就可以啦!

详细过程如下:

//展开五个字节,40bit
00000000 00000000 00000000 00000000 00000000

由于PTS和DTS真正的时间戳数据只占33bit(ts协议规定,具体看我博客);因此我们只需要将40bit的低33位用于组合时间戳:

//使用低33bit保存时间戳的值
0000000 0 00000000 00000000 00000000 00000000

到这里流程就已经很清晰了,那么接下来进行时间戳提取:

//pts[5]代表五字节pts数据,为了方便理解假设pts的值都为1
//提取PTS[32.30],pts[0]&0x0E:提取PTS[32.30]的3bit,左移29位表示将pts[0]的1-3bit(PTS[32.30])移动到timeus用于保存时间戳的低33位的最高位
//移动后变为:0000000 1 11000000 00000000 00000000 00000000
uint64_t timeus |= (pts[0]&0x0E) << 29;
//提取PTS[29.15],左移22的目的是紧跟PTS[32.30],pts[0]的最低位为标记位,没用直接覆盖掉
timeus |= pts[1] << 22;
//pts[2]&0xFE是因为pts[2]的最后1bit是标记位没用。
timeus |= (pts[2]&0xFE) << 14;
//移动后变为:0000000 1 11111111 11111111 10000000 00000000
//提取PTS[14.0],这个和提取提取PTS[29.15]是一样的
timeus |= pts[3] << 7;
timeus |= (pts[4]&0xFE);
//移动后变为:0000000 1 11111111 11111111 11111111 11111111
//时间戳转换:TS协议中时间戳的单位是90kHz(每秒90,000个计数单位),转换为本地系统时间单位,
//计算公式:newtimestamp = oldtimestamp*newtimebase/oldtimebase
timeus = timeus*1000000LL/90000LL;

timeus(微秒)转化为PTS,DTS

将timeus转化为ts协议的PTS,DTS只不过是将时间戳的33bit分为三部分,填充到TS协议的PTS,DTS的五字节的相应字段中,然后设置最高4bit和标记位。

流程都已经很清晰了,废话不多说直接开始编码:

//假设转换后的字节存放在pts[5]中,timeus是要转化的时间戳
//将时间戳转化为TS协议的时间戳以90000HZ为单位,以PTS为例,DTS同理
timeus = timeus*90000LL/1000000LL;
//填充第一个字节,前4bit为0010,接下来的3bit为时间戳的高3bit,最后1bit为标记位值为1
pts[0] = 0x20 | ((timeus >> 29)&0xE)|1;
//填充第二个字节,为时间戳的30-23
pts[1] = (timeus >> 22)&0xFF;
//填充第三个字节,为时间戳的22-15,最后1bit为标记位值为1
pts[2] = ((timeus >> 14)&0xFE) | 1;
//填充第四个字节,为时间戳的14-7
pts[3] = (timeus >> 7)&0xFF;
//填充第四个字节,为时间戳的6-0bit, 最后1bit为标记位值为1
pts[4] = ((timeus << 1)&0xFE) | 1;

你可能感兴趣的:(音视频,TS,流媒体,音视频,时间戳,pts/dts)