| 
					
				 | 
			
			
				@@ -241,21 +241,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // 解析sdp消息, 使用jainsip 自带的sdp解析方式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 String contentString = new String(request.getRawContent()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // jainSip不支持y=字段, 移除以解析。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                int ssrcIndex = contentString.indexOf("y="); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // 检查是否有y字段 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                String ssrcDefault = "0000000000"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                String ssrc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                SessionDescription sdp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (ssrcIndex >= 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    //ssrc规定长度为10个字节,不取余下长度以避免后续还有“f=”字段 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    String substring = contentString.substring(0, contentString.indexOf("y=")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    sdp = SdpFactory.getInstance().createSessionDescription(substring); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ssrc = ssrcDefault; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    sdp = SdpFactory.getInstance().createSessionDescription(contentString); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                SessionDescription sdp = gb28181Sdp.getBaseSdb(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 String sessionName = sdp.getSessionName().getValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 Long startTime = null; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -317,7 +304,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 String username = sdp.getOrigin().getUsername(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 String addressStr = sdp.getConnection().getAddress(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                logger.info("[上级点播]用户:{}, 通道:{}, 地址:{}:{}, ssrc:{}", username, channelId, addressStr, port, ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 Device device = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // 通过 channel 和 gbStream 是否为null 值判断来源是直播流合适国标 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (channel != null) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -341,8 +328,30 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    String ssrc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (gb28181Sdp.getSsrc() == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        logger.warn("[上级Invite] {} 平台:{}, 通道:{}, 缺少 ssrc,补充为: {}", sessionName, username, channelId, ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ssrc = gb28181Sdp.getSsrc(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    String streamTypeStr = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (mediaTransmissionTCP) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (tcpActive) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            streamTypeStr = "TCP-ACTIVE"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        }else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            streamTypeStr = "TCP-PASSIVE"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        streamTypeStr = "UDP"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (tcpActive != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         sendRtpItem.setTcpActive(tcpActive); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -469,7 +478,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false, 0, false, device.getStreamModeForParam()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             logger.info(JSONObject.toJSONString(ssrcInfo)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             sendRtpItem.setStreamId(ssrcInfo.getStream()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            sendRtpItem.setSsrc(ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             // 写入redis, 超时时回复 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             redisCatchStorage.updateSendRTPSever(sendRtpItem); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -480,12 +489,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             // 当前系统作为下级平台使用,当上级平台点播时不携带ssrc时,并且设备在当前系统中已经点播了。这个时候需要重新给生成一个ssrc,不使用默认的"0000000000"。 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            if (ssrc.equals(ssrcDefault)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                sendRtpItem.setSsrc(ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            sendRtpItem.setSsrc(ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             sendRtpItem.setStreamId(playTransaction.getStream()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             // 写入redis, 超时时回复 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             redisCatchStorage.updateSendRTPSever(sendRtpItem); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -496,11 +500,15 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } else if (gbStream != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if(ssrc.equals(ssrcDefault)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    String ssrc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (gb28181Sdp.getSsrc() == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    }else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ssrc = gb28181Sdp.getSsrc(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if("push".equals(gbStream.getStreamType())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         if (streamPushItem != null && streamPushItem.isPushIng()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             // 推流状态 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -545,7 +553,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (streamReady) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // 自平台内容 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            return  redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (sendRtpItem == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     logger.warn("服务器端口资源不足"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -584,7 +594,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (streamReady) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // 自平台内容 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback ->{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            return  redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (sendRtpItem == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     logger.warn("服务器端口资源不足"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -701,7 +713,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 dynamicTask.stop(callIdHeader.getCallId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (serverId.equals(userSetting.getServerId())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            app, stream, channelId, mediaTransmissionTCP, platform.isRtcp()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            app, stream, channelId, mediaTransmissionTCP, platform.isRtcp(), ssrcFromCallback -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                return redisCatchStorage.querySendRTPServer(platform.getServerGBId(), channelId, null, callIdHeader.getCallId()) != null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (sendRtpItem == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足"); 
			 |