最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

无线传屏技术 - Android Miracast的实现

IT圈 admin 25浏览 0评论

2024年9月10日发(作者:傅业)

无线传屏技术

—— Android下的Miracast实现

 AirPlay

AirPlay是苹果开发的一致无线技术,可以通过Wi-FiI将iPhone、iPad、iPodTouch等iOS

设备上的包括图片、音频、视频通过无线的方式传输到支持AirPlay设备。

AirPlay具备DLNA所没有的镜像功能(AirPlay镜像),可将iPhone或iPad上的画面无线

传输到电视上,即设备显示的是什么,电视屏幕显示的就是什么,而不仅限于图片和视频,

你可以拿着iPad来当做方向盘,看着大屏玩游戏。AirPlay镜像最牛的地方是可以实现双屏

游戏,让你的游戏有更多的交互,比如电视里显示的是游戏画面,而iPad上显示的是比赛

的路线图。

目前,AirPlay只适用于认证过的苹果设备,主要是苹果自己的设备,包括iPad、iPhone、

Apple TV等,和一些苹果授权的合作伙伴的设备,如向Pioneer和Sony提供技术授权的音响。

 DLNA

DLNA:Digital Living Network Alliance,是索尼、英特尔、微软等发起的一套PC、移动设

备、消费电器之间互联互通的协议,其宗旨是“随时随地享受音乐、照片和视频”。

DLNA与AirPlay功能比较类似,协议也大体相同,他们都可以让你手机中的媒体内容投

放到电视屏幕上。不同的是手机上的DLNA并没有类似Apple TV的AirPlay镜像功能,也没

有Apple TV所支持的双屏体游戏体验。目前DLNA更多只是能将手机的照片和视频投送到大

屏幕中。

另外,在线视频也可以用DLNA模式推送到客厅电视上显示,安卓系统部分播放器就具

备DLNA功能,目前支持无线推送的视频客户端有:腾讯视频、搜狐视频、PPTV视频。前

提是你有能支持DLNA的电视或电视盒。

DLNA是基于文件的,媒体文件可能有各种各样的编码格式,播放器这端必须能够处理

这么多种编码格式,通常为了比较好的播放体验,DLNA会先缓存一小段时间。

 Miracast

Miracast是由Wi-Fi联盟与2012年所制定,以Wi-Fi直连为基础的无线显示标准。支持

此标准的设备可通过无线方式分享视频画面,例如手机壳通过Miracast将影片或照片直接在

电视或其它装置播放而无需受到连接线缆长度的影响。与DLNA不同的是,Miracast也有类

似于AirPlay的镜像功能,可以将手机中屏幕内容直接投放到高清电视屏幕里,这样你也可

以通过电视屏幕来玩游戏了。Android4.2版本以后系统标配此功能(在设置或显示菜单中可

以找到,应用名称诸如:Wlan display、Wifi display、Miracast、Allshare cast、Mirroring screen、

无线显示等,只是各厂家命名不同而已)。可以将手机屏幕通过无线显示接收器将画面无线

传输到其它较大屏幕上,画面传输延迟150ms以下。

Miracast是实时的,它可以实时传输源端(Source)的输出,源端任何屏幕的操作都会

被传输到接收(Sink)端。如果源端是播放媒体文件,源端负责先对媒体文件解码,然后再

编码为H.264格式,接收端只需要做H.264的解码就可以了。相对DLNA,Miracast对于WiFi

通路的要求要更高一些。

 Android下的Miracast实现

实际上,Miracast是Wi-Fi联盟(Wi-Fi Alliance)对支持Wi-Fi Display功能的设备的认证

名称。通过Miracast认证的设备将在最大程度内保持对Wi-Fi Display功能的支持和兼容。由

此可知,Miracast考察的就是Wi-Fi Display(本文后续将不再区分Miracast和Wi-Fi Display)。

而Wi-Fi Display的核心功能就是让设备之间通过Wi-Fi无线网络来分享视音频数据。图1

所示为Wi-Fi Display中使用的其它Wi-Fi技术项。

Wi-Fi Miracast

Wi-Fi Protect Setup

11n/WMM/WPA2

图1 Miracast的支撑体系结构

Wi-Fi Direct:即Wi-Fi P2P,支持在没有AP(Access Point)的情况下,两个Wi-Fi

Wi-Fi Direct

设备直连并通信。

 Wi-Fi Protect Setup:用于帮助用户自动配置Wi-Fi网络、添加Wi-Fi设备等。

 11n/WMM/WPA2:其中11n指802.11n协议;WMM即Wi-Fi MultiMedia,是一种

针对实时视音频数据的QoS服务;而WPA2即Wi-Fi Protected Access第二版,主要用来给传

输的数据进行加密保护。

上述技术展,绝大部分功能由硬件厂商实现,而在Android中,对Miracast来说最重要

的是两个基础技术:一是Wi-Fi Direct,该功能由Android中的WifiP2pService来管理和控制;

一是Wi-Fi MultiMedia,为了支持Miracast,Android 4.2对MultiMedia系统也进行了修改。

Miracast的拓扑结构如图2所示,所支持的视音频格式如表1。

图2 Miracast的四种拓扑结构

分辨率 17种CEA格式,分辨率从640x480到1920x1080,帧率从24到60

29种VESA格式,分辨率从800x600到1920x1080,帧率从30到60

12种手持设备格式,分辨率从640x360到960x540,帧率从30到60

视频

音频

H.264高清

必选:LPCM 16bits,48kHz采样率,双声道

可选:LPCM 16bits,44.1kHz采样率,双声道

Advanced Audio coding

Dolby Advanced Codec 3

表1 Miracast视音频格式支持

Miracast以session为单位来管理两个设备之间的交互工作,主要步骤包括(按顺序):

 Device Discovery:通过Wi-Fi P2P来查找附近支持Wi-Fi P2P的设备。

 Device Selection:当设备A发现设备B后,A设备需要提示用户。用户可根据需要选

择是否和设备B配对。

 Connection Setup:Source和Display设备之间通过Wi-Fi P2P建立连接。根据Wi-Fi

Direct技术规范,这个步骤包括建立一个Group Owner和一个Client。此后,这两个设备将

建立一个TCP连接,同时一个用于RTSP协议的端口将被创建用于后续的Session管理和控制

工作。

 Capability Negotiation:在正式传输视音频数据前,Source和Display设备需要交换一

些Miracast参数信息,如双方所支持的视音频格式,二者协商成功后,才能继续后面的流程。

 Session Establishment and Streaming:上一步工作完成后,Source和Display设备将建

立一个Miracast Session,而后就可以开始传输视音频数据。Source端的视音频数据将经由

MPEG2TS编码后通过RTP协议传给Display设备,Display设备将解码收到的数据并显示出来。

 User Input back channel setup:这是一个可选步骤,主要用于在传输过程中处理用户

发起的一些控制操作,这些控制数据通过TCP在Source和Display设备之间传递。

 Payload Control:传输过程中,设备可根据无线信号的强弱,甚至设备的电量状况来

动态调整传输数据和格式。可调整的内容包括压缩率,视音频格式,分辨率等内容。

 Session teardown:停止整个Session。

综上所述,Miracast本质上就是一个包括服务端和客户端的基于Wi-Fi的网络应用,服

务端和客户端必须支持RTP/RTSP等网络协议和相应的编解码技术。

Miracast的Android实现涉及到系统的多个模块,包括:

 MediaPlayerService及相关模块:因为Miracast本身就涉及到RTP/RTSP及相应的编

解码技术。

 SurfaceFlinger及相关模块:SurfaceFlinger的作用是将各层UI数据混屏并投递到显

示设备中去显示。现在,SurfaceFlinger支持多个显示设备,而支持Miracast的远端设备也作

为一个独立的显示设备存在于系统中。

 WindowManagerService及相关模块:WindowManagerService用于管理系统中各个

UI层的位置和属性。由于并非所有的UI层都会通过Miracast投递到远端设备上,例如手机

中的视频可投递到远端设备上去显示,但假如在播放过程中,突然弹出一个密码输入框(可

能是某个后台应用程序发起的),则这个密码输入框就不能投递到远端设备上去显示。所以,

WindowManagerService也需要修改以适应Miracast的需要。

 DisplayManagerService及相关模块:DisplayManagerService服务是Android 4.2新

增的,用于管理系统中所有的Display设备。

1. SurfaceFlinger对Miracast的支持

相比前面的版本,Android 4.2中SurfaceFlinger的最大变化就是增加了一个名为

DisplayDevice的抽象层。相关结构如图3所示。

图3 SurfaceFlinger家族类图

 Surface系统定义了一个DisplayType的枚举,其中有代表手机屏幕的

DISPLAY_PRIMARY和代表HDMI等外接设备的DISPLAY_EXTERNAL。比较有意思的是,

作为Wi-Fi Display,它的设备类型是DISPLAY_VIRTUAL。

 SurfaceFlinger类,其内部有一个名为mDisplays的变量,它保存了系统中当前所有

的显示设备(DisplayDevice)。另外,SurfaceFlinger通过mCurrentState和mDrawingState来

控制显示层的状态。其中,mDrawingState用来控制当前正在绘制的显示层的状态,

mCurrentState表示当前所有显示层的状态。有这两种State显示层的原因是不论是Miracast

还是HDMI设备,其在系统中存在的时间是不确定的。例如用户可以随时选择连接一个

Miracast显示设备。为了不破坏当前正在显示的内容,这个新显示设备的一些信息将保存到

CurrentState中。等到SurfaceFlinger下次混屏前再集中处理。

 mCurrentState和mDrawingState的类型都是SurfaceFlinger的内部类State。由图3

可知,State首先通过layerSortedByZ变量保存了一个按Z轴排序的显示层数组(在Android

中,显示层的基类是LayerBase),另外还通过displays变量保存了每个显示层对应的

DisplayDeviceState。

 DisplayDeviceState的作用是保存对应显示层的DisplayDevice的属性以及一个

ISurfaceTexure接口。这个接口最终将传递给DisplayDevice。

 DisplayDevice代表显示设备,它有两个重要的变量,一个是mFrameBufferSurface

和mNativeWindow。mFrameBufferSurace是FrameBufferSurface类型,当显示设备不属于

VIRTUAL类型的话,则该变量不为空。对于Miracast来说,显示数据是通过网络传递给真

正的显示设备的,所有在Source端的SurfaceFlinger来说,就不存在FrameBuffer。故当设

备为VIRTUAL时,其对应的mFrameBufferSurface就为空。而ANativeWindow是Android

显示系统的老员工了。该结构体在多媒体的视频I/O、OpenGL ES等地方用得较多。而在普

通的UI绘制中,ISurfaceTexture接口用得较多。不过早在Android 2.3,Google开发人员就

通过函数指针将ANativeWindow的各项操作和ISurfaceTexture接口统一起来。

作为VIRTUAL的Miracast设备是如何通过DisplayDevice这一层抽象来加入到Surface

系统中来的呢?下面这段代码对理解DisplayDevice的抽象作用极为重要。如图4所示。

图4 SurfaceFlinger代码片段

由上图代码可知:

 对于非Virtual设备,DisplayDevice的FrameBufferSurface不为空。而且

SurfaceTextureClient的构造参数来自于FrameBufferSurface的getBufferQueue函数。

 如果是Virtual设备,SurfaceTextureClient直接使用了State信息中携带的surface

变量。

据此,可以推测出如图5所示的DisplayDevice的作用。

图5 DisplayDevice的隔离示意图

然后再来看看SurfaceFlinger中混屏操作的实现,代码如图6所示。

图6 SurfaceFlinger的混屏操作

由上可知,SurfaceFlinger将遍历系统中所有的DisplayDevice来完成各自的混屏工作。

2. Framework对Miracast的支持

为了彻底解决多显示设备的问题,Android 4.2在Framework中新增了一个名为

DisplayManagerService的服务,用来统一管理系统中的显示设备。DisplayManagerService和

系统其它几个服务都有交互。整体结构如图7所示。

图7 DisplayManagerService及相关类图

 DisplayManagerService主要实现了IDisplayManager接口。这个接口的大部分函数

都和Wi-Fi Display操作相关。

 DisplayManagerService和WindowManagerService交互紧密。因为

WindowManagerService管理系统所有UI显示,包括属性,Z轴位置等等。而且,

WindowManagerService是系统内部和SurfaceFlinger交互的重要通道。

 DisplayManagerService通过mDisplayAdapters来和DisplayDevice交互。每一个

DisplayDevice都对应有一个DisplayAdapter。

 系统定义了四种DisplayAdapter。HeadlessDisplayAdapter和OverlayDisplayAdapter

针对的都是Fake设备。其中OverlayDisplay用于帮助开发者模拟多屏幕之用。

LocalDisplayAdapter代表主屏幕,而WifiDisplayAdapter代表Wi-Fi Display。

3. Android中Miracast动态工作流程介绍

当用户从Settings程序中选择开启Miracast并找到匹配的Device后,系统将通过

WifiDisplayController的requestConnect函数向匹配设备发起连接。代码如下所示:

Public void requestConnect(String address){

for(WifiP2pDevice device:mAvailableWifiDisplayPeers){

if((address)){

connect(device);

}

}

}

连接指定设备的connect函数中,最重要的是updateConnection函数,我们抽取其中部

分代码来看,如图8所示:

图8 updateConnection函数片段

在上述代码中,系统创建了一个RemoteDisplay,并在此Display上监听(listen)。从注释

中可知,该RemoteDisplay就是和远端Device交互的RTP/RTSP通道,而且,一旦有远端Device

连接上,还会通过onDisplayConnected返回一个Surface对象。

根据前面对SurfaceFlinger的介绍,读者可以猜测出Miracast的重头好戏就在

RemoteDisplay以及它返回的这个Surface上了。确实如此,RemoteDisplay将调用

MediaPlayerService的listenForRemoteDisplay函数,最终会得到一个Native的RemoteDisplay

对象。相关类图如图9所示,由图9可知,RemoteDisplay有三个重要成员变量:

 mLooper:指向一个ALooper对象。这表明RemoteDisplay是一个基于消息派发和

处理的系统。

 mNetSession:指向一个ANetWorkSession对象。ANetWorkSession提供大部分的网

络操作。

 mSource:指向一个WifiDisplaySource对象。它从AHandler派生,是mLooper中消

息的处理者。注意,图中的M1、M3、M5等都是Wi-Fi Display技术规范中指定的消息名。

图9 RemoteDisplay类图

RemoteDisplay构造函数中,WifiDisplaySource的start函数将被调用。如此,一个类型

为kWhatStart的消息被加到消息队列中。该消息最终被WifiDisplaySource处理,结果是一

个RTSPServer被创建。代码如下所示:

If (err == OK) {

If (inet_aton(iface.c_str(), &mInterfaceAddr != 0) {

sp notify = new AMessage(kWhatRTSPNotify, id());

err = mNetSession->createRTSPServer(mInterfaceAddr, port, notify, &mSessionID);

} else {

err = -EINVAL;

}

}

之后,客户端发送的数据都将通过类型为kWhatRTSPNotify的消息加入到系统中来。

而这个消息的处理核心在onReceiveClientData函数中,它囊括了设备之间网络交互的所有细

节。其核心代码如图10所示。

图10 onReceiveClientData核心代码

根据前面的背景知识介绍,设备之间的交互将由Session来管理。在代码中,Session的

概念由WifiSource的内部类PlaybackSession来表示。先来看和其相关的类图结构,如图11

所示:

图11 PlaybackSession及相关类图

PlaybackSession及其内部类Track都从AHandler派生。故它们的工作也依赖于消

Track内部通过mMediaPull变量指向一个MediaPull对象。而MediaPull对象则保

息循环和处理。Track代表视频流或音频流。

存了一个MediaSource对象。在PlaybackSession中,此MediaSource的真正类型为

SurfaceMediaSource。它表明该Media的源来自Surface。

 BufferQueue从ISurfaceTexure中派生,根据前面对SurfaceFlinger的介绍,它就是

SurfaceFlinger代码示例中代表虚拟设备的State的surface变量。

当双方设备准备就绪后,MediaPull会通过kWhatPull消息处理不断调用MediaSource

的read函数。在SurfaceMediaSource实现的read函数中,来自SurfaceFlinger的混屏后的数

据经由BufferQueue传递到MediaPull中。代码如图12所示:

图12 MediaPull和SurfaceMediaSource的代码示意

从上图可知,MediaPull通过kWhatPull消息不断调用MediaSource的read函数;

SurfaceMediaSource的read函数通过mBufferQueue来读取数据。那么,mBufferQueue的数

据来自哪里呢?对,正是来自图4的SurfaceFlinger。然后,PlaybackSession拿到这些数据后

做编码,发送给远端设备。

2024年9月10日发(作者:傅业)

无线传屏技术

—— Android下的Miracast实现

 AirPlay

AirPlay是苹果开发的一致无线技术,可以通过Wi-FiI将iPhone、iPad、iPodTouch等iOS

设备上的包括图片、音频、视频通过无线的方式传输到支持AirPlay设备。

AirPlay具备DLNA所没有的镜像功能(AirPlay镜像),可将iPhone或iPad上的画面无线

传输到电视上,即设备显示的是什么,电视屏幕显示的就是什么,而不仅限于图片和视频,

你可以拿着iPad来当做方向盘,看着大屏玩游戏。AirPlay镜像最牛的地方是可以实现双屏

游戏,让你的游戏有更多的交互,比如电视里显示的是游戏画面,而iPad上显示的是比赛

的路线图。

目前,AirPlay只适用于认证过的苹果设备,主要是苹果自己的设备,包括iPad、iPhone、

Apple TV等,和一些苹果授权的合作伙伴的设备,如向Pioneer和Sony提供技术授权的音响。

 DLNA

DLNA:Digital Living Network Alliance,是索尼、英特尔、微软等发起的一套PC、移动设

备、消费电器之间互联互通的协议,其宗旨是“随时随地享受音乐、照片和视频”。

DLNA与AirPlay功能比较类似,协议也大体相同,他们都可以让你手机中的媒体内容投

放到电视屏幕上。不同的是手机上的DLNA并没有类似Apple TV的AirPlay镜像功能,也没

有Apple TV所支持的双屏体游戏体验。目前DLNA更多只是能将手机的照片和视频投送到大

屏幕中。

另外,在线视频也可以用DLNA模式推送到客厅电视上显示,安卓系统部分播放器就具

备DLNA功能,目前支持无线推送的视频客户端有:腾讯视频、搜狐视频、PPTV视频。前

提是你有能支持DLNA的电视或电视盒。

DLNA是基于文件的,媒体文件可能有各种各样的编码格式,播放器这端必须能够处理

这么多种编码格式,通常为了比较好的播放体验,DLNA会先缓存一小段时间。

 Miracast

Miracast是由Wi-Fi联盟与2012年所制定,以Wi-Fi直连为基础的无线显示标准。支持

此标准的设备可通过无线方式分享视频画面,例如手机壳通过Miracast将影片或照片直接在

电视或其它装置播放而无需受到连接线缆长度的影响。与DLNA不同的是,Miracast也有类

似于AirPlay的镜像功能,可以将手机中屏幕内容直接投放到高清电视屏幕里,这样你也可

以通过电视屏幕来玩游戏了。Android4.2版本以后系统标配此功能(在设置或显示菜单中可

以找到,应用名称诸如:Wlan display、Wifi display、Miracast、Allshare cast、Mirroring screen、

无线显示等,只是各厂家命名不同而已)。可以将手机屏幕通过无线显示接收器将画面无线

传输到其它较大屏幕上,画面传输延迟150ms以下。

Miracast是实时的,它可以实时传输源端(Source)的输出,源端任何屏幕的操作都会

被传输到接收(Sink)端。如果源端是播放媒体文件,源端负责先对媒体文件解码,然后再

编码为H.264格式,接收端只需要做H.264的解码就可以了。相对DLNA,Miracast对于WiFi

通路的要求要更高一些。

 Android下的Miracast实现

实际上,Miracast是Wi-Fi联盟(Wi-Fi Alliance)对支持Wi-Fi Display功能的设备的认证

名称。通过Miracast认证的设备将在最大程度内保持对Wi-Fi Display功能的支持和兼容。由

此可知,Miracast考察的就是Wi-Fi Display(本文后续将不再区分Miracast和Wi-Fi Display)。

而Wi-Fi Display的核心功能就是让设备之间通过Wi-Fi无线网络来分享视音频数据。图1

所示为Wi-Fi Display中使用的其它Wi-Fi技术项。

Wi-Fi Miracast

Wi-Fi Protect Setup

11n/WMM/WPA2

图1 Miracast的支撑体系结构

Wi-Fi Direct:即Wi-Fi P2P,支持在没有AP(Access Point)的情况下,两个Wi-Fi

Wi-Fi Direct

设备直连并通信。

 Wi-Fi Protect Setup:用于帮助用户自动配置Wi-Fi网络、添加Wi-Fi设备等。

 11n/WMM/WPA2:其中11n指802.11n协议;WMM即Wi-Fi MultiMedia,是一种

针对实时视音频数据的QoS服务;而WPA2即Wi-Fi Protected Access第二版,主要用来给传

输的数据进行加密保护。

上述技术展,绝大部分功能由硬件厂商实现,而在Android中,对Miracast来说最重要

的是两个基础技术:一是Wi-Fi Direct,该功能由Android中的WifiP2pService来管理和控制;

一是Wi-Fi MultiMedia,为了支持Miracast,Android 4.2对MultiMedia系统也进行了修改。

Miracast的拓扑结构如图2所示,所支持的视音频格式如表1。

图2 Miracast的四种拓扑结构

分辨率 17种CEA格式,分辨率从640x480到1920x1080,帧率从24到60

29种VESA格式,分辨率从800x600到1920x1080,帧率从30到60

12种手持设备格式,分辨率从640x360到960x540,帧率从30到60

视频

音频

H.264高清

必选:LPCM 16bits,48kHz采样率,双声道

可选:LPCM 16bits,44.1kHz采样率,双声道

Advanced Audio coding

Dolby Advanced Codec 3

表1 Miracast视音频格式支持

Miracast以session为单位来管理两个设备之间的交互工作,主要步骤包括(按顺序):

 Device Discovery:通过Wi-Fi P2P来查找附近支持Wi-Fi P2P的设备。

 Device Selection:当设备A发现设备B后,A设备需要提示用户。用户可根据需要选

择是否和设备B配对。

 Connection Setup:Source和Display设备之间通过Wi-Fi P2P建立连接。根据Wi-Fi

Direct技术规范,这个步骤包括建立一个Group Owner和一个Client。此后,这两个设备将

建立一个TCP连接,同时一个用于RTSP协议的端口将被创建用于后续的Session管理和控制

工作。

 Capability Negotiation:在正式传输视音频数据前,Source和Display设备需要交换一

些Miracast参数信息,如双方所支持的视音频格式,二者协商成功后,才能继续后面的流程。

 Session Establishment and Streaming:上一步工作完成后,Source和Display设备将建

立一个Miracast Session,而后就可以开始传输视音频数据。Source端的视音频数据将经由

MPEG2TS编码后通过RTP协议传给Display设备,Display设备将解码收到的数据并显示出来。

 User Input back channel setup:这是一个可选步骤,主要用于在传输过程中处理用户

发起的一些控制操作,这些控制数据通过TCP在Source和Display设备之间传递。

 Payload Control:传输过程中,设备可根据无线信号的强弱,甚至设备的电量状况来

动态调整传输数据和格式。可调整的内容包括压缩率,视音频格式,分辨率等内容。

 Session teardown:停止整个Session。

综上所述,Miracast本质上就是一个包括服务端和客户端的基于Wi-Fi的网络应用,服

务端和客户端必须支持RTP/RTSP等网络协议和相应的编解码技术。

Miracast的Android实现涉及到系统的多个模块,包括:

 MediaPlayerService及相关模块:因为Miracast本身就涉及到RTP/RTSP及相应的编

解码技术。

 SurfaceFlinger及相关模块:SurfaceFlinger的作用是将各层UI数据混屏并投递到显

示设备中去显示。现在,SurfaceFlinger支持多个显示设备,而支持Miracast的远端设备也作

为一个独立的显示设备存在于系统中。

 WindowManagerService及相关模块:WindowManagerService用于管理系统中各个

UI层的位置和属性。由于并非所有的UI层都会通过Miracast投递到远端设备上,例如手机

中的视频可投递到远端设备上去显示,但假如在播放过程中,突然弹出一个密码输入框(可

能是某个后台应用程序发起的),则这个密码输入框就不能投递到远端设备上去显示。所以,

WindowManagerService也需要修改以适应Miracast的需要。

 DisplayManagerService及相关模块:DisplayManagerService服务是Android 4.2新

增的,用于管理系统中所有的Display设备。

1. SurfaceFlinger对Miracast的支持

相比前面的版本,Android 4.2中SurfaceFlinger的最大变化就是增加了一个名为

DisplayDevice的抽象层。相关结构如图3所示。

图3 SurfaceFlinger家族类图

 Surface系统定义了一个DisplayType的枚举,其中有代表手机屏幕的

DISPLAY_PRIMARY和代表HDMI等外接设备的DISPLAY_EXTERNAL。比较有意思的是,

作为Wi-Fi Display,它的设备类型是DISPLAY_VIRTUAL。

 SurfaceFlinger类,其内部有一个名为mDisplays的变量,它保存了系统中当前所有

的显示设备(DisplayDevice)。另外,SurfaceFlinger通过mCurrentState和mDrawingState来

控制显示层的状态。其中,mDrawingState用来控制当前正在绘制的显示层的状态,

mCurrentState表示当前所有显示层的状态。有这两种State显示层的原因是不论是Miracast

还是HDMI设备,其在系统中存在的时间是不确定的。例如用户可以随时选择连接一个

Miracast显示设备。为了不破坏当前正在显示的内容,这个新显示设备的一些信息将保存到

CurrentState中。等到SurfaceFlinger下次混屏前再集中处理。

 mCurrentState和mDrawingState的类型都是SurfaceFlinger的内部类State。由图3

可知,State首先通过layerSortedByZ变量保存了一个按Z轴排序的显示层数组(在Android

中,显示层的基类是LayerBase),另外还通过displays变量保存了每个显示层对应的

DisplayDeviceState。

 DisplayDeviceState的作用是保存对应显示层的DisplayDevice的属性以及一个

ISurfaceTexure接口。这个接口最终将传递给DisplayDevice。

 DisplayDevice代表显示设备,它有两个重要的变量,一个是mFrameBufferSurface

和mNativeWindow。mFrameBufferSurace是FrameBufferSurface类型,当显示设备不属于

VIRTUAL类型的话,则该变量不为空。对于Miracast来说,显示数据是通过网络传递给真

正的显示设备的,所有在Source端的SurfaceFlinger来说,就不存在FrameBuffer。故当设

备为VIRTUAL时,其对应的mFrameBufferSurface就为空。而ANativeWindow是Android

显示系统的老员工了。该结构体在多媒体的视频I/O、OpenGL ES等地方用得较多。而在普

通的UI绘制中,ISurfaceTexture接口用得较多。不过早在Android 2.3,Google开发人员就

通过函数指针将ANativeWindow的各项操作和ISurfaceTexture接口统一起来。

作为VIRTUAL的Miracast设备是如何通过DisplayDevice这一层抽象来加入到Surface

系统中来的呢?下面这段代码对理解DisplayDevice的抽象作用极为重要。如图4所示。

图4 SurfaceFlinger代码片段

由上图代码可知:

 对于非Virtual设备,DisplayDevice的FrameBufferSurface不为空。而且

SurfaceTextureClient的构造参数来自于FrameBufferSurface的getBufferQueue函数。

 如果是Virtual设备,SurfaceTextureClient直接使用了State信息中携带的surface

变量。

据此,可以推测出如图5所示的DisplayDevice的作用。

图5 DisplayDevice的隔离示意图

然后再来看看SurfaceFlinger中混屏操作的实现,代码如图6所示。

图6 SurfaceFlinger的混屏操作

由上可知,SurfaceFlinger将遍历系统中所有的DisplayDevice来完成各自的混屏工作。

2. Framework对Miracast的支持

为了彻底解决多显示设备的问题,Android 4.2在Framework中新增了一个名为

DisplayManagerService的服务,用来统一管理系统中的显示设备。DisplayManagerService和

系统其它几个服务都有交互。整体结构如图7所示。

图7 DisplayManagerService及相关类图

 DisplayManagerService主要实现了IDisplayManager接口。这个接口的大部分函数

都和Wi-Fi Display操作相关。

 DisplayManagerService和WindowManagerService交互紧密。因为

WindowManagerService管理系统所有UI显示,包括属性,Z轴位置等等。而且,

WindowManagerService是系统内部和SurfaceFlinger交互的重要通道。

 DisplayManagerService通过mDisplayAdapters来和DisplayDevice交互。每一个

DisplayDevice都对应有一个DisplayAdapter。

 系统定义了四种DisplayAdapter。HeadlessDisplayAdapter和OverlayDisplayAdapter

针对的都是Fake设备。其中OverlayDisplay用于帮助开发者模拟多屏幕之用。

LocalDisplayAdapter代表主屏幕,而WifiDisplayAdapter代表Wi-Fi Display。

3. Android中Miracast动态工作流程介绍

当用户从Settings程序中选择开启Miracast并找到匹配的Device后,系统将通过

WifiDisplayController的requestConnect函数向匹配设备发起连接。代码如下所示:

Public void requestConnect(String address){

for(WifiP2pDevice device:mAvailableWifiDisplayPeers){

if((address)){

connect(device);

}

}

}

连接指定设备的connect函数中,最重要的是updateConnection函数,我们抽取其中部

分代码来看,如图8所示:

图8 updateConnection函数片段

在上述代码中,系统创建了一个RemoteDisplay,并在此Display上监听(listen)。从注释

中可知,该RemoteDisplay就是和远端Device交互的RTP/RTSP通道,而且,一旦有远端Device

连接上,还会通过onDisplayConnected返回一个Surface对象。

根据前面对SurfaceFlinger的介绍,读者可以猜测出Miracast的重头好戏就在

RemoteDisplay以及它返回的这个Surface上了。确实如此,RemoteDisplay将调用

MediaPlayerService的listenForRemoteDisplay函数,最终会得到一个Native的RemoteDisplay

对象。相关类图如图9所示,由图9可知,RemoteDisplay有三个重要成员变量:

 mLooper:指向一个ALooper对象。这表明RemoteDisplay是一个基于消息派发和

处理的系统。

 mNetSession:指向一个ANetWorkSession对象。ANetWorkSession提供大部分的网

络操作。

 mSource:指向一个WifiDisplaySource对象。它从AHandler派生,是mLooper中消

息的处理者。注意,图中的M1、M3、M5等都是Wi-Fi Display技术规范中指定的消息名。

图9 RemoteDisplay类图

RemoteDisplay构造函数中,WifiDisplaySource的start函数将被调用。如此,一个类型

为kWhatStart的消息被加到消息队列中。该消息最终被WifiDisplaySource处理,结果是一

个RTSPServer被创建。代码如下所示:

If (err == OK) {

If (inet_aton(iface.c_str(), &mInterfaceAddr != 0) {

sp notify = new AMessage(kWhatRTSPNotify, id());

err = mNetSession->createRTSPServer(mInterfaceAddr, port, notify, &mSessionID);

} else {

err = -EINVAL;

}

}

之后,客户端发送的数据都将通过类型为kWhatRTSPNotify的消息加入到系统中来。

而这个消息的处理核心在onReceiveClientData函数中,它囊括了设备之间网络交互的所有细

节。其核心代码如图10所示。

图10 onReceiveClientData核心代码

根据前面的背景知识介绍,设备之间的交互将由Session来管理。在代码中,Session的

概念由WifiSource的内部类PlaybackSession来表示。先来看和其相关的类图结构,如图11

所示:

图11 PlaybackSession及相关类图

PlaybackSession及其内部类Track都从AHandler派生。故它们的工作也依赖于消

Track内部通过mMediaPull变量指向一个MediaPull对象。而MediaPull对象则保

息循环和处理。Track代表视频流或音频流。

存了一个MediaSource对象。在PlaybackSession中,此MediaSource的真正类型为

SurfaceMediaSource。它表明该Media的源来自Surface。

 BufferQueue从ISurfaceTexure中派生,根据前面对SurfaceFlinger的介绍,它就是

SurfaceFlinger代码示例中代表虚拟设备的State的surface变量。

当双方设备准备就绪后,MediaPull会通过kWhatPull消息处理不断调用MediaSource

的read函数。在SurfaceMediaSource实现的read函数中,来自SurfaceFlinger的混屏后的数

据经由BufferQueue传递到MediaPull中。代码如图12所示:

图12 MediaPull和SurfaceMediaSource的代码示意

从上图可知,MediaPull通过kWhatPull消息不断调用MediaSource的read函数;

SurfaceMediaSource的read函数通过mBufferQueue来读取数据。那么,mBufferQueue的数

据来自哪里呢?对,正是来自图4的SurfaceFlinger。然后,PlaybackSession拿到这些数据后

做编码,发送给远端设备。

发布评论

评论列表 (0)

  1. 暂无评论