|
|
@ -1,16 +1,16 @@ |
|
|
package com.inspect.tcpserver.sip.service; |
|
|
package com.inspect.tcpserver.sip.service; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.inspect.tcpserver.sip.gb28181.MediaSession; |
|
|
|
|
|
import com.inspect.tcpserver.sip.gb28181.MediaSessionEx; |
|
|
|
|
|
import com.inspect.tcpserver.sip.gb28181.RtspClient; |
|
|
|
|
|
|
|
|
import com.inspect.tcpserver.sip.media.Gb28181StreamService; |
|
|
|
|
|
import com.inspect.tcpserver.sip.media.InviteSdpInfo; |
|
|
import com.inspect.tcpserver.sip.registry.SipEventRegistry; |
|
|
import com.inspect.tcpserver.sip.registry.SipEventRegistry; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.inspect.tcpserver.sip.utils.DigestUtil; |
|
|
import com.inspect.tcpserver.sip.utils.DigestUtil; |
|
|
|
|
|
import com.inspect.tcpserver.sip.utils.Gb28181SdpParser; |
|
|
import com.inspect.tcpserver.sip.utils.SipXmlEnvelope; |
|
|
import com.inspect.tcpserver.sip.utils.SipXmlEnvelope; |
|
|
import com.inspect.tcpserver.sip.utils.SipXmlParser; |
|
|
import com.inspect.tcpserver.sip.utils.SipXmlParser; |
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|
|
import org.springframework.stereotype.Service; |
|
|
import org.springframework.stereotype.Service; |
|
|
@ -85,12 +85,19 @@ public class SipClientService implements SipListener { |
|
|
@Value("${sip.expires}") |
|
|
@Value("${sip.expires}") |
|
|
private int expires; |
|
|
private int expires; |
|
|
|
|
|
|
|
|
|
|
|
private String rtpStreamHost= "192.168.1.116"; |
|
|
|
|
|
private int rtpStreamPort= 30000; |
|
|
|
|
|
private long rtpStreamSSRC = 12345678; |
|
|
|
|
|
|
|
|
private ClientTransaction lastRegisterTransaction; |
|
|
private ClientTransaction lastRegisterTransaction; |
|
|
private Timer refreshTimer = new Timer(true); |
|
|
private Timer refreshTimer = new Timer(true); |
|
|
private String fromTag = Long.toHexString(System.currentTimeMillis()); |
|
|
private String fromTag = Long.toHexString(System.currentTimeMillis()); |
|
|
|
|
|
|
|
|
private AtomicInteger cSeqCounter = new AtomicInteger(1); |
|
|
private AtomicInteger cSeqCounter = new AtomicInteger(1); |
|
|
|
|
|
|
|
|
|
|
|
@Autowired |
|
|
|
|
|
Gb28181StreamService streamService; |
|
|
|
|
|
|
|
|
private static final String[] IP_SERVICES = { |
|
|
private static final String[] IP_SERVICES = { |
|
|
"https://api.ipify.org", |
|
|
"https://api.ipify.org", |
|
|
"https://checkip.amazonaws.com", |
|
|
"https://checkip.amazonaws.com", |
|
|
@ -755,6 +762,7 @@ public class SipClientService implements SipListener { |
|
|
return Long.toHexString(System.currentTimeMillis() & 0xffffffffL); |
|
|
return Long.toHexString(System.currentTimeMillis() & 0xffffffffL); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private final String rtspInputUrl = "rtsp://admin:wd19216811@192.168.1.244:554/h264/ch1/sub/av_stream"; |
|
|
@Override |
|
|
@Override |
|
|
public void processRequest(RequestEvent requestEvent) { |
|
|
public void processRequest(RequestEvent requestEvent) { |
|
|
Request request = requestEvent.getRequest(); |
|
|
Request request = requestEvent.getRequest(); |
|
|
@ -838,11 +846,15 @@ public class SipClientService implements SipListener { |
|
|
handleInvite(requestEvent); |
|
|
handleInvite(requestEvent); |
|
|
} else if(Request.ACK.equals(request.getMethod())) { |
|
|
} else if(Request.ACK.equals(request.getMethod())) { |
|
|
// RFC 3261: The ACK request does not generate a response. |
|
|
// RFC 3261: The ACK request does not generate a response. |
|
|
// ACK 是“事务内请求”,不是普通 SIP 方法,不生成任何 Response,ACK 是“事务内请求”,不是普通 SIP 方法 |
|
|
|
|
|
|
|
|
|
|
|
//Thread.sleep(30); |
|
|
|
|
|
|
|
|
// ACK 是"事务内请求", 不是普通 SIP 方法, 不生成任何 Response |
|
|
log.info("CALL startRtspToRtp"); |
|
|
log.info("CALL startRtspToRtp"); |
|
|
//startRtspToRtp(); |
|
|
|
|
|
|
|
|
byte[] raw = request.getRawContent(); |
|
|
|
|
|
if (raw != null) { |
|
|
|
|
|
String inviteAckContent = new String(raw, StandardCharsets.UTF_8); |
|
|
|
|
|
log.info("INVITE ACK content: \n{}", inviteAckContent); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
streamService.startPushStream(rtspInputUrl, rtpStreamHost, rtpStreamPort); |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
Response notImpl = messageFactory.createResponse(Response.NOT_IMPLEMENTED, request); |
|
|
Response notImpl = messageFactory.createResponse(Response.NOT_IMPLEMENTED, request); |
|
|
@ -860,105 +872,6 @@ public class SipClientService implements SipListener { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private Process ffmpegProcess; |
|
|
|
|
|
|
|
|
|
|
|
// private void startRtspToRtp() { |
|
|
|
|
|
// try { |
|
|
|
|
|
// String cmd = |
|
|
|
|
|
// "ffmpeg -rtsp_transport tcp " + |
|
|
|
|
|
// "-i \"rtsp://admin:wd19216811@192.168.1.244:554/h264/ch1/sub/av_stream\" " + |
|
|
|
|
|
// "-an -vcodec copy " + |
|
|
|
|
|
// "-f rtp -payload_type 96 " + |
|
|
|
|
|
// "\"rtp://192.168.1.116:50000?tcp\""; |
|
|
|
|
|
// |
|
|
|
|
|
// ProcessBuilder pb = new ProcessBuilder( |
|
|
|
|
|
// "bash", "-c", cmd |
|
|
|
|
|
// ); |
|
|
|
|
|
// pb.redirectErrorStream(true); |
|
|
|
|
|
// |
|
|
|
|
|
// ffmpegProcess = pb.start(); |
|
|
|
|
|
// |
|
|
|
|
|
// new Thread(() -> { |
|
|
|
|
|
// try (BufferedReader br = |
|
|
|
|
|
// new BufferedReader(new InputStreamReader( |
|
|
|
|
|
// ffmpegProcess.getInputStream()))) { |
|
|
|
|
|
// String line; |
|
|
|
|
|
// while ((line = br.readLine()) != null) { |
|
|
|
|
|
// System.out.println("[FFmpeg] " + line); |
|
|
|
|
|
// } |
|
|
|
|
|
// } catch (IOException ignored) {} |
|
|
|
|
|
// }).start(); |
|
|
|
|
|
// |
|
|
|
|
|
// } catch (Exception e) { |
|
|
|
|
|
// e.printStackTrace(); |
|
|
|
|
|
// } |
|
|
|
|
|
// |
|
|
|
|
|
// try { |
|
|
|
|
|
// MediaSession session = new MediaSession( |
|
|
|
|
|
// "192.168.1.116", |
|
|
|
|
|
// 50000, |
|
|
|
|
|
// 1, |
|
|
|
|
|
// false, |
|
|
|
|
|
// "rtsp://admin:wd19216811@192.168.1.244:554/h264/ch1/sub/av_stream" |
|
|
|
|
|
// ); |
|
|
|
|
|
// } catch (Exception e) { |
|
|
|
|
|
// |
|
|
|
|
|
// } |
|
|
|
|
|
// |
|
|
|
|
|
// |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
// private void startRtspToRtp() { |
|
|
|
|
|
// try { |
|
|
|
|
|
// MediaSession session = new MediaSession( |
|
|
|
|
|
// "192.168.1.116", |
|
|
|
|
|
// 50000, |
|
|
|
|
|
// 1 |
|
|
|
|
|
// ); |
|
|
|
|
|
// |
|
|
|
|
|
// session.startRtsp( |
|
|
|
|
|
// "rtsp://admin:wd19216811@192.168.1.244:554/h264/ch1/sub/av_stream" |
|
|
|
|
|
// ); |
|
|
|
|
|
// |
|
|
|
|
|
// } catch (Exception e) { |
|
|
|
|
|
// e.printStackTrace(); |
|
|
|
|
|
// } |
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
private void startRtspToRtp() { |
|
|
|
|
|
try { |
|
|
|
|
|
MediaSessionEx session = new MediaSessionEx( |
|
|
|
|
|
"192.168.1.116", |
|
|
|
|
|
50000, |
|
|
|
|
|
1 |
|
|
|
|
|
); |
|
|
|
|
|
//session.start(); |
|
|
|
|
|
|
|
|
|
|
|
RtspClient client = new RtspClient( |
|
|
|
|
|
"rtsp://admin:wd19216811@192.168.1.244:554/h264/ch1/sub/av_stream" |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// client.start((h264, pts90k) -> { |
|
|
|
|
|
// try { |
|
|
|
|
|
// session.onH264Frame(h264, pts90k); |
|
|
|
|
|
// } catch (Exception e) { |
|
|
|
|
|
// e.printStackTrace(); |
|
|
|
|
|
// } |
|
|
|
|
|
// }); |
|
|
|
|
|
client.start((h264, pts90k) -> { |
|
|
|
|
|
try { |
|
|
|
|
|
session.onH264Frame(h264, pts90k); |
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void handleInvite(RequestEvent requestEvent) throws Exception { |
|
|
private void handleInvite(RequestEvent requestEvent) throws Exception { |
|
|
Request request = requestEvent.getRequest(); |
|
|
Request request = requestEvent.getRequest(); |
|
|
log.info("Received INVITE:\n{}", request); |
|
|
log.info("Received INVITE:\n{}", request); |
|
|
@ -978,6 +891,11 @@ public class SipClientService implements SipListener { |
|
|
if (raw != null) { |
|
|
if (raw != null) { |
|
|
String sdp = new String(raw, StandardCharsets.UTF_8); |
|
|
String sdp = new String(raw, StandardCharsets.UTF_8); |
|
|
log.info("INVITE SDP:\n{}", sdp); |
|
|
log.info("INVITE SDP:\n{}", sdp); |
|
|
|
|
|
InviteSdpInfo sdpInfo = Gb28181SdpParser.parse(sdp); |
|
|
|
|
|
log.info("INVITE sdpInfo: {}", sdpInfo); |
|
|
|
|
|
rtpStreamHost = sdpInfo.ip; |
|
|
|
|
|
rtpStreamPort = sdpInfo.port; |
|
|
|
|
|
rtpStreamSSRC = sdpInfo.ssrc; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// ③ 构造 200 OK + SDP |
|
|
// ③ 构造 200 OK + SDP |
|
|
|