AirPlay是苹果公司的在iOS4.2OS X Mountain Lion中加入的一种播放技术,可以将iPhoneiPod touchiPadMac(需要OS X Mountain Lion或更新版)上的视频镜像传送到支持Airplay的设备(如:音箱、Apple TV)中播放。使用Airplay需要iOS4.2版本的设备或Mac电脑上的iTunes10.1以上版本。视频镜像则需要iOS 5OS X Mountain Lion

当用户的设备(Mac, PC, iPod touch, iPhone, iPad)与支持AirPlay技术的音箱在同一无线局域网(WIFI)内的时候,用户在MacPC上打开iTunes 10或更高版本后,就会在iTunes音量条旁边(iTunes 10在窗口的右下角)看到一个AirPlay按钮。点击该AirPlay按钮,然后选择需要同步到的设备,就可以选择将音乐或视频无线同步到设备进行播放。而iPod touch, iPhoneiPad用户则可以在相应的“音乐”,“视频”以及支持AirPlay功能的第三方软件界面找到AirPlay按钮,操作同MacPC

由于AirPlay并非是开源的而且需要逆向获得AirPlay key,所以要实现AirPlay的难度不小,网上流传的AirPlay协议都是非官方的,WirelessDisplay群里有下载好的协议,每次 IOS的升级都会对AirPlay协议进行一定的修改,给刚接触想学习AirPlay的朋友推荐几个简单的AirPlay实现

第一个流传出来的AirPlay是由James Laird大神发布的,原因就是他的女朋友想将自己的ipod无线投到音响上播放,当时只有苹果官方的盒子才能够支持,James Laird一怒之下破解了当时的AirPlay协议,并且公开了Private Apple AirPlay key

//github.com/abrasive/shairport

这个daemon采用c语言编写,可以进行ios7及以下设备的音频投射,在公司用ipod实测可用。

//github.com/gpfduoduo/AirPlay-Receiver-on-Android

我天朝人发布的开源项目,支持IOS8.4之前的音视频投屏以及图片推送,经过实测可用。

 

AirPlay版本繁多,协议也比较多:镜像,非镜像,图片,视频,音频,第三方app等等各种协议之间都有差别,以后会慢慢给大家介绍的。

要实现AirPlay的第一步就是要实现iosAirPlay之间的相互发现,可以使用zeroconfmdns等开源协议来实现,下一章会详细介绍介绍这几种发现协议。

要实现airPlay的镜像Server端功能,要从以下几个方面来考虑

  • 1.发现过程
  • 2.协商过程
  • 3.视频传输
  • 4.解密过程

 

发现过程

使用Bonjour,可以参考mDNSResponderjmdns,注册两个服务:airtunesairplayAirplayTxt以及RaopTxt照着demo填写就可以了,也可以根据自己的要求修改其中的值,

需要注意的如下:

airtunes:   “12345@wirelessdisplay” , ”_raop._tcp.”airplay:    “wirelessdisplay” , ”_airplay._tcp.”

参数中”_airplay._tcp.”和’’_raop._tcp.”不可修改。

发布了服务之后,ios设备中应该就可以搜索到Server端了

协商过程

c-s: pair-setup

s-c: xxx

c-s: pair-verify

s-c: xxx

c-s: fp-setup

s-c: xxx

c-s: fp-setup

s-c: xxx

setup

setup response

setup

setup respnose

pair-setup,pair-verify配对验证,Server端根据收到的信息进行回复,格式类似RTSP

fp-setup(第一次和第二次)Fairplay相关。

第一次setup阶段会收到一大串数据,是按照plist格式生成的,用相应的方法进行解析可以得到ekeyeiv等信息,用于后续的解密。

第二次setup阶段获得type,通过type来判断视频数据或音频数据,通知接收端建立传输通道准备进行音视频数据的发送,加密过的屏幕镜像数据通过指定的端口(一般为7100)发送到接收端。

接收端收到发送过来的数据后进行解密,解密后的数据就可以进行播放了。

中间也可能会有GET_PARAMETERSET_PARAMETER来调整音量等信息。

 

解密部分目前主要有两种方法:

1.从apptvmacOS获取。

2.从市面上已有的可投屏产品中获取。

AIRPLAY镜像投屏过程中,音视频数据都是加密过的,对于接收端来说,需要正确解密后才能对音视频数据进行处理,音频和视频的解密过程还不一样。音频相对简单一点,视频会复杂一些。这一块的解密过程是没有公开的,是苹果自身的Fairplay DRM协议部分。现在市面上的第三方Airplay接收端无非都是通过逆向过程破解了相关部分。

本文针对音频的处理做一个介绍,音频部分的处理相对简单一点。

解密过程:

1 音频采用AES CBC128进行加密,这一部分可以使用开源的openssl库进行处理

2 该算法需要解密的输入参数包括aeskeyaeskiv,通过ANNOUNCE请求中携带,ANNOUNCE请求同时还会携带音频的编码信息。

通过解密过程后,我们会得到AAC编码的音频数据,播放器播放AAC数据还需要对其进行解码。

在我们实现的接收端程序,协商出来的是AAC-ELD编码。对于AAC的解码,可以使用一些开源的库,如fdk,ffmpeg等,也可以使用android提供的MediaCodec进行解码。

但笔者曾经在某些Android手机上发现,解码AAC-ELD有问题。推荐大家用fdk进行解码。

使用fdkaac进行解码,其实在网上也能找到很多例子,但笔者发现很多例子有一处错误,在低版本的fdk上不会出现错误,但是在高版本的fdk会出现crash这样的问题。话不多说,直接通过部分代码来说明过程。

初始化解码器:

  1. UCHAReld_conf[] = { 0xF8, 0xE8, 0x50, 0x00 };          //44100,2channels,s16
  2. UCHAR*aac_eld_conf[] = { eld_conf };                   //TODO just for aac eld config
  3. staticUINT aac_eld_conf_len = sizeof(eld_conf);
  4. decoder = aacDecoder_Open(TT_MP4_RAW, 1);
  5. AAC_DECODER_ERROR ret = aacDecoder_ConfigRaw(decoder, aac_eld_conf, &aac_eld_conf_len);
  6. buffer = newINT_PCM[960];
  7. buffer_size = 1920;
  8. pcm_size = 960;

上述代码中eld_conf这一块的值对应android MediaCodec aacCSD buffer #0具体什么含义看规范吧。

每次编码和发送的采用数为480,故下面申请对应长度的Buffer

 

解码过程:

  1. bytesValid = dataLen;
  2. while(bytesValid){  
  3. ret = aacDecoder_Fill(decoder, reinterpret_cast<UCHAR**>(&p_frame), (UINT*)&size, &bytesValid);
  4. if (ret != AAC_DEC_OK) {
  5. printf(“aacDecoder_Fill return %x.\r\n”, ret);
  6. return;
  7. }
  8. for(;;) {
  9. ret = aacDecoder_DecodeFrame(decoder, buffer, pcm_size, 0);
  10. if(ret == AAC_DEC_OK) {
  11. dump_audio_data((unsigned char*)buffer,buffer_size);
  12. elseif (ret == AAC_DEC_NOT_ENOUGH_BITS)
  13. break;
  14. else{
  15. printf(“aacDecoder_DecodeFrame return %x.\r\n”, ret);
  16. return;
  17. }
  18. }
  19. }

aacDecoder_DecodeFrame填入的参数为pcm_size,其单位为short,而不是byte。网上的例子很多都是在这里错误。请各位务必注意。

必捷网络现提供技术全国领先的Airpaly SDK苹果无线投屏软件开发工具包,支持同时多路,支持镜像/视频/图片/音乐,支持MAC OS/iOS6/iOS7/iOS8/iOS9/iOS10/iOS11投屏,支持Linux/Android/Windows/X86/ARM/MIPS等,可根据需求定制开发,通过电话或者在线咨询联系我们获取更多无线投屏sdk(airplay sdk、miracast sdk)相关信息,欢迎咨询!