冗余程度 <-> 丟包率
FEC編碼產生冗余包過程 發送RTP包過程
接收解碼,以及FEC恢復丟失包過程
https://www.cnblogs.com/x_wukong/p/7841012.html
https://www.cnblogs.com/talkaudiodev/p/8053062.html
3,PLC
PLC也主要針對丟包因素。它本質上是一種信號處理方法,利用前面收到的一個或者幾個包來近似的產生出當前丟的包。產生補償包的技術有很多種,比如基音波形復制(G711 Appendix A PLC用的就是這種技術)、波形相似疊加技術(WSOLA)、基音同步疊加(PSOLA)技術等,這些都很專業,有興趣可以找相關的文章看看。對codec而言,如果支持PLC功能,如G729,就不需要再在外部加PLC功能了,只需要對codec做相應的配置,讓它的PLC功能使能。如果不支持PLC功能,如G711,就需要在外部實現PLC。
PLC對小的丟包率(< 15%)有比較好的效果,大的丟包率效果就不好了,尤其是連續丟包,第一個丟的包補償效果還不錯,越到后面丟的包效果越差。
把Jitter Buffer、FEC、PLC結合起來就可以得到如下的接收側針對網絡環境因素的提高音質方案:
從網絡收到的RTP包如是原始包不僅要PUT進JB,還要PUT進FEC。如是冗余包則只PUT進FEC,在FEC中如果一組包中原始包的個數加上冗余包的個數達到指定值就開始做FEC解碼得到丟失的原始包,並把那些丟失的原始包PUT進JB。在需要的時候把語音幀從JB中GET出解碼並有可能做PLC。
4,重傳
重傳也主要針對丟包這種因素,把丟掉的包再重新傳給對方,一般都是采用按需重傳的方法。我在用重傳的方法時是這樣做的:接收方把收到的包排好序后放在buffer里,如果收到RTP包頭中的sequence number能被5整除(即模5),就統計一下這個包前面未被播放的包有哪些沒收到(即buffer里相應位置為空), 采用比特位的方式記錄下來(當前能被5整除的包的前一個包用比特位0表示,丟包置1,不丟包置0,比特位共16位(short型),所以最多可以看到前16個包是否有丟包),然后組成一個控制包(控制包的payload有兩方面信息:當前能被5整除的包的sequence number(short型)以及上面組成的16位的比特位)發給對方,讓對方重發這些包。接收方收到這個控制包后就能解析出哪些包丟了,然后重傳這些包。在控制包的payload里面也可以把每個丟了的包的sequence number發給對方,這里用比特位主要是減小payload大小,省流量。
在實際使用中重傳起的效果不大,主要是因為經常重傳包來的太遲,已經錯過了播放窗口而只能主動丟棄了。它是這些方法中效果最差的一個。
5,RFC2198
RFC2198是RTP Payload for Redundant Audio Data(用於冗余音頻數據的RTP負載格式),用了它后在當前RTP包中不僅可以承載當前語音的payload,還可以承載前幾個包的payload,承載以前包的個數越多,在高丟包率的情況下效果越好,但是延時也就越大,同時消耗的流量也就越多。相比於FEC,它消耗的流量更多,因為FEC用一組RTP包編碼生一個或多個成冗余包,而它一個RTP包就帶一個或多個以前包的payload。在有線網絡或者WIFI下可以用,在蜂窩網絡下建議慎用。
以上就是我用過的提高音質的方法。還有其他方法,我沒實踐過,就不寫了,寫出來也是紙上談兵。歡迎大家補充其他的方法。