前言

本文介绍TS文件封装格式,是一种被广泛应用的文件格式。全称为MPEG2-TS。其中TS即"Transport Stream"的缩写。

PS和TS

如下图所示,PES封包后能按需打出PS流和TS流,其中区别如下:

MPEG2-PS主要应用于存储的具有固定时长的节目,全称是Program Stream,如DVD电影;

MPEG-TS则主要应用于实时传送的节目,比如实时广播的电视节目。

PS 流 (Program Stream):节目流,PS 流由 PS 包组成,而一个 PS 包又由若干个 PES 包组成。一个 PS 包由具有同一时间基准的一个或多个 PES 包复合合成。

TS 流 (Transport Stream):传输流,TS 流由固定长度(188 字节)的 TS 包组成,TS 包是对 PES 包的另一种封装方式,同样由具有同一时间基准的一个或多个 PES 包复合合成。PS 包是不固定长度,而 TS 包为固定长度。

这两种格式的主要区别是将DVD上的VOB文件的前面一截剪掉(或者干脆就是数据损坏),那么就会导致整个文件无法解码,而电视节目是你任何时候打开电视机都能解码(收看)的。

所以,MPEG2-TS格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。

TS格式概览

TS是一种音视频封装格式,全称为MPEG2-TS。其中TS即"Transport Stream"的缩写。
TS格式是主要用于直播的码流结构,具有很好的容错能力。通常TS流的后缀是.ts、.mpg或者.mpeg,多数播放器直接支持这种格式的播放。
TS流中不包含快速seek的机制,只能通过协议层实现seek。HLS协议基于TS流实现的。

TS文件(码流)由多个TS Packet组成的,其TS包大小固定为188字节,以包头sync_byte为起始的一连串流。
TS文件(码流)可以分为三层:TS层(Transport Stream)、PES层(Packet Elemental Stream)、ES层(Elementary Stream)。
ES层就是音视频数据;
PES层是在音视频数据上加了时间戳等对数据帧的说明信息;
TS层是在PES层上加入了数据流识别和传输的必要信息。

TS层

TS层分为三个部分:TS Header、Adaptation Field、Payload。
TS Header固定4个字节;Adaptation Field可能存在也可能不存在,主要作用是给不足188字节的数据做填充;Payload是PES数据。

header,4字节

sync_byte(同步字节):
固定为0x47;该字节由解码器识别,使包头和有效负载可相互分离。

transport_error_indicator(传输错误标志):
1表示在相关的传输包中至少有一个不可纠正的错误位。当被置1后,在错误被纠正之前不能重置为0。

payload_unit_start_indicator(负载起始标志):
1表示该包是一个完整的包的开始;0表示是不是一个完整的包;

transport_priority(传输优先级标志):
‘1’表明当前TS包的优先级比其他具有相同PID, 但此位没有被置‘1’的TS包高。

PID:
指示存储与分组有效负载中数据的类型。
PID的作用就好比是一份文件的文件名。有了标识值的TS包,会放进一个叫节目映射表(PMT)的控制信息中,PMT本身就是一个TS包,所以也有自己的PID值(有PAT包指定),这个表里面的PID值与该路节目ES的音频、视频、数据的PID一一对应。最后将与该路节目有关的传送包复接起来,共同形成单路节目传送流,即TS流,从上图可以看出,视频数据的PID值是45,音频数据的PID值是78,填充数据的PID值是69…。
在多路节目传送流中,还有一个特殊的控制信息PAT(它是节目辅助表的意思),PAT本身也是一个TS包(在ISO/IEC 13818-1里有说明,PAT(Program Association Table)的PID值为0x00,所有TS包的标识(即sync_byte)为0x47),即上图中的表格数据部分。在PAT中,包含的就是每路TS流对应的PMT表所在的TS包的PID信息,其实PAT表中的数据为TS包的PID,这个TS包的内容为PMT。
通过对PID的译码,就可以对单个节目传送流进行解码。
所以解析起来就像这样: 先接收一个负载为PAT的TS包(TS包头为0x47 0xXX 0x00 0xXX),在整个数据包里找到一个PMT包的PID(program_map_PID)。然后再接收一个含有PMT的TS包(TS包头为0x47 0x00 program_map_PID 0xXX),在这个TS包里找到有关填入数据类型的PID,PMT中可能含有不止一个TS包的PID数据,PMT中stream_type、elementary_PID决定了TS包的类型和PID,然后用PMT中的PID值匹配接收到的TS包,如果匹配上,那么该TS包的负载内容就是填入实际的数据。

transport_scrambling_control(加扰控制标志):
表示TS流分组有效负载的加密模式。空包为‘00’,如果传输包包头中包括调整字段,不应被加密。其他取值含义是用户自定义的。

adaptation_field_control(适配域控制标志):
表示包头是否有调整字段或有效负载。‘00’为ISO/IEC未来使用保留;‘01’仅含有效载荷,无调整字段;‘10’ 无有效载荷,仅含调整字段;‘11’ 调整字段后为有效载荷,调整字段中的前一个字节表示调整字段的长度length,有效载荷开始的位置应再偏移[length]个字节。空包应为‘10’。

  • continuity_counter(连续性计数器):
    随着每一个具有相同PID的TS流分组而增加,当它达到最大值后又回复到0。范围为0~15。

文章最底部,领取最新最全C++音视频学习提升资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)

Adaptation Field

Adaptation Field的长度要包含传输错误指示符标识的一个字节。
PCR是节目时钟参考,PCR、DTS、PTS都是对同一个系统时钟的采样值,PCR是递增的,因此可以将其设置为DTS值,音频数据不需要PCR。
打包TS流时PAT和PMT表是没有Adaptation Field的,不够的长度直接补0xff即可。
视频流和音频流都需要加adaptation field,通常加在一个帧的第一个ts包和最后一个ts包里,中间的ts包不加。

Payload

TS包中Payload所传输的信息包括两种类型:视频、音频的PES包以及辅助数据;节目专用信息PSI。
TS包也可以是空包。空包用来填充TS流,可能在重新进行多路复用时被插入或删除。
视频、音频的ES流需进行打包形成视频、音频的 PES流。辅助数据(如图文电视信息)不需要打成PES包。

PES层

从上面的结构图可以看出,PES层是在每一个视频/音频帧上加入了时间戳等信息,PES包内容很多,下面我们说明一下最常用的字段:

packet_start_code_prefix:
3字节,开始码,固定为0x000001。
stream id:
音频取值(0xc0-0xdf),通常为0xc0;视频取值(0xe0-0xef),通常为0xe0。
pes packet length:
后面pes数据的长度,0表示长度不限制,只有视频数据长度会超过0xffff。
pes data length:
后面数据的长度,取值5或10。
pts:
33bit值
dts:
33bit值

 ES层

ES层指的就是音视频数据。
一般的,视频为H.264视频,音频为AAC音频。

PAT

Program Association Table 节目关联表,每个 TS 流对应一张,用来描述该 TS 流中有多少个节目。

TS 流中中,PAT 包重复实现,大约 0.5 秒出现一个,保证实时解码性
表示 PAT 表的 TS 包 PID 值为 0,便于识别
PAT 的 payload 中传送特殊 PID 的列表,每个 PID 对应一个节目(对应一张 PMT 表)
PAT 表是 TS 流的基础,任何一个 TS 流解析寻找节目都是从 PAT 表开始查找

typedef struct TS_PAT_Program {unsigned program_number       :16;  // 节目号,为 0x0000 时表示这是 NIT,节目号为 0x0001 时, 表示这是 PMTunsigned reserved             :3    // 保留,固定为 111unsigned program_map_PID      :13;  // 节目号对应内容的 PID 值
} TS_PAT_Program;typedef struct TS_PAT {unsigned table_id                     : 8;  // 固定 0x00 ,标志是该表是 PATunsigned section_syntax_indicator     : 1;  // 段语法标志位,固定为 1unsigned zero                         : 1;  // 0unsigned reserved_1                   : 2;  // 保留位,固定为 11unsigned section_length               : 12; // 段长度,表示从下一个字段开始到 CRC32(含) 之间有用的字节数unsigned transport_stream_id          : 16; // TS 流 ID,一般为 0x0001,区别于一个网络中其它多路复用的流unsigned reserved_2                   : 2;  // 保留位,固定为 11unsigned version_number               : 5;  // PAT 版本号,固定为 00000,如果 PAT 有变化则版本号加 1unsigned current_next_indicator       : 1;  // 固定为 1,表示这个 PAT 表有效,如果为 0 则要等待下一个 PAT 表unsigned section_number               : 8;  // 分段的号码。PAT 可能分为多段传输,第一段为 00,以后每个分段加 1,最多可能有 256 个分段unsigned last_section_number          : 8;  // 最后一个分段的号码std::vector<TS_PAT_Program> program;unsigned CRC_32                       : 32; // CRC32 校验码
} TS_PAT;

PMT

Program Map Table,节目映射表,该表的 PID 是由 PAT 表 提供给出的。表征一路节目所有流信息。包含:

当前节目中包含的所有 Video 数据的 PID
当前节目中包含的所有 Audio 数据的 PID
与当前节目关联在一起的其他数据的 PID(如数字广播,数据通讯等使用的 PID)
如果 TS 流中包含多个节目,那么就会有多个 PMT 表。只要我们处理了 PMT 表,那么我们就可以获取该节目中所有的流信息,如当前节目包含多少个 Video、多少个 Audio 和其他数据及每种数据对用的流 PID 分别是多少。

typedef struct TS_PMT_Stream {unsigned stream_type              : 8;  // 指示本节目流的类型,H.264 编码对应 0x1b,AAC 编码对应 0x0f,MP3 编码对应 0x03unsigned reserved1                : 3;  // 保留位,固定为 111unsigned elementary_PID           : 13; // 指示该流的 PID 值unsigned reserved2                : 3;  // 保留位,固定为 1111unsigned ES_info_length           : 12; // 前两位 bit 为 00,指示跟随其后的描述相关节目元素的字节数std::vector<unsigned> descriptor;
} TS_PMT_Stream;typedef struct TS_PMT {unsigned table_id                     : 8;  // 取值随意,一般使用 0x02, 表示 PMT 表unsigned section_syntax_indicator     : 1;  // 段语法标志位,固定为 1unsigned zero                         : 1;  // 固定为 0unsigned reserved_1                   : 2;  // 保留位,固定为 11unsigned section_length               : 12; // 段长度,表示从下一个字段开始到 CRC32(含) 之间有用的字节数unsigned program_number               : 16; // 当前 PMT 表映射到的节目号,1、2、3unsigned reserved_2                   : 2;  // 保留位,固定为 11unsigned version_number               : 5;  // PMT 版本号码,固定为 00000,如果 PAT 有变化则版本号加 1unsigned current_next_indicator       : 1;  // 发送的 PMT 表 是当前有效还是下一个 PMT 有效unsigned section_number               : 8;  // 分段的号码。PMT 可能分为多段传输,第一段为 00,以后每个分段加 1,最多可能有 256 个分段unsigned last_section_number          : 8;  // 分段数unsigned reserved_3                   : 3;  // 保留位,固定为 111unsigned PCR_PID                      : 13; // 指明 TS 包的 PID 值,该 TS 包含有 PCR 同步时钟,unsigned reserved_4                   : 4;  // 预留位,固定为 1111unsigned program_info_length          : 12; // 前 2bit 为 00,该域指出跟随其后对节目信息的描述的字节数。std::vector<TS_PMT_Stream> PMT_Stream;unsigned reserved_5                   : 3;  // 保留位,0x07unsigned reserved_6                   : 4;  // 保留位,0x0Funsigned CRC_32                       : 32; // CRC32 校验码
} TS_PMT;

TS流生成及解析流程

TS 流生成流程
将原始音视频数据压缩之后,压缩结果组成一个基本码流(ES)。
对ES(基本码流)进行打包形成PES。
在PES包中加入时间戳信息(PTS/DTS)。
将PES包内容分配到一系列固定长度的传输包(TS Packet)中。
在传输包中加入定时信息(PCR)。
在传输包中加入节目专用信息(PSI) 。
连续输出传输包形成具有恒定比特率的MPEG-TS流。

TS 流解析流程
复用的MPEG-TS流中解析出TS包;
从TS包中获取PAT及对应的PMT;
从而获取特定节目的音视频PID;
通过PID筛选出特定音视频相关的TS包,并解析出PES;
从PES中读取到PTS/DTS,并从PES中解析出基本码流ES;
将ES交给解码器,获得压缩前的原始音视频数据。

音视频 TS格式解析相关推荐

  1. 音视频 FLV格式解析

    前言 本文介绍FLV封装格式,直播场景下拉流比较常见的是http-flv直播流,具有延时低.易传输等特点. 格式概览 总体上看,FLV包括文件头(File Header)和文件体(File Body) ...

  2. AVI音视频封装格式学习(三)——AVI 数据结构解析

    这里介绍AVI会使用到的数据结构,为了避免翻译引入歧义,决定该部分还是使用英文原文,如后续有时间再进行翻译. AVIMAINHEADER structure The AVIMAINHEADER str ...

  3. 音视频封装格式、编码格式知识

    常见的AVI.RMVB.MKV.ASF.WMV.MP4.3GP.FLV等文件其实只能算是一种封装标准. 一个完整的视频文件是由音频和视频2部分组成的.H264.Xvid等就是视频编码格式,MP3.AA ...

  4. AVI音视频封装格式学习(四)——linux系统C语言AVI格式音视频封装应用

    拖了很久的AVI音视频封装实例,花了一天时间终于调完了,兼容性不是太好,但作为参考学习使用应该没有问题.RIFF和AVI以及WAV格式,可以参考前面的一些文章.这里详细介绍将一个H264视频流和一个2 ...

  5. AVI音视频封装格式学习(五)——h265与PCM合成AVI文件

    不知道是处于版权收费问题还是什么原因,H265现在也并没有非常广泛的被普及.将h265数据合成AVI的资料现在在网上也基本上没有.使用格式化工厂工具将h265数据封装成AVI格式,发现它在封装的时候其 ...

  6. 音视频封装格式、编码格式

    音视频封装格式.编码格式 概述 常见的AVI.RMVB.MKV.ASF.WMV.MP4.3GP.FLV等文件其实只能算是一种封装标准. 一个完整的视频文件是由音频和视频2部分组成的.H264.Xvid ...

  7. AVI音视频封装格式学习(二)——AVI RIFF文件参考

    AVI RIFF文件参考 AVI RIFF File Reference 微软AVI文件格式是与捕获,编辑和播放音视频流的应用程序一起使用的RIFF文件规范.通常,AVI文件包含多个不同类型的数据流. ...

  8. ffmpeg4.4项目学习--音视频基本格式

    目录 一.引言 二.音视频基本格式学习 ------> 2.1.图像压缩数据格式 ------> 2.2.PCM ------> 2.3.H264 ------> 2.4.AA ...

  9. 【媒体工具】音视频信息常用解析工具

    前言 信息查看工具 综合信息查看:MediaInfo 二进制信息查看:UltraEdit 单项详细分析 封装格式:Elecard Format Analyzer 视频编码数据:Elecard Stre ...

  10. 音视频同步原理解析;音频编码和解码原理

    视频流中的DTS/PTS到底是什么? DTS(解码时间戳)和PTS(显示时间戳)分别是解码器进行解码和显示帧时相对于SCR(系统参考)的时间戳.SCR可以理解为解码器应该开始从磁盘读取数据时的时间. ...

最新文章

  1. 软件系统的4大技术本质
  2. 基于深度学习的事件因果关系抽取综述
  3. linux下安装ftp服务器
  4. WinForm控件之【NumericUpDown】
  5. flutter系列InheritedWidget介绍
  6. linux 线程退出 signal,Linux signal 那些事儿 (3)
  7. x86_64 arm制linux-gcc,arm-linux-gcc 制作
  8. 分享:TreeFrog 1.1 发布,C++ Web 应用开发框架
  9. WinCE6.0 R3 安装记
  10. 国内python镜像源记录
  11. Windows Server 2012搭建文件服务器
  12. 【CGAL_网格处理】平滑处理
  13. My 10 favorite APPs
  14. Python电影票房数据可视化分析基础实践
  15. 网线交叉网线线序接法
  16. 中国古代30大名将VS100名将排行(按时间顺序)
  17. 如何调整DOSBox窗口大小
  18. 宇视科技android面试_在宇视科技工作是怎样的体验?
  19. ISD9160学习笔记01_大联大Nuvoton ISD9160语音识别开发板初体验
  20. Qt笔记(五十七)之显示图片缩略图

热门文章

  1. 飞客蠕虫病毒?分析、定位、处理
  2. Microsoft Office 2016 简体中文Vl批量官方授权版镜像下载
  3. python之time:基于python语言利用time模块计算运行时间—计算机器学习模型训练前后的时间代码实现
  4. vfp体积计算机程序,计算机vfp教程第9章 报表与菜单设计
  5. 股市的逻辑-201006-2
  6. 软件需求文档模板及说明
  7. 【java】第十三章、高级事件处理
  8. 数学之美系列 1.3w字精简版阅读笔记
  9. 学习总结(一):ad画板总结
  10. python session过期_设置session过期时间