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:

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示例:

ISO/IEC 13818-1 PID=0x0 CC=1Header: 0x474000110100 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的值:

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:

MPEG2 Program Association TableTable ID: Program Association Table (PAT) (0x00)1... .... .... .... = Syntax indicator: 1.011 .... .... .... = Reserved: 0x3.... 0000 0000 1101 = Length: 13Transport Stream ID: 0x000011.. .... = Reserved: 0x3..00 001. = Version Number: 0x01.... ...1 = Current/Next Indicator: Currently applicableSection Number: 0Last Section Number: 0Program 0x0001 -> PID 0x0100Program Number: 0x0001111. .... .... .... = Reserved: 0x7...0 0001 0000 0000 = Program Map PID: 0x0100CRC 32: 0x2df65295 [unverified][CRC 32 Status: Unverified]

PMT

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

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

MPEG2 Program Map TableTable ID: Program Map Table (PMT) (0x02)1... .... .... .... = Syntax indicator: 1.011 .... .... .... = Reserved: 0x3.... 0000 0010 0001 = Length: 33Program Number: 0x000111.. .... = Reserved: 0x3..00 001. = Version Number: 0x01.... ...1 = Current/Next Indicator: Currently applicable (0x1)Section Number: 0Last Section Number: 0111. .... .... .... = Reserved: 0x7...1 0000 0000 0000 = PCR PID: 0x10001111 .... .... .... = Reserved: 0xf.... 0000 0000 0000 = Program Info Length: 0x000Stream PID=0x1011Stream 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: 0x10111111 .... .... .... = Reserved: 0xf.... 0000 0000 1010 = ES Info Length: 0x00aDescriptor Tag=0x28Descriptor Tag=0x2aStream PID=0x1100Stream type: ISO/IEC 13818-7 Audio with ADTS transport syntax (0x0f)111. .... .... .... = Reserved: 0x7...1 0001 0000 0000 = Elementary PID: 0x11001111 .... .... .... = Reserved: 0xf.... 0000 0000 0000 = ES Info Length: 0x000CRC 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包)

[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 Streamprefix: 000001stream: video-stream (0xe0)
PES extensionlength: 19221... .... must-be-one: True.0.. .... must-be-zero: Falsescrambling-control: not-scrambled (0).... 0... priority: False.... .1.. data-alignment: True.... ..0. copyright: False.... ...0 original: False1... .... 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: Falseheader-data-length: 5
PES header data: 2101c5c1a9presentation 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

文章转载:

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

Miracast技术详解(三):RTP MPEG2-TS相关推荐

  1. Miracast技术详解(一):Wi-Fi Display

    Miracast概述 Miracast Miracast是由Wi-Fi联盟于2012年所制定,以Wi-Fi直连(Wi-Fi Direct)为基础的无线显示标准.支持此标准的消费性电子产品(又称3C设备 ...

  2. P2P技术详解(三):P2P技术之STUN、TURN、ICE详解

    本文是<P2P理论详解>系列文章中的第2篇,总目录如下: <P2P技术详解(一):NAT详解--详细原理.P2P简介> <P2P技术详解(二):P2P中的NAT穿越(打洞 ...

  3. P2P技术详解(三):P2P技术之STUN、TURN、ICE详解 (webrtc)

    https://www.cnblogs.com/mlgjb/p/8243690.html 简单的说,TURN与STURN的共同点都是通过修改应用层中的私网地址达到NAT穿透的效果,异同点是TURN是通 ...

  4. miracast技术详解

    miracast是什么? Miracast是由Wi-Fi联盟于2012年所制定,以Wi-Fi直连(Wi-Fi Direct)为基础的无线显示标准.支持此标准的消费性电子产品(又称3C设备)可透过无线方 ...

  5. P2P技术详解(三):P2P中的NAT穿越(打洞)方案详解(进阶分析篇)

    目录 1.NAT和NAPT 2.NAT带来的问题 3.P2P通信穿越NAT的技术.方法 4.NAT穿越技术1:应用层网关 4.1.原理 4.2.限制 5.NAT穿越技术2:中间件技术 5.1.原理 5 ...

  6. 群签名和环签名的区别_Monero技术详解(三):核心技术—环签名(1)

    在前文介绍了Monero的一次性地址方案.从方案看来,Monero中的UTXO只有一次性地址,用户地址是产生一次性地址的基础,用户对UTXO的所有权并不能显现地看出来.发送人在每次交易时创建一次性地址 ...

  7. P2P技术详解(一):NAT详解——详细原理、P2P简介(转)

    这是一篇介绍NAT技术要点的精华文章,来自华3通信官方资料库,文中对NAT技术原理的介绍很全面也很权威,对网络应用的应用层开发人员而言有很高的参考价值. <P2P技术详解>系列文章 ➊ 本 ...

  8. 015. P2P技术详解(一):NAT详解——详细原理、P2P简介

    http://www.52im.net/thread-50-1-1.html 这是一篇介绍NAT技术要点的精华文章,来自华3通信官方资料库,文中对NAT技术原理的介绍很全面也很权威,对网络应用的应用层 ...

  9. IPv6技术详解:基本概念、应用现状、技术实践(上篇)

    本文来自微信技术架构部的原创技术分享. 1.前言 普及IPV6喊了多少年了,连苹果的APP上架App Store也早已强制IPV6的支持,然并卵,因为历史遗留问题,即使在IPV4地址如果饥荒的情况下, ...

最新文章

  1. 对python的认识作文500字_对阅读新认识作文500字
  2. Kafka分区分配策略(Partition Assignment Strategy)
  3. IOS研究之App转让流程须知具体介绍
  4. WebAPi添加常用扩展方法及思维发散
  5. C#中泛型在Class上的实现
  6. python写入文字到txt只写入最后一行_python文件写入:向txt写入内容的设置
  7. Windows平台RTSP播放器/RTMP播放器设计需要考虑的几个点
  8. 传相互宝或于6月11日被关停 蚂蚁集团回应:假消息
  9. 15 个可在 Chrome 浏览器上体验 WebGL 的例子
  10. scale data:线性空间映射
  11. 大数据项目实施工作流程及大数据运维的日常工作流程
  12. java游戏编程:三路兵线,BOSS走位,代码和视频
  13. C++17尝鲜:fold expression(折叠表达式)
  14. AppleTalk--网络大典
  15. Spring Boot整合Shiro + Springboot +vue
  16. HDU - 1465 不容易系列之一 【错排】
  17. 牛人网站和博客---站得高看得更远(CV类)
  18. 鞍部在哪里_等高线地形图中鞍部的高度怎么看
  19. PHP ajax 远程下载PDF文件保存在本地服务器
  20. CY7C68013A的惊天大秘密:实现对全速和高速模式的切换

热门文章

  1. iOS 动画实战之Lottie动画
  2. 硬件在环仿真(HiL)测试介绍
  3. 2018年中国电影总票房突破609亿这个惊心动魄的数字
  4. HighCharts结构及详细配置(中文对比)
  5. 小米台灯突然自己亮了_米家又上三款新品,台灯耳机都有升级
  6. Python 异步编程之——线程
  7. AutoHotkey 与 AutoIt 的恩恩怨怨
  8. masm32开发com组件介绍[一][二][三]
  9. 2020年最新开发者调查报告,你不可不知的内容
  10. JavaWeb要解决的细节问题