github:https://github.com/bigonelby/webrtcUml/tree/master/latest
這張圖介紹了probe的過程
probe過程比較復雜,由于是對網(wǎng)絡的探測心包,因此大致的思路贱勃,就是構建probecluster丁寄;將probecluster信息分配給發(fā)送的數(shù)據(jù)包儡羔;將發(fā)送信息緩存在history中殴蹄;收到feedback的時候,從緩存中找到相應的發(fā)送信息章姓;由發(fā)送拧抖,接收的時間推算出bitrate
上面介紹了大概過程煤搜,對于cluster而言,還經(jīng)歷了合-分-合這幾個階段唧席,剛剛創(chuàng)建cluster的時候擦盾,每個cluster都是一個整體,是一個合的狀態(tài)淌哟;當需要將cluster分配給發(fā)送包時迹卢,有可能很多個包對應相同的cluster,這就相當于將分配好的cluster分解徒仓,開來了腐碱;最后收到feedback時,要將這些分解后的cluster重新合并掉弛,這又是一個合的過程
首先要看看的就是cluster的產(chǎn)生症见,這個cluster的產(chǎn)生實際上幕后的推手就是RtpTransportControllerSend,這是一個至關重要的類殃饿,他的很多行為都會導致cluster的產(chǎn)生谋作,比如當網(wǎng)絡變化時;當網(wǎng)絡路由變化時乎芳;當設置配置修改時等遵蚜,都會觸發(fā)重新probe。RtpTransportControllerSend的得力助手自然就是NetworkControllerInterface了奈惑,而其實現(xiàn)類GoogCcNetworkController也是我們的老朋友了吭净。我們以周期性的probe為例,來看看probe產(chǎn)生的過程肴甸。周期性的觸發(fā)者就是RtpTransportControllerSend寂殉,在StartProcessPeriodTasks時,開啟周期性更新雷滋,即UpdateControllerWithTimeInterval不撑,進而觸發(fā)NetworkControllerInterface的OnProcessInterval方法,然后調(diào)用ProbeController的Process方法晤斩。ProbeController焕檬,顧名思義,就是Probe的控制器澳泵,因此會根據(jù)當前的網(wǎng)絡帶寬預估值estimated_bitrate_bps_实愚,結合ProbeControllerConfig配置,決策出需要構建的ProbeClusterConfig的target_data_rate,以及id這些初始的關鍵信息腊敲』魑梗可以說ProbeController為probecluster分配了唯一的clusterid,以及對應的target_data_rate碰辅,這是cluster的起點
繼續(xù)看GooCCNetworkController的OnProcessInterval方法懂昂,這個方法返回了NetworkControllerUpdate,這個類其中的成員就是probe_cluster_configs没宾,這個vector是由ProbeController產(chǎn)生的凌彬。至此,RtpTransportControllerSend得到了助手GooCCNetworkController的決策報告循衰,即NetworkControllerUpdate铲敛,在這個報告里,有ProbeClusterConfig信息会钝,這個信息將送給下一個部門
下面我們看第二部分伐蒋,pacing模塊根據(jù)指示構建ProbeCluster。上面的介紹已經(jīng)知道迁酸,RtpTransportControllerSend已經(jīng)拿到助手的決策報告先鱼,因此已經(jīng)知道需要進行probe,以及所對應的ProbeClusterConfig胁出,緊接著型型,RtpTransportControllerSend就把這份報告交給了pacing模塊段审,其pacer()指向的正是PacedSender全蝶,這個模塊負責將rtp包發(fā)送到網(wǎng)絡,不過在此之前寺枉,他要首先看看probe的情況抑淫。當他發(fā)現(xiàn)需要probe時,就將相關的信息姥闪,交給他的助手prober_了始苇,即BitrateProber,BitrateProber的作用就是根據(jù)決策出來的ProbeClusterConfig這個配置筐喳,生產(chǎn)出ProbeCluster了催式。ProbeCluster有個關鍵的信息就是pace_info,即PacedPacketInfo避归,這可是一個核心的信息荣月!首先,send_bitrate_bps指明了這個cluster的目標探測比特率梳毙,probe_cluster_id正是每個cluster的唯一標識符哺窄,起到身份證的作用!接下來probe_cluster_min_probes和probe_cluster_min_bytes,這兩個成員也很重要萌业,他們是從BitrateProberConfig獲取到的坷襟,其作用是決策出這個cluster究竟需要多少次probe,以及最小的bytes生年,換句話說婴程,這兩個變量決定了這個cluster到哪里才算是完成了任務!
我們來看看究竟可以從BitrateProber中獲取什么抱婉,最重要的就是剛開始知道要進行probe時排抬,通過CreateProbeCluster生產(chǎn)出所有的ProbeCluster,保存在其成員clusters_中授段,創(chuàng)建的過程上面已經(jīng)說了蹲蒲,根據(jù)傳遞下來的ProbeClusterConfig。然后通過ProbeSent這個方法侵贵,告訴BitrateProber模塊究竟已經(jīng)probe發(fā)送了多少數(shù)據(jù)了届搁,這里還有一道手續(xù),就是用到了6中介紹的兩個變量窍育,根據(jù)probe_cluster_min_probes和probe_cluster_min_bytes這兩個閾值卡睦,決定了這個cluster是否已經(jīng)完成任務了,如果超過這兩個閾值漱抓,則會將這個cluster從vector中移除表锻。最后一個核心的方法就是CurrentCluster了,他會返回當前的ProbeCluster的PacedPacketInfo
一切順利的話乞娄,就就到達第三部分了瞬逊,即ProbeCluster印記送達發(fā)送模塊。什么是ProbeCluster的印記呢仪或,就是PacedPacketInfo确镊!Pacing的過程之前已經(jīng)介紹過,PacingController會通過PacketRouter的SendPacket將包發(fā)送出去范删,當然蕾域,這里要補充兩個額外的工作,就是要拿到rtppacket所分配的cluster到旦,即通過BitrateProber的CurrentCluster方法旨巷,得到當前的PacedPacketInfo印記,這個印記將隨著這個rtp包一直傳輸?shù)桨l(fā)送層添忘。當成功發(fā)送數(shù)據(jù)后采呐,要通過BitrateProber的ProbeSent方法來更新probe的數(shù)據(jù),內(nèi)部會決策當前的probecluster是否已經(jīng)達到閾值昔汉,完成任務懈万,如果確實已經(jīng)達到閾值拴清,則會從clusters_這個向量中移除出去,這樣会通,下一個包就將用之后的印記了口予。通過這個過程,我們也可以了解到涕侈,這就是上述的從合到分的過程沪停,一個cluster可以對應多個rtp包,每當發(fā)送rtp包的時候裳涛,如果處于probe狀態(tài)木张,都會從BitrateProber中拿到對應的印記PacedPacketInfo,如果處理的幾個包沒有超過兩個cluster閾值端三,則這些包使用的是相同的cluster舷礼,即他們的clusterid都相同。這樣郊闯,就將同一個cluster分配到不同的rtp包中去了妻献,完成了從合到分的過程
pacing的發(fā)送過程之前已有介紹,這里不再復述团赁,總之育拨,最終rtp包到達了RtpSenderEgress模塊,隨著rtp包一同而來的欢摄,就是其印記PacedPacketInfo熬丧。RtpSenderEgress會構建RtpPacketSendInfo這個類,這個類的成員pacing_info正是這個包的印記PacedPacketInfo怀挠。構建好RtpPacketSendInfo后析蝴,RtpSenderEgress將這個信息反饋給其觀察者TransportFeedbackObserver,這個觀察者有一個接口就是OnAddPacket唆香,就是專門為了收集RtpPacketSendInfo信息的
接下來終于來到了第四部分發(fā)送模塊緩存cluster印記嫌变。前面已經(jīng)介紹,發(fā)送前躬它,每個包對應的印記將以回調(diào)的形式匯報給TransportFeedbackObserver,而實現(xiàn)這個接口的正是RtpTransportControllerSend东涡!可見RtpTransPortControllerSend就如同如來佛祖一樣冯吓,掌控著所有信息。接著疮跑,RtpTransportControllerSend將此信息轉(zhuǎn)達給TransportFeedbackAdapter组贺,他會將這些核心信息保存在其history_中,每個history_的成員都是PacketFeedback祖娘,這個類信息是由RtpPacketSendInfo生成的失尖。最終,包的印記,就被保存在PacketFeedback的SentPacket的pacing_info成員中掀潮,供后續(xù)使用
終于一路來到了第五部分菇夸,即發(fā)送模塊收到feedback后,根據(jù)緩存決策最終bitrate仪吧。前面已經(jīng)說過每個包在發(fā)送之前庄新,都會將pacing印記保存在TransportFeedbackAdapter中。接下來我們介紹一下這些保存的pacing印記究竟該如何使用薯鼠。真正的使用的地方择诈,就是在接收到這些包的feedback反饋時,此時該包已經(jīng)發(fā)送到接收端出皇,接收端整理了收到這些包的信息羞芍,通過transport-feedback的RTCP報文,反饋給發(fā)送端郊艘。關于transport-feedback報文涩金,之前已經(jīng)介紹過,這里不再重復暇仲。而接收這些報文信息的步做,依然是我們的老朋友,佛祖奈附,RtpTransportControllerSend全度。通過其OnTransportFeedback方法得到這些信息。當然斥滤,這些信息還是需要交由TransportFeedbackAdapter處理一下将鸵,因為通過transport-feedback報文,我們只能知道每個包的接收信息佑颇,那么發(fā)送信息該如何獲取呢顶掉?當然是TransportFeedbackAdapter的緩存history_中。這個history_是一個map挑胸,其key即為transport-id痒筒,這個id是每個包獨一無二的。通過這個transport-id的索引茬贵,我們可以在history_中找到對應的PacketFeedback簿透,其send成員SentPacket記錄了發(fā)送的相關信息,當然解藻,當初的pacing印記PacedPacketInfo也在這里
經(jīng)過TransportFeedbackAdapter的加工后老充,將信息匯總到TransportPacketsFeedback中,這個類由TransportFeedbackAdapter生成螟左,其維護的向量表packet_feedbacks記錄了包信息啡浊,對應的類為PacketsResult觅够。特別的PacketsResult的sent_packet成員即為SendPacket,記錄著包的發(fā)送相關信息
最終RtpTransportControllerSend會將處理好的信息TransportPacketsFeedback交給controller_巷嚣,即GoogCcNetworkController喘先,該模塊會進一步將信息交給其成員probe_bitrate_estimator_來處理。這個成員對應的類是ProbeBitrateEstimator涂籽,這個類接收所有有probe印記的包苹祟,并進一步處理。每個PacketsResult信息评雌,都會進行HandleProbeAndEstimateBitrate的處理树枫。這個處理方式將所有相同clusterid的包,合并成相同額AggregatedCluster景东,這里體現(xiàn)了從分到合的過程砂轻。整理成AggregatedCluster后斤吐,通過信息就可以決策出發(fā)送的碼率和接收的碼率了,因為信息已經(jīng)很充分庄呈,我們知道這個cluster的實際大小派阱,以及發(fā)送和接收的相關信息了贫母。當發(fā)送碼率和接收碼率比較接近時,我們選取兩者的最小值绿贞,作為評估后的帶寬值籍铁,即estimated_data_rate_寨辩。至此歼冰,整個probe過程終于可以告一段落隔嫡!