Miracast技术详解(三):RTP & MPEG2-TS

 发表于 2020-02-06 |  分类于 Miracast

Miracast音视频流概述

在上一篇文章中,我们已经成功完成RTSP能力协商与会话的建立,并准备开始音视频流的传输阶段。那么下一步,就是对音视频流进行解析,并将音视频展示给用户的过程。这样整个Miracast的流程就算分析完毕了。

先简单来总结下,在Miracast底层的实现中,是采用RTP协议对MPEG2-TS数据包进行封装,其中MPEG2-TS又同时封装了Audio和Video两种ES(Elementary Stream)。其中Audio格式一般为AAC,Video则为H.264。那么只要将RTP数据包解析成对应Audio和Video的裸流,那么在上层我们通过MediaCodec或FFmpeg进行解码,即可完成音视频的展示。

而这里的关键,就是如何把RTP的数据包解析出裸流。所以接下来我们会着重对RTP与MPEG2-TS格式进行详细的分析~

抓包准备

跟上篇博客类似,要分析RTP与MPEG2-TS的格式,最好的方法就是抓取RTP的数据包,并对照协议文档一个个字节进行分析。Android上可以采用tcpdump工具抓取UDP的包,然后通过Wireshark工具导入进行分析。在此之前,不要忘记需要在Analyze->Enabled Protocols中勾选RTP/RTCP包及MPEG相关的解析选项。

最终抓取到的数据包如下图所示,通过Wireshark的过滤功能我们可以很方便的过滤RTP协议的数据包:

​编辑

RTP

实时传输协议(Real-time Transport Protocol)是一个网络传输协议,此协议详细说明了在互联网上传递音频和视频的标准数据包格式。RTP协议常用于流媒体系统(配合RTSP协议),且一般情况下,RTP会搭配RTCP协议一起使用。如:WebRTC与Chromecast底层中的应用。

在通信过程中,音视频的数据是通过RTP包进行传输,RTCP主要用来做数据流控制,如发送/接收端的Report,还有丢包的统计与重传等等…(因为RTP是创建在UDP协议上的)

但经过多台手机的抓包测试,发现抓到的UDP数据中只包含了RTP数据包,而没有发现RTCP数据包,这也是我在测试中发现的非常不符合RTP使用标准的一个现象~ 具体的原因未知,在Miracast Native Sink端的源码中,是有关于RTP与RTCP的相关处理代码的。同时我也反编译了一些Miracast竞品的代码,发现也没有对RTCP进行处理。Anyway,我们这里就先不考虑RTCP的处理,先着重分析RTP数据包格式。

根据rfc3550标准定义,RTP的包头定义如下,在RTP包头之后的所有数据都归属于Payload:

1
2
3
4
5
6
7
8
9
10
11
12
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|  CC   |M|     PT      |       sequence number         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           synchronization source (SSRC) identifier            |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|            contributing source (CSRC) identifiers             |
|                             ....                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

由于包头都是标准的,因此解析起来没有啥问题。其中CC包含了CSRC数目,默认为0,也就代表着CSRC为空,前面12个字节一直到SSRC我们都可以通过标准包头解析出来。而后面的Payload数据,则全部属于MPEG2-TS数据包。

MPEG2-TS

MPEG2-TS传输流(MPEG-2 Transport Stream,又称MPEG-TS、MTS、TS)是一种传输和存储包含视频、音频与通信协议各种数据的标准格式,用于数字电视广播系统,如DVB、ATSC、ISDB、IPTV等等。其中1个TS承载多个子TS,通常子TS是分组化基本流(PES, Packetized elementary stream),分组化基本流上又承载着基本流(ES,Elementary Stream)。

TS分组

TS分组(TS Packet),长度固定为188字节,它是基本的传输单位。多个不同的ES的内容会分别被封装到TSP中通过同一个TS传输。每个TS分组以固定的同步字节起始,这个同步字节的值为0x47,它也是TS分组头的一部分。TS分组的固定头长度为4字节,其后为可选部分,为Payload或适配域。格式如下图所示:

​编辑

TS Packet包头各个字段及解释如下表:

名称比特数描述
同步字节( sync byte)8表示TS包的开头,值固定为0x47
传输错误指示位(Transport Error Indicator)1值为1时,表示在相关的传送包中至少有一个不可纠正的错误位
Payload单元开始指示位(Payload Unit Start Indicator)1该字段用来表示有效Payload中带有PES包或PSI数据,也代表一个完整的音视频数据帧的开始
传输优先级(Transport Priority)1值为1时,表示此包在相同PID的分组中具有更高的优先级
分组ID(PID)13用于识别TS分组的ID,音视频流分别对应不同的PID
传输加扰控制(Transport Scrambling control)2值为0时表示Payload未加密,Miracast中一般为0
适配域存在标志(Adaptation field exist)2表示在包头后面是否有适配域或Payload,其中1代表仅有载荷,2代表仅有适配域,3代表适配域和载荷都存在
连续性计数器(Continuity counter)4对于具有相同PID值的Payload而言,从0~15连续循环,用来检测是否有丢失的TS包

如下为PID=0x0的PAT包的Header示例:

1
2
3
4
5
6
7
8
9
10
ISO/IEC 13818-1 PID=0x0 CC=1
    Header: 0x47400011
        0100 0111 .... .... .... .... .... .... = Sync Byte: Correct (0x47)
        .... .... 0... .... .... .... .... .... = Transport Error Indicator: 0
        .... .... .1.. .... .... .... .... .... = Payload Unit Start Indicator: 1
        .... .... ..0. .... .... .... .... .... = Transport Priority: 0
        .... .... ...0 0000 0000 0000 .... .... = PID: Program Association Table (0x0000)
        .... .... .... .... .... .... 00.. .... = Transport Scrambling Control: Not scrambled (0x0)
        .... .... .... .... .... .... ..01 .... = Adaptation Field Control: Payload only (0x1)
        .... .... .... .... .... .... .... 0001 = Continuity Counter: 1

适配域

在MPEG2-TS中,为了传送打包后长度不足188B(包括包头)的不完整TS包,或者为了在系统层插入节目时钟参考PCR字段,需要在TS包中插入可变长字节的适配域。适配域包含对较高层次解码功能有用的相关信息,格式基于若干标识符,以表示该字段的某些特定扩展位是否存在。适配域的格式如上图Adaptation Field所示,各个字段及解释如下表:

名称比特数描述
适配域长度(Adaptation Field Length)8适配域的长度,单位为字节,不包含当前字节
不连续指示位(Discontinuity indicator)1如果根据连续性计数器或PCR计算,确认当前分组处于不连续状态,则取值为1
随机访问指示位(Random Access indicator)1如果当前分组是一个PES的起始,取值为1
ES优先级指示位(Elementary stream priority indicator)1取值为1时ES优先级更高
PCR标识(PCR flag)1取值为1时表示适配域中有PCR域
OPCR标识(OPCR flag)1取值为1时表示适配域中有OPCR域
接续点标识(Splicing point flag)1取值为1时表示适配域中有接续倒数计数器域
传输私有数据标识 (Transport private data flag)1取值为1时表示适配域中有私有数据域
适配域扩展标识(Adaptation field extension flag)1取值为1时表示适配域中有适配域扩展域
(可选)节目时钟参考(PCR,Program Clock Reference)33+6+9包括一个33比特的低精度部分(90kHz)+6位的填充部分+一个9比特的高精度部分(27MHz,取值为0-299)

PCR

其中适配域中的节目时钟参考(PCR,Program Clock Reference)使得解码后的内容可以正确地同步播放。PCR通常每隔100ms至少要被传输一次。我们可以从TS分组的适配域中得到特定节目的PCR值,PCR的PID由该节目的PMT中的PCR_PID域指定。

PCR在MPEG-2系统中是非常重要的,因为解码器中的视频和音频抽样时钟都锁定于与PCR所相同的本地时钟,也就是说,视频和音频解码过程能否正常进行,首先取决于解码器能否准确恢复PCR。解码系统应当基于PCR生成高精度的系统定时时钟(System Timing Clock,STC),用于同步声音ES和视频ES的内容。

如下为PID=PCR_PID的TS包头及适配域的情况,其中PCR Flag值为1,在其固定头后紧接着PCR的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ISO/IEC 13818-1 PID=0x1000 CC=0
    Header: 0x47500020
        0100 0111 .... .... .... .... .... .... = Sync Byte: Correct (0x47)
        .... .... 0... .... .... .... .... .... = Transport Error Indicator: 0
        .... .... .1.. .... .... .... .... .... = Payload Unit Start Indicator: 1
        .... .... ..0. .... .... .... .... .... = Transport Priority: 0
        .... .... ...1 0000 0000 0000 .... .... = PID: Unknown (0x1000)
        .... .... .... .... .... .... 00.. .... = Transport Scrambling Control: Not scrambled (0x0)
        .... .... .... .... .... .... ..10 .... = Adaptation Field Control: Adaptation Field only (0x2)
        .... .... .... .... .... .... .... 0000 = Continuity Counter: 0
    [MPEG2 PCR Analysis]
    Adaptation Field Length: 183
    Adaptation Field
        0... .... = Discontinuity Indicator: 0
        .0.. .... = Random Access Indicator: 0
        ..0. .... = Elementary Stream Priority Indicator: 0
        ...1 .... = PCR Flag: 1
        .... 0... = OPCR Flag: 0
        .... .0.. = Splicing Point Flag: 0
        .... ..0. = Transport Private Data Flag: 0
        .... ...0 = Adaptation Field Extension Flag: 0
        Program Clock Reference: 0x0000000084bbac4f
        Stuffing: ffffffffffffffffffffffffffffffffffffffffffffffff…

PID

表示TS Packet的数据类型,每一种PSI表和每个ES都对应一个PID值。这个PID十分重要,它是辨别码流信息的关键,也是节目信息的唯一标识。除PAT表包的PID永远是0外,还有2种包的PID是协议预留的:一是空包,它主要用作码流填充,PID是0x1FFF;二是条件访问表(CAT),其PID值总是1。PID的分配可使用如下表格进行总结:

PID值PID值用途
0x0000节目关联表(PAT,Program Association Table)
0x0001条件访问表(CAT,Conditional Access Table)
0x0003 ~ 0x000F保留
0x0010 ~ 0x1FFE可分配为network PID,PMT的PID,ES的PID等等…
0x1FFF空包

PSI

节目专用信息(PSI,Program Specific Information),描述特定节目相关的属性。MPEG-2标准规定了4种PSI:

  • 节目关联表(PAT,Program Association Table)
  • 节目映射表(PMT,Program Map Table)
  • 条件访问表(CAT,Conditional Access Table)
  • 网络信息表(NIT,Network Information Table)

其中MPEG-2标准规定了PAT和PMT的具体结构,而且在Miracast Sink端的源码中,也只是用到了PAT和PMT。因此,我们只需对这2种PSI进行分析即可。

PAT

节目关联表(PAT: Program Association Table)列出了该TS内所有节目,其PID固定为0x0000,一般在Miracast中Sink端收到的首包,就会包含PAT。PAT包的格式如下图所示:

​编辑

如下为PID=0x0的PAT包的Payload示例,其中比较重要的有Program编号与PID的映射关系表,如下编号为1的Program对应的PID为0x0100。拿到了Program的PID后,我们就可以根据PID找到对应的PMT:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
MPEG2 Program Association Table
    Table ID: Program Association Table (PAT) (0x00)
    1... .... .... .... = Syntax indicator: 1
    .011 .... .... .... = Reserved: 0x3
    .... 0000 0000 1101 = Length: 13
    Transport Stream ID: 0x0000
    11.. .... = Reserved: 0x3
    ..00 001. = Version Number: 0x01
    .... ...1 = Current/Next Indicator: Currently applicable
    Section Number: 0
    Last Section Number: 0
    Program 0x0001 -> PID 0x0100
        Program Number: 0x0001
        111. .... .... .... = Reserved: 0x7
        ...0 0001 0000 0000 = Program Map PID: 0x0100
    CRC 32: 0x2df65295 [unverified]
    [CRC 32 Status: Unverified]
PMT

节目映射表(PMT: Program Map Table)包含特定节目相关的信息(如:音频、视频ES流),每一个节目有一个PMT,包含特定节目的Program编号、PCR_PID、以及该节目对应的所有ES的PID。PMT包的格式如下图所示:

​编辑

如下为PID=0x0100的PMT包的Payload示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MPEG2 Program Map Table
    Table ID: Program Map Table (PMT) (0x02)
    1... .... .... .... = Syntax indicator: 1
    .011 .... .... .... = Reserved: 0x3
    .... 0000 0010 0001 = Length: 33
    Program Number: 0x0001
    11.. .... = Reserved: 0x3
    ..00 001. = Version Number: 0x01
    .... ...1 = Current/Next Indicator: Currently applicable (0x1)
    Section Number: 0
    Last Section Number: 0
    111. .... .... .... = Reserved: 0x7
    ...1 0000 0000 0000 = PCR PID: 0x1000
    1111 .... .... .... = Reserved: 0xf
    .... 0000 0000 0000 = Program Info Length: 0x000
    Stream PID=0x1011
        Stream type: AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC 14496-10 Video (0x1b)
        111. .... .... .... = Reserved: 0x7
        ...1 0000 0001 0001 = Elementary PID: 0x1011
        1111 .... .... .... = Reserved: 0xf
        .... 0000 0000 1010 = ES Info Length: 0x00a
        Descriptor Tag=0x28
        Descriptor Tag=0x2a
    Stream PID=0x1100
        Stream type: ISO/IEC 13818-7 Audio with ADTS transport syntax (0x0f)
        111. .... .... .... = Reserved: 0x7
        ...1 0001 0000 0000 = Elementary PID: 0x1100
        1111 .... .... .... = Reserved: 0xf
        .... 0000 0000 0000 = ES Info Length: 0x000
    CRC 32: 0x00fd72f1 [unverified]
    [CRC 32 Status: Unverified]

经过上述包格式的分析,我们可以得出以下重要信息:

  • 可以根据PAT中Program编号与PID的映射关系表,对比Program编号,值为0x0001与期望一致,是匹配的Program。
  • 紧接着我们可以得到PCR_PID的值为0x1000,后续只要收到PID为该值的TS包,则可以解析出PCR信息。
  • 最后,我们可以看到该PMT中包含2个ES流,PID分别为0x10110x1100,分别对应了H.264(0x1b)的视频流与AAC(0x0f)音频流。

PES

分组化基本流(PES, Packetized elementary stream)组合了多个音频与视频ES流,一个PES包其实就是一帧音视频。但一个TS包只有188B的大小,是不可能放下一帧数据的。所以如果我们要获得一帧完整的数据,就需要把连续几个TS包里的数据全部取出来,才能组合成一个PES包。那么我们怎么知道该从哪里开始到哪里结束是一个PES包呢?

前面TS分组章节我们分析了分组格式,里面有一个Payload Unit Start Indicator字段,值为1时代表一个完整的音视频数据包的开始。那么从这里开始,直到下一个值为1的包为止(相同PID的ES流),把所有的这些TS包组合起来就是一个PES包。

有关PES包的格式,如下图所示:

​编辑

在这个PES结构中,最重要的部分是解码时间标记DTS(Decode Time Stamp)播出时间标记PTS(Presentation Time Stamp)。有了DTS和PTS,解码器就可以从编码器传送的I、B与P帧中重建视频流。即DTS告诉解码器何时解码帧,而PTS则告诉解码器何时显示帧。

以下为PID=0x1011的某个视频PES包的示例:(已完成TS包的重新组装,总共11个TS包)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[11 Message fragments (1928 bytes): #1649(184), #1649(184), #1649(184), #1649(184), #1649(184), #1649(184), #1649(184), #1650(184), #1650(184), #1650(184), #1650(88)]
    [Frame: 1649, payload: 0-183 (184 bytes)]
    [Frame: 1649, payload: 184-367 (184 bytes)]
    [Frame: 1649, payload: 368-551 (184 bytes)]
    [Frame: 1649, payload: 552-735 (184 bytes)]
    [Frame: 1649, payload: 736-919 (184 bytes)]
    [Frame: 1649, payload: 920-1103 (184 bytes)]
    [Frame: 1649, payload: 1104-1287 (184 bytes)]
    [Frame: 1650, payload: 1288-1471 (184 bytes)]
    [Frame: 1650, payload: 1472-1655 (184 bytes)]
    [Frame: 1650, payload: 1656-1839 (184 bytes)]
    [Frame: 1650, payload: 1840-1927 (88 bytes)]
    [Message fragment count: 11]
    [Reassembled MP2T length: 1928]
MPEG TS Packet (reassembled)
Packetized Elementary Stream
    prefix: 000001
    stream: video-stream (0xe0)
PES extension
    length: 1922
    1... .... must-be-one: True
    .0.. .... must-be-zero: False
    scrambling-control: not-scrambled (0)
    .... 0... priority: False
    .... .1.. data-alignment: True
    .... ..0. copyright: False
    .... ...0 original: False
    1... .... pts-flag: True
    .0.. .... dts-flag: False
    ..0. .... escr-flag: False
    ...0 .... es-rate-flag: False
    .... 0... dsm-trick-mode-flag: False
    .... .0.. additional-copy-info-flag: False
    .... ..0. crc-flag: False
    .... ...0 extension-flag: False
    header-data-length: 5
PES header data: 2101c5c1a9
    presentation time stamp (PTS): 82.559511111 seconds
PES data: 0000000141ea0138738cc32a650a996299f6299c847d3f3d…

其中pts-flag: True,我们可以从PES header data前5个字节取出PTS,剩下的字节则为PES data,也就是一帧裸流数据。 剩下的工作就是把视频流数据送到应用层做解码,然后展示,整个过程结束~

总结

从RTP数据包解析出音视频的裸流,主要经过以下几个步骤:

  • 解析RTP固定12字节头,取出其后的Payload数据(MPEG2-TS包)
  • 以188B的大小裁剪出N个TS包
  • 解析TS包,查找PID=0的PAT包并解析,得到PMT的PID
  • 根据PID查找到PMT包并解析,得到PCR_PID与音视频ES流的PID
  • 根据音视频ES流的PID解析出对应的音视频TS包
  • 根据Payload Unit Start Indicator字段,组装同一个PES下的TS包
  • 对完整的PES包进行解析,得到PTS/DTS与最终的音视频裸流数据,流程结束

参考

  • 《数字电视业务信息及其编码》- 方涛 编著
  • ISO_IEC_13818-1_2007_PDF_version_(en).pdf

# Android # Miracast # RTP # MPEG2-TS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值