今天發現一個奇怪的問題,用上位機的linphone客戶端撥打下位機的sip客戶端能夠正常工作,但是反過來就出問題了。 抓包發現linphone發送了大量的IP fragmentation 數據包,google才知道,當發現的數據大於MTU時就發產生IP分片的數據包。RTP打包時不是已經進行了分片操作了嗎?正常情況應該不會出現這種情況纔對。
linphone對h264進行RTP打包在rfc3984.c中進行,打包函數如下:
void rfc3984_pack(Rfc3984Context *ctx, MSQueue *naluq, MSQueue *rtpq, uint32_t ts){
switch(ctx->mode){
case 0:
rfc3984_pack_mode_0(ctx,naluq,rtpq,ts);
break;
case 1:
rfc3984_pack_mode_1(ctx,naluq,rtpq,ts);
break;
default:
ms_error("Bad or unsupported mode %i",ctx->mode);
}
}
看來程序中定義了兩種打包模式,看看兩種模式有什麼區別
static void rfc3984_pack_mode_0(Rfc3984Context *ctx, MSQueue *naluq, MSQueue *rtpq, uint32_t ts){
mblk_t *m;
bool_t end;
int size;
while((m=ms_queue_get(naluq))!=NULL){
end=ms_queue_empty(naluq);
size=m->b_wptr-m->b_rptr;
if (size>ctx->maxsz){
ms_warning("This H264 packet does not fit into mtu: size=%i",size);
}
send_packet(rtpq,ts,m,end);
}
}
/*process NALUs and pack them into rtp payloads */
static void rfc3984_pack_mode_1(Rfc3984Context *ctx, MSQueue *naluq, MSQueue *rtpq, uint32_t ts){
mblk_t *m,*prevm=NULL;
int prevsz=0,sz;
bool_t end;
while((m=ms_queue_get(naluq))!=NULL){
end=ms_queue_empty(naluq);
sz=m->b_wptr-m->b_rptr;
if (ctx->stap_a_allowed){
if (prevm!=NULL){
if ((prevsz+sz)<(ctx->maxsz-2)){
prevm=concat_nalus(prevm,m);
m=NULL;
prevsz+=sz+2;/*+2 for the stapa size field*/
continue;
}else{
/*send prevm packet: either single nal or STAP-A*/
if (prevm->b_cont!=NULL){
ms_debug("Sending STAP-A");
}else
ms_debug("Sending previous msg as single NAL");
send_packet(rtpq,ts,prevm,FALSE);
prevm=NULL;
prevsz=0;
}
}
if (sz<(ctx->maxsz/2)){
/*try to aggregate it with next packet*/
prevm=m;
prevsz=sz+3; /*STAP-A header + size*/
m=NULL;
}else{
/*send as single nal or FU-A*/
if (sz>ctx->maxsz){
ms_debug("Sending FU-A packets");
frag_nalu_and_send(rtpq,ts,m,end, ctx->maxsz);
}else{
ms_debug("Sending Single NAL");
send_packet(rtpq,ts,m,end);
}
}
}else{
if (sz>ctx->maxsz){
ms_debug("Sending FU-A packets");
frag_nalu_and_send(rtpq,ts,m,end, ctx->maxsz);
}else{
ms_debug("Sending Single NAL");
send_packet(rtpq,ts,m,end);
}
}
}
if (prevm){
ms_debug("Sending Single NAL (2)");
send_packet(rtpq,ts,prevm,TRUE);
}
}
模式0竟然沒有RTP打包分片操作,而是直接send出去了,難怪IP協議自動進行了分片處理。於是想到,將RTP打包模式設置爲1應該就可以了,後來發現可以直接通過SDP中的packetization-mode指定RTP打包模式。項目中出現的奇怪問題是因爲,linphone默認使用了模式1打包,而下位機發送的SDP信息中沒有指定packetization-mode。 在正位的發送的SDP中將packetization-mode指定爲1,問題就解決了。
轉載自:http://blog.csdn.net/gavinr/article/details/7388295