[资料]airplay协议

简介: [资料]airplay协议

相关资料

Unofficial AirPlay Protocol Specification

Android 开发 AirPlay Server

AirReceiver 使用Java写的运行在PC端的AirPlay接收端

DroidAirPlay 基于AirReceiver代码转换成安卓项目的实现代码

AndroidAirPlayReceiver基于DroidAirPlay改造后能直接使用的安卓工程

https://www.ietf.org/rfc/rfc2326.txt

相关技术

服务发现:

mDns

ssdp

流程

转自知乎大佬 刘同学被占用了

https://zhuanlan.zhihu.com/p/34324606

Airplay Mirroring客户端的同屏交互过程,分为三个主要步骤:

1, 设备广播与发现

2, 信息交互与能力协商

3, 音视频数据接收与解扰

设备广播与发现:

Airplay设备间的广播与发现通过Bonjour协议进行。Bonjour也被称为ZeroConf, mDNS等,可以用来在局域网内进行数据记录广播与发现。该协议比较成熟,网上可以找到诸多介绍。对于实现的Airplay(包括Mirroring)接收端而言,首先需要注册两类服务,即airtunes和airplay。 Airtunes服务主要用来处理广播视音频接收能力协商,是最为重要的服务内容,对应Bonjour记录名称为’_raop._tcp’,注册服务端口不限,一般为了避免冲突,建议采用较高的端口数;Airplay服务主要用来兼容传统的streaming等服务,对应记录名称为’_airplay._tcp’,注册端口一般为7000。

具体的服务广播内容,可以进行局域网抓包,找到对应记录内容。

当接收端通过Bonjour广播器服务能力后,发送端(如iPhone等各类iOS设备)就可以发现该接收端。

信息交互与能力协商:

当发送端发现接收端后,可以开始信息交互与能力协商过程。该部分协议协议格式类似rtsp协议格式。主要分为两个阶段,设备匹配与和能力协商。

当发送端链接服务端后,设备匹配过程即开始。通信双方会进行fairplay加密协议进行信息交换,当完成信息交换后,客户端后续必须使用这部分信息来处理加密过的密钥,才能获得进一步视音频解密密钥。在iOS9之后,在fairplay过程之前,增加一个设备匹配过程,即pair-setup、pair-verify过程,其主要算法是较为标准的非对称公钥交换算法。

当两端成功匹配后,开始进行能力协商与信息交换,这些信息包括,设备名称、代号,音视频接收相关端口配置,视频接收能力以及加密密钥等,相关信息使用binary plist格式进行封装。

可以参考https://github.com/espes/Slave-in-the-Magic-Mirror找到相关协议交互的一些细节。

音视频数据接收与解密

双方协商成功后,发送端开始向接收端发送视音频数据,mirroring数据是通过TCP进行发送,为h.264 ES流格式。音频是通过RTP协议进行发送,根据内容的不同音频编码为ALAC或者AAC-ELD。

音视频流都是通过AES进行了加密处理,密钥需要通过上面一步的进过信息交互后的fairplay模组对setup过程中接收到的加密密钥进行解密,获得的AES解密需要的IV和KEY,然后经过AES解扰,即可以获得最终的视音频清流。

其他需要注意的地方:

Airplay没过Session传送过来的视频h264码流,只有开头一个关键帧. 因此这种情况并不适合直播这种需要固定GOP的场景. 还需要做进一步的转码的工作,或者直接在压缩域进行处理,获得合理的GOP结构。

广播发现

协议交互

https://blog.csdn.net/mirkerson/article/details/8601333?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-1&spm=1001.2101.3001.4242

/info

request:

response:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>pk</key>
  <data>
  XYMxJlYMsZoUGTcneJbw/UN7poAeshCsTDnZAHLXDag=
  </data>
  <key>name</key>
  <string>Apple TV</string>
  <key>vv</key>
  <integer>2</integer>
  <key>statusFlags</key>
  <integer>68</integer>
  <key>keepAliveLowPower</key>
  <integer>1</integer>
  <key>keepAliveSendStatsAsBody</key>
  <integer>1</integer>
  <key>pi</key>
  <string>b08f5a79-db29-4384-b456-a4784d9e6055</string>
  <key>sourceVersion</key>
  <string>220.68</string>
  <key>deviceID</key>
  <string>00:50:56:C0:00:01</string>
  <key>macAddress</key>
  <string>00:50:56:C0:00:01</string>
  <key>model</key>
  <string>AppleTV3,2</string>
  <key>audioFormats</key>
  <array>
    <dict>
      <key>audioInputFormats</key>
      <integer>67108860</integer>
      <key>audioOutputFormats</key>
      <integer>67108860</integer>
      <key>type</key>
      <integer>100</integer>
    </dict>
    <dict>
      <key>audioInputFormats</key>
      <integer>67108860</integer>
      <key>audioOutputFormats</key>
      <integer>67108860</integer>
      <key>type</key>
      <integer>101</integer>
    </dict>
  </array>
  <key>audioLatencies</key>
  <array>
    <dict>
      <key>audioType</key>
      <string>default</string>
      <key>inputLatencyMicros</key>
      <false/>
      <key>outputLatencyMicros</key>
      <false/>
      <key>type</key>
      <integer>100</integer>
    </dict>
    <dict>
      <key>audioType</key>
      <string>default</string>
      <key>inputLatencyMicros</key>
      <false/>
      <key>outputLatencyMicros</key>
      <false/>
      <key>type</key>
      <integer>101</integer>
    </dict>
  </array>
  <key>features</key>
  <integer>130367356918</integer>
  <key>displays</key>
  <array>
    <dict>
      <key>height</key>
      <integer>1080</integer>
      <key>width</key>
      <integer>1920</integer>
      <key>rotation</key>
      <false/>
      <key>widthPhysical</key>
      <false/>
      <key>heightPhysical</key>
      <false/>
      <key>widthPixels</key>
      <integer>1920</integer>
      <key>heightPixels</key>
      <integer>1080</integer>
      <key>refreshRate</key>
      <real>0.016667</real>
      <key>maxFPS</key>
      <integer>60</integer>
      <key>features</key>
      <integer>14</integer>
      <key>overscanned</key>
      <false/>
      <key>uuid</key>
      <string>e5f7a68d-7b0f-4305-984b-974f677a150b</string>
    </dict>
  </array>
</dict>
</plist>

SETUP

response:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>timingPort</key>
  <integer>6000</integer>
  <key>eventPort</key>
  <integer>47010</integer>
  <key>streams</key>
  <array>
    <dict>
      <key>type</key>
      <integer>96</integer>
      <key>controlPort</key>
      <integer>6001</integer>
      <key>dataPort</key>
      <integer>6003</integer>
    </dict>
  </array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>et</key>
  <integer>32</integer>
  <key>eiv</key>
  <data>
  aAW66U8aj8bSvSFEJYVr1w==
  </data>
  <key>timingProtocol</key>
  <string>NTP</string>
  <key>sessionUUID</key>
  <string>F2F647DB-1E87-4AA6-B2AF-AA6CE0BF9D3F</string>
  <key>osName</key>
  <string>iPhone OS</string>
  <key>osBuildVersion</key>
  <string>17F80</string>
  <key>sourceVersion</key>
  <string>420.45</string>
  <key>timingPort</key>
  <integer>53648</integer>
  <key>isScreenMirroringSession</key>
  <true/>
  <key>osVersion</key>
  <string>13.5.1</string>
  <key>ekey</key>
  <data>
  RlBMWQECAQAAAAA8AAAAACbSNQTFG57dB11iWsNtMj8AAAAQvJ5sT/YIec4lRLGGRXsi
  HZ0UBENC+6P6Vco8NOvFLRsXN1Qi
  </data>
  <key>deviceID</key>
  <string>F8:95:EA:78:14:F0</string>
  <key>model</key>
  <string>iPhone10,3</string>
  <key>name</key>
  <string>姝︽眽鐨勬祴璇曟満iPhoneX 2</string>
  <key>macAddress</key>
  <string>F8:95:EA:83:87:59</string>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>timingPort</key>
  <integer>0</integer>
  <key>eventPort</key>
  <integer>46001</integer>
  <key>streams</key>
  <array>
    <dict>
      <key>type</key>
      <integer>110</integer>
      <key>dataPort</key>
      <integer>46000</integer>
    </dict>
  </array>
</dict>
</plist>

音视频接收



相关文章
|
1月前
|
安全 数据安全/隐私保护 网络架构
什么是TACACS+协议?
【4月更文挑战第12天】
67 2
|
1月前
|
安全 数据安全/隐私保护 网络架构
认识TACACS+协议
TACACS+(Terminal Access Controller Access-Control System Plus)是一种用于网络认证、授权和账户(AAA)服务的协议。它最初由Cisco开发,用于管理路由器、交换机等网络设备的访问控制。
22 0
|
1月前
|
缓存 网络协议 算法
|
网络协议
ModbusTCP协议
ModbusTCP协议
202 0
ModbusTCP协议
|
11月前
|
自然语言处理 Dubbo Java
doubbo 有哪些协议
doubbo 有哪些协议
65 0
|
传感器 芯片 开发者
一文看懂I2C协议
一文看懂I2C协议
421 0
一文看懂I2C协议
|
网络协议 网络架构
各种协议的简单理解
各种协议的简单理解
77 0
各种协议的简单理解
|
安全 数据安全/隐私保护
KWP2000协议
KWP2000协议
182 0
|
网络协议
Diameter协议
【本文转载于Diameter协议】 Diameter是计算机网络中使用的一个认证、授权和审计协议。它从功能更少的RADIUS协议进化而来,并且取代之。        Dimater应用通过添加新的命令或属性扩展基础协议,例如使用扩展认证 协议(EAP)。 与RADIUS协议比较        名字是一个单词游戏(从RADIUS,半径到DIAMETER,直径),从
5385 0
|
网络协议
协议的理解
协议 计算机 网络 计算机网络
120 0