MPEG-TS 封装格式详解

MPEG-TS 封装格式详解

简介

MPEG-TS一种标准数据容器格式,传输与存储音视频、节目与系统信息协议数据,应用于数字广播系统,譬如DVB,ATSC与IPTV。传输流在MPEG-2第1部分系统中规定,正式称为ISO / IEC标准13818-1或ITU-T建议书。

MPEG2/DVB是一种多媒体传输、复用技术,在数字电视广播中可提供数百个节目频道。复用的含义是,可以同时传输多层节目。MPEG-TS 主要应用于实时传送的节目,比如实时广播的电视节目。MPEG-TS 格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。简单地说,如果 DVD 上的 VOB 文件数据部分损坏了,就会导致整个文件无法解码,而电视节目是任何时候打开电视机都能解码的。

注意,DVB全称为Digital Video Broadcasting,包括不同的系统,如卫星数字电视广播系统,有线数字电视广播系统,地面开路数字电视广播系统,交互式数字电视广播系统以及数字电视加扰系统。DVB系统标准是一种全球数字电视技术的标准。如何定义广播中的比特流语法与句法,以实现在比特流中复用数字音频与视频,欧洲的DVB采用数字视频压缩MPEG-2标准,该标准是定义比特流的语法与句法的一个ISO/IEC标准,即13818-1标准。DVB系统的核心技术是采用MPEG-2技术进行视频、音频的编码,使用统一的MPEG-2传输流(TS流)。

MPEG-2标准中,有两种不同的码流输出到信道,一种是节目码流(PS: Program Stream),适用于没有传输误差的场景;一种是传输流(TS:Transport Stream),适用于有信道噪声的传输场景。节目流设计用于合理可靠的媒体,如光盘(如DVD),而传输流设计用于不太可靠的传输,即地面或卫星广播。此外,传输流可以携带多个节目。

MPEG-2 system(编号13818-1)是MPEG-2标准的其中一部分,该部分描述了多个视频,音频和数据多种基本流(ES)合成传输流(TS)和节目流(PS)的方式。

基本概念

  • ES(Elementary Stream):基本码流,包含音频、视频、数据的连续码流。直接从编码器出来的数据流,可以是编码过的视频数据流(H.264、MJPEG等),音频数据流(AAC),或其他编码数据流的统称。ES流经过PES打包器之后,被转换成PES包。

  • PES(Packet Elementary Stream):ES形成的分组称为PES分组,是用来传递ES的一种数据结构。PES流是ES流经过PES打包器处理后形成的数据流,在这个过程中完成了将ES流分组、打包、加入包头信息(主要加入了PTS/DTS信息)等操作(对ES流的第一次打包)。PES流的基本单位是PES包,PES包由包头和payload组成。每个PES包的PID是一致的,一个PES包可能由若干个TS包组成。

  • TS(Transport Stream):传输流,固定长度188字节。TS在PES层上加入了数据流识别和传输的必要信息,是对PES的重新封装。TS含有独立的一个或者多个program,一个program又可以包含多个视频,音频和文字信息的ES流。

TS 文件格式

一个 .ts 文件实际上由多个 ts packet 组成,每个 ts packet 大小固定为 188 Bytes。可以是AAC、H264、 PAT、PMT等。每个TS都有PID。

ts 层分为三个部分:ts header、adaptation field、payload。ts header 固定 4 个字节;adaptation field 可能存在也可能不存在,主要作用是给不足 188 字节的数据做填充;payload 是 pes 数据。188-4-adaptation field 就是payload的大小。

在这里插入图片描述

ts文件分为三个层次:ts层、pes层、es层。es层就是音视频数据,pes层是在音视频数据上加了时间戳等数据帧的说明信息,ts层是在pes层上加入了数据流识别和传输的必要信息。

ts 层的内容是通过 PID 值来标识的,主要内容包括:PAT 表、PMT 表、音频流、视频流。解析 ts 流要先找到 PAT 表,只要找到 PAT 就可以找到 PMT,然后就可以找到音视频流了。PAT 表的和 PMT 表需要定期插入 ts 流,因为用户随时可能加入 ts 流,这个间隔比较小,通常每隔几个视频帧就要加入 PAT 和 PMT。PAT 和 PMT 表是必须的,还可以加入其它表如 SDT(业务描述表)等,不过 HLS 流只要有 PAT 和 PMT 就可以播放了。

  • PAT 表:主要的作用就是指明了 PMT 表的 PID 值。
  • PMT 表:主要的作用就是指明了音视频流的 PID 值。
  • 音频流/视频流:承载音视频内容。

在这里插入图片描述

ES流打包成PES流:

在这里插入图片描述

PES流打包成TS流:

在这里插入图片描述

PSI(Program Specific Information)

PSI(节目特定信息)表用来描述传送流的组成结构。

PSI信息由四种类型的表组成,包括节目关联表(PAT,Program Association Table),节目映射表(PMT,Program Map Table),条件接收表(CAT,Conditional Access Table),网络信息表(NIT,Network Infomation Table)。

结构名 PID 值 描述
PAT 0x0000 解析 .ts 文件的第一步就是找到 PAT 表,然后获取 PMT 表的 PID 值
PMT 在 PAT 中给出 根据 PMT 表找到 audio pes packet 和 video pes packet 的 PID 值
CAT 0x0001 将一个或多个专用EMM流分别与唯一的PID相关联,描述了TS流的加密方式
NIT PAT 中给出 描述整个网络,如多少个TS流,频点和调制方式等

其中,PAT与PMT两张表帮助我们找到该传送流中的所有节目与流。PAT告诉我们,该TS流由哪些节目组成,每个节目的节目映射表PMT的PID是什么;而PMT告诉我们,该节目由哪些流组成,每一路流的类型与PID是什么。CAT与NIT暂时不考虑。

节目关联表(PAT,Program Association Table)

PAT 层次图:

在这里插入图片描述

各字段解释:

字段 类型 描述
table_id 8b 固定为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校验码

PAT 句法图:

在这里插入图片描述

节目映射表(PMT,Program Map Table)

PMT 层次图:

在这里插入图片描述

各字段解释:

字段 类型 描述
table_id 8b PMT表取值随意
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校验码

PMT 句法图:

在这里插入图片描述

实例

在这里插入图片描述

举个例子,你找个一个TS包,它的PID是0,说明它的负载内容是PAT信息,解析PAT信息,你发现节目1的PMT表的PID是0x10,接着,你在比特流中寻找一个PID为0x10的TS包,它的负载内容是节目1的PMT表信息,解析该PMT信息,你可以发现第一路流是MPEG2音频流,PID号0x21,第二路流是MPEG2视频流,PID号是0x22,第三路流是DVB字幕流,PID号是0x23,解析完毕,凡是比特流中PID号为0x22的TS包,所负载的内容为MPEG2视频流,把这些包一个一个找出来,把其中的有效码流一部分一部分的拼接起来,然后送给解码器去解码。

注意,就一般的视频流而言,只要拼接成一个完整的PES包,就可以送出去给解码器,然后再继续拼接下一个PES包。

TS Header

TS 包的包头提供关于传输方面的信息,大小固定为 4 字节。

TS Header 的结构如下:

在这里插入图片描述

以下是各字段的详细解释:

  1. sync_byte(8bits):同步字节,是包中的第一个字节,固定为 0x47,表示后面是一个 TS 分组(注:后面包中的数据不会出现 0x47 的),用于建立发送端和接收端包的同步。
  2. transport_error_indicator(1bit):传输错误标志位,为 1 表示在相关的传输包中至少有一个不可纠正的错误位。当被置 1 后,在错误被纠正之前不能重置为 0。
  3. payload_unit_start_indicator(1bit):负载起始标识,针对不同的负载,有不同的含义。
    • PES:置为 1,标识 TS 包的有效载荷以 PES 包的第一个字节开始,即此 TS 包为 PES 包的起始包,且此 TS 分组中有且只有一个 PES 包的起始字段;置为 0,表示 TS 包不是 PES 包的起始包,是后面的数据包。
    • PSI:置为 1,表示 TS 包中带有 PSI 数据分段的第一个字节,即这个 TS 包是 PSI Section 的起始包,则此 TS 包的负载的第一个字节带有 pointer_field,用来指示 PSI 数据在 payload 中的位置;置为 0,表示 TS 包不带有 PSI Section 的第一个字节,即此 TS 包不是 PSI 的起始包,即在有效负载中没有 pointer_filed,有效负载的开始就是 PSI 的数据内容。对于空包,payload_unit_start_indicator 应该置为 0。
      比如:若 TS 包载荷为 PAT,则当接收到 TS 包的 payload_unit_start_indicator 为 1 时,表明这个 TS 包包含了 PAT 头信息,从这个包里面解析出 section_length 和 continuity_counter,然后继续收集后面的 payload_unit_start_indicator = 0 的 TS 包,并判断 continuity_counter 的连续性,不断读出 TS 包中的净载荷(也就是 PAT 数据),用 section_length 作为收集 TS 包结束条件。
  4. transport_priority(1bit):传输优先标志,为 1 表明当前 TS 包的优先级比其他具有相同 PID,但此位没有被置 1 的 TS 包高。
  5. transport_priority(1bit):传输优先标志,为 1 表明当前 TS 包的优先级比其他具有相同 PID,但此位没有被置 1 的 TS 包高。
  6. PID(13bits):指示有效负载中数据的类型。PID 是识别 TS 包的重要参数,用来识别 TS 包所承载的数据。在 TS 码流生成时,每一类业务(视频,音频,数据)的基本码流均被赋予一个不同的识别号 PID,解码器借助于 PID 判断某一个 TS 包属于哪一类业务的基本码流。标准中定义的 PID 分配见如下表:
PID 值 描述
0x0000 节目关联表(program association table, PAT)
0x0001 条件访问表(conditional access table, CAT)
0x0002 传送流描述表(transport stream description table, TSDT)
0x0003~0x000F 保留
0x0010~0x1FFE 自由分配
0x1FFF 空包
  1. transport_scrambling_control(2bits):有效负载加密模式标志,00 表示未加密。如果传输包包头中包括调整字段,不应被加密。其他取值含义是用户自定义的。

  2. adaption_field_control(2bits):调整字段标志,表示此 ts 首部是否跟随调整字段和负载数据。占 2bits,字段值含义如下:

    • 00:保留;
    • 01:表示无调整字段,只有有效负载数据;
    • 10:表示只有调整字段,无有效负载数据;
    • 11:表示有调整字段,且其后跟随有效负载数据;
  3. continuity_counter(4bits):循环计数器,用于对传输误码进行检测。在发送端对所有的包都做 0~15 的循环计数,起始值不一定是 0。在接收终端,如发现循环计数器的值有中断,表明数据在传输中有丢失。

代码实现:

typedef struct MPEGTS_FIXED_HEADER
{
	/* byte 0 */
	unsigned sync_byte : 8; // 同步字节,值为 0x47

	/* byte 1, 2 */
	unsigned transport_error_indicator : 1; // 传输错误指示位,置 1 时,表示传送包中至少有一个不可纠正的错误位
	unsigned payload_unit_start_indicator : 1; // 负载单元起始指标位,针对不同的负载,有不同的含义
	unsigned transport_priority : 1; // 传输优先级,表明该包比同个 PID 的但未置位的 TS 包有更高的优先级
	unsigned PID : 13; // 该 TS 包的 ID 号,如果净荷是 PAT 包,则 PID 固定为 0x00

	/* byte 3 */
	unsigned transport_scrambling_control : 2; // 传输加扰控制位
	unsigned adaptation_field_control : 2; // 自适应调整域控制位,分别表示是否有调整字段和负载数据
	unsigned continuity_counter : 4;// 连续计数器,随着具有相同 PID 的 TS 包的增加而增加,达到最大时恢复为 0
	/* 如果两个连续相同 PID 的 TS 包具有相同的计数,则表明这两个包是一样的,只取一个解析即可。 */
} MPEGTS_FIXED_HEADER; // MPEG-TS 包头占 4 字节

调整字段(adaptation field)

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

当 TS Header 的 adaption_field_control 字段的第一个比特位是 1 时,说明该 TS packet 有调整字段(adaptation field)。

调整字段包括对较高层次的解码功能有用的相关信息,调整字段的格式基于采用若干标志符,以表示该字段的某些特定扩展是否存在。调整字段由调整字段长度、不连续指示器、随机存取器、PCR标志符、基本数据流优先级指示器、拼接点标志符、传送专用数据标志、调整字段扩展标志以及有相应标志符的字段组成。

adaptation field 结构如下:

字段 大小 描述
adaptation_field_length 8 bit 调整字段长度
discontinuity_indicator 1 bit 不连续指示器,一般为 0
random_access_indicator 1 bit 随机存取器,一般为 0
elementary_stream_priority_indicator 1 bit 基本数据流优先级指示器,一般为 0
PCR_flag 1 bit PCR标志符,携带 pcr 时置 1
OPCR_flag 1 bit OPCR标志符,一般为 0
splicing_point_flag 1 bit 拼接点标志符,一般为 0
transport_private_data_flag 1 bit 传送专用数据标志,一般为 0
adaptation_field_extension_flag 1 bit 调整字段扩展标志,一般为 0
PCR 40 bit 当 PCR_flag=1 时携带
stuffing_bytes 不定 填充字节,取值0xff

针对不同的 ts payload,adaptation field 的应用方式也不同:

  • 针对 PAT、PMT,不足 188 Bytes 的部分直接使用 0xff 进行填充,而不会使用 adaptation field(但是也有例外,有的编码器会携带)。
  • 针对 PES packet,才会使用 adaptation field 做填充。
    • audio PES packet 不会在 adaptation field 中携带 PCR 字段。
    • video PES packet 可以选择是否在 adaptation field 中携带 PCR 字段。一般 PES packet 被拆分时,会在第一个和最后一个拆分包添加 adaptation field。第一个拆分包的 adaptation field 才会携带 pcr 时钟,且主要作用是为了携带 pcr 时钟,而不是为了填充数据;最后一个拆分包的 adaptation field 不会携带 pcr 时钟,只做填充用。

PCR 属于编码端的时钟,其作用是如果编码端时钟源与解码端时钟源不同步,那么解码端应该采用 pcr 作为自己的时钟源,以同步编码端。

例如编码端时钟是解码端的 2 倍,解码端是正常的物理时钟,这时一个物理世界 5min 的视频,因为编码端时钟源走得太快,那么最后一个视频帧的 dts 就是 10min。播放端直接播放的话,就会播放 10min,显得播放得很慢。所以播放端需要加快播放,方法就是采用 pcr 时钟作为自己的时钟源,让自己的时钟走得跟编码端一样快,这样看起来就是正常速度播放了。

注意,adaptation field 最少占用 1 个字节,即 adaptation_field_length 字段,这样最少可以填充 1 个字节。

adaptation field 层次图:

在这里插入图片描述

adaptation field 句法图:

在这里插入图片描述

PES(Packet Elemental Stream)

每个 pes packet 都包含一个完整的视频帧或音频帧,pes packet 结构如下:

  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  | pes header |   optional pes header    |      pes payload    |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      6 Byte           3~259 Byte              max 65526 Byte

PES 层次图:

在这里插入图片描述

PES 句法图:

在这里插入图片描述

pes header

6 Bytes 固定的 PES Header 结构如下:

字段 大小 描述
packet_start_code_prefix 3 比特 起始码,固定为 0x000001
stream_id 1 比特 PES 包中的负载流类型。音频取值(0xc0-0xdf),通常为0xc0;视频取值(0xe0-0xef),通常为0xe0
PES_packet_length 2 比特 PES 包长度,包括此字段后的可选包头和负载的长度。0表示长度不限制,只有视频数据长度会超过0xffff

optional pes header

optional pes header 可选包头中的控制信息有很多,这里我们只给出与 pts、dts 有关的结构:

字段 大小 描述
PTS_DTS_flags 2 bit 10 表示 PES 头部有 PTS 字段,11 表示有 PTS 和 DTS 字段,00 表示都没有,10 被禁止
pts 40 bit 实际 pts 长度占用 33 bit
dts 40 bit 实际 dts 长度占用 33 bit

PTS(显示时间戳)和 DTS(解码时间戳),是用来音视频同步的。DTS/PTS是相对SCR(系统参考)的时间戳,是以 90000 为单位,PTS/DTS 到 ms 的转换公式是 PTS/90,系统时钟频率为 90Khz,所以转换到秒为 PTS/90000。

PTS 和 DTS 字段的长度为 40 bit,实际中间有 7 个填充位,有效长度为 33 bit。

在这里插入图片描述

ES(Elementary Stream)

es 层指的就是音视频数据。

以视频数据为 H.264 格式,音频数据为 AAC 格式为例:

video:
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |   start code    | nalu header |          h264 data            |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         4 byte          1 byte               x byte
audio:
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  | adts header |                     aac data                    |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      7 byte                           x byte

关于 H.264 的详细介绍:H.264 压缩与编解码原理

关于 AAC 的详细介绍:AAC 格式详解

实例:TS 封装过程

一个 PAT 包含整个 TS 流的信息,其中里面有一张表,比较重要的两个属性 program_number 和program_map_PID,可能出现多对,每一对 program_number 表示一个节目,而与该 program_number 对应的 program_map_PID 则表示该节目对应的流信息应该放在一个 PMT 表中,而该 PMT 表的 PID 应该与这里的 program_map_PID 相等。

一个PMT中描述了流的类型,其中0x0f表示AAC音频,而0x1b表示H264视频,除这两种之外还有其他流,例如字幕。elementay_PID表示该流的数据应该存放在以该PID为表示的TS包中。

  +-+-+-+-+-+-+-+-+-+-+-+
  | PAT                 | 
  |                     |
  | program_number  5   |___
  | program_map_PID 10  |   |
  |                     |   |
  | program_number  6   |___|__  
  | program_map_PID 11  |   |  |
  |                     |   |  |  
  | program_number  7   |   |  |   
  | program_map_PID 12  |   |  |
  |                     |   |  |
  |         ...         |   |  |
  |                     |   |  |
  +-+-+-+-+-+-+-+-+-+-+-+   |  |
                            |  |
  +-+-+-+-+-+-+-+-+-+-+-+   |  |
  | PMT                 |   |  |
  | TS Header PID = 10  |<——   |
  |                     |      |
  | stream_type    0x0f |______|__________________0x0f表示AAC音频,下方AAC数据打包PID=20,   
  | elementary_PID 20   |      |
  | stream_type    0x1b |______|__________________0x1b表示H264视频,下方H264数据打包PID=22 
  | elementary_PID 22   |      |
  |                     |      |  
  +-+-+-+-+-+-+-+-+-+-+-+      |
                               |
  +-+-+-+-+-+-+-+-+-+-+-+      |
  | PMT                 |      | 
  | TS Header PID = 11  |<————— 
  |                     |
  | stream_type    0x0f |   
  | elementary_PID 23   |
  | stream_type    0x1b |
  | elementary_PID 24   |
  |                     |  
  +-+-+-+-+-+-+-+-+-+-+-+

音频数据打包过程:

裸ACC数据:
  +-+-+-+-+-+-+-+-+-+-+-+
  |         AAC         |          
  +-+-+-+-+-+-+-+-+-+-+-+
添加PES头的ACC数据:
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  | AAC PES |         AAC         |          
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
添加TS头将PES分割之后的TS包,假设正好分割成2个TS包,包大小固定188字节,不够用adaptation域填充一般填充0xFF:
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |TS | AAC PES |  AAC 1  |TS | adaptation|    AAC 2    |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |- - - - Packet 1 - - - |- - - - - Packet 2 - - - - - |
  <假设 PID = 20 的TS包>            

视频数据打包过程:

裸H264数据,一帧:
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |              H264             |          
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
添加PES头之后的H264数据,一帧表示一个PES包:
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  | H264 PES|           H264                |          
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
将一个PES包分割之后,分别添加TS头之后的TS包。
这里假设分割成3个TS包,每个包固定大小188字节(包含TS包头在内),
最后一个包不够188字节使用adaptaion域填充0xFF:
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |TS | H264 PES| H264 1|TS |  H264 2     |TS | adaptation|  H264 3 |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |- - - Packet 1 - - - |- - Packet 2 - - | - - - - Packet 3 - - - -|
  <假设 PID = 22 的TS包>

现在回头看下面这个是不是有些头绪了。

在这里插入图片描述

参考

  1. https://www.cnblogs.com/moonwalk/p/16200434.html
  2. https://blog.csdn.net/leek5533/article/details/104993932/
  3. https://www.cnblogs.com/jimodetiantang/p/9140808.html
  4. https://zhuanlan.zhihu.com/p/612042998
  5. https://blog.csdn.net/Kayson12345/article/details/81266587
  6. https://www.cnblogs.com/lvyunxiang/p/15792678.html
  7. https://blog.csdn.net/u012117034/article/details/124881444
  8. https://blog.csdn.net/michaeluo/article/details/75263462
  9. TS协议解析第四部分(adaptation field)
  10. https://blog.csdn.net/m0_60259116/article/details/125451635
  11. https://www.cnblogs.com/jimodetiantang/p/9146855.html

相关推荐

  1. ts + websocket封装

    2024-06-06 23:22:02       29 阅读
  2. ts封装浏览器indexedDB

    2024-06-06 23:22:02       11 阅读
  3. 封装请求头内容格式

    2024-06-06 23:22:02       37 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-06 23:22:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-06 23:22:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-06 23:22:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-06 23:22:02       20 阅读

热门阅读

  1. vue 常用的 UI 框架及表格

    2024-06-06 23:22:02       16 阅读
  2. 【Git】在错误分支上开发了怎么办

    2024-06-06 23:22:02       9 阅读
  3. 服务器硬件基础知识

    2024-06-06 23:22:02       9 阅读
  4. Sass详解

    2024-06-06 23:22:02       8 阅读
  5. 从handle得到GraphicBuffer

    2024-06-06 23:22:02       10 阅读
  6. 云计算面试题

    2024-06-06 23:22:02       7 阅读
  7. 赶紧收藏!2024 年最常见 20道 Kafka面试题(十)

    2024-06-06 23:22:02       10 阅读
  8. 详细分析Vue3中的卡槽知识点(附Demo)

    2024-06-06 23:22:02       10 阅读