ts 流基础(白话讲解).

article/2025/10/9 13:18:32

----------------------------------------
author: hjjdebug
date:     2022年 09月 27日 星期二
----------------------------------------

ts 流就是188个字节构成的流数据.
先来点最简单的. ts 头部,4字节
ts 流是47开头的,以188字节为单位的打包流,由4字节包头及包体构成.
4字节第一个4字节为47.第2,3个字节为包id,占低位13个bit,故最多8192个包id, 第4各字节是计数器占低4bit.
包ID 是标明包身份的,以后慢慢会熟悉起来,连续计数器是用来判断是否有丢包的,正常同id的包是依次向上加1.
这就是最基本的认知了

要想搞清头部,再说说第2byte的前3bit,
最高位bit7, error bit, 表示该包是否出错,出错当然应该扔掉了.
次高位bit6, 叫syntax_indicatior, 该位以后会讲到,不同的包类型会对它分别置0或置1.
bit5, 是表示该包的重要性的.
再说说第4byte 的高4bit,
最高2bit是加扰控制, 00为未加扰,其它用户定义
次2bit为适配域,00:保留,01:无适配域有负载,10:有适配域无负载,11:有适配域有负载

于是用c语言可以定义出下面一个结构: ts_header
typedef struct
{
    uint8_t sync_byte; /*0x47*/
    uint16_t transport_error_indicator : 1;
    uint16_t payload_unit_start_indicator : 1;        //负载开始标记
    uint16_t transport_priority : 1;
    uint16_t PID : 13;
    uint8_t transport_scrambling_control : 2;
    uint8_t adaptation_field_control : 2;
    uint8_t continuity_counter : 4;  
} __attribute__((packed)) ts_header;
第5个字节是适配域长度,然后后边的字节是适配域. 无适配域此值为0.
至于适配域都包含什么内容,以后再说. 先说无适配域的情况。从第6个字节开始。

要想播出节目,ts流中除了要包含音频流,视频流这些基础流外,还要包含其它一些信息。
这些信息专业名词叫PSI/SI, (节目专有信息/服务信息),
那么什么是节目专有信息呢(program specific information)?
PAT,PMT,CAT,NIT这4个表是节目专有信息 , 节目播放所必须
服务信息是由其它表构成的,例如SDT,EIT,TDT等,这些是附加信息。

各种表一般都对应的是一个table表头,后面是表体.
table表头由1byte tableid,及2bytes 长度构成,长度占低12位,意味着表不会超过4K大小
后边的数据归入本表.
那长度前面的4bit 又是什么意思呢? 用途不大,看后面定义. 这样讲清了table表的前3byte
长度之后的后5bytes分别是扩展表id 2byte,version_number,section_number,last_section_number
版本号 version_number 的意思是,以pat表为例,当pat表变化时, version_number 会改变
section_number,last_section_number 用来表达pat 表是否已经被收完整了. 这样就占掉了8个字节
后面的数据用表体来解释.


用c可如下定义了table_header
struct table_header
{
    uint8_t table_id;
    uint16_t section_syntax_indicator : 1;        //格式标记,pat,pmt 都为1,标记section 开始?
    uint16_t private_bit : 1;
    uint16_t reserved : 2;
    uint16_t section_length : 12;                //节的长度
    uint16_t table_id_ext;                        //扩展的id
    uint8_t reserved1 : 2;
    uint8_t version_number : 5;                    //版本号
    uint8_t current_next_indicator : 1;            //当前,下一个标记
    uint8_t section_number;                        // 节号及最后的节号
    uint8_t last_section_number;                //对应到流中的字节,后面除crc外,只在内存中存在
};

还好,这些表头的格式各种表是一致的
开头8bytes, tableID(1)+len(2)+表头(5),及crcbyte, 中间为表体.

--------------------------------------------------------
那么什么是PAT呢?(pragram association table) 节目关联表.
--------------------------------------------------------
这个表用来描述ts流中由几套节目,节目的pmt_id 是多少.
这个表的13bits pid 固定为0,8bits tableID 固定为0,播放节目都是从搜pat开始的。
前面20个pid 都是被固定分配好的,都成标准了,不能随便定义了,这里先介绍pid固定为0的pat
ts 流中可能有一套节目,也可能有多套节目。
这个pat表头就是从第6byte 开始的. 当然pmt表头也是从第6字节开始.此为后话。
从第6字节开始,

我们给一个实例分析:
47 40 00 10 00 00 B0 0D 00 01 C1 00 00 00 01 F0
00 2A B1 04 B2

47 40 00 10:
47 同步头
40 00: 13bitpid 为0, 前面3bit代表

:transport_error_indicatior(1),payload_unit_start(1),transport_priority(1)

第4byte含义trasport_scramling(2),adaption_field_ctrol(2),continuity_counter(4)
10: 不加扰,有负载,计数值为0
00 适配域长度为0

下面就是pat表数据了

其数据结构定义如下:

PAT数据结构
program_association_section()
{
    table_id;//8位固定为0x00,表示该表是PAT表
    section_syntax_indicator;//1,段语法标志位,固定为1
    '0';//1,固定为0 为了防止和ISO13818Video流格式中的控制字冲突而设置的
    reserved;//2,保留位,一般都是1,这样前4位就是B
    section_length;//12,段的大小,表示这个字节后面有用的字节数,包括CRC32.假如后面的字节加上前面的字节数少于188,后面会用0xFF填充,假如这个数值比较大,则PAT会分成几部分来传输。
    transport_stream_id;//16该传输流的ID,区别于一个网络中其他多路复用的流
    reserved;//2
    version_number;//5,范围0-31,表示PAT的版本号,标注当前节目的版本,这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经改变了,程序必须重新收索节目
    current_next_indicator;//1,表示发送的PAT是当前有效还是下一个PAT有效
    section_number;//8,分段的号码,PAT可能分为多个段传输,第一段为00,以后每个分段加1,最大可能有256个分段
    last_section_number;//8,最后一个分段的号码
    for(i=0;i<N;i++)
    {
        program_number;//16,节目号
        reserved;//3
        if(program_number=='0')
        {
            network_PID;//13,网络信息表(NIT)的PID,网络信息表提供了该物理网络的一些信息,和电视台相关的,
        }
        else
        {
            program_map_PID//13,节目映射表的PID,节目号大于0时对应的PID,每个节目对应一个
        }
        CRC_32;//32,CRC32校验码
    }
}

下面来分析具体数据:

00 B0 0D:
00 tableid
B0 0D: 数据长度12bits,B的含义'1011' 必需要这样写,代表section_syntax_indicator 为1,保留位11
00 01 c1 00 00: 5数据解释,扩展id及3个number
00 01 是扩展id, 也有叫transport_stream_id?
c1 是,reserved1(2bit),version_number(5)=0, current_next_indicator((1)
00 00, section_number 和last_section_number 都是0,在本节就把表数据表示完了.

循环体数据从pat偏移8字节开始,每4bytes为1组

00 01 F0 00
前16个bit为节目号,后13bit 为pmt_pid, 当节目号为0时, 后13bit 时nit pid, 本码流没有nit信息
此时的pmt_pid为0x1000

我看到有人写代码, 当判定是PAT表时(PID=0),直接从buffer[15],buffer[16]拿PMT的PID, 真是简单直接啊,省掉了一大堆没有啥用途的东西!. PAT主要就是干这个的.

2A B1 04 B2: 为crc32
讲清了pat, 再来看什么是pmt
--------------------------------------------------------
什么是PMT(pragram mat table) 节目映射表
--------------------------------------------------------
回顾pat 它告诉了我们有几套节目,每套节目的pmt表id是多少.
pmt 会告诉我们该套节目包含哪些基础流,及基础流的相关信息. lets go!

其数据结构定义如下:

PMT数据结构:

TS_program_map_section()
{
    table_id; // 8 固定为0x02,表示该表是PMT
    section_syntax_indicator; //1 段语法标志位,固定为1
    '0';//1
    reserved;//2
    section_length; //12 表示这个字节后面有用的字节数,包括CRC32。假如后面的字节加上前面的字节数少于188,后面会用0XFF填充。假如这个数值比较大,则PMT会分成几部分来传输。
    program_number; //16 节目号,表示该PMT对应的节目号
    reserved;// 2
    version_number; //5范围0-31,表示PMT的版本号,标注当前节目的版本,这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经改变了,程序必须重新收索节目
    current_next_indicator;//1表示发送的PMT是当前有效还是下一个PAT有效
    section_number; // 8 分段的号码固定为0x00
    last_section_number;//8最后分段的号码 固定为0x00
    reserved;//3
    PCR_PID; //13 PCR(节目时钟参考)所在TS分组的PID,根据PID可以去搜索相应的TS分组,解出PCR信息。
    reserved; //4
    program_info_length; //12该节目的信息长度,在此字段之后可能会有一些字节描述该节目的信息
    for (i=0; i<N; i++)
    {
        descriptor();
    }
    for (i=0;i<N1;i++)
    {
        stream_type;//8 指示了PID为elementary_PID的PES分组中原始流的类型,比如视频流,音频流等
        reserved; //3
        elementary_PID;//13 该节目中包括的视频流,音频流等对应的TS分组的PID
        reserved; //4
        ES_info_length;//12 该节目相关原始流的描述符的信息长度
        for (i=0; i<N2; i++)
        {
            descriptor();
        }
    }
}

上个例子数据吧.
47 50 00 10 00 02 B0 1D 00 01 C1 00 00 E1 00 F0
00 1B E1 00 F0 00 0F E1 01 F0 06 0A 04 65 6E 67
00 8D 82 9A 07
//有了上面的基础,下面拣重要的叙述
47 50 00 10: pid 是0x1000, pmt pid
00 : 适配域长度为0
02 B0 1D: tableid 02, 长度0x1d, 正好把数据分完 ,  PMT_TID = 0x02  buffer[7]是loop 长度
00 01 c1 00 00: 扩展id 2bytes,,这里的扩展id实际是节目号, version号0,current_next_indicator(1), sec_num:00, last_sec_num:00,一个表搞定.
最末4byte为crc, 中间为私有数据
E1 00 : 低13bits 是PCR_PID = 0x100                有人直接从buffer[13],buffer[14]取PCR_PID
F0 00 : 低12bits 是节目信息长度,为0                buffer[15],buffer[16]为额外信息长度,可以跳过
然后进入循环体:

1B : 流类型, H.264/14496-10 video (MPEG-4/AVC)  (0x1B,0x02 都是视频流)
E1 00 : 低13bit 为基础流id = 0x100
F0 00 : 低12bit 为描述符长度 = 0

0F : 流类型 ,     STEAM_TYPE_ADTS_AUDIO = 0x0F,  (0x03,0x04,0x06,0x0F都是音频流)
E1 01 : 基础流id=0x101
F0 06 : 描述符长度为6,
0A 04 65 6E 67 00

0A 是一个标签,代表语言 _(ISO_639_language, 0x0A)
04 为标签长度,后面是描述字符串. "eng" 代表英文

有了这两个表,就可以找到基础流了,至于其它表例如sdt等,告诉你节目叫什么名字等,并不是必需的,但有时也是需要的


参考: 1. tsanalyse     代码(github)
参考: 2. tsinfo     代码(ubuntu source)
参考: 3. ISO/IEC 13818-1 标准

参考图1:pat 表

 参考图2: pmt 表


http://chatgpt.dhexx.cn/article/v9C4QU3C.shtml

相关文章

什么是TS流?

前言 什么是TS流&#xff1f; 百度说&#xff1a;transport stream&#xff08;传送流&#xff09;简称TS流&#xff0c;是根据ITU-T Rec.H.222.0|ISO/IEC 13818-2 和ISO/IEC 13818-3协议定义的一种数据流&#xff0c;防止有可能发生严重错误时进行一道或多道程序编码数据的传…

hls之m3u8、ts流格式详解

2019独角兽企业重金招聘Python工程师标准>>> HLS&#xff0c;Http Live Streaming 是由Apple公司定义的用于实时流传输的协议&#xff0c;HLS基于HTTP协议实现&#xff0c;传输内容包括两部分&#xff0c;一是M3U8描述文件&#xff0c;二是TS媒体文件。 1、M3U8文件…

TS流概述(ES流-基本流,PES流-打包基本码流,PS流-节目流,TS流-传输流)

一、TS流概述 ES流(Elementary Stream&#xff0c;基本流)&#xff1a;数字电视各组成部分编码后所形成的直接表示基本元素内容的流&#xff0c;包含视频、音频或数据的连续码流。 PES流&#xff08;Paketized Elementary Stream&#xff0c;打包基本码流):是将基本的码流ES流…

网络流媒体(四)———TS流

1. 数字视频压缩MPEG-2标准 MPEG-2是MPEG&#xff08;Moving Picture Experts Group&#xff0c;运动图像专家组&#xff09;组织制定的视频和音频有损压缩标准之一&#xff0c;它的正式名称为“基于数字存储媒体运动图像和语音的压缩标准”。与MPEG-1标准相比&#xff0c;MPEG…

Segmentation笔记4-Boundary-Aware Network for Fast and High-Accuracy Portrait Segmentation

创新点 1.提出了BANet 2.提出了refine loss 总结 图片引起不适。。。 网络流程如下&#xff1a; 图片经过语义分支得到1/4大小的特征图。将其上采样到原图大小&#xff0c;c 1作为边界特征挖掘分支的边界注意力图。注意力图由BA loss监督。将原图与注意力图拼接&#xff…

diffusion medical image segmentation

1、Diffusion Models for Implicit Image Segmentation Ensembles code&#xff1a;https://github.com/JuliaWolleb/Diffusion-based-Segmentation 2、MedSegDiff: Medical Image Segmentation with Diffusion Probabilistic Model code: https://github.com/WuJunde/MedS…

weakly supervised semantic segmentation

Weakly Supervised Semantic Segmentation by Pixel-to-Prototype Contrast CVPR2022 北京大学 Though image-level weakly supervised semantic segmentation (WSSS) has achieved great progress with Class Activation Maps (CAMs) as the cornerstone, the large supervis…

16. Segmentation

Segmentation 1. Segmentation: Generalized Base/Bounds 我们可以看一下&#xff08;Figure 16.1&#xff09;&#xff0c;尽管每个CPU都有一对硬件寄存器&#xff08;base register和bounds register&#xff09;&#xff0c;但是还是不可避免的会产生内存浪费&#xff08;阴…

segmentation_models.pytorch实战:使用segmentation_models.pytorch图像分割框架实现对人物的抠图

文章目录 摘要二分类语义分割的常用做法数据集segmentation_models.pytorch简介与使用一、安装二、创建模型 训练测试总结 摘要 在前面的文章中&#xff0c;我提到过segmentation_models.pytorch语义分割框架&#xff0c;今天这篇文章向大家展示如何使用segmentation_models.p…

mac Segmentation Fault

今天跑SEDR的代码遇到一个很奇怪的错误&#xff0c;我已经定位到了错误的地方在于 这个很奇怪的一个错误&#xff0c;test_z的维度是(3460*28),很明显不是内存的问题&#xff0c;就很奇怪 后面看到这个 https://stackoverflow.com/questions/64841082/segmentation-fault-11-p…

QT SIGSEGV Segmentation fault

QT程序在运行时&#xff0c;出现崩溃。百思不得其姐&#xff0c;所以认真思考&#xff08;上网百度&#xff09;了一番&#xff0c;原来遇到此错误的不止我一人&#xff0c;故记录下来&#xff0c;以防下次再犯类似错误。 错误提示&#xff1a; Ssignal Received - Qt Creato…

Image Segmentation

先介绍几个概念,也是图像处理当中的最常见任务. 1. 语义分割(semantic segmentation) 2. 目标检测(object detection) 3. 目标识别(object recognition) 4. 实例分割(instance segmentation) 一、语义分割 首先需要了解一下什么是语义分割(semantic segmentation). 语义…

unable to execute command: Segmentation

编译时出错&#xff1a; clang: error:unable to execute command: Segmentation fault: 11 clang: error:linker command failed due to signal (use -v to see invocation) Architectures的debug改为NO就可以 以上方法不行&#xff1a; enable bitcode改成No。原因是第三方库…

Segmentation Fault错误原因总结

一、 什么是“Segmentation fault in Linux” 所谓的段错误就是指访问的内存超过了系统所给这个程序的内存空间&#xff0c;通常这个值是由gdtr来保存的&#xff0c;他是一个48位的寄存器&#xff0c;其中的32位是保存由它指向的gdt表&#xff0c;后13位保存相应于gdt的下标&am…

Segmentation Fault原因总结

转载链接&#xff1a;https://www.cnblogs.com/silence-hust/p/4487026.html 最近在项目上遇到了Segmentation Fault的错误&#xff0c;一直调试不出来是哪里出了问题&#xff0c;对于刚接触嵌入式的&#xff0c;也不知道该如何去调试一个项目&#xff0c;定位内存问题&#x…

segmentation fault 段错误解决方法

一、出现Segmentation Fault 1. 文件打开失败却使用了fclose()&#xff1b;fclose找不到指针fp。 解决方法&#xff1a; 当打开文件成功&#xff0c;即成功获得文件句柄后&#xff0c;再进行关闭句柄操作。 2. 文件正在写操作&#xff0c;异常断电、程序异常中断&#xff0c;导…

Segmentation-传统分割算法

“图像分割就是把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。它是由图像处理到图像分析的关键步骤。”---百度百科 本文将继续介绍常见的图像处理算法之图像分割算法,图像分割是从图像中找出目标所在的区域&#xff0c;把图像分成若干个特定的、…

图像分割(Segmentation)

文章目录 图像分割FCNU-NetSegNetDeepLab图像分割常用数据集 图像分割 图像分割是预测图像中每一个像素所属的类别或者物体。基于深度学习的图像分割算法主要分为两类&#xff1a; 语义分割&#xff08;Semantic Segmentation&#xff09; 为图像中的每个像素分配一个类别。 …

网站中木马病毒了怎么办

不少站长们辛辛苦苦的创建了一个网站&#xff0c;却由于安全维护措施做的不到位&#xff0c;最终导致网站中木马病毒&#xff0c;网站被跳转或无法打开等棘手情况&#xff0c;或点击进去是杂七杂八的灰色网站。若处理不及时&#xff0c;容易受到搜索引擎的惩罚&#xff0c;如官…