long到number转换 ts_ts流中的pcr与pts计算与逆运算

mpeg2ts文件格式中有pcr和pts的概念,其代码含义如下:

PCR(Program Clock Reference)——指示系统时钟本身的瞬时值的时间标签称为节目参考时钟标签(PCR)。

PTS(Presentation Time Stamp)——指示音视频显示时间的时间戳称为显示时间戳(PTS)。

二者的更具体含义可以网上查找资料,本博文的重点不再于此。本博文主题为:利用编码帧bitstream所携带的时间戳,如何换算出ts文件中的pcr和pts值。

1. 一段典型的音视频ts数据包:

AAC: 47 41 E1 3F 07 10 00 F9 F2 B6 FE B3 00 00 01 C0 01 6A 84 80 05 21 07 CF CA DB 。。。(bitstream)。。。

AVC: 47 41 E2 3D 07 10 00 F9 F2 B6 FE B3 00 00 01 E0 98 65 84 80 05 21 07 CF CA DB 。。。(bitstream)。。。

红色的六个字节为pcr值(188Bytes的TS数据包的第7个字节),粉红色的四个半字节为pts值(头的尾部,后面直接跟编码数据)。

2. pcr及pts算法介绍(pcr_val(48b)和pts[32..30..0](33b))

两段典型的示例如下:

时间戳为00:06:04.013(timsUs=364013000)的一帧数据,其pcr的值:00 F9 F2 A9 7E 0D ,其pts[32...0]值为:21 07 CF CA A5

时间戳为00:06:04.034(timsUs=364034000)的一帧数据,其pcr的值:00 F9 F6 59 FE CF ,其pts[32...0]值为:21 07 CF D9 69

其中,编码模块送给封装模块(Android中为MPEG2TSWriter)的编码帧所携带的时间戳并不是“00:06:04.013”形式,而是一个long long型的整数,单位为微秒,例如364013000(代表364.013秒),换算成人容易识别的格式(hh:mm:ss)为:00:06:04.013。

注意,ts在封装时,标准规定了pcr值和pts各个位如何排布(参考下面的pcr_val和pts_val数组,即符合spec规定)。

3. timeUs和pcr之间转换

正向运算:timeUs -> pcr (用于封装)

float tmp = timeUs / 1000000 + (timeUs % 1000000) / 1000 * 0.001; //timeUs以us为单位,tmp以s为单位,即换算成xy.z格式(小数点放在倒数第六个字节前),xy为秒值,z为毫秒值

long long pcr = (long long)(tmp * 27000000.0);

long long pcr_low = pcr % 300LL;

long long pcr_high = pcr / 300LL;

unsigned char pcr_val[6]; //待写到ts文件中的6个字节值

pcr_val[0] = pcr_high>>25;

pcr_val[1] = pcr_high>>17;

pcr_val[2] = pcr_high>>9;

pcr_val[3] = pcr_high>>1;

pcr_val[4] = pcr_high<<7 | pcr_low>>8 | 0x7e;

pcr_val[5] = pcr_low;

逆向运算:pcr -> timeUs (用于解封装时获取时间戳,由已知ts文件算出音视频帧的时间戳)

long long PCR_LOW = pcr_val[5] + ((pcr_val[4]&0x1)<<8);

long long PCR_HIGH = (pcr_val[4]>>7) + (pcr_val[3]<<1) + (pcr_val[2]<<9) + (pcr_val[1]<<17) + (pcr_val[0]<<25);

long long PCR = PCR_HIGH * 300 + PCR_LOW;

float TMS = PCR / 27000000.0;

4. timeUs和pts之间的转换

正向运算:timeUs -> pts

long long pts = timeUs * 9LL / 100LL;

unsigned char pts_val[5];

pts_val[0] = 0x20 | (((pts >> 30) & 7) << 1) | 1;

pts_val[1] = (pts >> 22) & 0xff;

pts_val[2] = (((pts >> 15) & 0x7f) << 1) | 1;

pts_val[3] = (pts >> 7) & 0xff;

pts_val[4] = ((pts & 0x7f) << 1) | 1;

逆向运算:pts -> timeUs

long long PTS = (pts_val[4]>>1) | (pts_val[3]<<7) | (pts_val[2]>>1)<<15 | pts_val[1]<<22 | (pts_val[0]>>1)<<30;

long long TIMEUS = PTS * 100LL / 9LL;

5. 完整demo

409741c71b82244e42a8dc34c45aa6f2.png

b8caf6a7f0ff94ebebc445bcc752de79.png

1 #include

2

3 int main(void)4 {5 long long timeUs = 364034000;6

7 float tm = timeUs / 1000000 + (timeUs % 1000000) / 1000 * 0.001;8 long long pcr = (long long)(tm * 27000000.0);9 long long pcr_low = pcr %300LL;10 long long pcr_high = pcr /300LL;11

12 unsigned char pcr_val[6];13 pcr_val[0] = pcr_high>>25;14 pcr_val[1] = pcr_high>>17;15 pcr_val[2] = pcr_high>>9;16 pcr_val[3] = pcr_high>>1;17 pcr_val[4] = pcr_high<<7 | pcr_low>>8 | 0x7e;18 pcr_val[5] =pcr_low;19 printf("calculate pcr by timeUs!\n");20 printf("timeUs=%lld us, tm=%f s\n", timeUs, tm);21 printf("pcr=%llx, pcr_low=%#llx, pcr_high=%#llx\n", pcr, pcr_low, pcr_high);22 printf("pcr_val[0-5]: %#x, %#x, %#x, %#x, %#x, %#x\n", pcr_val[0], pcr_val[1], pcr_val[2], pcr_val[3], pcr_val[4], pcr_val[5]);23

24 long long PCR_LOW = pcr_val[5] + ((pcr_val[4]&0x1)<<8);25 long long PCR_HIGH = (pcr_val[4]>>7) + (pcr_val[3]<<1) + (pcr_val[2]<<9) + (pcr_val[1]<<17) + (pcr_val[0]<<25);26 long long PCR = PCR_HIGH * 300 +PCR_LOW;27 float TMS = PCR / 27000000.0;28 printf("revert test by pcr_val[0-5]!\n");29 printf("PCR_LOW=%#llx, PCR_HIGH=%#llx, PCR=%#llx, TMS=%f s\n", PCR_LOW, PCR_HIGH, PCR, TMS);30

31 printf("---------------------------------------------------------------------------\n");32 printf("calculate pts by timeUs!\n");33 long long pts = timeUs * 9LL /100LL;34 unsigned char pts_val[5];35 pts_val[0] = 0x20 | (((pts >> 30) & 7) << 1) | 1;36 pts_val[1] = (pts >> 22) & 0xff;37 pts_val[2] = (((pts >> 15) & 0x7f) << 1) | 1;38 pts_val[3] = (pts >> 7) & 0xff;39 pts_val[4] = ((pts & 0x7f) << 1) | 1;40 printf("pts_val[0-4]: %#x, %#x, %#x, %#x, %#x\n", pts_val[0], pts_val[1], pts_val[2], pts_val[3], pts_val[4]);41

42 printf("revert test by pts_val[0-4]!\n");43 long long PTS = (pts_val[4]>>1) | (pts_val[3]<<7) | (pts_val[2]>>1)<<15 | pts_val[1]<<22 | (pts_val[0]>>1)<<30;44 long long TIMEUS = PTS * 100LL /9LL;45 printf("PTS=%lld, TIMEUS=%lld\n", PTS, TIMEUS);46

47 long long PTS_VAL = (1LL * pts_val[0]<<32) + (1LL * pts_val[1]<<24) + (1LL * pts_val[2]<<16) + (1LL * pts_val[3]<<8) + (1LL * pts_val[4]);48 long long PTS1 = ((PTS_VAL>>1)&0x7f) | ((PTS_VAL>>8)&0xff)<<7 | ((PTS_VAL>>(16+1))&0x7f)<<15 | ((PTS_VAL>>24)&0xff)<<22 | ((PTS_VAL>>(32+1))&7)<<30;49 long long TIMEUS1 = PTS1 * 100LL /9LL;50 printf("PTS1=%lld, TIMEUS1=%lld\n", PTS1, TIMEUS1);51

52 return 0;53 }

View Code

运行结果:

edb8f1cf9f43ea723f1f21210ed0d1e8.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值