在《Android PVPlayer引擎的實(shí)現(xiàn)》一文中我們重點(diǎn)介紹了PVPlayerInterface播放引擎的實(shí)現(xiàn)過(guò)程,今天要學(xué)習(xí)的是OpenCORE中另外兩種媒體引擎:記錄引擎(PVAuthor Engine)和雙向引擎(PV2way Engine)。
PVAuthorEngineInterface記錄引擎
在記錄引擎中,對(duì)音頻、視頻文件均提供了記錄支持,其客戶(hù)端可以分為兩種類(lèi)型:上層應(yīng)用和適配器。其中適配器客戶(hù)端作用在于將記錄引擎的接口映射為其他框架或者應(yīng)用所需的特定接口。
記錄引擎支持的數(shù)據(jù)源包括攝像頭、麥克風(fēng),甚至未經(jīng)編碼的元數(shù)據(jù)流等。經(jīng)過(guò)記錄引擎處理,源數(shù)據(jù)流會(huì)被編碼為客戶(hù)端指定的數(shù)據(jù)格式。
客戶(hù)端通過(guò)PVAuthorEngineInterface、PVErrorEventObserver、PVInformationalEvent Observer、PVCommandStatusObserver等觀(guān)察器來(lái)接受命令、狀態(tài)信息和錯(cuò)誤信息等。記錄引擎的實(shí)現(xiàn)位于external\opencore\engines\author目錄下,下圖顯示的是記錄引擎的類(lèi)圖。

PVAuthor類(lèi)繼承關(guān)系圖
在記錄引擎中,狀態(tài)之間的變遷同樣是通過(guò)狀態(tài)機(jī)控制的,其狀態(tài)包括PVAE_STATE_IDLE、PVAE_STATE_OPENED、PVAE_STATE_INITIALIZED、PVAE_STATE_ RECORDING、PVAE_STATE_PAUSED、PVAE_STATE_ERROR等,下圖顯示了記錄引擎中的狀態(tài)躍遷。

PVAuthor引擎狀態(tài)圖
當(dāng)執(zhí)行多媒體記錄時(shí),首先要?jiǎng)?chuàng)建一個(gè)記錄引擎,然后添加數(shù)據(jù)源。具體的執(zhí)行過(guò)程如下圖所示。

PVAutoor執(zhí)行過(guò)程圖
在添加完數(shù)據(jù)源后,還需要選擇組合器和添加MediaTrack,才方能開(kāi)始媒體記錄。
CPV2WayInterface雙向引擎
隨著芯片處理能力和無(wú)線(xiàn)帶寬的提高,3G技術(shù)得到不斷推廣,視頻電話(huà)逐漸走進(jìn)普通用戶(hù)的視野。為了支持視頻電話(huà)業(yè)務(wù),在OpenCORE中,提供了依賴(lài)于平臺(tái)的多媒體雙向引擎,對(duì)H.324M(3G-324M在H.324M基礎(chǔ)上指定了H.263作為強(qiáng)制基本標(biāo)準(zhǔn),而把MPEG-4作為視頻編碼推薦標(biāo)準(zhǔn),AMR作為音頻編碼強(qiáng)制標(biāo)準(zhǔn),主要用于無(wú)線(xiàn)網(wǎng)絡(luò))、H.323(主要用于有線(xiàn)互聯(lián)網(wǎng),無(wú)QoS保障)、SIP(側(cè)重NGN網(wǎng)絡(luò))等主流視頻電話(huà)協(xié)議棧都提供了支持。
在3G移動(dòng)終端中,通常采用的是3G-324M協(xié)議棧,目前擁有3G-324M協(xié)議棧核心技術(shù)的廠(chǎng)商主要有達(dá)麗星(Dilithium)、銳迪訊(Radvision)等。
隨著無(wú)線(xiàn)移動(dòng)網(wǎng)絡(luò)進(jìn)一步朝著IP化的方向演進(jìn)和基于3G-324M協(xié)議棧控制復(fù)雜等缺陷方面的考慮,在3GPP R5版本中,正式引入了基于SIP協(xié)議族的多媒體子系統(tǒng)(IMS, IP Multimedia Subsystem),使基于SIP的移動(dòng)視頻通話(huà)業(yè)務(wù)成為可能。
雙向引擎的輸入數(shù)據(jù)可以有麥克風(fēng)、攝像頭等,輸出數(shù)據(jù)源有顯示屏、揚(yáng)聲器等。數(shù)據(jù)源和數(shù)據(jù)槽均由以應(yīng)用或者適配層的形式存在的客戶(hù)端添加。
客戶(hù)端利用工廠(chǎng)類(lèi)CPV2WayEngineFactory或者CPV2WayProxyFactory來(lái)獲得一個(gè)繼承CPV2WayInterface接口的雙向引擎的引用(在目前的版本中,雙向引擎為CPV324m2Way)。另外,客戶(hù)端還必須實(shí)現(xiàn)雙向引擎的觀(guān)察者接口(PVCommandStatusObserver、PVInformationalEventObserver、PVErrorEventObserver),以獲得收到命令完成情況、狀態(tài)信息和錯(cuò)誤信息的途徑,并將這些接口傳遞給雙向引擎。
客戶(hù)端還應(yīng)基于PV2WayMIO類(lèi)或PVMFNodeInterface接口實(shí)現(xiàn)雙向引擎所需的數(shù)據(jù)源和數(shù)據(jù)槽,數(shù)據(jù)源和數(shù)據(jù)槽在實(shí)現(xiàn)上都是基于Oscl_Vector向量的?蛻(hù)端會(huì)通過(guò)CPV2WayInterface接口執(zhí)行視頻會(huì)話(huà)過(guò)程中的相關(guān)操作,如初始化、添加數(shù)據(jù)源、添加數(shù)據(jù)槽、連接、暫停、恢復(fù)、斷連等。雙向引擎的實(shí)現(xiàn)位于external\opencore\engines\2way目錄下,下圖所示為雙向引擎的主要類(lèi)的繼承關(guān)系圖。

PV2Way類(lèi)繼承關(guān)系圖
在目前的設(shè)計(jì)中,OpenCORE的雙向引擎內(nèi)置了7種狀態(tài):空閑(EIdle)、初始化(EInitializing)、建立(ESetup)、連接中(EConnecting)、已連接(EConnected)、斷連中(EDisconnecting)、重設(shè)(EResetting)。
其中“EIdle”狀態(tài)模式為雙向引擎對(duì)象的初創(chuàng)狀態(tài),尚沒(méi)有任何資源被分配。
在“EInitializing”狀態(tài)下,引擎嘗試獲得可用的設(shè)備資源(如編解碼、內(nèi)存等),準(zhǔn)備接受建立參數(shù)和視頻連接。如果成功,則引擎狀態(tài)轉(zhuǎn)換為“ESetup”狀態(tài),如果失敗,則釋放已請(qǐng)求成功的資源,轉(zhuǎn)換為“EIdle”狀態(tài)。
在收到編碼、復(fù)用、捕獲能力、渲染能力等建立參數(shù)的過(guò)程中,引擎處于“ESetup”狀態(tài),在引擎狀態(tài)轉(zhuǎn)換為“EConnecting”狀態(tài)之前,有效的數(shù)據(jù)源和數(shù)據(jù)槽應(yīng)被添加到雙向引擎中。
當(dāng)引擎對(duì)象收到一個(gè)請(qǐng)求連接的呼叫時(shí),引擎轉(zhuǎn)換為“ESetup”狀態(tài)。在該模式下,移動(dòng)終端將和遠(yuǎn)程終端交換媒體支持能力和信道配置信息,為接下來(lái)的媒體信道連接做好準(zhǔn)備。
在協(xié)議棧的控制面信令完成通信后,終端開(kāi)始嘗試基于通信雙方的支持能力建立音頻、視頻軌跡,數(shù)據(jù)源和數(shù)據(jù)槽將在這一過(guò)程中轉(zhuǎn)入運(yùn)行,引擎轉(zhuǎn)換為“EConnecting”狀態(tài)。
當(dāng)因通信完成或者資源不足等原因,引擎決定斷開(kāi)信道和復(fù)用設(shè)備時(shí),引擎的狀態(tài)轉(zhuǎn)換為“EDisconnecting”狀態(tài)。
如果終端開(kāi)始釋放所有雙向引擎占用的通信資源,則引擎轉(zhuǎn)為“EResetting”狀態(tài)。
下圖顯示了雙向引擎的狀態(tài)躍遷。

PV2Way狀態(tài)圖
在A(yíng)ndroid中,目前支持的基于CPV2WayInterface接口的雙向引擎為CPV324m2Way。數(shù)據(jù)源和數(shù)據(jù)槽均是基于PV2WayMIO類(lèi)派生的。
為了進(jìn)行視頻通話(huà),首先需要?jiǎng)?chuàng)建一個(gè)雙向引擎,然后添加數(shù)據(jù)源和數(shù)據(jù)槽,具體的交互過(guò)程如下圖所示。

PV2Way交互過(guò)程圖
OpenCORE所能支持的媒體格式參看pvmf_format_type.h?蛻(hù)端和服務(wù)器進(jìn)行通信協(xié)商編碼的過(guò)程如下:
代碼:FormatInList的實(shí)現(xiàn)
CodecSpecifier* PV2WayMIO::FormatInList(PVMFFormatType& type)
{
Oscl_Map< PVMFFormatType, CodecSpecifier*,
OsclMemAllocator, pvmf_format_type_key_compare_class >::iterator it =
iFormatsMap.begin();
it=iFormatsMap.find(type); //查找匹配格式
if (!(it==iFormatsMap.end()))
return (*it).second;
return NULL;
}
本文為華清遠(yuǎn)見(jiàn)3G學(xué)院android培訓(xùn)原創(chuàng)資料,轉(zhuǎn)載請(qǐng)注明出處!