【音视频】TS协议介绍

发布于:2025-07-10 ⋅ 阅读:(27) ⋅ 点赞:(0)

参考博客:
https://2048.csdn.net/68270d17606a8318e85713f3.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NDE4ODgwNSwiZXhwIjoxNzUyNjM1MjcwLCJpYXQiOjE3NTIwMzA0NzAsInVzZXJuYW1lIjoiQW50b25pbzkxNSJ9.oPiMSZSr-cNiR5VmlmOqC8Mr_YNz3H_8O9koA3c_NkQ&spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-6-123919042-blog-130913479.235%5Ev43%5Epc_blog_bottom_relevance_base5&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-6-123919042-blog-130913479.235%5Ev43%5Epc_blog_bottom_relevance_base5&utm_relevant_index=7

一、TS协议概述

TS(Transport Stream,传输流)协议是一种用于音频、视频和数据等多媒体内容传输和存储的容器格式,是 MPEG-2 标准(ISO/IEC 13818-1)的一部分。它最初主要为广播电视领域设计,用于在不可靠的传输环境(如卫星、电缆、IP 网络)中实现稳定的多媒体数据传输,后来在 IPTV、网络流媒体(如 HLS 协议中 TS 作为分片文件格式)等领域也得到了广泛应用。

二、TS协议结构

TS(Transport Stream,传输流),一种常见的视频封装格式,是基于MPEG-2的封装格式(所以也叫MPEG-TS),后缀为.ts

2.1 TS的分层结构

TS文件分为三层,如下所示(可以倒序看更好理解):

  • TS层(Transport Stream):在PES层基础上加入了数据流识别信息和传输信息。一个ts视频文件含有多个ts单元包。
  • PES层(Packet Elemental Stream):在ES层基础上加入时间戳(PTS/DTS)等信息。每个ts单元含有一个pes头+多个es包。
  • ES层(Elementary Stream):压缩编码后的音视频数据。

如下图所示,xB表示字节数不确定,4B表示字节数为4个

在这里插入图片描述

2.2 TS层

  • TS传输流,是由固定⻓度的包组成,含有独⽴时间基准的⼀个或多个节⽬,适⽤于误码较多的环境,并且从流的任意⼀段开始都可以独⽴解码。PS(Program Stream):节⽬流,PS流与TS流的区别在于,PS流的包结构是可变⻓度,⽽TS流的包结构是固定⻓度。

  • ts包大小固定为188字节,ts层分为三个部分:ts header、adaptation field、payload。

  • ts header固定4个字节;每188字节单元就有一个ts header。

  • adaptation field可能存在也可能不存在,主要作用是给不足188字节的数据做填充。

  • payload是 PES 数据,或者PAT,PMT等。PAT、PMT是解析ts寻找音视频流很重要的表。

ts Header + adaptation field 格式如下:

在这里插入图片描述

2.2.1 TS Header

TS Header格式如下:

字段名称 位宽 说明
sync_byte 8bit 同步字节,固定为0x47
transport_error_indicator 1bit 传输错误指示符,表明在ts头的adapt域后由一个无用字节,通常都为0,这个字节算在adapt域长度内
payload_unit_start_indicator 1bit 负载单元起始标示符,一个完整的数据包开始时标记为1
transport_priority 1bit 传输优先级,0为低优先级,1为高优先级,通常取0
pid 13bit pid值(Packet ID号码,唯一的号码对应不同的包)
transport_scrambling_control 2bit 传输加扰控制,00表示未加密
adaptation_field_control 2bit 是否包含自适应区, ‘00’ 保留; ‘01’ 为无自适应域,仅含有效负载; ‘10’ 为仅含自适应域,无有效负载; ‘11’ 为同时带有自适应域和有效负载。
continuity_counter 4bit 递增计数器,从0 - f,起始值不一定取0,但必须是连续的

PID信息非常关键,它直接表征本次TS包的用途。比较重要的是PAT和PMT。

  • 常用的PID值:
PID取值 PID值使用描述
0x0000 节目关联表(program association table, PAT)
0x0001 条件访问表(conditional access table, CAT)
0x0002 传送流描述表(transport stream description table, TSDT)
0x0003~0x000F 保留
0x0010~0x1FFE 可以分配为network PID, Program map PID, elementary PID, 或其它
0x1FFF 空包(8191)
  • ts 层的内容是通过 PID 值来标识的,主要内容包括:PAT 表、PMT 表、⾳频流、视频流。
  • 解析 ts 流要先找到 PAT 表,只要找到 PAT 就可以找到 PMT,然后就可以找到⾳视频流了。
  • PAT 表的和 PMT 表需要定期插⼊ ts 流,因为⽤户随时可能加⼊ ts 流,这个间隔⽐较⼩,通常每隔⼏个视频帧就要加⼊ PAT和 PMT。
  • PAT 和 PMT 表是必须的,还可以加⼊其它表如 SDT(业务描述表)等,不过 hls 流只要有PAT 和 PMT 就可以播放了。

不同类型的表有不同的作用:

  1. PAT 表:主要的作⽤就是指明了 PMT 表的 PID 值。
  2. PMT 表:主要的作⽤就是指明了⾳视频流的 PID 值。
  3. ⾳频流/视频流:承载⾳视频内容。

2.1.2 Adaptation field

  • 在MPEG-2 TS中,为了传送打包后长度不足188B的不完整TS,或者为了在系统层插入节目时钟参考(program clock reference, PCR),需要在TS包中插入可变字节的调整字段。

  • 调整字段其中一个重要作用是解决编解码器的音视频同步问题。一般在视频帧中的TS包的调整字段中,每隔一定传输时间,传送系统时钟27MHz的一个抽样值给接收机,作为解码器解码时的时钟参考信息PCR。

  • PCR通常每隔100ms至少被传输一次。PCR的数值所表示的是解码器在读完这个抽样值的最后那个字节时,解码器本地时钟所应处的状态。通常情况下,PCR不直接改变解码器的本地时钟,而是作为参考基准来调整本地时钟,使之与PCR趋于一致。

字段名称 位宽 说明
Adaptation_field_length 8b 其数值指示的是之后数据长度
Discontinuity_indicator 1b 1代表当前TS包不连续状态为真
Random_access_indicator 1b 为1时表明下一个相同PID的包应该含有PTS和原始访问点
Elementrary_stream_priority_indicator 1b 为1时表明比相同PID包的优先级高
PCR_flag 1b 为1时代表调整字段中含有PCR(节目时钟参考,用于恢复与编码端一致的时钟顺序),其结构尚未列出(下同)
OPCR_flag 1b 为1时代表调整字段中含有OPCR。
Splicing_point_flag 1b 为1时代表调整字段中存在拼接点splice_countdown
Transport_private_data_flag 1b 为1时代表调整字段中存在至少一个私有数据
Adapatation_filed_extension_flag 1b 为1时代表存在调整字段的扩展

⾃适应区的⻓度要包含传输错误指示符标识的⼀个字节。pcr 是节⽬时钟参考,pcr、dts、pts 都是对同⼀个系统时钟的采样值,pcr 是递增的,因此可以将其设置为 dts 值,⾳频数据不需要 pcr。如果没有字段,ipad 是可以播放的,但 vlc ⽆法播放。打包 ts 流时 PAT 和 PMT 表是没有 adaptation field 的,不够的⻓度直接补 0xff 即可。视频流和⾳频流都需要加 adaptation field,通常加在⼀个帧的第⼀个 ts包和最后⼀个 ts 包⾥,中间的 ts 包不加。

如下图所示:

在这里插入图片描述

2.1.3 payload

前边提到了PAT和PMT,它们都是PSI之一(节目专用信息(Program Special Information, PSI)。MPEG-2 TS传送的TS包携带两类信息:

  1. 已压缩的音视频(PES)
  2. 与之相关的符号化表(PSI),由传送包PES的PID来标识。

如果是PSI,那么payload内容为PAT表结构、PMT表结构;如果为音视频,那么payload内容为PES包。

PAT 格式如下表

字段名称 位宽 说明
table_id 8b PAT表固定为0x00
section_syntax_indicator 1b 固定为1
zero 1b 固定为0
reserved 2b 固定为11
section_length 12b 后面数据的长度
transport_stream_id 16b 传输流ID,固定为0x0001
reserved 2b 固定为11
version_number 5b 版本号,固定为00000,如果PAT有变化则版本号加1
current_next_indicator 1b 固定为1,表示这个PAT表可以用,如果为0则要等待下一个PAT表
section_number 8b 固定为0x00
last_section_number 8b 固定为0x00
开始循环
program_number 16b 节目号为0x0000时表示这是NIT,节目号为0x0001时,表示这是PMT
reserved 3b 固定为111
PID 13b 节目号对应内容的PID值
结束循环
CRC32 32b 前面数据的CRC32校验码

在这里插入图片描述

PMT 格式如下表

字段名称 位宽 说明
table_id 8b PMT表取值随意,0x02
section_syntax_indicator 1b 固定为1
zero 1b 固定为0
reserved 2b 固定为11
section_length 12b 后面数据的长度
program_number 16b 频道号码,表示当前的PMT关联到的频道,取值0x0001
reserved 2b 固定为11
version_number 5b 版本号,固定为00000,如果PAT有变化则版本号加1
current_next_indicator 1b 固定为1
section_number 8b 固定为0x00
last_section_number 8b 固定为0x00
reserved 3b 固定为111
PCR_PID 13b PCR(节目参考时钟)所在TS分组的PID,指定为视频PID
reserved 4b 固定为1111
program_info_length 12b 节目描述信息,指定为0x000表示没有
开始循环
stream_type 8b 流类型,标志是Video还是Audio还是其他数据,h.264编码对应0x1b,aac编码对应0x0f,mp3编码对应0x03
reserved 3b 固定为111
elementary_PID 13b 与stream_type对应的PID
reserved 4b 固定为1111
ES_info_length 12b 描述信息,指定为0x000表示没有
结束循环
CRC32 32b 前面数据的CRC32校验码

在这里插入图片描述

  • 程序在读取N环的时候会读取该节目所有的码流列表及其PID,解析的时候可以根据PID来分离。
  • N环描述符包括的信息如下图所示。节目时钟参考PCR的PID和视频的PID是相等的。
  • 由PAT得出所有的节目列表,选定收看的节目后,筛选出等于该节目PID的TS包,就可以得到该节目的所有码流的PID映射表,这样接收机就可以只接收PID等于该节目的码流的TS包即可收看该节目。

在这里插入图片描述

2.2 pes 层:Packet Elemental Stream

pes 层是在每⼀个视频/⾳频帧上加⼊了时间戳等信息,pes 包内容很多,这⾥只留下最常⽤的。

pes 层格式如下图:
在这里插入图片描述

pes 层内容如下表:

字段名称 位宽 说明
pes start code 3B 开始码,固定为0x000001
stream id 1B 音频取值(0xc0 - 0xdf),通常为0xc0
视频取值(0xe0 - 0xef),通常为0xe0
pes packet length 2B 后面pes数据的长度,0表示长度不限制,
只有视频数据长度会超过0xffff
flag 1B 通常取值0x80,表示数据不加密、无优先级、备份的数据
flag 1B 取值0x80表示只含有pts,取值0xc0表示含有pts和dts
pes data length 1B 后面数据的长度,取值5或10
pts 5B 33bit值
dts 5B 33bit值
  • pts 是显示时间戳、dts 是解码时间戳,视频数据两种时间戳都需要,⾳频数据的 pts 和 dts 相同,所以只需要 pts。

  • 有 pts 和 dts 两种时间戳是 B 帧引起的,I 帧 和 P 帧的 pts 等于 dts。如果⼀个视频没有B 帧,则 pts 永远和 dts 相同。从⽂件中顺序读取视频帧,取出的帧顺序和 dts 顺序相同。dts 算法⽐较简单,初始值 + 增量即可,pts 计算⽐较复杂,需要在 dts 的基础上加偏移量。

  • ⾳频的 pes 中只有 pts(同 dts),视频的 I、P 帧两种时间戳都要有,视频 B 帧只要 pts(同 dts)。

  • 打包 pts 和 dts 就需要知道视频帧类型,但是通过容器格式我们是⽆法判断帧类型的,必须解析 h.264内容才可以获取帧类型。

举例说明:

.          I P B B B P
读取顺序: 1 2 3 4 5 6
dts 顺序: 1 2 4 5 6 3
pts 顺序: 1 2 3 4 5 6

点播视频 DTS 算法:
dts = 初始值 + 90000 / video_frame_rate

  • 初始值可以随便指定,但是最好不要取 0。
  • video_frame_rate 就是帧率,比如 23、30。
  • pts 和 dts 是以 timestamp 为单位的,1s = 90000 time scale,一帧就应该是 90000/video_frame_rate 个 timescale。
  • 用一帧的 timescale 除以采样频率就可以转换为一帧的播放时长。

点播音频 DTS 算法:
dts = 初始值 + (90000 * audio_samples_per_frame) / audio_sample_rate

  • audio_samples_per_frame 这个值与编解码相关,aac 取值 1024,mp3 取值 1158。
  • audio_sample_rate 是采样率,比如 24000、41000。
  • AAC 一般解码出来是每声道 1024 个 sample,也就是说一帧的时长为 1024/sample_rate 秒。所以每帧时间戳依次为 0, 1024/sample_rate, …, 1024*n/sample_rate 秒。

注: 直播视频的 dts 和 pts 应该直接用直播数据流中的时间,不应该按公式计算。

2.3 es 层:Elementary Stream

es 层指的就是⾳视频数据。这⾥只介绍 h.264 视频和 aac ⾳频。

2.3.1 h.264 视频

  • 打包 h.264 数据时必须给视频数据加上⼀个 nalu(Network Abstraction Layer Unit),nalu 包括nalu header 和 nalu type,nalu header 固定为 0x00000001(帧开始)或 0x000001(帧中)。

  • h.264 的数据是由 slice 组成的,slice 的内容包括:视频、sps、pps 等。nalu type 决定了后⾯的h.264 数据内容。

0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|F|NRI| TYPE |
+-+-+-+-+-+-+-+-+
  • F:1bit,forbidden_zero_bit,h.264 规定必须取 0。
  • NRI:2bits,nal_ref_idc,取值为 0~3,指示这个 nalu 的重要性,I 帧、sps、pps 通常取 3,P 帧常取 2,B 帧通常取 0
  • Type:5bits,取值如下表所示:
nal_unit_type 说明
0 未使用
1 非IDR图像片,IDR指关键帧
2 片分区A
3 片分区B
4 片分区C
5 IDR图像片,即关键帧
6 补充增强信息单元(SEI)
7 SPS序列参数集
8 PPS图像参数集
9 分解符
10 序列结束
11 码流结束
12 填充
13~23 保留
24~31 未使用

打包 es 层数据时 pes 头和 es 数据之间要加⼊⼀个 type=9 的 nalu,关键帧 slice 前必须要加⼊type=7 和 type=8 的 nalu,⽽且是紧邻的。如下图所示:

在这里插入图片描述

2.3.2 aac⾳频

打包aac⾳频必须加上⼀个adts(Audio Data Transport Stream)头,共7Byte,adts包括fixed_header和variable_header两部分,各28bit。

fixed_header

字段名称 位宽 说明
syncword 12b 固定为0xfff
id 1b 0表示MPEG-4,1表示MPEG-2
layer 2b 固定为00
protection_absent 1b 固定为1
profile 2b 取值0~3,1表示aac
sampling_frequency_index 4b 表示采样率,0: 96000 Hz,1: 88200 Hz,2: 64000 Hz,3: 48000 Hz,4: 44100 Hz,5: 32000 Hz,6: 24000 Hz,7: 22050 Hz,8: 16000 Hz,9: 12000 Hz,10: 11025 Hz,11: 8000 Hz,12: 7350 Hz
private_bit 1b 固定为0
channel_configuration 3b 取值0~7,1: 1 channel: front-center,2: 2 channels: front-left, front-right,3: 3 channels: front-center, front-left, front-right,4: 4 channels: front-center, front-left, front-right, back-center
original_copy 1b 固定为0
home 1b 固定为0

variable_header

字段名称 位宽 说明
syncword 12b 固定为0xfff
id 1b 0表示MPEG-4,1表示MPEG-2
layer 2b 固定为00
protection_absent 1b 固定为1
profile 2b 取值0~3,1表示aac
sampling_frequency_index 4b 表示采样率,0: 96000 Hz,1: 88200 Hz,2: 64000 Hz,3: 48000 Hz,4: 44100 Hz,5: 32000 Hz,6: 24000 Hz,7: 22050 Hz,8: 16000 Hz,9: 12000 Hz,10: 11025 Hz,11: 8000 Hz,12: 7350 Hz
private_bit 1b 固定为0
channel_configuration 3b 取值0~7,1: 1 channel: front-center,2: 2 channels: front-left, front-right,3: 3 channels: front-center, front-left, front-right,4: 4 channels: front-center, front-left, front-right, back-center
original_copy 1b 固定为0
home 1b 固定为0

更多资料:https://github.com/0voice


网站公告

今日签到

点亮在社区的每一天
去签到