1. WifiDisplay簡(jiǎn)介
Wi-Fi Display經(jīng)常和Miracast聯(lián)系在一起。實(shí)際上,Miracast是Wi-Fi聯(lián)盟(Wi-Fi Alliance)對(duì)支持Wi-Fi Display功能的設(shè)備的認(rèn)證名稱。通過(guò)Miracast認(rèn)證的設(shè)備將在最大程度內(nèi)保持對(duì)Wi-Fi Display功能的支持和兼容。
Miracast的Android實(shí)現(xiàn)涉及到系統(tǒng)的多個(gè)模塊,包括:
1. MediaPlayerService及相關(guān)模塊
原因很明顯,因?yàn)镸iracast本身就牽扯到RTP/RTSP及相應(yīng)的編解碼技術(shù)。
SurfaceFlinger的作用是將各層UI數(shù)據(jù)混屏并投遞到顯示設(shè)備中去顯示?,F(xiàn)在,SurfaceFlinger將支持多個(gè)顯示設(shè)備。而支持Miracast的遠(yuǎn)端設(shè)備也做為一個(gè)獨(dú)立的顯示設(shè)備存在于系統(tǒng)中。
3. WindowManagerService及相關(guān)模塊
WindowManagerService用于管理系統(tǒng)中各個(gè)UI層的位置和屬性。由于并非所有的UI層都會(huì)通過(guò)Miracast投遞到遠(yuǎn)端設(shè)備上。例如手機(jī)中的視頻可投遞到遠(yuǎn)端設(shè)備上去顯示,但假如在播放過(guò)程中,突然彈出一個(gè)密碼輸入框(可能是某個(gè)后臺(tái)應(yīng)用程序發(fā)起的),則這個(gè)密碼輸入框就不能投遞到遠(yuǎn)端設(shè)備上去顯示。所以,WindowManagerService也需要修改以適應(yīng)Miracast的需要。
4. DisplayManagerService及相關(guān)模塊
DisplayManagerService服務(wù)是Android 4.2新增的,用于管理系統(tǒng)中所有的Display設(shè)備。
5. WifiService及相關(guān)模塊
WifiDisplay協(xié)議的實(shí)現(xiàn)建立在WifiP2P的基礎(chǔ)上,其中涉及的Wifi技術(shù)包括WiFi-Direct(WiFi P2P)、Wi-Fi Protected Setup(Wifi網(wǎng)絡(luò)自動(dòng)配置及添加網(wǎng)絡(luò))、11n/WMM/WPA2(11n就是802.11n協(xié)議,它將11a和11g提供的Wi-Fi傳輸速率從56Mbps提升到300甚至600Mbps。WMM是Wi-Fi Multimedia的縮寫,是一種針對(duì)實(shí)時(shí)視音頻數(shù)據(jù)的QoS服務(wù)。而WPA2意為Wi-Fi Protected Acess第二版,主要用來(lái)給傳輸?shù)臄?shù)據(jù)進(jìn)行加密保護(hù))。
圖1 給出了WFD涉及的技術(shù)及協(xié)議框圖,基于WifiP2P網(wǎng)絡(luò)技術(shù),利用RTSP作為音頻及視頻流控制協(xié)議,涉及了流媒體的傳輸、控制、加密、解密、編碼及解碼等技術(shù)流程。
WFD中涉及的技術(shù)層面比較多,相關(guān)的協(xié)議也比較多,包括了WIFI P2P技術(shù)、RTSP及RTP技術(shù)、流媒體技術(shù)以及音視頻編解碼相關(guān)的技術(shù),如果要對(duì)WFD有比較深入的了解,還需要花費(fèi)較多的時(shí)間去研究相關(guān)的技術(shù)細(xì)節(jié)。
圖1 WFD涉及的技術(shù)及協(xié)議框圖
2. WifiDisplay協(xié)議流程
建立WifiDisplay主要步驟如下:
1. WFD Device Discovery(WFD設(shè)備發(fā)現(xiàn))
2. WFD Service Discovery (Optional)(WFD服務(wù)發(fā)現(xiàn)(可選))
3. Device Selection(設(shè)備選擇)
4. WFD Connection Setup(WFD連接)
5. WFD Capability Negotiation(WFD能力協(xié)商)
6. WFD Session Establishment(WFD會(huì)話建立)
7. User Input Back Channel Setup (Optional)(UIBC反向控制)
8. Link Content Protection Setup (Optional)(內(nèi)容保護(hù),即數(shù)據(jù)加密)
9. Payload Control(負(fù)載控制)
10. WFD Source and WFD Sink standby (Optional)
11. WFD Session Teardown(會(huì)話終止)
WFD設(shè)備通過(guò)wifiP2P連接后,Sink端與Source端建立TCP連接,Sink端為Client而Source端為Server。默認(rèn)端口為7236,執(zhí)行的協(xié)議為RTSP協(xié)議。建立連接后進(jìn)行RTSP協(xié)商。步驟6,協(xié)商成功后建立會(huì)話;步驟7,UIBC通道建立,用于Sink端反向控制Source端,該步驟為可選實(shí)現(xiàn);步驟8,對(duì)與傳輸?shù)膬?nèi)容做加密保護(hù)(HDCP),步驟9,開(kāi)始音頻及視頻流的傳輸與控制,Payload Control:傳輸過(guò)程中,設(shè)備可根據(jù)無(wú)線信號(hào)的強(qiáng)弱,甚至設(shè)備的電量狀況來(lái)動(dòng)態(tài)調(diào)整傳輸數(shù)據(jù)和格式??烧{(diào)整的內(nèi)容包括壓縮率,視音頻格式,分辨率等內(nèi)容。步驟11,會(huì)話終止。
圖 2 會(huì)話建立及協(xié)商過(guò)程圖
RTSP M1和M2主要協(xié)商Source和Sink都支持的RTSP methods。
RTSP M3和M4主要協(xié)商Source和Sink在會(huì)話中使用的參數(shù)。
圖3 RTSP協(xié)議控制圖
當(dāng)RTSP M7的請(qǐng)求和響應(yīng)消息成功交換完成,WFD Source及WFD Sink之間就建立了會(huì)話。
RTSP協(xié)議控制中主要有以下幾種狀態(tài)SETUP、PLAY、PAUSE、TEARDOWN
通過(guò)下面命令抓取了WifiDisplay相關(guān)的協(xié)議包,主要是RTSP控制流相關(guān)的協(xié)議包。
tcpdump -i any -w /savePath
具體的協(xié)議包相關(guān)的內(nèi)容如圖4所示,協(xié)議中相關(guān)的流程及步驟和圖1、2中的交互流程是一致的,具體包括以下幾個(gè)主要步驟OPTIONS、GET_PARAMETER、SET_PARAMETER、 SETUP、PLAY、TEARDOWN等,這些都是RTSP中相關(guān)的協(xié)議內(nèi)容。
當(dāng)Source與Sink設(shè)備完成PLAY的交互后,Source端便開(kāi)始傳輸音頻及視頻流給Sink端,Sink端作為被動(dòng)接收端,只需要在P2P interface的19000(默認(rèn)的RTP數(shù)據(jù)傳輸端口)綁定監(jiān)聽(tīng)接收來(lái)自Source端的數(shù)據(jù)流對(duì)相關(guān)的音視頻流做處理即可。圖5給出了音視頻流的協(xié)議包,可以看到音視頻的傳輸通過(guò)MPEG TS、MPEG PES等相關(guān)協(xié)議作為傳輸載體。
圖4 完整RTSP協(xié)商流程,協(xié)商的內(nèi)容主要是視頻流的控制方法及支持的音頻及視頻格式
圖5 完成協(xié)商后開(kāi)始傳輸音頻及視頻流,即TS包及PES包
對(duì)于WifiDisplay會(huì)話管理有以下模型可供參考,該結(jié)構(gòu)大致分為四個(gè)層次, UI、 Session Policy Management、協(xié)議實(shí)現(xiàn)層及基于Wifi的網(wǎng)絡(luò)傳輸層。在協(xié)議實(shí)現(xiàn)層中主要分為幾個(gè)模塊WFD Ddiscovery、WFD Link Establishment、 UIBC、Capability Negotiation、Session/Stream Control等。
圖6 WFD設(shè)備會(huì)話管理的模型
圖7 音頻及視頻流控制模型
實(shí)時(shí)流協(xié)議RTSP是一個(gè)應(yīng)用層協(xié)議,用于控制具有實(shí)時(shí)特性的數(shù)據(jù)(例如多媒體流)的傳送。RTSP協(xié)議一般與RTP/RTCP和RSVP等底層協(xié)議一起協(xié)同工作,提供基于Internet的整套的流服務(wù)。它可以選擇發(fā)送通道(例如:UDP、組播UDP和TCP)和基于RTP的發(fā)送機(jī)制。它可以應(yīng)用于組播和點(diǎn)播。RTP, RTCP,RSVP 定義如下:
1. 實(shí)時(shí)傳輸協(xié)議RTP(Real-time Transport protocol)
2. 實(shí)時(shí)傳輸控制協(xié)議RTCP(Real-time Transport Control protocol)
3. 實(shí)時(shí)流協(xié)議RTSP(Real Time Streaming protocol)
4. 資源預(yù)留協(xié)議RSVP(Resource Reserve Protocol)
客戶端與服務(wù)器運(yùn)行實(shí)時(shí)流控制協(xié)議RTSP,以對(duì)該流進(jìn)行各種VCR控制信號(hào)的交換,如播放(PLAY)、停止(PAUSE)、快進(jìn)、快退等。當(dāng)服務(wù)完畢,客戶端提出拆線(TEARDOWN)請(qǐng)求。服務(wù)器使用RTP/UDP協(xié)議將媒體數(shù)據(jù)傳輸給客戶端,一旦數(shù)據(jù)抵達(dá)客戶端,客戶端應(yīng)用程序即可播放輸出。在流式傳輸中,使用RTP/RTCP/UDP和RTSP/TCP兩種不同的通信協(xié)議在客戶端和服務(wù)器間建立聯(lián)系。
3. WifiDisplay顯示框架實(shí)現(xiàn)
為了實(shí)現(xiàn)WifiDisplay google在Android現(xiàn)有顯示系統(tǒng)的基礎(chǔ)上加入的虛擬設(shè)備的支持,下圖給出了Android顯示系統(tǒng)的架構(gòu)圖。
圖8 DisplayDevice的隔離示意圖
圖9 Android圖層示意圖
1.WindowManagerService
管理窗口之間的關(guān)系。包括位置、優(yōu)先級(jí)等。
2.SurfaceFlinger
負(fù)責(zé)對(duì)各個(gè)Surface按照Z(yǔ)-order進(jìn)行Merge,然后把Merge之后的Buffer顯示到Display上。
3.DisplayManagerService
管理在系統(tǒng)中加載的各個(gè)Display。包括管理各個(gè)Display的生命周期,并且對(duì)各個(gè)Display進(jìn)行配置。當(dāng)Display狀態(tài)變化的時(shí)候向系統(tǒng)和應(yīng)用程序發(fā)送通知。
void SurfaceFlinger::doComposition() { ATRACE_CALL(); const bool repaintEverything = android_atomic_and(0, &mRepaintEverything); for (size_t dpy=0 ; dpy& hw(mDisplays[dpy]); if (hw->isDisplayOn() && (hw->getDisplayType() != DisplayDevice::DISPLAY_EXTERNAL)) { // transform the dirty region into this screen's coordinate space const Region dirtyRegion(hw->getDirtyRegion(repaintEverything)); // repaint the framebuffer (if needed) doDisplayComposition(hw, dirtyRegion); hw->dirtyRegion.clear(); hw->flip(hw->swapRegion); hw->swapRegion.clear(); } // inform the h/w that we're done compositing hw->compositionComplete(); } postFramebuffer(); }
SurfaceFlinger將遍歷系統(tǒng)中所有的DisplayDevice來(lái)完成各自的混屏工作。
圖10 WifiDisplay顯示模型
作為Wifi-Diplay Source的設(shè)備建立RTSP Server,將SurfaceFlinger merge的Buffer數(shù)據(jù)stream到Wifi-Diplay的peer端。作為Wifi-Diplay Sink的設(shè)備是一個(gè)RTSP的Client端,從peer端讀取數(shù)據(jù),在built-in的Display上顯示。
4. Android WifiDisplay實(shí)現(xiàn)
4.1 Source端實(shí)現(xiàn)
基于Android6.0 代碼Source端入口在原生Settings->設(shè)備->顯示->投射,這個(gè)功能如果正常使用時(shí),需要更改一個(gè)配置項(xiàng)。
該配置項(xiàng)路徑為
frameworks/base/core/res/res/values/config.xml
該入口的主要作用是掃描并發(fā)現(xiàn)sink設(shè)備。
4.1.1 設(shè)備掃描及發(fā)現(xiàn)
圖11 設(shè)備發(fā)現(xiàn)流程圖
當(dāng)用戶點(diǎn)擊了optionMenu中enable wifi display選項(xiàng)時(shí),會(huì)觸發(fā)相關(guān)的設(shè)備掃描及更新操作,在WifiDisplaySettings和WifiDisplayController都有注冊(cè)ContentObserver來(lái)監(jiān)控這個(gè)值的變化。觸發(fā)設(shè)備掃描的是在WifiDisplayController中通過(guò)updateWfdEnableState()進(jìn)行的,最終通過(guò)WifiP2pManager.requestPeers來(lái)完成設(shè)備的掃描工作,獲取掃描到的設(shè)備列表是在WifiDisplaySettings通過(guò)update(int changes)進(jìn)行的。對(duì)于設(shè)備連接狀態(tài)的管理主要通過(guò)updateConnection()來(lái)進(jìn)行。由于設(shè)備的連接過(guò)程是一個(gè)異步過(guò)程,所以在設(shè)備操作相關(guān)的過(guò)程中會(huì)反復(fù)調(diào)用updateConnection() 來(lái)判定設(shè)備狀態(tài)及更新連接操作。
private void update(int changes) { boolean invalidateOptions = false; // Update settings. if ((changes & CHANGE_SETTINGS) != 0) { mWifiDisplayOnSetting = Settings.Global.getInt(getContentResolver(), Settings.Global.WIFI_DISPLAY_ON, 0) != 0; mWifiDisplayCertificationOn = Settings.Global.getInt(getContentResolver(), Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0; mWpsConfig = Settings.Global.getInt(getContentResolver(), Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID); // The wifi display enabled setting may have changed. invalidateOptions = true; } // Update wifi display state. if ((changes & CHANGE_WIFI_DISPLAY_STATUS) != 0) { mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus(); // The wifi display feature state may have changed. invalidateOptions = true; } // Rebuild the routes. final PreferenceScreen preferenceScreen = getPreferenceScreen(); preferenceScreen.removeAll(); // Add all known remote display routes. final int routeCount = mRouter.getRouteCount(); for (int i = 0; i < routeCount; i++) { MediaRouter.RouteInfo route = mRouter.getRouteAt(i); if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) { preferenceScreen.addPreference(createRoutePreference(route)); } } // Additional features for wifi display routes. if (mWifiDisplayStatus != null && mWifiDisplayStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) { // Add all unpaired wifi displays. for (WifiDisplay display : mWifiDisplayStatus.getDisplays()) { if (!display.isRemembered() && display.isAvailable() && !display.equals(mWifiDisplayStatus.getActiveDisplay())) { preferenceScreen.addPreference(new UnpairedWifiDisplayPreference( getActivity(), display)); } } // Add the certification menu if enabled in developer options. if (mWifiDisplayCertificationOn) { buildCertificationMenu(preferenceScreen); } } // Invalidate menu options if needed. if (invalidateOptions) { getActivity().invalidateOptionsMenu(); } }
圖12 Source端 RTSP連接流程圖
下圖是Source端設(shè)備建立連接的流程圖,主要建立RSTP協(xié)議的Socket連接,通過(guò)接收Sink端的協(xié)議信息解析相關(guān)操作,代碼流程如下圖所示。
socket的建立主要在WidiSourceRtsp.cpp的prepareListenSocket函數(shù)中實(shí)現(xiàn),并在這個(gè)socket上監(jiān)聽(tīng)是否有客戶端的連接請(qǐng)求, rtsp消息處理在cbHandleParserEvent中處理。
在WidiSession.cpp中RSTP及media event處理主要通過(guò)WorkHandler處理,相關(guān)消息處理在函數(shù)onMessageReceived中處理。
4.2 Sink端的實(shí)現(xiàn)
圖13 給出了sink端的實(shí)現(xiàn)框架圖,從框架圖可以看出APP主要和Sink API交互,Sink API和框架服務(wù)中的Wifi server 及 mediaserver交互,APP通過(guò)Control interface進(jìn)行WFD相關(guān)的控制操作,底層狀態(tài)的接收則通過(guò)Events interface,也就是一些相關(guān)的回調(diào)方法來(lái)處。
圖13 Sink端 實(shí)現(xiàn)框架結(jié)構(gòu)圖
圖 14 RTSP會(huì)話流程圖
圖15 WFD控制流程圖
圖14給出了Intel實(shí)現(xiàn)的sink端的RTSP會(huì)話管理流程圖,RTSP的協(xié)議實(shí)現(xiàn)主要通過(guò)C++實(shí)現(xiàn),對(duì)于協(xié)商后相關(guān)的狀態(tài)反饋通過(guò)回調(diào)函數(shù)完成,如果想進(jìn)一步了解相關(guān)的流程,請(qǐng)查看相關(guān)的代碼。
圖15 給出了WFD會(huì)話管理的流程圖,WFD中除了RTSP的實(shí)現(xiàn),還包括連接認(rèn)證(Connection Auth)、視頻流加密及解密(HDCP)、UIBC實(shí)現(xiàn)等。
4.2.1 設(shè)備如何被發(fā)現(xiàn)
init P2P channel
mP2pManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE); Looper looper = mHandlerThread.getLooper(); if (mP2pManager == null || looper == null) { throw new NullPointerException("Failed to get P2P_SERVICE or widi_receiver thread looper"); } mChannel = mP2pManager.initialize(context, looper, mChannelListener);
advertise Sink
WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo(); wfdInfo.setWfdEnabled(true); wfdInfo.setDeviceType(WifiP2pWfdInfo.PRIMARY_SINK); wfdInfo.setSessionAvailable(true); wfdInfo.setControlPort(7236); wfdInfo.setMaxThroughput(50); Log.d(TAG,"advertise sink"); mP2pManager.setWFDInfo(mChannel, wfdInfo, mActionListener); mHandler.post(mDiscoverPeers); mCallbackHandler.post(mSendEnabled); discover peers public void run() { mP2pManager.discoverPeers(mChannel, mActionListener); mHandler.postDelayed(this, DISCOVER_INTERVAL_MS); }
經(jīng)過(guò)這三個(gè)階段的工作,其他設(shè)備就可以發(fā)現(xiàn)這臺(tái)設(shè)備了
4.2.2 設(shè)備p2p連接后如何建立RTSP連接
P2P連接上之后可以從相關(guān)Intent中獲取到Source端傳遞過(guò)來(lái)的建立RTSP連接的ip和端口,Sink端根據(jù)這些信息主動(dòng)去連接。
else if (netInfo.getState() == NetworkInfo.State.CONNECTED) { if (mRtsp != null) { Log.i(TAG, "Ignoring extra CONNECTED event"); return; } WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO); if (p2pInfo == null) { Log.i(TAG, "WIFI_P2P_INFO is not available"); return; } if (p2pInfo.groupFormed) { mHandler.removeCallbacks(mDiscoverPeers); WifiP2pGroup group = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP); if (group == null) { Log.i(TAG, "WIFI_P2P_GROUP is not availble"); return; } mP2pInterface = group.getInterface(); mSourceRtspPort = 7236; if (p2pInfo.isGroupOwner) { Collectiondevices = group.getClientList(); if (devices != null) { if (devices.isEmpty()) Log.i(TAG, "Device list empty!"); else { for (WifiP2pDevice device : devices) { if (sReflectionInited) { // use reflection instead of: // mSourceMacAddress = device.interfaceAddress; try { mSourceMacAddress = (String) sIfAddr.get(device); } catch (Exception e) { Log.e(TAG, "Failed to get interfaceAddress field" + " by reflection: " + e); } } else Log.e(TAG, "Reflection not initialiazed," + "can't get interfaceAddress content"); if (device.wfdInfo != null) { mSourceRtspPort = device.wfdInfo.getControlPort(); Log.i(TAG, "mSourceRtspPort obtained is " + mSourceRtspPort); } else Log.i(TAG, "Using default RTSP Port=" + mSourceRtspPort); } } } } else { mSourceIp = p2pInfo.groupOwnerAddress.getHostAddress(); if (group.getOwner().wfdInfo != null) { mSourceRtspPort = group.getOwner().wfdInfo.getControlPort(); Log.i(TAG, "mSourceRtspPort obtained is " + mSourceRtspPort); } else Log.i(TAG, "Using default RTSP Port=" + mSourceRtspPort); } if (mSourceIp != null && mSourceRtspPort > 0 && mSourceRtspPort <= 65535) { mHandler.post(new ConnectRtsp(mSourceIp, mSourceRtspPort)); } } } }
4.2.3 RTSP連接實(shí)現(xiàn)
執(zhí)行完下面的代碼后,RTSP連接就建立起來(lái)了,相關(guān)的視頻流通過(guò)mediaplay來(lái)完成處理。
public void run() { Log.i(TAG, "Connect RTSP " + sourceIp + "/" + sourceRtspPort); mConnectorTypeRequested = false; mDisplayManager.registerDisplayListener(mDisplayListener, null); try { Log.d(TAG,"media reset begin"); mMediaPlayer.reset(); Log.d(TAG,"media reset over"); mMediaPlayer.setDataSource("intel_rtp://" + mP2pInterface + ":" + RTP_LISTEN_PORT); mMediaPlayer.prepare(); } catch (Exception e) { Log.e(TAG, "Exception trying to play media", e); } mSourceIp = sourceIp; mRtsp = new WidiSinkRtsp(); if (mRtsp.init(sourceIp + ":" + sourceRtspPort, mSinkListener) == 0) mRtsp.start(); } } 編輯:黃飛
-
WIFI
+關(guān)注
關(guān)注
81文章
5327瀏覽量
205887 -
無(wú)線信號(hào)
+關(guān)注
關(guān)注
2文章
268瀏覽量
20667 -
RTSP
+關(guān)注
關(guān)注
0文章
14瀏覽量
12257 -
視頻編解碼
+關(guān)注
關(guān)注
2文章
54瀏覽量
11841 -
Miracast
+關(guān)注
關(guān)注
0文章
6瀏覽量
18750
原文標(biāo)題:WifiDisplay(Miracast)技術(shù)原理及實(shí)現(xiàn)
文章出處:【微信號(hào):哆啦安全,微信公眾號(hào):哆啦安全】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
WIFI無(wú)線技術(shù)各種熱門設(shè)計(jì)方案~
熱門PCB設(shè)計(jì)技術(shù)方案
世平推出基于 WIFI 互聯(lián)技術(shù)的車載影音導(dǎo)航系統(tǒng)方案
基于Dragonboard 410c的miracast簡(jiǎn)單總結(jié)
淺析Miracast無(wú)線顯示技術(shù)
毫米波終端技術(shù)實(shí)現(xiàn)挑戰(zhàn)及測(cè)試方案
請(qǐng)問(wèn)Miracast怎么實(shí)現(xiàn)大小設(shè)備間的無(wú)縫視頻共享?
請(qǐng)問(wèn)Rk3566或者rk3568支持miracast作為sink端的功能嗎
MIP技術(shù)簡(jiǎn)單介紹,及技術(shù)實(shí)現(xiàn)方案
德州儀器宣布推出端對(duì)端Miracast系統(tǒng)
DragonBoard 410c的Miracast無(wú)線同屏技術(shù)介
Miracast 是什么,如何在Windows 10上使用Miracast
無(wú)線投屏技術(shù)之Miracast、DLNA與AirPlay的技術(shù)分析
Miracast技術(shù)跨操作系統(tǒng)支持不同設(shè)備間的視頻共享

評(píng)論