ffmpeg——TS流解析

article/2025/10/9 10:51:04

RTSP(Real Time Streaming Protocol),实时流传输协议,是TCP/IP协议体系中的一个应用层协议,该协议定义了一对多应用程序如何有效地通过IP网络传送多媒体数据。RTSP在体系结构上位于RTP和RTCP之上,它使用TCP或UDP完成数据传输。

实时传输协议RTP(Real-time Transport Protocol)是一个网络传输协议,RTP协议详细说明了在互联网上传递音频和视频的标准数据包格式。

将TS/PS的解析文件定义在libavformat/mpegts.c文件中
将音频、视频的解码定义在libavcodec/mpeg12.c文件中

  1. MPEG2-TS的demuxer函数
AVInputFormat ff_mpegts_demuxer = {.name           = "mpegts",.long_name      = NULL_IF_CONFIG_SMALL("MPEG-TS (MPEG-2 Transport Stream)"),.priv_data_size = sizeof(MpegTSContext),.read_probe     = mpegts_probe,   //分析是三种TS格式的哪一种.read_header    = mpegts_read_header,//读数据头信息,比如在ts流当中的数据包大小,还ts流中的节目信息,//sdt表,pmt表,video pid,audio pid等等,以便后面读数据时使用。   .read_packet    = mpegts_read_packet,.read_close     = mpegts_read_close,.read_timestamp = mpegts_get_dts,.flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,.priv_class     = &mpegts_class,
};

该结构通过av_register_all函数注册到ffmpeg的主框架中,通过mpegts_probe函数来检测是否是TS流格式,然后通过 mpegts_read_header函数找到一路音频流和一路视频流(注意:在该函数中没有找全所有的音频流和视频流),最后调用 mpegts_read_packet函数将找到的音频流和视频流数据提取出来,通过主框架推入解码器。

  1. 解析流中的TS格式
/** 出现3种格式,主要原因是:* TS标准是 188Bytes;* 日本标准是192Bytes的DVH-S格式;* 第三种的 204Bytes则是在188Bytes的基础上,加上16Bytes的FEC(前向纠错).*/#define TS_DVHS_PACKET_SIZE 192
#define TS_FEC_PACKET_SIZE 204
#define TS_PACKET_SIZE 188mpegts_probe,   //分析是三种TS格式的哪一种
  1. MPEG2-TS头解析
static int mpegts_read_header(AVFormatContext *s)
{MpegTSContext *ts = s->priv_data;AVIOContext *pb   = s->pb;pos = avio_tell(pb);//保存流的当前位置,便于检测操作完成后恢复到原来的位置len = avio_read(pb, buf, sizeof(buf));//从pb中读入一段流到bufts->raw_packet_size = get_packet_size(buf, len);//主要是调用analyze,获得ts包的类型ts->auto_guess = 0;if (s->iformat == &ff_mpegts_demuxer){
//挂载解析SDT表的回调函数到ts->pids变量上,这样在handle_packet函数中根据对应的pid找到对应处理回调函数。mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1);// 向ts->pids中注册pid为SDT_PID的packet的回调函数//同上,只是挂上PAT解析的回调函数mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1);// 向ts->pids中注册pid为PAT_PID的packet的回调函数
//探测一段流,便于检测出SDT,PAT,PMT表handle_packets(ts, probesize / ts->raw_packet_size);//打开add pes stream的标志,这样在handle_packet函数中发现了pes的pid,就会自动建立该pes的stream。ts->auto_guess = 1;}seek_back(s, pb, pos);//恢复到检测前的位置。
}

对mpegts_open_section_filter:
这里写图片描述

就是struct MpegTSContext;中有NB_PID_MAX(8192)个TS的Filter,
而每个struct MpegTSFilter,可能是PES的Filter,或者是Section的Filter。

MpegTSContext::auto_guess /* if true, all pids are analyzed to find streams /
为1时,则在handle_packet的函数中只要发现一个PES的pid就建立该PES的stream
auto_guess主要作用是用来在TS流中没有业务信息时,如果被设置成了1的话,那么就会将任何一个PID的流当做媒体流建立对应的PES数据结构。
在mpegts_read_header函数的过程中发现了PES的pid,但是不建立对应的流,只是分析PSI信息。相关的代码见handle_packet函数的下面的代码:

handle_packet(MpegTSContext *ts, const uint8_t *packet) 
{MpegTSFilter *tss;tss = ts->pids[pid];if (ts->auto_guess && !tss && is_start) {add_pes_stream(ts, pid, -1);//若auto_guess为1,建立所有的pid的流tss = ts->pids[pid];}
}
pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{MpegTSContext *ts = filter->u.section_filter.opaque;for (;;) {sid = get16(&p, p_end);pmt_pid = get16(&p, p_end);pmt_pid &= 0x1fff;MpegTSFilter *fil = ts->pids[pmt_pid];program = av_new_program(ts->stream, sid);//创建一个AVProgramif (program) {program->program_num = sid;program->pmt_pid = pmt_pid;}if (!ts->pids[pmt_pid])mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1);//打开pmt_pid对应的filteradd_pat_entry(ts, sid);//在ts->prg中增加一个programadd_pid_to_pmt(ts, sid, 0); // add pat pid to programadd_pid_to_pmt(ts, sid, pmt_pid);在ts中找到节目好为sid的节目,再将pmt_pid增加到该节目的pid中
}
pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{MpegTSContext *ts = filter->u.section_filter.opaque;for (;;) {stream_type = get8(&p, p_end);pid = get16(&p, p_end)  & 0x1fff;if (ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES) {pes = ts->pids[pid]->u.pes_filter.opaque;if (!pes->st) {pes->st     = avformat_new_stream(pes->stream, NULL);  //创建pes对应的AVStreamif (!pes->st)goto out;pes->st->id = pes->pid;}st = pes->st;//st为pes的AVStream}if (pes && !pes->stream_type)mpegts_set_stream_info(st, pes, stream_type, prog_reg_desc);//设置上面新建的AVStream的参数add_pid_to_pmt(ts, h->id, pid);//将pid增加到pmt中av_program_add_stream_index(ts->stream, h->id, st->index);设置AVProgram的stream_index
}
  1. MPEG2-TS的包处理
    handle_packets函数在两个地方被调用,一个是mpegts_read_header函数中,另外一个是mpegts_read_packet函数中,被mpegts_read_header函数调用是用来搜索PSI业务信息,nb_packets参数为探测的ts包的个数;在mpegts_read_packet函数中被调用用来搜索补充PSI业务信息和demux PES流,nb_packets为0,0不是表示处理的包的个数为0。
static int handle_packets(MpegTSContext *ts, int64_t nb_packets)
{ts->stop_parse = 0;
//该变量指示一次handle_packets处理的结束。在mpegts_read_packet被调用的时候,如果发现完一个PES的包,则
//ts->stop_parse = 1,则当前分析结束。packet_num = 0;for (;;){packet_num++;read_packet(s, packet, ts->raw_packet_size, &data);//根据sync_byte(0x47),读入一个ts包datahandle_packet(ts, data);//处理一个ts包}
}

可以说handle_packet是mpegts.c代码的核心,所有的其他代码都是为这个函数准备的。
在调用该函数之前先调用read_packet函数获得一个ts包(通常是188bytes),然后传给该函数,packet参数就是TS包。

static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
{MpegTSFilter *tss;int len, pid, cc, expected_cc, cc_ok, afc, is_start, is_discontinuity,has_adaptation, has_payload;const uint8_t *p, *p_end;int64_t pos;pid = AV_RB16(packet + 1) & 0x1fff;//获得该包的PIDif (pid && discard_pid(ts, pid))return 0;is_start = packet[1] & 0x40;//是否位pes或section的开头,即payload_unit_start_indicatortss = ts->pids[pid];//ts->auto_guess在mpegts_read_header函数中被设置为0,也就是说在ts检测过程中是不建立pes stream的。if (ts->auto_guess && !tss && is_start) {//如果ts->auto_guess为1,则所有的pid都会去分析,寻找pesadd_pes_stream(ts, pid, -1);tss = ts->pids[pid];}//在mpegts_read_header函数中,调用handle_packet函数只是处理TS流的业务信息,
//因为并没有为对应的PES建立tss,所以tss为空,直接返回。if (!tss)return 0;ts->current_pid = pid;afc = (packet[3] >> 4) & 3;//adaptation_field_control若位0,表示将来用,无效if (afc == 0) /* reserved value */return 0;has_adaptation   = afc & 2;has_payload      = afc & 1;is_discontinuity = has_adaptation &&packet[4] != 0 && /* with length > 0 */(packet[5] & 0x80); /* and discontinuity indicated *//* continuity check (currently not used) */cc = (packet[3] & 0xf);expected_cc = has_payload ? (tss->last_cc + 1) & 0x0f : tss->last_cc;cc_ok = pid == 0x1FFF || // null packet PIDis_discontinuity ||tss->last_cc < 0 ||expected_cc == cc;tss->last_cc = cc;if (!cc_ok) {av_log(ts->stream, AV_LOG_DEBUG,"Continuity check failed for pid %d expected %d got %d\n",pid, expected_cc, cc);if (tss->type == MPEGTS_PES) {PESContext *pc = tss->u.pes_filter.opaque;pc->flags |= AV_PKT_FLAG_CORRUPT;}}p = packet + 4;//p到达负载if (has_adaptation) {int64_t pcr_h;int pcr_l;if (parse_pcr(&pcr_h, &pcr_l, packet) == 0)tss->last_pcr = pcr_h * 300 + pcr_l;/* skip adaptation field */p += p[0] + 1;}/* if past the end of packet, ignore */p_end = packet + TS_PACKET_SIZE;if (p >= p_end || !has_payload)return 0;pos = avio_tell(ts->stream->pb);if (pos >= 0) {av_assert0(pos >= TS_PACKET_SIZE);ts->pos47_full = pos - TS_PACKET_SIZE;}//在开始时,ts->pids中,只有PAT 和 SDT的 pid Filter不是null,因此其它的数据全部抛弃,
//只处理PAT 和 SDT packet中的数据if (tss->type == MPEGTS_SECTION) {//表示当前的TS包包含一个新的业务信息段if (is_start) {/* pointer field present */len = *p++;if (len > p_end - p)return 0;if (len && cc_ok) {//ts包包含了两个section的内容
/*这个时候TS的负载有两个部分构成:1)从TS负载开始到pointer field字段指示的位置;2)从pointer field字段指示的位置到TS包结束1)位置代表的是上一个段的末尾部分。2)位置代表的新的段开始的部分。下面的代码是保存上一个段末尾部分数据,也就是1)位置的数据。 *//* write remaining section bytes */write_section_data(ts, tss, p, len, 0); /* check whether filter has been closed */if (!ts->pids[pid])return 0;}p += len;if (p < p_end) {write_section_data(ts, tss,  p, p_end - p, 1); //保留新的段数据,也就是2)位置的数据。}} else {if (cc_ok) {write_section_data(ts, tss,p, p_end - p, 0);//保存段中间的数据。}}} else {//正常的PES数据的处理int ret;// Note: The position here points actually behind the current packet.if (tss->type == MPEGTS_PES) {if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start,   pos - ts->raw_packet_size)) < 0) //pes类型return ret;}}return 0;
}
write_section_data(AVFormatContext *s, MpegTSFilter *tss1, const uint8_t *buf, int buf_size, int is_start)//将数据写入到对应的pid Filter中的uint8_t *section_buf; 中

以PAT为例子,在static int mpegts_read_header(AVFormatContext *s)中,将static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) 函数赋值给 PAT_PID Filter的section_cb,因此,此处调用这个函数,处理写入到section_buf中的数据。

http://blog.chinaunix.net/uid-24322243-id-2620178.html
http://blog.csdn.net/u013354805/article/details/51546511
http://blog.csdn.net/xiruanliuwei/article/details/28167757
http://blog.csdn.net/hjksfw900/article/details/3784821


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

相关文章

网页视频下载(TS流下载合成)

前言 最近《流浪地球》比较火&#xff0c;想找资源下载看看&#xff0c;无奈只找到了网址 http://m.tlyy.tv/【现已变成不良网站】 &#xff0c;但是我的chrome插件也嗅探不到网页上的视频。。于是乎&#xff0c;右击页面&#xff0c;inspect 走起… 步骤 首先发现 m3u8文件…

TS流分析

一 从TS流开始 数字电视机顶盒接收到的是一段段的码流&#xff0c;我们称之为TS&#xff08;Transport Stream&#xff0c;传输流&#xff09;&#xff0c;每个TS流都携带一些信息&#xff0c;如Video、Audio以及我们需要学习的PAT、PMT等信息。因此&#xff0c;我们首先需要了…

ts流中的时间概念: pcr,pts,dts 实例解说

ts流中的时间概念: pcr,pts,dts 实例解说 ---------------------------------------- PCR OPCR ---------------------------------------- ts流包头4字节,第5字节为适配域长度,若不为0&#xff0c;第六字节为适配域标志. 适配域有5个标志&#xff0c;这里先说两个,节目参考时钟…

TS流解析【PCR】自己的总结

http://www.cnblogs.com/ztteng/articles/3166025.html http://blog.csdn.net/liuhongxiangm/article/details/8981032 http://blog.sina.com.cn/s/blog_6b94d5680101ton7.html http://blog.csdn.net/jl2011/article/details/47044647 二.TS流包含的内容 一段TS流&#xf…

ES流、PES流、PS流和TS流介绍

流媒体系统结构 整个传输过程为&#xff1a;音视频数据分别通过图像声音编码器打包成ES&#xff08;elemental stream 基本数据流&#xff09;&#xff0c;在通过PES打包器打包成PES&#xff08;packet elemental stream分组的基本数据流&#xff09;&#xff0c;之后通过PS复用…

TS流基本知识【HI3798 AVPLAY播放TS流】

目录 一、TS流相关知识 1.1 TS流、PS流、PES流和ES流都是什么&#xff1f; 1.2 TS流是如何产生的&#xff1f; 1.3TS流的格式 二、从TS流到PAT、PMT 2.1 PAT表&#xff08;Program Association Table&#xff0c;节目关联表&#xff09; 2.1.1PAT表的描述&#xff08;表…

TS流

TS流的健壮性很好&#xff0c;所以适合用在无线视频传输。但是&#xff0c;TS流一帧数据的格式较为复杂&#xff0c;所以需要有优秀的分析工具。 比如&#xff0c;EasyICE。&#xff08;此软件仅供非商业使用&#xff0c;而且每次开打都需要联网验证是否是最新版本&#xff09…

ts流格式

1.ts简介 ts流最早应用于数字电视领域&#xff0c;其格式非常复杂包含的配置信息表多大十几个&#xff0c;视频格式主要是mpeg2。苹果公司发明的http live stream流媒体是基于ts文件的&#xff0c;不过他大大简化了传统的ts流&#xff0c;只需要2个最基本的配置表PAT和PMT&…

ts流格式详解

ts介绍 ts文件为传输流文件&#xff0c;视频编码主要格式h264/mpeg4&#xff0c;音频为acc/MP3。 ts文件分为三层&#xff1a;ts层Transport Stream、pes层 Packet Elemental Stream、es层 Elementary Stream. es层就是音视频数据&#xff0c;pes层是在音视频数据上加了时间戳…

MPEG-2 TS流结构浅析

一、概述 MPEG-2是MPEG&#xff08;Moving Picture Experts Group&#xff0c;运动图像专家组&#xff09;组织制定的视频和音频有损压缩标准之一&#xff0c;它的正式名称为“基于数字存储媒体运动图像和语音的压缩标准”。MPEG-2标准是在1994年11月为数字电视而提出来…

RTSP中TS流结构分析

RTSP中TS流结构分析 UDP数据包整体结构RTP Header结构TS Header结构PAT结构PMT结构PES Header结构ES层Wireshark抓取TS包 UDP数据包整体结构 在使用UDP传输TS流时&#xff0c;整个数据包结构如下&#xff1a; RTP Header结构 RTP结构如下图&#xff1a; 各字段的含义如下&…

TS流理论分析

TS&#xff08;Transport Stream&#xff09;流由TS包组成&#xff0c;而每个TS包的⻓度&#xff1a;固定为188 Bytes或204 Bytes&#xff0c;204 Bytes⻓度是在188Bytes后⾯增加了16 Bytes的CRC校验数据。 ts 层的内容是通过 PID 值来标识的&#xff0c;主要内容包括&#xff…

TS流详细解析

1、PAT表的TS包 0x47&#xff1a;包头识别符 Sync_code 0x40 0x00&#xff1a;0100 0000 0000 0000 0b&#xff1a;transport_error_Indicator 为1的包丢弃 1b&#xff1a;payload_unit_start_indicator是否忽略头部后的第一个字节 0b&#xff1a;transport_priority 传输优先级…

ts 流基础(白话讲解).

---------------------------------------- author: hjjdebug date: 2022年 09月 27日 星期二 ---------------------------------------- ts 流就是188个字节构成的流数据. 先来点最简单的. ts 头部&#xff0c;4字节 ts 流是47开头的,以188字节为单位的打包流&#xff0…

什么是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…