retina显示屏的好处是3sm响应屏好吗

CSS | Amaze UI
CSS浏览器默认样式统一,基础样式,网格,表格、表单、按钮及常用组件样式。 目录CSS CSS 概述 Amaze UI CSS 大致分为四部分。基础(默认)样式使用 normalize.css 统一浏览器差异, 以及一些基础的元素样式。布局样式包含用于布局的 Grid、AVG Grid,以及一些辅助 Class。元素样式对 code、form、table 等 HTML 元素定义更多的样式。页面组件定义网页中常用的、多个元素组合在一起的组件样式,如分页、面包屑导航等。浏览器前缀 Amaze UI 2.0 开始移除了所有标准属性的浏览器前缀,构建时通过
自动添加。当前的 AutoPrefixer 浏览器支持设置为:[
'ie &= 8',
'ie_mob &= 10',
'ff &= 30',
'chrome &= 34',
'safari &= 7',
'opera &= 23',
'ios &= 7',
'android &= 2.3',
'bb &= 10'
]响应式断点 尺寸class 简写断点区间描述smallsm0 - 640px处理绝大数手机的横竖屏模式()mediummd641px - 1024px平板的横竖屏模式largelg1025px +桌面设备目前 Amaze UI 对大于 1025px 的屏幕并没有做划分,虽然现在大屏显示器越来越多,但是设计一个过宽的网页对用户来说并不友好,用户眼睛左右移动的区间太大,浏览起来比较累。当然,一些特殊类型(购物、视频等)的网站例外。LESS 变量中定义了一些 Media Query 变量,使用 LESS 的用户可以引入该文件,直接使用这些变量。@screen:
~"only screen";
@landscape:
~"@{screen} and (orientation: landscape)";
@portrait:
~"@{screen} and (orientation: portrait)";
@small-up:
~"@{screen}";
@small-only:
~"@{screen} and (max-width: @{breakpoint-small-max})";
@medium-up:
~"@{screen} and (min-width:@{breakpoint-medium-min})";
@medium-only:
~"@{screen} and (min-width:@{breakpoint-medium-min}) and (max-width:@{breakpoint-medium-max})";
@large-up:
~"@{screen} and (min-width:@{breakpoint-large-min})";
@large-only:
~"@{screen} and (min-width:@{breakpoint-large-min}) and (max-width:@{breakpoint-large-max})";使用 HTML5 Amaze UI 在 HTML5 下开发,没有测试其他 DOCTYPE,使用之前确保你的 HTML 第一行是 &!doctype html&。建议使用的 HTML head:&!doctype html&
class="no-js"&
charset="utf-8"&
http-equiv="X-UA-Compatible" content="IE=edge"&
name="description" content=""&
name="keywords" content=""&
name="viewport"
content="width=device-width, initial-scale=1"&
&Amaze UI Examples&
name="renderer" content="webkit"&
http-equiv="Cache-Control" content="no-siteapp"/&
rel="icon" type="image/png" href="{{assets}}i/favicon.png"&
name="mobile-web-app-capable" content="yes"&
rel="icon" sizes="192x192" href="{{assets}}i/app-icon72x72@2x.png"&
name="apple-mobile-web-app-capable" content="yes"&
name="apple-mobile-web-app-status-bar-style" content="black"&
name="apple-mobile-web-app-title" content="Amaze UI"/&
rel="apple-touch-icon-precomposed" href="assets/i/app-icon72x72@2x.png"&
name="msapplication-TileImage" content="assets/i/app-icon72x72@2x.png"&
name="msapplication-TileColor" content="#0e90d2"&
rel="stylesheet" href="assets/css/amazeui.min.css"&
rel="stylesheet" href="assets/css/app.css"&
src="assets/js/jquery.min.js"&&
src="assets/js/amazeui.min.js"&&
&参考链接:移动优先 Amaze UI 以移动优先的理念开发,需要在 meta 中设置相关 viewport 属性。width=device-width, initial-scale=1 是必须的,而且我们认为好的设计是不需要用户去操作窗口缩放的,所以加上了 maximum-scale=1, user-scalable=no。 name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"&国情国情 不可否认,这是一个神奇的国度,一切合理与不合理都可以用国情来解释。前端开发也不例外。渲染引擎 国内不少 X 核 浏览器,对于前端开发者,他们更多时候可能充当了 Troublemaker 的角色,不过也会有让人眼前一亮的一刻。 name="renderer" content="webkit"&这行代码可以指定网页使用 webkit 引擎渲染,当然,只对 。就这点而言,我希望所有所有的小白都去用 360 浏览器,那该有多好...防(zhēn)狼(cāo)术(dài) 如果你的网站不想被剥去外衣、往赤裸的身体上贴广告,就加上。 http-equiv="Cache-Control" content="no-siteapp" /&Class 命名说明 关注分离 Amaze UI CSS class 命名遵循关注分离、松耦合的原则,同时注重易于理解、理解,在参考
的基础上,采用更优雅的书写方式。下面的代码直观展示了 Amaze UI CSS class 命名规范。.am-post
.am-post-title
.am-post-meta
.am-post-sticky
.am-post-active
.am-post-title-highlight {}
关注分离示例
class="am-post"&
class="am-post-title"&&
class="am-post-meta"&&
class="am-post-content"&
&上面的代码中,可以直接使用下面的样式控制元素:.am-post & h2 {
.am-post & p {
}乍看是没什么问题,这两个选择符也不会影响到 &main& 里面的元素,但是如果更改了 HTML 标签, 就必须同时修改 CSS 选择符,无疑加大了维护的工作量。所以,给相应元素加上 class 是关注分离一个不错的选择。 class="am-post"&
class="am-post-title"&&
class="am-post-meta"&&
class="am-post-content"&
&关注分离反模式
class="am-nav"&
class="am-nav-item"&&
class="am-nav-item"&&
class="am-nav-item"&&
&上面是一个导航代码片段,我们给 &li& 都加上了 .am-nav-item class,表面是遵循关注分离,其实是一种反模式,因为 &ul& 里面肯定是要放 &li& 的,在没有其它更复杂的元素在里面的情况下,给 &li& 加 class 显然是多余的。所以, 关注分离并不是简单地给每个元素都加上 class,还需结合实际情况区别对待。相关阅读:“多类症”(Classitis) 当 HTML 源代码满眼望去都是 class 时,是不是很抓狂?不过为了实现代码复用,减少重复冗余,难免要把代码拆分在不同的 class 下面。我们只能寻找一个平衡点,避免过细的拆分,减少不必要的 class。选择符书写 虽然使用 LESS 编写样式可以很方便的嵌套,但是我们不建议过度嵌套选择符,有些嵌套是没有必要的。同时,我们也不建议把多个选择器堆叠在一起。.ui.form .fields.error .field .ui.selection.dropdown .menu .item:hover {
}看看上面来自
的选择符,威武霸气吧,整行都是选择符,class 加 class,n 层嵌套,我只想呵呵...选择符嵌套在必要的情况下一般不超过三层;选择符叠加一般不多于两个。一点禁忌 我们崇尚自由,但并不是百无禁忌。Amaze UI 中有两个表示状态的 class:.am-active - 激活.am-disabled - 禁用不要单独使用、直接在里面编写样式!!!/* 可以嵌套用 */
.am-nav .am-active {
/* 可以堆叠用 */
.am-btn.am-active {
/* 绝不要单独用!!! */
.am-active {
/* 当然,如果你想给自己找点乐,那就随便了 */禁用响应式 不喜欢响应式?可以尝试禁用:删除 head 里的视口设置 meta 标签;固定容器 .am-container 宽度(可以自己添加一个 class,不一定要使用内置的):.am-container {
width: 980px !important;
max-width:
}使用网格系统时,只添加 .am-u-sm-* class,移除其他断点的 class。至此,布局层的响应式被禁用了()。不过,这仅仅是个开始,一些组件的样式细节可能还需要调整,只能陪你到这了……关于命名空间 似乎有些人看着 .am 有些不顺眼,在这里专门做一下说明。可能有人不知道命名空间是什么东西,和
中的 yui、 中的 pure 一样,Amaze UI 里的 am 就是命名空间。命名空间使类名变得冗长,可为什么还要加呢?目的:防御与无侵入! 更直白的话说,我不犯人,也不让人犯我。CSS 多基于 Class 应用样式,我们不愿看到:多个框架共存时,按照我们的 CSS 编写的 HTML 结构应用了其他框架的样式;从第三方抓取的 HTML 存在 class 相同的元素,意外地应用了 Amaze UI 的样式;用户编写自己的代码时,意外的覆盖了框架中的样式;多人协作开发时,发生命名冲突,样式相互影响;__第三方服务(如分享按钮、评论组件)会向页面中插入一些样式,可能会意外的应用到我们编写的结构;……Amaze UI 内部在用,平台上的开发者也在用,命名空间能够有效地减少这些问题。仅限于此,与品牌宣传什么的扯不上关系。何去何从? 命名空间会被删除吗?一般不会,不过也说不定,不过那也是很久很久以后的事。我真的不喜欢命名空间这个东西,怎么办?未来版本会尝试自定义命名空间的可能性。你也可以尝试自己在编译的过程中把命名空间去掉,前端编译工具那么多,何不试试?不然葱油拌?还是飘香拌?妹子只能说这么多了,再往下就只能说:你不懂我,我不怪你。在微信上关注我们SM-3数字智能加码器说明书_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
赠送免券下载特权
10W篇文档免费专享
部分付费文档8折起
每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
SM-3数字智能加码器说明书
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩9页未读,
定制HR最喜欢的简历
你可能喜欢1688.com,阿里巴巴打造的全球最大的采购批发平台
1688/淘宝会员(仅限会员名)请在此登录
cbulogin.center.eu13Server is OK三星平板: 三星三款全新 SM-T53X系列平板电脑曝光_第三媒体平板电脑(TablePC)频道
→ 三星平板: 三星三款全新 SM-T53X系列平板电脑曝光
三星平板: 三星三款全新 SM-T53X系列平板电脑曝光
作者:&&&&
来源:第三媒体&&&&
据报道:三星将推出新款平板电脑SM-T531,目前已经通过蓝牙技术联盟认证,此外,据介绍,这款平板SM-T531还在印度产品进出口网站的数据库中现身,该平板采用10.1英寸屏幕,一块现身的新品还有SM-T530和SM-
[正文] & &
&& 据报道:三星将推出新款电脑SM-T531,目前已经通过蓝牙技术联盟认证,此外,据介绍,这款SM-T531还在印度产品进出口网站的数据库中现身,该采用10.1英寸屏幕,一块现身的新品还有SM-T530和SM-T535,都采用8英寸显示屏。
&& 可以看出这三款机型都为SM-T53X系列,目前,还不清楚这三款机型是支持不同网络版本的机型,还是采用AMOLED显示屏的不同尺寸机型。
&& (第三媒体 )
】 【 字体:
&&&上一篇:&&&下一篇:
平板电脑(TablePC)导航: |
&Advertisement
&十大最受关注的平板电脑(TablePC)新闻
&十大最受关注的平板电脑产品
&十大热门平板电脑(TablePC)驱动/软件下载
&十大最受关注的平板电脑品牌
&(Samsung)
&(TECLAST)
&(ViewSonic)
&十大热门常用软件下载
& & Re: 三星平板: 三星三款全新 SM-T53X系列平板电脑曝光
飘零雪 路过 帮 顶一下!!!
作者:痴嘿明仔&&&
&&&&&&&&&&&& 字数: 0
其他平板电脑
(01-26) (01-26) (01-26) (01-26) (01-24) (01-24) (01-26) (01-26) (01-24) (01-24) (01-24)多屏互动技术研究(三)之Airplay研究
Airplay技术研究
1. Airplay简介
AirPlay 是苹果开发的一种无线技术,可以通过WiFi将iPhone 、iPad、iPod touch 等iOS 设备上的包括图片、音频、视频及镜像通过无线的方式传输到支持AirPlay 设备(IOS8后,AirPlay可使用P2P直连,绕过了WIFI,具体有待深入)。
AirPlay支持如下几种使用场景:
o 从iOS设备上传输并显示照片、幻灯片;
o 从iOS设备或者Itunes软件中传输并播放音频;
o 从iOS设备或者Itunes软件中传输并播放视频;
o 对iOS设备或者OS X Mountain Lion进行屏幕镜像。由于此功能需要硬件的硬解码支持,所以只能在iPad 2、iPhone 4S、带Sandy Bridge CPU的Mac电脑(或更新的设备)上支持。
最初这套协议名字叫AirTunes,只支持音频流播放。 后来苹果开发Apple TV时,对此协议进行了扩充和改进,加入了视频支持,并改名叫做AIRPLAY。
1.1 Airplay协议构成
AirPlay并不是完全重新开始写的一个协议, 是好几个现有的协议的组合, 其中有的协议是完全标准的, 有一部分协议进行了一些修改,有的则是完全私有的。
o Multicast DNS (aka Bonjour) 用于发布服务, 启动后, 在iOS的控制中心菜单中就能看到对应的设备;
o HTTP / RTSP / RTP
用于流媒体服务, 传输音视频数据, 进行播放控制等;
o NTP 时间同步;
o FairPlay DRM加密
完全私有的加密协议。
1.2 Airplay难点分析
1.2.1 Airplay 协议文档缺失
AirPlay是Apple的私有协议族, 没有公开的官方文档作为参考. 目前能够参考的是github上nto大神整理的一份非官方的协议spec文档, 但是完全照着文档的描述是无法兼容新的iOS系统(iOS9/10)的, 新系统对协议有改变,而这份文档的最后更新日期是2012年, 这些变更内容都没有包含。
1.2.2 Airplay 敏感数据加密的破解
有人会说Airplay毕竟是通过网络交互的协议, 当年 nto能够整理出一份spec, 现在也可以通过抓包, 分析的方式得到新的交互过程, 缺少了文档不过是增加一些破解协议的难度而已. 但是以保护用户隐私著称的Apple, 不会明文传输音视频数据的. Airplay协议中有着比较完善的DRM保护, 传输的音视频都是用AES算法加密过的, 而AES的key 则是在握手的过程中通过Fairplay协议保护的, 这一部分是Apple重点保护的内容, 目前没有人能真正破解。
1.3 Airplay 握手建连
建连握手部分是经过修改的RTSP协议, 与HTTP协议比较类似, 都是客户端(iOS系统)发起请求, 接收端针对请求内容进行回应的方式. 每个请求包括:方法+路径+header+content等内容。
主要的交互过程如下:
4次POST请求, 分别对应的路径为 /pair-setup, /pair-verify和两次/fp-setup这是开头于FairPlay相关的核心加密部分, 任何一次POST的回复内容不对都会导致握手失败。SETUP请求 不同版本的iOS系统中, SETUP方法的次数可能不同。
在SETUP方法中能得到比较多的信息, 比如后面视频AES解密需要用到的ekey和eiv. 接收端需要将自己的监听的接收端口airVideoPort回复给客户端.这些信息需要对这次请求的content使用Apple的Binary plist格式进行解码才能提取, 回复内容也要编码为Binary plist格式. 后续完成握手后, 客户端会通过 airVideoPort 端口建立 TCP连接, 然后将屏幕画面通过H.264编码后再通过AES加密处理后, 向连接持续发送。
一次GET请求, 路径为/info, 这里接收端需要回复一个Binary plist格式的数据, 将用户配置的画面分辨率, 最大帧率等信息传递到客户端。
可能有多次GET_PARAMETER和SET_PARAMETER请求用于调整音量大小。
一次RECORD请求, 表明握手完成, airplay镜像开始。
在镜像过程中会每秒都收到POST请求,路径为/feedback, 相当于心跳, 用于保持TCP的长连接。
1.4 Airplay Screen Mirroring 视频数据传输
视频数据传输是客户端通过TCP 单方向的往接收端灌加密后的数据. 数据内容分为头部和载荷. 头部包含了载荷的类型, 长度, 时间戳等信息. 载荷部分有两种, 一种是H.264的参数集, sps, pps等; 另一种就是AES加密后的H.264裸流, 没有填充到封装格式中, 用SETUP请求中得到的key和iv解密后,即可送到视频解码器中解码。
2. 实现机制
实现Airplay主要分为以下几个步骤:
1. 设备发现,也就是实现音视频服务发现功能;
2. 设备连接及信令处理;
3. 音视频数据包解密及解码处理。
2.1 设备发现
实现AIRPLAY协议的软件不需要再做任何配置就能发现同一网络中的相关设备,这主要得益于Bonjour(基于M-DNS协议实现)。Bonjour:苹果为基于组播域名服务(multicast DNS)的开放性Zeroconf标准所起的名字。Zeroconf (零设置网络标准):全称为Zero configuration networking,中文名则为零配置网络服务标准,是一种用于自动生成可用IP地址的网络技术,不需要额外的手动配置和专属的配置服务器。具体例子为:用户拥有一台apple tv和一台iPhone5s,那之只要都连入到同一个无线局域网内,iphone4s就会自动找出apple tv,那么在播放音乐或者视频时候,用户只要点击推送,就可以讲音乐和视频推送到apple tv上播放。
关于mDNS部分,苹果已经开源了一个工程:mDNSResponder,可以进行参考,另外JAVA下也有一个开源实现jmdns,而在Android平台中,自Android4.1开始官方实现了一套Nsd API(网络服务发现),也实现了此功能。
服务发布后的查询响应包如下:
图1 服务发布后的查询响应包
在这个查询包中有下面几个关键字段,Name、Service、Port,AirPlay服务名称格式如下:AS-XX._airplay._tcp.local, RAOP服务名称格式如下:000B828B571E@AS-XX._raop._tcp.local. Service字段也就是.号分割的第一项,第二项说明了服务的类别:_airplay是视频服务,_raop是音频服务,第三项说明数据传输的协议,可以通过tcp或者udp传输。Port声明了RTSP及HTTP信令交互的端口,也就是接收端以这两个端口分别创建ServerSocket,Client可以通过这两个端口与服务端建立起来连接。所以在发布airplay及raop服务之前必须准备好这两个ServerSocket, 当iphone/ipad发现服务并发起连接时,信令便通过这两个端口来与接收端进行交互。在镜像流程中,信令会随机选择一个通道进行信令交互。
下面是mDNS中txt相关字段的抓包及各个字段的含义,在最新的IOS系统中增加了比较多的字段,有些字段的含义暂时还不明确,但是这个并不影响服务被发现,只要声明了比较关键的字段服务就会被发现。
raop中比较关键的字段有ch, cn,et, sr,ss, tp等,各字段的具体含义及取值在下面的表格中已写明。
airplay中比较关键的字段有devicesid,features等,各个字段具体含义及取值在下面的表格中。
图2 mDNS查询包
The name is formed using the MAC address of the device and the name of the remote speaker which will be shown by the clients.
The following fields appear in the TXT record:
description
TXT record version 1
audio channels: stereo
audio codecs
supported encryption types
supported metadata types
does the speaker require a password?
audio sample rate: 44100 Hz
audio sample size: 16-bit
supported transport: TCP or UDP
server version 220.68
AppleTV2,1
device model
supported features
Audio codecs
description
Apple Lossless (ALAC)
AAC ELD (Enhanced Low Delay)
Encryption Types
description
no encryption
RSA (AirPort Express)
MFiSAP (3rd-party devices)
FairPlay SAPv2.5
Metadata Types
description
The following fields are available in the TXT record:
description
AppleTV2,1
device model
58:55:CA:1A:E2:88
MAC address of the device
bitfield of supported features
server is password protected
The pw field appears only if the AirPlay server is password protected. Otherwise it is not included in the TXT record.
The features bitfield allows the following features to be defined:
description
video supported
photo supported
VideoFairPlay
video protected with FairPlay DRM
VideoVolumeControl
volume control supported for videos
VideoHTTPLiveStreams
http live streaming supported
slideshow supported
mirroring supported
ScreenRotate
screen rotation supported
audio supported
AudioRedundant
audio packet redundancy supported
FPSAPv2pt5_AES_GCM
FairPlay secure auth supported
PhotoCaching
photo preloading supported
2.2 设备连接及信令处理
当iPhone手机端发现接收端以后就会通过TCP连接上来,然后会通过RTSP协议进行交互,不过经过苹果的数次升级和变更,现在虽然表面上还是基于RTSP协议,不过已经和标准的RTSP协议区别很大了,如果想学习标准的RTSP协议,有个非常好的开源项目live555值得参考。接下来重点来了,我们的接收端需要处理来自手机端发来的各种请求命令,并且做出正确的响应。
2.2.1 Mirror基本流程
流程简图如下:
1.| &————–fp-setup————& |
2.| &————–fp-setup————& |
3.| &————–SETUP—————& |
4.| &————–GET /info———–& |
5.| &————–GET_PARAMMETER——& |
| | 6 | &————–SET_PARAMMETER——& |
7 | &————–POST /feedback——& | (every 2 seconds)
streaming data to port bytes headers | H264 DATA | 128bytes headers | H264 DATA | …
伪代码大致如下:
if (!strcmp(method,"POST") && !strcmp(uri,"/pair-setup")) {
res = request_handle_pairsetup(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method,"POST") && !strcmp(uri,"/pair-verify")) {
res = request_handle_pairverify(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "POST") && !strcmp(uri,"/fp-setup")) {
res = request_handle_fpsetup(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "POST") && !strcmp(uri, "/auth-setup")) {
res = request_handle_authsetup(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "GET") && !strcmp(uri, "/info")) {
res = request_handle_info(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "GET") && !strcmp(uri, "/stream.xml")) {
res = request_handle_streamxml(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "OPTIONS")) {
res = request_handle_options(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "ANNOUNCE")) {
res = request_handle_announce(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "SETUP")) {
res = request_handle_setup(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "SET_PARAMETER")) {
res = request_handle_setparameter(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "FLUSH")) {
res = request_handle_flush(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "TEARDOWN")) {
res = request_handle_teardown(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "RECORD")) {
res = request_handle_record(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method, "GET_PARAMETER")) {
res = request_handle_getparameter(conn, request, res, &responseData, &responseDataLen);
} else if (!strcmp(method,"POST") && !strcmp(uri,"/feedback")) {
res = request_handle_feedback(conn, request, res, &responseData, &responseDataLen);
其中有些命令是为了兼容老版本协议而存在的。
2.2.2 Mirror交互流程
下面以一次完整的镜像流程抓包分析相关的交互流程。
大致交互流程如下:
一. POST /pair-setup POST /pair-verify等命令用于配对验证,其中会用到ed25519,SHA-512,AES等算法。
PS. 目前这一步相关的加密流程比较复杂,还有找到破解的方法,但是在发布Airplay服务时候可以设置特定的features跳过这一步的验证流程。
二. POST /fp-setup命令是FairPlay相关,FairPlay是苹果公司开发的一种DRM(数字版权管理)技术,苹果的视频和音频传输都在这种技术的保护之下被AES加密后传输,这个FairPlay技术也是整个AirPlay中最难的部分,真的很难。
三. 第一个SETUP命令,手机端会传输大量的参数给到接收端,其中最重要的两个参数是ekey和eiv,它们经过一些变换之后要用于AES解密的。要重点说的是参数是用plist格式保存的,与标准的RTSP协议完全不同。
四. GET /info命令 手机端会通过此命令获取接收端的一些参数,比如接收端能接受的音频格式,能播放的视频长和宽,分辨率等。
五. GET_PARAMETER和SET_PARAMETER命令用于调整音量大小,比较简单。
六. RECORD命令好像没什么具体要做的,因为重要的事情都在SETUP命令里面做了。
七. 第二个SETUP命令,手机端通过这个命令通知接收端,准备建立屏幕镜像传输通道,命令中的type参数等于110,代表是屏幕镜像。接收端会在应答报文中将自己的接收端口告诉手机端,也就是dataPort这个参数,默认一般是7100。手机端会通过TCP连接上这个端口,然后将屏幕镜像通过h264编码以后再通过AES加密处理后通过这个端口源源不断的传给接收端,而具体的承载协议是苹果自定义的。
八. POST /feedback命令 每秒钟手机端都会向接收端发一次这个命令,我理解为定时保活的意思。
每次推送音频及视频的时候会有一个二次SETUP的交互,音频和视频的交互内容稍有不同,主要是端口、数据类型及数据格式等的交互。
Client相关信令的相关内容主要通过plist这种格式,这是苹果专门的一种xml形式的内容交换格式,目前java端可以通过dd-plist.jar完成数据解析。
完整的Mirror交互抓包如下:
POST /pair-setup RTSP/1.0
Content-Length: 32
Content-Type: application/octet-stream
DACP-ID: E28CCF9054EDE3B9
Active-Remote:
User-Agent: AirPlay/320.20
1t&..*….i1”m,.. g.|h.Y…t..M.RTSP/1.0 200 OK
Date: Thu, 19 Oct :35 GMT
Content-Type: application/octet-stream
Server: AirTunes/220.68
Content-Length: 32
8.5…p.*…..A.%.Yn…..w
POST /pair-verify RTSP/1.0
X-Apple-PD: 1
X-Apple-AbsoluteTime:
Content-Length: 68
Content-Type: application/octet-stream
DACP-ID: E28CCF9054EDE3B9
Active-Remote:
User-Agent: AirPlay/320.20
…………..k……)oWL..t.%s..(.b1t&..*….i1”m,.. g.|h.Y…t..M.RTSP/1.0 200 OK
Date: Thu, 19 Oct :36 GMT
Content-Type: application/octet-stream
Server: AirTunes/220.68
Content-Length: 96
.^{ …O. j..Xa+..y….+.^.!…p…nF.!.g*.W….. .U…L…b[bz.tf………sm..”…..,A.=….g..
POST /pair-verify RTSP/1.0
X-Apple-PD: 1
X-Apple-AbsoluteTime:
Content-Length: 68
Content-Type: application/octet-stream
DACP-ID: E28CCF9054EDE3B9
Active-Remote:
User-Agent: AirPlay/320.20
……H.u6.Fq`.(V?..+6.4.7…^..&…..K.L………….T1Wv7I.*ke.m..RTSP/1.0 200 OK
Date: Thu, 19 Oct :36 GMT
Content-Type: application/octet-stream
Server: AirTunes/220.68
Content-Length: 0
POST /fp-setup RTSP/1.0
X-Apple-ET: 32
Content-Length: 16
Content-Type: application/octet-stream
DACP-ID: E28CCF9054EDE3B9
Active-Remote:
User-Agent: AirPlay/320.20
FPLY…………RTSP/1.0 200 OK
Date: Thu, 19 Oct :36 GMT
Content-Type: application/octet-stream
X-Apple-ET: 32
Server: AirTunes/220.68
Content-Length: 142
FPLY………..2.W..RO…z.d.{.D$…~.
.z..]..’0.Y….:.M…….M…{V…….C….e.N.9.[..d..]..&.j.~.V.+..@Bu.ZD.Y.rV…Q8…’r..W.P.*.Fh.
POST /fp-setup RTSP/1.0
X-Apple-ET: 32
Content-Length: 164
Content-Type: application/octet-stream
DACP-ID: E28CCF9054EDE3B9
Active-Remote:
User-Agent: AirPlay/320.20
FPLY………….p..gO.;……%jXB…..*…..T….x….#.E.^.]|…..s….
j……….q..pT….y.Gq&..r.
.+..ZW.._..Z……H…&…k’..k..4…M;r..XU.vc…z,…..O.RTSP/1.0 200 OK
Date: Thu, 19 Oct :36 GMT
Content-Type: application/octet-stream
X-Apple-ET: 32
Server: AirTunes/220.68
Content-Length: 32
FPLY……….XU.vc…z,…..O.
SETUP rtsp://192.168.123.47/3033009 RTSP/1.0
Content-Length: 425
Content-Type: application/x-apple-binary-plist
DACP-ID: E28CCF9054EDE3B9
Active-Remote:
User-Agent: AirPlay/320.20
bplist00……….
………RetTname]sourceVersionZtimingPortXdeviceIDUmodelZmacAddress^osBuildVersion[sessionUUIDTekeySeiv. ..GrandStream-6plusV320.20..&..D8:BB:2C:1F:28:94YiPhone7,1_..D8:BB:2C:1F:28:92U14G60_.$54C77E8B-F4BE-4BB1-A9D7-D246D6672D8BO.HFPLY…….&….?z.(…K`…..}…..’……W…B…6j..w.{^..d…,…!.O..Ds*..i#6…D.T.!…..”.’.5.@.I.O.Z.i.u.z.~……………….H………………………….[
二进制的plist转换成xml格式如下:
&?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"&
version="1.0"&
&GrandStream-6plus&
&sourceVersion&
&timingPort&
&deviceID&
&D8:BB:2C:1F:28:94&
&iPhone7,1&
&macAddress&
&D8:BB:2C:1F:28:92&
&osBuildVersion&
&sessionUUID&
&0DBDA1BF--9F25-&
RlBMWQECAQAAAAA8AAAAAF5xvfwQNcVLHM2KurVtQCMAAAAQC8/GGZ7i56Hu5wMkHYQ0Bh/SImp90UX8SzQltjNHayrNtwmX
SdqQ7TXGEvz+R80Xi4IoaA==
关键字段已通过红色字体标出,et,加密类型;timingPort, NTP同步端口, ekey/eiv主要用AES解密,用于后期视频帧的解密处理。
RTSP/1.0 200 OK
Date: Thu, 19 Oct :37 GMT
Server: AirTunes/220.68
Content-Length: 284
3. 关键代码实现
目前能跑通的流程为发现流程、连接流程,相关代码实现如下,音视频数据解密及解码流程还没有仔细去研究。
raop服务发布,相关txt设置如下:
protected ServiceInfo onCreateServiceInfo(byte[] hwAddr, String name, int port) {
String identifier = getStringHardwareAdress(hwAddr)
Map&String, String& txt = new HashMap&String, String&()
txt.put("tp", "UDP")
txt.put("sm", "false")
txt.put("sv", "false")
txt.put("ek", "0")
txt.put("et", "0,1")
txt.put("md", "0,1,2")
txt.put("cn", "0,1")
txt.put("sr", "44100")
txt.put("ch", "2")
txt.put("ss", "16")
txt.put("pw", "false")
txt.put("vn", "3")
txt.put("txtvers", "1")
txt.put("vs", AirPlay.SRCVERS)
txt.put("am",AirPlay.MODEL)
//txt.put("pk", AirTunes.PKSTR)
//txt.put("da", "true")
//txt.put("ft", AirPlay.FEATURES)
txt.put("w", "1")
//txt.put("vn", "65537")
//txt.put("sf", "0x4")
return ServiceInfo
.create(AirTunes.AIR_TUNES_SERVICE_TYPE,
identifier + "@" + name ,
port, 0, 0, txt)
airplay服务发布:
protected ServiceInfo onCreateServiceInfo(byte[] hwAddr, String name, int port) {
String addr = getStringHardwareAdress(hwAddr)
Map&String, String& txt = new HashMap&String, String&()
txt.put("deviceid", addr)
txt.put("features", String.format("0x%04x", AirPlay.FEATURES))
txt.put("model", AirPlay.MODEL)
txt.put("srcvers", AirPlay.SRCVERS)
txt.put("vv", "1")
//txt.put("rhd", "1.9.7")
txt.put("flags", "0x44")
txt.put("pi", AirPlay.PISTR)
txt.put("pk", AirPlay.PKSTR)
return ServiceInfo.create(AirPlay.TYPE, name, port, 0, 0, txt)
3.2 RTSP信令解析
信令相关的代码太多,只截取SETUP命令的处理
if(contentType.equals("application/x-apple-binary-plist")){
NSDictionary dict = (NSDictionary) BinaryPropertyListParser.parse(packet.getContent())
Log.d(TAG,"[SETUP], dict
is "+dict.toXMLPropertyList())
//process ekey && eiv
NSData ekeyData = (NSData)dict.get("ekey")
NSData eivData = (NSData)dict.get("eiv")
if(ekeyData != null && eivData != null){
response.append("Audio-Jack-Status", " type=analog")
String ekey =
(ekeyData).getBase64EncodedData()
String eiv = (eivData).getBase64EncodedData()
mAudioSession = AudioSession.parse(ekey, eiv, mKey)
NSNumber timingportObj = (NSNumber)dict.get("timingPort")
Log.d(TAG,"[SETUP], timingportObj
is "+timingportObj.toString())
timingPort =timingportObj.intValue()
// Address
Pattern p = Pattern.compile("SETUP\\s(rtsp://.*?)\\s")
Matcher m = p.matcher(packet.getRawPacket())
if ( m.find() && mAudioSession != null) {
String uri = m.group(1)
Log.d(TAG, "[SETUP] uri is "+uri+", timingPort is "+timingPort)
InetAddress iaddr = InetAddress.getByName(Uri.parse(uri).getHost())
// Creaet Audio Server
mAudioServer = AudioServer.create(mAudioSession, iaddr, 0, timingPort)
if(mAudioServer != null ){
NSDictionary reponsedict = new NSDictionary()
Log.d(TAG,"local event Port is "+mAudioServer.getServerPort()+
time port is "+mAudioServer.getTimingPort())
reponsedict.put("eventPort",
AirPlay.PORT)
reponsedict.put("timingPort", mAudioServer.getTimingPort())
Log.d(TAG,"[SETUP]response content is"+reponsedict.toXMLPropertyList())
byte[] contents = BinaryPropertyListWriter.writeToArray(reponsedict)
response.append("Content-Length", contents.length+"")
response.setContent(contents, 0, contents.length)
//second SETUP
NSDictionary reponsedict = new NSDictionary()
NSDictionary mirrorDic = new NSDictionary()
mirrorDic.put("dataPort",
mirrorDic.put("type", 110)
reponsedict.put("streams", NSArray.wrap(new NSObject[]{mirrorDic}))
Log.d(TAG,"[SETUP]response content is "+reponsedict.toXMLPropertyList())
byte[] contents = BinaryPropertyListWriter.writeToArray(reponsedict)
//byte[] contents = reponsedict.toXMLPropertyList().getBytes()
response.append("Content-Length", contents.length+"")
response.finalizeHeader()
response.setContent(contents, 0, contents.length)
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace()
} catch (PropertyListFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace()
} catch (Exception e){
e.printStackTrace()
4. 总结与展望
目前实现了设备发现、设备连接功能。但是相关音频及视频解码流程还没有跑通,涉及的内容比较多,能力及精力有限,还没能进一步去研究相关实现及解密解码流程。在前面的步骤中虽然实现了发现和连接,但是有很多字段的含义及用途不清楚,网上能找到的一份协议并非官方并且是比较老的版本,12年以前的,很多流程都已经变更了,参考意义有限。这些字段对后期音视频解码是否影响暂不清楚。后期如果需要进步研究的话,首先需要理清楚前面协议的字段与后面音视频流参数之间的关系,其次,需要搞清楚后期发送的数据包相关头部字段的信息及数据加密类型。最后,最关键的是能够找到相关的解密方法及解码器。如果这些问题解决掉了,最终能够实现镜像功能。
5. 参考文档
[1] Unofficial AirPlay Protocol Specification——
[2] AirPlay协议浅析——
[3] 关于airplay协议实现镜像功能研究——
[4] ios 9.3 POST /pair-setup,POST /pair-verify ——
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!}

我要回帖

更多关于 显示屏响应时间14ms 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信