0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

RTC腳手架的設(shè)計(jì)與實(shí)現(xiàn)(下)

jf_78858299 ? 來(lái)源:網(wǎng)易云音樂(lè)技術(shù)團(tuán)隊(duì) ? 作者:AirLand ? 2023-05-26 16:48 ? 次閱讀

由于所有的 Player 都有這個(gè)邏輯因此可以將這部分再抽象成一個(gè) AbsPlayer:

abstract class AbsPlayerIDataSource, CB : ICallback>
    : IPlayer

最后整個(gè) Player 的類(lèi)圖如下所示:

圖片

image.png

這里我們不關(guān)注 Player 的功能具體是如何實(shí)現(xiàn)的,比如如何推流,如何拉流,如何進(jìn)行 RTC 等。畢竟每個(gè)項(xiàng)目底層所用的服務(wù)商 sdk 各不相同,技術(shù)實(shí)現(xiàn)也不同,因此這里我們只從架構(gòu)的層面去探討。

2、Player 的切換

Player 的切換針對(duì)的就是部分場(chǎng)景 RTC,這里我們引入 SwitchablePlayer 的概念專(zhuān)門(mén)用于此種場(chǎng)景,而其本身也繼承自 AbsPlayer, 具備 Player 的所有功能。只不過(guò)這些功能是通過(guò)裝飾者模式由其內(nèi)部真正的 Player 來(lái)實(shí)現(xiàn),同時(shí)增加了 Switch 的能力。再講到 Switch 能力之前先來(lái)思考幾個(gè)問(wèn)題。

  1. 何時(shí)觸發(fā) Switch?
  2. 如何進(jìn)行 Switch?
  3. Switch 的目標(biāo)對(duì)象 Player 從何而來(lái)?

第一個(gè)問(wèn)題何時(shí)觸發(fā) Switch :我們知道只要觸發(fā) Switch 就意味著需要啟動(dòng)另外的 Player,而啟動(dòng) Player 又需要上面提到的 IDataSource,因此我們只需要判斷啟動(dòng) Player 所傳入的 IDataSource 類(lèi)型和當(dāng)前 Player 的 IDataSource 類(lèi)型是否相同,如果不同便可觸發(fā)。判斷的具體邏輯是對(duì)比當(dāng)前 Player 泛型參數(shù)的 IDataSource 類(lèi)型( AbsPlayer第一個(gè)范型參數(shù) )和傳入的 IDataSource 類(lèi)型來(lái)實(shí)現(xiàn)。

private fun isSourceMatch(
        player: AbsPlayer<IDataSource, ICallback>?,
        ds: IDataSource
    ): Boolean {
        if (player == null) {
            return false
        } else {
            val clazz = player::class.java
            var type = getGenericSuperclass(clazz) ?: return false
            while (Types.getRawType(type) != AbsPlayer::class.java) {
                type = getGenericSuperclass(type) ?: return false
            }
            return if (type is ParameterizedType) {
                val args = type.actualTypeArguments
                if (args.isNullOrEmpty()) {
                    false
                } else {
                    Types.getRawType(args[0]).isInstance(ds) && isSameSource(player, ds)
                }
            } else {
                false
            }
        }
    }

第二個(gè)問(wèn)題如何進(jìn)行 Switch :這個(gè)就比較簡(jiǎn)單了只需要停止掉當(dāng)前的 Player 再啟動(dòng)目標(biāo) Player 即可。

第三個(gè)問(wèn)題 Switch 的目標(biāo)對(duì)象 Player 從何而來(lái) :SwitchablePlayer 并不清楚業(yè)務(wù)需要哪些 Player ,只是對(duì) Player 功能的一層包裝以及維護(hù) Switch 功能,因此具體的 Player 創(chuàng)建需要由業(yè)務(wù)層來(lái)實(shí)現(xiàn), SwitchablePlayer 只提供一個(gè)獲取 Player 的抽象方法例如:

abstract fun getPlayer(ds: IDataSource): AbsPlayer<out IDataSource, out ICallback>?

另外由于進(jìn)行 Switch 的時(shí)候會(huì)停止掉當(dāng)前的 Player,而被停止的 Player 是否能復(fù)用,如果能復(fù)用則可以將其緩存起來(lái),下次使用優(yōu)先從緩存中獲得。整個(gè)SwitchablePlayer對(duì)應(yīng)的流程如圖所示:

圖片

image.png

在使用時(shí)調(diào)用者可以根據(jù)自己的業(yè)務(wù)定義相關(guān) Player,例如在直播-> PK 的業(yè)務(wù)中,涉及到兩個(gè) Player 的切換即:LivePlayer 和 PKPlayer

class LivePKSwitchablePlayer : SwitchablePlayer(false) {
        override fun getPlayer(ds: IDataSource): AbsPlayer<out IDataSource, out ICallback> {
            return when (ds) {
                is LiveDataSource -> {
                    LivePlayer()
                }
                is PKDataSource -> {
                    PKPlayer()
                }
                else -> LivePlayer()
            }
        }

    }
3、流程封裝

對(duì)于整個(gè) RTC 流程的封裝需要搞清楚兩件事情:

  1. RTC 的主體流程是怎樣的
  2. 業(yè)務(wù)調(diào)用方需要的是什么,關(guān)注的又是什么

由于 RTC 的主體流程和日常打電話相似,所以筆者以此類(lèi)比,這樣大家更容易理解。下圖所示即為整個(gè)通話過(guò)程。圖片

搞清楚整個(gè)流程后,接下來(lái)就是搞清楚第二件事情,業(yè)務(wù)調(diào)用方需要的是什么,關(guān)注的又是什么。結(jié)合上圖來(lái)看關(guān)注的大概有三點(diǎn):

  • 第一就是需要具備撥打和掛斷的入口;( Player 的 Start 和 Stop
  • 第二就是要能知道當(dāng)前的通話狀態(tài)比如是否正在連通,是否已經(jīng)接通,是否通話結(jié)束;( Player 的 狀態(tài)維護(hù)
  • 第三就是一些反饋比如對(duì)方未接通,對(duì)方不在服務(wù)區(qū),手機(jī)號(hào)是空號(hào)等。( Player 的 核心事件回調(diào)即之前提到的 ICallback

而至于它是如何連通的,底層做了哪些操作,撥打電話的人對(duì)此毫不關(guān)心?;谏鲜鑫覀兊恼w功能設(shè)計(jì)所要關(guān)注的點(diǎn)就有了。

1、通過(guò)設(shè)計(jì)一個(gè) manager 來(lái)管理 Player 并對(duì)外暴露 Start 和 Stop 方法。

2、對(duì) Player 進(jìn)行狀態(tài)維護(hù),并讓其狀態(tài)可被上層監(jiān)聽(tīng)。

3、Player 的一些核心事件回調(diào)也可被上層監(jiān)聽(tīng)。

其中第一點(diǎn)和第三點(diǎn)比較簡(jiǎn)單,這里就不做過(guò)多的贅述。第二點(diǎn)狀態(tài)維護(hù),筆者使用了 StateMachine 狀態(tài)機(jī)來(lái)實(shí)現(xiàn),在不同的狀態(tài)執(zhí)行不同的操作,同時(shí)每一種狀態(tài)都對(duì)應(yīng)一個(gè)狀態(tài)碼,上層可以通過(guò)監(jiān)聽(tīng)狀態(tài)碼來(lái)感知狀態(tài)變化。

圖片

image.png

狀態(tài)碼和核心事件的設(shè)置這里使用了 LiveData 去處理

class RtcHolder : IRtcHolder {
    private val _rtcState = MutableLiveData(RtcStatus.IDLE)
    private val _rtcEvent = MutableLiveData(RtcEvent.IDLE)
    val rtcState = _rtcState.distinctUntilChanged()
    val rtcEvent = _rtcEvent.distinctUntilChanged()
    private val callBack = object : IRtcCallBack {
        override fun onCurrentStateChange(stateCode: Int) {
            _rtcState.value = stateCode
        }

        override fun onEvent(eventCode: Int) {
            _rtcEvent.value = eventCode
        }
       
       //......省略其他代碼
        
    }

     init {
        //上層狀態(tài)監(jiān)聽(tīng) 
        rtcState.observeForever {
            when (it) {
                RtcStatus.CONNECT_END -> {
                    ToastHelper.showToast("通話結(jié)束")
                }
            }
        }
    }
    //......省略其他代碼
}

到這里整個(gè)腳手架的方案設(shè)計(jì)就結(jié)束了,其中服務(wù)商 SDK 封裝部分以及監(jiān)控部分,筆者準(zhǔn)備放到下期再來(lái)講解。

總結(jié)

本文介紹了 RTC 腳手架產(chǎn)生的背景,并以通俗易懂的方式一步步闡述設(shè)計(jì)過(guò)程以及最終實(shí)現(xiàn)。在此期間發(fā)現(xiàn)問(wèn)題,解決問(wèn)題,引出思考。由于受限于篇幅,不能將每一個(gè)點(diǎn)都進(jìn)行詳盡的介紹,有興趣的同學(xué)如有疑問(wèn),可以留言,一起探討學(xué)習(xí)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RTC
    RTC
    +關(guān)注

    關(guān)注

    2

    文章

    523

    瀏覽量

    66228
  • 騰訊云
    +關(guān)注

    關(guān)注

    0

    文章

    207

    瀏覽量

    16750
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    利用愛(ài)星物聯(lián)服務(wù)腳手架實(shí)現(xiàn)定制服務(wù)

    和相關(guān)工具,可能理解起來(lái)還是云里霧里,還是沒(méi)法下手定制開(kāi)發(fā)吧? 別急,理論指導(dǎo)實(shí)踐來(lái)了。 本文介紹基于API腳手架和微服務(wù)腳手架構(gòu)建自定義的對(duì)應(yīng)服務(wù),以及自定義服務(wù)怎么與愛(ài)星物聯(lián)IoT平臺(tái)服務(wù)進(jìn)行交互 (內(nèi)容屬于下圖紅色線框部
    的頭像 發(fā)表于 06-07 09:38 ?1890次閱讀
    利用愛(ài)星物聯(lián)服務(wù)<b class='flag-5'>腳手架</b><b class='flag-5'>實(shí)現(xiàn)</b>定制服務(wù)

    2010年迪拜五大行業(yè)展|迪拜建材展|緊固件|腳手架|建筑五金|衛(wèi)?。沾桑罄硎?/a>

    ;建筑安全設(shè)備;混凝土-預(yù)制、建筑系統(tǒng);建筑立面、盤(pán)座面及包覆;加熱裝置;模板/百葉窗;工具-空氣、手動(dòng)及電動(dòng);砌體-磚、預(yù)制、水泥、灰漿;螺帽、錨桿、螺絲、鉸鏈等;建筑拆除;木材-框架及結(jié)構(gòu);腳手架
    發(fā)表于 09-06 15:51

    2011年沙特建材展|吉達(dá)建材展|五大行業(yè)展|緊固件|腳手架|玻璃|門(mén)窗|

    |吉達(dá)建材展|五大行業(yè)展|緊固件|腳手架|玻璃|門(mén)窗|2011年沙特建材展|吉達(dá)建材展|五大行業(yè)展|緊固件|腳手架|玻璃|門(mén)窗|2011年沙特建材展|吉達(dá)建材展|五大行業(yè)展|緊固件|腳手架|玻璃|門(mén)窗
    發(fā)表于 09-06 15:55

    2011年沙特建材展|吉達(dá)建材展|五大行業(yè)展|緊固件|腳手架|玻璃|門(mén)窗|

    ;nbsp;2011年沙特建材展|吉達(dá)建材展|五大行業(yè)展|緊固件|腳手架|玻璃|門(mén)窗|2011年沙特建材展|吉達(dá)建材展|五大行業(yè)展|緊固件|腳手架|玻璃|門(mén)窗|2011年沙特建材展|吉達(dá)建材展|五大行業(yè)展
    發(fā)表于 09-06 16:05

    懸挑式腳手架監(jiān)理控制要點(diǎn)

    懸挑式腳手架一般有兩種:一種是每層一挑,將立桿底部頂在樓板、梁或墻體等建筑部位,向外傾斜固定后,在其上部搭設(shè)橫桿、鋪腳手板形成施工層,施工一個(gè)層高,待轉(zhuǎn)入上層
    發(fā)表于 12-15 14:29 ?15次下載

    腳手架的避雷方法

    搭設(shè)在曠野山坡上雷擊區(qū)的鋼腳手架在雷雨季節(jié)應(yīng)設(shè)避雷裝置,避雷裝置包括接閃器、接地極、接地線。
    發(fā)表于 01-19 15:26 ?18次下載

    物聯(lián)網(wǎng)腳手架系統(tǒng)能帶來(lái)什么益處

    橫向移動(dòng)不是腳手架上工人唯一需要擔(dān)心的事情。超重載荷對(duì)立柱施加的壓力過(guò)大可能會(huì)導(dǎo)致結(jié)構(gòu)崩塌。平板下面的物聯(lián)網(wǎng)傳感器可以在壓力成為問(wèn)題之前測(cè)量到它。
    發(fā)表于 03-20 10:16 ?567次閱讀

    科學(xué)家研發(fā)可溶解的植入骨折的腳手架材料——特殊繃帶

    植入骨折的腳手架材料,能夠促使身體自身的骨細(xì)胞長(zhǎng)入其中并治愈骨折。而現(xiàn)在,科學(xué)家們開(kāi)發(fā)了一種特殊的繃帶,也可以做到這一點(diǎn)。
    的頭像 發(fā)表于 09-25 11:30 ?1713次閱讀

    腳手架掛牌方案需要符合哪些層面的規(guī)定

    腳手架掛牌的過(guò)程中,當(dāng)然就必須應(yīng)用到方案,即然是方案,又和生產(chǎn)安全有關(guān),也就必須讓它符合各個(gè)方面的規(guī)定,那麼必須讓這類(lèi)方案符合哪些層面的規(guī)定呢? 最先就必須讓它符合機(jī)器設(shè)備構(gòu)造上的規(guī)定,由于生產(chǎn)線
    發(fā)表于 02-11 10:52 ?1350次閱讀

    腳手架掛牌一般在哪些情況使用比較好

    在工業(yè)化生產(chǎn)的過(guò)程中,為了更好地保證生產(chǎn)安全,也是有一些情況必須應(yīng)用到腳手架掛牌的,那麼它會(huì)在哪些的情況開(kāi)展應(yīng)用呢?最先便是在機(jī)器檢修之時(shí)必須開(kāi)展應(yīng)用。由于在對(duì)機(jī)器檢修的情況,不
    發(fā)表于 02-01 14:43 ?1081次閱讀

    關(guān)于針對(duì)腳手架掛牌的歸納分析

    描述:用五金鎖具鎖定防護(hù)設(shè)備來(lái)防止很多人 隨便操作過(guò)程安全防護(hù)的能量源或者機(jī)器設(shè)備,(腳手架掛牌)直到維修結(jié)束,五金鎖具消除。 :運(yùn)用衣服標(biāo)簽來(lái)警告別人早就被安全防護(hù)的能量源或者機(jī)器設(shè)備不能隨便
    發(fā)表于 03-01 11:50 ?761次閱讀

    為何需要腳手架掛牌,它的作用是怎樣的

    腳手架掛牌是便于避免員工在進(jìn)行維修、維修保養(yǎng)時(shí),遇到來(lái)自設(shè)備的發(fā)生意外啟動(dòng)、出現(xiàn)異常啟動(dòng)、動(dòng)力裝置釋放出所導(dǎo)致的風(fēng)險(xiǎn)性,以保證 員工的人身安全。進(jìn)行腳手架掛牌操作程序的根本所在,斷掉設(shè)備與動(dòng)力裝置
    發(fā)表于 03-05 11:39 ?1950次閱讀

    腳手架掛牌的具體流程是怎樣的

    第一步:提前準(zhǔn)備工作? 提前準(zhǔn)備關(guān)閉能源。(腳手架掛牌)普遍的能源種類(lèi)有(電磁能,機(jī)械動(dòng)能,空氣能熱水器等......)和它的潛在性風(fēng)險(xiǎn)。放好防護(hù)維護(hù)裝置(安全鎖具),并提前準(zhǔn)備關(guān)閉能源 第二步
    發(fā)表于 03-08 10:35 ?1464次閱讀

    腳手架掛牌是什么,有什么作用

    上邊的案例,看了后耐人尋味。有誤實(shí)際操作腳手架掛牌,導(dǎo)致這么多可憐生命的身亡和資產(chǎn)的損害。由此可見(jiàn)恰當(dāng)應(yīng)用安全鎖具,是一件多么的關(guān)鍵的事兒。溫州市博士安全用品 解釋一什么叫腳手架掛牌?
    發(fā)表于 03-22 10:27 ?2017次閱讀

    RTC腳手架的設(shè)計(jì)與實(shí)現(xiàn)(上)

    RTC即 Real-Time Communication 的簡(jiǎn)稱(chēng)是一種給行業(yè)提供高并發(fā)、低延時(shí)、高清流暢、安全可靠的全場(chǎng)景、全互動(dòng)、全實(shí)時(shí)的音視頻服務(wù)的終端服務(wù)。上面是比較官方的解釋?zhuān)ㄋ椎膩?lái)講就是
    的頭像 發(fā)表于 05-26 16:48 ?623次閱讀
    <b class='flag-5'>RTC</b><b class='flag-5'>腳手架</b>的設(shè)計(jì)與<b class='flag-5'>實(shí)現(xiàn)</b>(上)