1. 為什么要調整輸出塊大小
首先在RTMP_Connect0函數中LibRTMP是關閉了Nagle算法這個TCP選項的,為了實時性這樣做是好的,但是要注意到LibRTMP的結構體RTMP的成員是有m_outChunkSize,並且在RTMP_Init函數中被初始化了默認值128,然后整個LibRTMP代碼沒有改變m_outChunkSize的接口函數,內部也沒有改變m_outChunkSize的實現邏輯,也沒有發送改變塊大小的消息給流媒體服務器的代碼邏輯,關閉Nagle加如此小的塊大小會導致很多小包,而以太網的MTU是1500,這樣如果用在播放客戶端由於主要是接收媒體流到也沒有什么,但是如果用在發布媒體流的推流客戶端網絡效率就太低了,並且IP小包太多還會引起流媒體的服務器軟中斷升高,導致內核占用的CPU過高。m_outChunkSize在發送給流媒體服務器消息會用於分塊,所以從這個方面來說LibRTMP還是部分支持改變塊大小的,這部分邏輯實現不需要任何改變。
2. 調整輸出塊大小的函數
static int
ChangeChunkSize(RTMP *r,int outChunkSize)
{
RTMPPacket packet;
char pbuf[RTMP_MAX_HEADER_SIZE + 4];
packet.m_nBytesRead = 0;
packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
packet.m_packetType = RTMP_PACKET_TYPE_CHUNK_SIZE;
packet.m_nChannel = 0x04;
packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
packet.m_nTimeStamp = 0;
packet.m_nInfoField2 = 0;
packet.m_hasAbsTimestamp = 0;
packet.m_nBodySize = 4;
r->m_outChunkSize = outChunkSize;
r->m_outChunkSize = htonl(r->m_outChunkSize);
memcpy(packet.m_body, &r->m_outChunkSize, 4);
r->m_outChunkSize = ntohl(r->m_outChunkSize);
return RTMP_SendPacket(r, &packet, TRUE);
}
注1:RTMP協議的消息類型01(RTMP_PACKET_TYPE_CHUNK_SIZE宏的值)就是用於改變輸出塊大小的消息類型,結合MTU
注2:outChunkSize大小可以選擇1500-20(IP頭)-20(TCP頭)=1460,考慮到IP頭、TCP頭有擴展選項,加之PPPoE,為保證起見可選為1360,也可以設為大於MTU的其它值,不過這樣的話就會出現IP分片了,也不是好習慣。
注3:每當調用本函數后就順便修改了RTMP的成員變量m_outChunkSize,以保持與服務器收到的一致。
3. 調用調整輸出塊大小的函數的時機
隨時可以調整,只不過在調用ChangeChunkSize函數后,要注意到這個函數內部已經改變了RTMP的成員變量m_outChunkSize,這樣在調用這個函數之后的所有發給流媒體服務器的消息要以這個塊大小來分塊,由於TCP的有序性,服務器在收到該改變塊大小的消息后也會以此塊大小來解析后序的所有消息,由於播放客戶端主要是拉流,播放端需要傳給服務器的數據不多,可以不修改,基於此可以在收到connect的響應后的處理邏輯中調用ChangeChunkSize函數,具體如下(HandleInvoke函數中部分代碼):
if (r->Link.protocol & RTMP_FEATURE_WRITE)
{
ChangeChunkSize(r, 1360);//若不改拉流時的輸出塊大小在這里調用ChangeChunkSize
SendReleaseStream(r);
SendFCPublish(r);
}
else
{
RTMP_SendServerBW(r);
RTMP_SendCtrl(r, 3, 0, 300);
}
//ChangeChunkSize(r,1360);//若推、拉流時的輸出塊大小都改變在這里調用ChangeChunkSize
4. 調整輸出塊大小帶來的變化
- 主要用於發布媒體的源流媒體服務器CPU下降10%
- 通過調整流媒體服務器的輸出塊大小與媒體流發布客戶端一致,流媒體不再需要分塊了,而是可以直接轉發,這樣也會節省一定CPU
- 每一路媒體流流量下降15%
5 音頻小包如何處理
對於44.1KHZ雙聲音,對於采集周期為2048個樣本的音頻數據通過AAC+SBR音頻編碼后大小在100到300字節之間結合實時性,有兩個處理策略,1 小包就小了,為了實時也就這樣了,必竟音頻數據量不大 2 RTMP本身是基於RTMP塊流協議的,可以在應用層將音頻塊與視頻塊合包,當接近MTU時才通過socket 發送給流媒體服務器。