GB28181Description sdp 消息封装

This commit is contained in:
shikong 2023-08-24 01:27:40 +08:00
parent 60df3e396f
commit 7b008248d4
5 changed files with 250 additions and 11 deletions

View File

@ -0,0 +1,64 @@
package cn.skcks.docking.gb28181.core.sip.gb28181.sdp;
import gov.nist.javax.sdp.SessionDescriptionImpl;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import javax.sdp.Connection;
import javax.sdp.Origin;
import javax.sdp.SessionDescription;
import javax.sdp.URI;
import java.util.Optional;
@EqualsAndHashCode(callSuper = false)
@Data
public class GB28181Description extends SessionDescriptionImpl implements SessionDescription {
public static class Convertor {
@SneakyThrows
public static GB28181Description convert(SessionDescriptionImpl sessionDescription){
GB28181Description gb28181Description = new GB28181Description();
gb28181Description.setMediaDescriptions(sessionDescription.getMediaDescriptions(true));
gb28181Description.setBandwidths(sessionDescription.getBandwidths(true));
Connection connection = sessionDescription.getConnection();
if (connection != null){
gb28181Description.setConnection(connection);
}
gb28181Description.setEmails(sessionDescription.getEmails(true));
gb28181Description.setTimeDescriptions(sessionDescription.getTimeDescriptions(true));
Origin origin = sessionDescription.getOrigin();
if(origin != null){
gb28181Description.setOrigin(origin);
}
gb28181Description.setAttributes(sessionDescription.getAttributes(true));
URI uri = sessionDescription.getURI();
if(uri != null){
gb28181Description.setURI(uri);
}
return gb28181Description;
}
}
private SsrcField ssrcField;
GB28181Description(){
super();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(super.toString());
sb.append(getSsrcField() == null ? "" : getSsrcField().toString());
return sb.toString();
}
}

View File

@ -1,8 +1,20 @@
package cn.skcks.docking.gb28181.core.sip.gb28181.sdp;
import javax.sdp.SessionDescription;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import gov.nist.core.Separators;
import gov.nist.javax.sdp.SessionDescriptionImpl;
import gov.nist.javax.sdp.fields.AttributeField;
import gov.nist.javax.sdp.fields.ConnectionField;
import gov.nist.javax.sdp.fields.TimeField;
import gov.nist.javax.sdp.fields.URIField;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import javax.sdp.*;
import java.util.*;
public class MediaSdpHelper {
public static final Map<String, String> RTPMAP = new HashMap<>() {{
@ -18,7 +30,88 @@ public class MediaSdpHelper {
put("125", "profile-level-id=42e01e");
}};
public SessionDescription build(String deviceId, String channelId, String rtpIp, int rtpPort, String streamMode){
return null;
@AllArgsConstructor
@Getter
public enum Action {
PLAY("Play"),
PLAY_BACK("Playback"),
DOWNLOAD("Download");
@JsonValue
private final String action;
@JsonCreator
public static Action fromCode(String action) {
for (Action a : values()) {
if (a.getAction().equalsIgnoreCase(action)) {
return a;
}
}
return null;
}
}
@SneakyThrows
public static GB28181Description build(Action action, String deviceId, String channelId, String netType, String rtpIp, int rtpPort, long ssrc, StreamMode streamMode, TimeDescription timeDescription){
GB28181Description description = GB28181Description.Convertor.convert((SessionDescriptionImpl) SdpFactory.getInstance().createSessionDescription(action.getAction()));
Version version = SdpFactory.getInstance().createVersion(0);
description.setVersion(version);
Connection connectionField = SdpFactory.getInstance().createConnection(ConnectionField.IN, netType, rtpIp);
description.setConnection(connectionField);
MediaDescription mediaDescription = SdpFactory.getInstance().createMediaDescription("video", rtpPort, 0, SdpConstants.RTP_AVP, MediaSdpHelper.RTPMAP.keySet().toArray(new String[0]));
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("recvonly",null));
MediaSdpHelper.RTPMAP.forEach((k, v)->{
Optional.ofNullable(MediaSdpHelper.FMTP.get(k)).ifPresent((f)->{
mediaDescription.addAttribute((AttributeField) SdpFactory.getInstance().createAttribute(SdpConstants.FMTP.toLowerCase(), StringUtils.joinWith(Separators.SP,k,f)));
});
mediaDescription.addAttribute((AttributeField) SdpFactory.getInstance().createAttribute(SdpConstants.RTPMAP, StringUtils.joinWith(Separators.SP,k,v)));
});
if(streamMode == StreamMode.TCP_PASSIVE){
// TCP-PASSIVE
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("setup","passive"));
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("connection","new"));
} else if(streamMode == StreamMode.TCP_ACTIVE){
// TCP-ACTIVE
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("setup","active"));
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("connection","new"));
}
description.setMediaDescriptions(new Vector<>() {{
add(mediaDescription);
}});
description.setTimeDescriptions(new Vector<>(){{
add(timeDescription);
}});
Origin origin = SdpFactory.getInstance().createOrigin(channelId, 0, 0, ConnectionField.IN, netType, rtpIp);
description.setOrigin(origin);
description.setSsrcField(new SsrcField(ssrc));
return description;
}
@SneakyThrows
public static GB28181Description play(Action action, String deviceId, String channelId, String netType, String rtpIp, int rtpPort, long ssrc, StreamMode streamMode){
TimeDescription timeDescription = SdpFactory.getInstance().createTimeDescription();
return build(action, deviceId, channelId, netType, rtpIp, rtpPort, ssrc, streamMode, timeDescription);
}
@SneakyThrows
public static GB28181Description playback(Action action, String deviceId, String channelId, String netType, String rtpIp, int rtpPort, long ssrc, StreamMode streamMode, Date start, Date end) {
TimeField timeField = new TimeField();
timeField.setStart(start);
timeField.setStop(end);
TimeDescription timeDescription = SdpFactory.getInstance().createTimeDescription(timeField);
GB28181Description description = build(action, deviceId, channelId, netType, rtpIp, rtpPort, ssrc, streamMode, timeDescription);
URIField uriField = new URIField();
uriField.setURI(StringUtils.joinWith(":", channelId, "0"));
description.setURI(uriField);
return description;
}
}

View File

@ -0,0 +1,28 @@
package cn.skcks.docking.gb28181.core.sip.gb28181.sdp;
import gov.nist.core.Separators;
import gov.nist.javax.sdp.fields.SDPField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
public class SsrcField extends SDPField {
private static final String SSRC_FIELD = "y=";
public SsrcField() {
super(SSRC_FIELD);
}
private long ssrc;
@Override
public String encode() {
return SSRC_FIELD + ssrc + Separators.NEWLINE;
}
public String toString(){
return encode();
}
}

View File

@ -0,0 +1,27 @@
package cn.skcks.docking.gb28181.core.sip.gb28181.sdp;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum StreamMode {
UDP("UDP"),
TCP_ACTIVE("TCP-ACTIVE"),
TCP_PASSIVE("TCP-PASSIVE");
@JsonValue
private final String mode;
@JsonCreator
public static StreamMode fromCode(String mode) {
for (StreamMode m : values()) {
if (m.getMode().equalsIgnoreCase(mode)) {
return m;
}
}
return null;
}
}

View File

@ -1,6 +1,10 @@
package cn.skcks.docking.gb28181.core.sip.message.event;
import cn.hutool.core.util.RandomUtil;
import cn.skcks.docking.gb28181.core.sip.gb28181.sdp.GB28181Description;
import cn.skcks.docking.gb28181.core.sip.gb28181.sdp.MediaSdpHelper;
import cn.skcks.docking.gb28181.core.sip.gb28181.sdp.SsrcField;
import cn.skcks.docking.gb28181.core.sip.gb28181.sdp.StreamMode;
import gov.nist.core.NameValue;
import gov.nist.core.Separators;
import gov.nist.javax.sdp.MediaDescriptionImpl;
@ -12,6 +16,7 @@ import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import javax.sdp.*;
import java.net.URL;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
@ -119,12 +124,13 @@ public class SipEventTest {
@Test
@SneakyThrows
public void sdpTest() {
SessionDescription sessionDescription = SdpFactory.getInstance().createSessionDescription("Play");
GB28181Description description = GB28181Description.Convertor.convert((SessionDescriptionImpl) SdpFactory.getInstance().createSessionDescription("Play"));
Version version = SdpFactory.getInstance().createVersion(0);
sessionDescription.setVersion(version);
description.setVersion(version);
Connection connectionField = SdpFactory.getInstance().createConnection(ConnectionField.IN, Connection.IP4, "10.10.10.20");
sessionDescription.setConnection(connectionField);
description.setConnection(connectionField);
MediaDescription mediaDescription = SdpFactory.getInstance().createMediaDescription("video", 6666, 0, SdpConstants.RTP_AVP, MediaSdpHelper.RTPMAP.keySet().toArray(new String[0]));
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("recvonly",null));
@ -143,18 +149,39 @@ public class SipEventTest {
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("setup","active"));
mediaDescription.addAttribute((AttributeField)SdpFactory.getInstance().createAttribute("connection","new"));
sessionDescription.setMediaDescriptions(new Vector<>() {{
description.setMediaDescriptions(new Vector<>() {{
add(mediaDescription);
}});
TimeDescription timeDescription = SdpFactory.getInstance().createTimeDescription();
sessionDescription.setTimeDescriptions(new Vector<>(){{add(timeDescription);}});
description.setTimeDescriptions(new Vector<>(){{add(timeDescription);}});
// channelId
Origin origin = SdpFactory.getInstance().createOrigin("44050100001310000006", 0, 0, ConnectionField.IN, Connection.IP4, "10.10.10.20");
sessionDescription.setOrigin(origin);
description.setOrigin(origin);
// mediaDescription.setPreconditionFields();
URIField uriField = new URIField();
uriField.setURI("44050100001310000006:0");
description.setURI(uriField);
// GB28181Description description = (GB28181Description) description;
description.setSsrcField(new SsrcField(12345678));
SessionDescription sessionDescription = description;
sessionDescription.setSessionName(SdpFactory.getInstance().createSessionName("PlayBack"));
log.info("\n{}", sessionDescription);
}
@Test
@SneakyThrows
void mediaSdpHelperTest(){
String deviceId = "44050100001110000006";
String channel = "44050100001310000006";
int rtpPort = 5080;
String rtpIp = "10.10.10.20";
long ssrc = RandomUtil.randomLong(10000000,100000000);
GB28181Description description = MediaSdpHelper.build(MediaSdpHelper.Action.PLAY, deviceId, channel, Connection.IP4, rtpIp, rtpPort, ssrc, StreamMode.UDP, SdpFactory.getInstance().createTimeDescription());
log.info("\n{}", description);
}
}