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

 1 #include <stdio.h>
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 }

  运行结果:

  

 

ts流中的pcr与pts计算与逆运算的更多相关文章

  1. FFMPEG中关于ts流的时长估计的实现(转)

    最近在做H.265 编码,原本只是做编码器的实现,但客户项目涉及到ts的封装,搞得我不得不配合了解点ts方面的东西.下面技术文档不错,转一下. ts流中的时间估计 我们知道ts流中是没有时间信息的,我 ...

  2. FFMPEG中关于ts流的时长估计的实现

    ts流中的时间估计 我们知道ts流中是没有时间信息的,我门来看看ffmpeg是怎么估计其duration的 方法1.通过pts来估计 static void estimate_timings_from ...

  3. TS流解析 三

    应该说真正了解TS,还是看了朋友推荐的<数字电视业务信息及其编码>一书之后,MPEG2 TS和数字电视是紧密不可分割的,值得总结一下其中的一些关系. ISO/IEC-13818-1:系统部 ...

  4. TS流基本概念

    在MPEG-2标准中,有两种不同类型的码流输出到信道:一种是节目码流(Program Stream, PS),适用于没有误差产生的媒体存储,如DVD等存储介质:另一种是传送流(Transport st ...

  5. MPEG2 PS和TS流格式

    http://blog.csdn.net/alangdangjia/article/details/9495193 应该说真正了解TS,还是看了朋友推荐的<数字电视业务信息及其编码>一书之 ...

  6. TS流格式(转)

    一 从TS流开始 数字电视机顶盒接收到的是一段段的码流,我们称之为TS(Transport Stream,传输流),每个TS流都携带一些信息,如Video.Audio以及我们需要学习的PAT.PMT等 ...

  7. TS流PAT/PMT详解

    一 从TS流开始 从MPEG-2到DVB,看着看着突然就出现了一大堆表格,什么PAT.PMT.CAT……如此多的表该怎样深入了解呢? 我们知道,数字电视机顶盒接收到的是一段段的码流,我们称之为TS(T ...

  8. TS流解析 一

    一 从TS流开始 数字电视机顶盒接收到的是一段段的码流,我们称之为TS(Transport Stream,传输流),每个TS流都携带一些信息,如Video.Audio以及我们需要学习的PAT.PMT等 ...

  9. TS流分析

    http://blog.csdn.net/zxh821112/article/details/17587215 一 从TS流开始 数字电视机顶盒接收到的是一段段的码流,我们称之为TS(Transpor ...

随机推荐

  1. Paxos 协议

    可用性与一致性 为了向用户提供更好的服务体验,现代软件架构越来越注重系统的可用性availability. 正是在这种趋势的驱动下,微服务与容器化技术才能在今天大行其道. 而高可用架构的前提是冗余: ...

  2. 介绍使用Cordova和Web Starter Kit开发Android

    介绍 如今,每个人都想制作移动应用程序,为什么不呢?世界上有更多的移动设备比任何其他用户设备.Android尤其流行,但是为什么不从一个众所周知的跨平台应用的基础开始呢?Android的开发显然比其他 ...

  3. 3-kubernetes监控与日志管理

    监控集群资源利用率 metrics-server是一个集群范围的资源使用情况的数据聚合器,作为一个应用部署在集群中 metrics-server从每个节点上kubelet API收集指标,通过kube ...

  4. 实现Excel文件的上传和解析

    前言 本文思维导图 一.需求描述 实现一个页面上传excel的功能,并对excel中的内容做解析,最后存储在数据库中. 二.代码实现 需求实现思路: 先对上传的文件做校验和解析,这里我们通过Excel ...

  5. 解决vue、js 下载图片浏览器默认预览而不是下载

    在网页上,如果我们下载的地址对应的是一个jpg文件,txt文件等,点击链接时,浏览器默认的是打开这些文件而不是下载,那么如何才能实现默认下载呢? 后端解决 这就是Content-Disposition ...

  6. 拉格朗日乘子法与KKT条件

    拉格朗日乘子法 \[min \quad f = 2x_1^2+3x_2^2+7x_3^2 \\s.t. \quad 2x_1+x_2 = 1 \\ \quad \quad \quad 2x_2+3x_ ...

  7. centos 6.4 配置本地yum源(iso镜像)

    1.先挂载 iso镜像  eg: mount -o loop /home/帐号/downloads/CentOS.iso /mnt/iso 2.用管理员帐号备份CentOS-Base.repo   e ...

  8. ttl转以太网

    ttl转以太网 ttl转以太网ZLSN3007S是实现TTL电平串口转以太网的"超级网口",产品自带网络变压器和RJ45网口,可以方便实现单片机.各类TTL电平串口设备的联网.首先 ...

  9. linux(centos8):基于java13安装rocketmq-4.7.1(解决jdk不兼容的报错)

    一,Rocketmq是什么? 1, RocketMQ是一个队列模型的消息中间件,具有高性能.高可靠.高实时.分布式特点 相比kafka,rocketmq的实时性更强 2,官方网站: http://ro ...

  10. spring boot:配置druid数据库连接池(开启sql防火墙/使用log4j2做异步日志/spring boot 2.3.2)

    一,druid数据库连接池的功能? 1,Druid是阿里巴巴开发的号称为监控而生的数据库连接池 它的优点包括: 可以监控数据库访问性能 SQL执行日志 SQL防火墙 2,druid的官方站: http ...