AirPlay Android接收端学习一 协议
一 AirPlay 接收端描述
AirPlay是苹果的私有协议,苹果官方未开放api和sdk,目前相对权威的一份非官方协议文档。这篇文档详细描述了aiplay 服务发现、图片、音视频、镜像投屏的相关协议,给我们开发airplay设备提供了很好的参考。但是不足之处是文档已经有6年多时间没有更新过,对于IOS的新变化可能没有完全同步。在开发过程中我们可能会面临一些未知的坑,需要针对具体问题来逐一解决。
1.1 Airplay服务发现
Airplay设备启动之后可以发布两类服务:
1.RAOP (Remote Audio Output Protocol),用于音频传输。
2.AirPlay service 用于图片、视频、镜像等媒体的传输。
实现AIRPLAY协议的APP不需要再做任何配置就能发现同一网络中的接收端设备,这主要得益于Bonjour(基于M-DNS协议实现)。Bonjour:苹果为基于组播域名服务(multicast DNS)的开放性Zeroconf标准所起的名字。Zeroconf (零设置网络标准):全称为Zero configuration networking,中文名则为零配置网络服务标准,是一种用于自动生成可用IP地址的网络技术,不需要额外的手动配置和专属的配置服务器。具体例子为:用户拥有一台apple tv和一台iPhone5s,只要都连入到同一个无线局域网内,iphone4s就会自动找出apple tv,那么在播放音乐或者视频时候,用户只要点击推送,就可以讲音乐和视频推送到apple tv上播放
对于接收端,我们主要关注RAOP服务:
RAOP service from Device Name
name: 5855CA1AE288@Device Name
type: _raop._tcp
port: 49152
txt:txtvers=1ch=2cn=0,1,2,3da=trueet=0,3,5md=0,1,2pw=falsesv=falsesr=44100ss=16tp=UDPvn=65537vs=130.14am=AppleTV2,1sf=0x4
服务名称由设备的mac地址和设备名称组成。
TXT属性包括:
name | value | description |
---|---|---|
txtvers | 1 | TXT记录版本 |
ch | 2 | 音频通道:立体声 |
cn | 0,1,2,3 | 音频编解码格式 |
et | 0,3,5 | 支持的加密类型 |
md | 0,1,2 | 支持的元数据类型 |
pw | false | 接收端是否需要密码 |
sr | 44100 | 音频码率 |
ss | 16 | 音频采样率 |
tp | UDP | 支持的传输层协议 |
vs | 130.14 | 服务端版本 |
am | AppleTV2,1 | 设备模式 |
音频编解码
cn | 描述 |
---|---|
0 | PCM |
1 | Apple Lossless (ALAC) |
2 | AAC |
3 | AAC ELD (Enhanced Low Delay) |
IOS设备作为AirPlay客户端,发送的音频流默认是ALAC格式,安卓设备作为接收端,系统自带的MediaPlayer无法解码ALAC格式,因此需要先使用开源的代码对ALAC格式的音频流进行解码,解码生成PCM数据,最后可以通过AudioTrack来播放PCM流。
加密类型
et | 描述 |
---|---|
0 | 没加密 |
1 | RSA (AirPort Express) |
3 | FairPlay |
4 | MFiSAP (3rd-party devices) |
5 | FairPlay SAPv2.5 |
元数据
md | 描述 |
---|---|
0 | text 文本 |
1 | artwork 插图 |
2 | progress 播放进度 |
总结:
通过RAOP服务发现协议中的描述,可以知道Airplay接收端服务的名称、支持的音频编解码格式、加密类型以及音频播放的进度、插入、歌曲和歌手名称等。这些可以满足我们使用IOS手机或者pad向安卓平台AirPlay接收端同步歌曲的基本需求。
二 音频流传输
音频流传输采用RTSP(Real Time Streaming Protocol)协议 (RFC 2326)。实时流传输协议,是TCP/IP协议体系中的一个应用层协议,由哥伦比亚大学、网景和RealNetworks公司提交的IETF RFC标准。
音频传输协议主要包括:RTSP请求、RTP流、音量控制、元数据、认证、远程控制。
2.1 RTSP请求
OPTIONS请求向RTSP服务端询问它支持的方法,以Apple TV为例,它支持:ANNOUNCE, SETUP, RECORD, PAUSE, FLUSH, TEARDOWN, OPTIONS, GET_PARAMETER, SET_PARAMETER, POST and GET.当客户端知道服务端支持的方法之后,便可以通过这些方法名向服务器发送数据来实现指定的功能。我们来详细看一下主要的方法描述:
ANNOUNCE
通过SDP(Session Description Protocol)服务描述协议向RTSP服务端发送音频流数据的属性,编解码器和加密密钥等信息。
RECORD
RECORD请求启动音频流传输
FLUSH
FLUSH请求停止音频流传输
TEARDOWN
结束RTSP会话
2.2 RTP流
音频包完全符合RTP协议。控制和定时分组并不完全符合RTP标准。
2.3 音量控制
通过SET_PARAMETER请求可以用来调节音量。音量值是float类型,-144表示静音,音量范围在-30到0之间。
示例
client → serverSET_PARAMETER rtsp://fe80::217:f2ff:fe0f:e0f6/3413821438 RTSP/1.0
CSeq: 6
Session: 1
Content-Type: text/parameters
Content-Length: 20
User-Agent: iTunes/10.6 (Macintosh; Intel Mac OS X 10.7.3) AppleWebKit/535.18.5
Client-Instance: 56B29BB6CB904862
DACP-ID: 56B29BB6CB904862
Active-Remote: 1986535575volume: -11.123877
server → clientRTSP/1.0 200 OK
Server: AirTunes/130.14
CSeq: 6
2.4 元数据
SET_PARAMETER请求可以用来传输元数据,元数据内容包括:音频名称、作者名字、专辑名称、插图、音频时长。RTP-Info 头部包含了rtptime参数,表示元数据的有效时间。
2.5 认证
发送的音频数据需要通过RSA认证,所有的二进制数据需要使用Base64 (RFC 4648) 进行加密。
客户端:
在ANNOUNCE 请求中,通过Apple-Challenge 发送128位随机数据。
生成一个128位的AES key,使用RSA公钥加密。
服务端:
使用RSA私钥解密AES key,AES key将被用来解密音频数据
使用RSA私钥对Apple-Challenge进行签名,通过Apple-Response头部发送返回结果给客户端
客户端:
使用RSA公钥对Apple-Response进行解密,检查数字与之前发送的数字是否相同。
2.6 远程控制
airplay服务端可以通过DACP (Digital Audio Control Protocol)协议向客户端发送命令:改变当前播放的音轨状态、暂停、重播,调整播放列表等。airplay客户端通过在RTSP请求中包含DACP-ID头文件来告诉服务端自己支持的命令范围。
总结:
airplay客户端通过向服务端发送OPTIONS请求获取服务端支持的方法列表,随后可以向服务端发送这些命令来建立和结束RTSP会话。客户端发送的音频数据需要RSA认证:首先客户端通过RSA公钥加密128位的AES key,然后服务端通过RSA私钥解密key,随后使用解密后的key来解密音频负荷数据包。客户端可以SET_PARAMETER 请求来调节音量,传输音轨名称、专辑名手、作者名称、音轨播放进度等信息。airplay服务端可以通过DACP发送远程控制命令来实现:改变当前播放的音轨状态、暂停、重播,调整播放列表等。
三 代码参考实现
AirReceiver(https://github.com/fgp/AirReceiver)使用Java写的运行在PC端的AirPlay接收端
DroidAirPlay(https://github.com/pentateu/DroidAirPlay) 基于AirReceiver代码转换成安卓项目的实现代码
AndroidAirPlayReceiver(https://github.com/zhhp1121/AndroidAirPlayReceiver)基于DroidAirPlay改造后能直接使用的安卓工程
AirPlay Android接收端学习一 协议相关推荐
- Android Studio --- [学习笔记]RadioButton、CheckBox、ImageView、ListView、TCP的三次握手
说明 源代码 在2.x里有TCP的三次挥手与四次握手,先对它进行简单的回答(百度).预计在下一篇里,会继续说明TCP 接上一篇: Android Studio - > [学习笔记]Button. ...
- Android RIL学习
Android RIL学习 tomorrow.cyz@gmail.com 1.Android RIL概念 Android RIL是基于telephony 服务和raido 硬件层的抽象层.Androi ...
- android p2p 学习
android p2p 学习 TCP的三次握手(建立连接)和四次挥手(关闭连接) http://www.cnblogs.com/Jessy/p/3535612.html C/S(客户/服务器)模型: ...
- android开发用百度识别图片格式,Android开发学习之路-机器学习库(图像识别)、百度翻译...
对于机器学习也不是了解的很深入,今天无意中在GitHub看到一个star的比较多的库,就用着试一试,效果也还行.比是可能比不上TensorFlow的,但是在Android上用起来比较简单,毕竟Tens ...
- Android设备标准HID协议(外接输入设备)接入蓝牙扫描枪的各种坑与解决办法
因工作需要最近在做一款蓝牙条码.二维码扫描器枪支持Android设备(执行标准HID协议)的外接输入设备,在开发过程中遇到一些问题,在此记录下来,以便供大家借鉴学习,希望有类似需求的同行少走些弯路.好 ...
- Android USB的AOA协议设备端(主机模式,配件模式),ADB连接
USB的ADB/AOA协议(一种是ADB模式,一种是AOA模式).AOA协议是Google公司推出的用于实现Android设备与外围设备之间USB通信的协议. ADK中与USB配件模式相关的两个类是U ...
- JAVA软件海豚_[Java教程]海豚星空扫码投屏 Android 接收端 SDK 集成 六步骤
[Java教程]海豚星空扫码投屏 Android 接收端 SDK 集成 六步骤 0 2020-08-20 12:00:32 扫码投屏,开放网络,独占设备,不需要额外下载软件,微信扫码,发现设备.支持标 ...
- Android逆向 学习Android安全和逆向开发的路线总结,啃下这些Framework技术笔记
此篇整理了最完整的–Android逆向学习线路知识体系.希望给迷糊的入门者指出一个明确的方向. 真心建议:先正向开发几年再搞逆向吧--正向都不会破解的是啥?不看代码只会脱壳?只会xposed ?远远不 ...
- java/android 设计模式学习笔记(1)--- 单例模式
前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使 ...
最新文章
- AI一周热闻:GitHub免费开放无限私有库;苹果市值蒸发超450亿美元;小米入股TCL...
- 程序员的疯狂:打工与创业的残酷区别
- 微服务平台的发展趋势
- linux sort命令
- 关于QMap的几点总结思考
- NC119-最小的k个数
- Docker入门-docker compose的使用
- Matplotlib常用库方法
- 2020年末总结,脚踏实地,一步一个脚印——致敬自己一年的心酸历程
- mysql查询某张表的所有外键_oracle中查询所有外键引用到某张表的记录
- spring mvc学习(15)Referenced file contains errors
- java变量命名规则_浅谈JAVA开发规范与开发细节(上)
- HTML_CSS_JS_JSON
- shell 脚本中 while 只执行一次
- inputstreamreader未关闭会导致oom_【搞定面试官】你还在用Executors来创建线程池?会有什么问题呢?
- tensorflow内存溢出问题
- CAS Tomcat实现单点登录
- ajax跨域请求wcf服务,jQuery ajax跨域发布到WCF休息服务
- 模拟信号幅度调制之AM
- 安卓桌面软件哪个好_每日提醒软件哪个好?电脑上有什么好用的可以每天提醒的桌面便签软件...
热门文章
- Springboot集成Durid远程连接数据库一直报ERROR 1045 (28000): Access denied for user
- 0x80070570文件或目录损坏且无法读取 CHKDSK修复方法
- 不想学python也不想写博客的第四天
- 小米vr一体机html,小米VR一体机体验:一款让你大开眼界的产品
- Iphone 免费申请App ID
- 备份oracle错误12546,解决了ORACLE数据备份出现Message 206错误
- python抢票系统代码及解说_python抢票程序
- 成功解决Exception unhandled RuntimeError run loop already started File: F:\Program Files\Python\Python
- spring注解是怎么实现的?
- 越想越难,越做越简单,电磁兼容性设计