- 今天发现一个奇怪的问题,用上位机的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,问题就解决了