Reference:
Android Wi-Fi Display(Miracast)介绍
Performance Analysis of H.264/AVC, H.264/SVC, and VP8 over IEEE 802.11 Wireless Networks
WiFi Display概念
Miracast是Wi-Fi聯盟(Wi-Fi Alliance)對支持Wi-Fi Display功能的設備的認證名稱。通過Miracast認證的設備將在最大程度內保持對Wi-Fi Display功能的支持和兼容。Wi-Fi Display的核心功能就是讓設備之間通過Wi-Fi無線網路來分享視音頻數據。
圖1 Miracast的支撐體系結構
- Wi-Fi Direct:也就是Wi-Fi P2P。它支持在沒有AP(Access Point)的情況下,兩個Wi-Fi設備直連並通信。
- Wi-Fi Protected Setup:用於幫助用戶自動配置Wi-Fi網路、添加Wi-Fi設備等。
- 11n/WMM/WPA2:
- 11n就是802.11n協議,它將11a和11g提供的Wi-Fi傳輸速率從56Mbps提升到300甚至600Mbps。
- WMM是Wi-Fi Multimedia的縮寫,是一種針對實時視音頻數據的QoS服務。
- WPA2意為Wi-Fi Protected Acess第二版,主要用來給傳輸的數據進行加密保護
Android中,對Miracast來說最重要的是兩個基礎技術:
- Wi-Fi Direct:該功能由Android中的WifiP2pService來管理和控制。
- Wi-Fi Multimedia:為了支持Miracast,Android 4.2對MultiMedia系統也進行了修改
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。
Android 4.2 Miracast功能實現介紹
- MediaPlayerService及相關模塊:因為Miracast本身就牽扯到RTP/RTSP及相應的編解碼技術。
- SurfaceFlinger及相關模塊:SurfaceFlinger的作用是將各層UI數據混屏並投遞到顯示設備中去顯示。現在,SurfaceFlinger將支持多個顯示設備。而支持Miracast的遠端設備也做為一個獨立的顯示設備存在於系統中。
- WindowManagerService及相關模塊:WindowManagerService用於管理系統中各個UI層的位置和屬性。由於並非所有的UI層都會通過Miracast投遞到遠端設備上。例如手機中的視頻可投遞到遠端設備上去顯示,但假如在播放過程中,突然彈出一個密碼輸入框(可能是某個後台應用程序發起的),則這個密碼輸入框就不能投遞到遠端設備上去顯示。所以,WindowManagerService也需要修改以適應Miracast的需要。
- DisplayManagerService及相關模塊:DisplayManagerService服務是Android 4.2新增的,用於管理系統中所有的Display設備。
SurfaceFlinger對Miracast的支持
- 圖3 SurfaceFlinger家族類圖
Surface系統定義了一個DisplayType的枚舉,其中有代表手機屏幕的DISPLAY_PRIMARY和代表HDMI等外接設備的DISPLAY_EXTERNAL。比較有意思的是,作為Wi-Fi Display,它的設備類型是DISPLAY_VIRTUAL。
SurfaceFlinger
- mDisplays的變數:它保存了系統中當前所有的顯示設備(DisplayDevice)。
- mDrawingState:用來控制當前正在繪製的顯示層的狀態
- mCurrentState:表示當前所有顯示層的狀態。
有mDrawingState和mCurrentState顯示層的原因是不論是Miracast還是HDMI設備,其在系統中存在的時間是不確定的。例如用戶可以隨時選擇連接一個Miracast顯示設備。為了不破壞當前正在顯示的內容,這個新顯示設備的一些信息將保存到CurrentState中。等到SurfaceFlinger下次混屏前再集中處理。
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設備,DisplayDevice的FrameBufferSurface不為空。而且SurfaceTextureClient的構造參數來自於FrameBufferSurface的getBufferQueue函數。
- 如果是Virtual設備,SurfaceTextureClient直接使用了State信息中攜帶的surface變數。
- 圖5 DisplayDevice的隔離示意圖
Framework對Miracast的支持
為了徹底解決多顯示設備的問題,Android 4.2乾脆在Framework中新增了一個名為DisplayManagerService的服務,用來統一管理系統中的顯示設備
- 圖: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
Android中Miracast動態工作流程介紹
- 圖:updateConnection函數片段
當用戶從Settings程序中選擇開啟Miracast並找到匹配的Device後,系統將通過WifiDisplayController的requestConnect函數向匹配設備發起連接,最終將調用connect函數去連接指定的設備。系統創建了一個RemoteDisplay,並在這個Display上監聽(listen)。從註釋中可知,該RemoteDisplay就是和遠端Device交互的RTP/RTSP通道。而且,一旦有遠端Device連接上,還會通過onDisplayConnected返回一個Surface對象。
- 圖:RemoteDisplay類圖
RemoteDisplay將調用MediaPlayerService的listenForRemoteDisplay函數,最終會得到一個Native的RemoteDisplay對象
RemoteDisplay有三個重要成員變量:
- mLooper,指向一個ALooper對象。這表明RemoteDisplay是一個基於消息派發和處理的系統。
- mNetSession指向一個ANetWorkSession對象。從它的API來看,ANetworkSession提供大部分的網絡操作。
- mSource指向一個WifiDisplaySource對象。它從AHandler派生,故它就是mLooper中消息的處理者。注意,圖中的M1、M3、M5等都是Wi-Fi Display技術規範中指定的消息名。
RemoteDisplay構造函數中,WifiDisplaySource的start函數將被調用。如此,一個類型為kWhatStart的消息被加到消息隊列中。該消息最終被WifiDisplaySource處理,結果是一個RTSPServer被創建,如下圖所示
- 圖:kWhatStart消息的處理結果
以後,客戶端發送的數據都將通過類型為kWhatRTSPNotify的消息加入到系統中來。而這個消息的處理核心在onReceiveClientData函數中,它囊括了設備之間網絡交互的所有細節。其核心代碼如下圖所示:
- 圖:onReceiveClientData核心代碼示意
根據前面的背景知識介紹,設備之間的交互將由Session來管理。在代碼中,Session的概念由WifiSource的內部類PlaybackSession來表示。
- 圖:PlaybackSession及相關類圖
- PlaybackSession及其內部類Track都從AHandler派生。故它們的工作也依賴於消息循環和處理。 Track代表視頻流或音頻流。
- Track內部通過mMediaPull變量指向一個MediaPull對象。而MediaPull對象則保存了一個MediaSource對象。在PlaybackSession中,此MediaSource的真正類型為SurfaceMediaSource。它表明該Media的源來自Surface。
- BufferQueue從ISurfaceTexure中派生,根據前面對SurfaceFlinger的介紹,它就是SurfaceFlinger代碼示例中代表虛擬設備的State的surface變量。
- 當雙方設備準備就緒後,MediaPull會通過kWhatPull消息處理不斷調用MediaSource的read函數。
在SurfaceMediaSource實現的read函數中,來自SurfaceFlinger的混屏後的數據經由BufferQueue傳遞到MediaPull中
- 圖:MediaPull和SurfaceMediaSource的代碼示意圖
左圖中,MediaPull通過kWhatPull消息不斷調用MediaSource的read函數。
右圖中,SurfaceMediaSource的read函數由通過mBufferQueue來讀取數據。
沒有留言:
張貼留言