Commit 421c2f56020bfe60b0e0c90e9d509abf03354dab
1 parent
d0f5d684
使用jainsip的方式解析sdp
Showing
9 changed files
with
80 additions
and
699 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/Codec.java deleted
100755 → 0
| 1 | -/* | |
| 2 | - This file is part of Peers, a java SIP softphone. | |
| 3 | - | |
| 4 | - This program is free software: you can redistribute it and/or modify | |
| 5 | - it under the terms of the GNU General Public License as published by | |
| 6 | - the Free Software Foundation, either version 3 of the License, or | |
| 7 | - any later version. | |
| 8 | - | |
| 9 | - This program is distributed in the hope that it will be useful, | |
| 10 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | - GNU General Public License for more details. | |
| 13 | - | |
| 14 | - You should have received a copy of the GNU General Public License | |
| 15 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | - | |
| 17 | - Copyright 2010 Yohann Martineau | |
| 18 | -*/ | |
| 19 | - | |
| 20 | -package com.genersoft.iot.vmp.gb28181.sdp; | |
| 21 | - | |
| 22 | -public class Codec { | |
| 23 | - | |
| 24 | - private int payloadType; | |
| 25 | - private String name; | |
| 26 | - | |
| 27 | - public int getPayloadType() { | |
| 28 | - return payloadType; | |
| 29 | - } | |
| 30 | - | |
| 31 | - public void setPayloadType(int payloadType) { | |
| 32 | - this.payloadType = payloadType; | |
| 33 | - } | |
| 34 | - | |
| 35 | - public String getName() { | |
| 36 | - return name; | |
| 37 | - } | |
| 38 | - | |
| 39 | - public void setName(String name) { | |
| 40 | - this.name = name; | |
| 41 | - } | |
| 42 | - | |
| 43 | - @Override | |
| 44 | - public boolean equals(Object obj) { | |
| 45 | - if (!(obj instanceof Codec)) { | |
| 46 | - return false; | |
| 47 | - } | |
| 48 | - Codec codec = (Codec)obj; | |
| 49 | - if (codec.getName() == null) { | |
| 50 | - return name == null; | |
| 51 | - } | |
| 52 | - return codec.getName().equalsIgnoreCase(name); | |
| 53 | - } | |
| 54 | - | |
| 55 | - @Override | |
| 56 | - public String toString() { | |
| 57 | - StringBuffer buf = new StringBuffer(); | |
| 58 | - buf.append(RFC4566_28181.TYPE_ATTRIBUTE).append(RFC4566_28181.SEPARATOR); | |
| 59 | - buf.append(RFC4566_28181.ATTR_RTPMAP).append(RFC4566_28181.ATTR_SEPARATOR); | |
| 60 | - buf.append(payloadType).append(" ").append(name).append("/"); | |
| 61 | - buf.append(9000).append("\r\n"); | |
| 62 | - return buf.toString(); | |
| 63 | - } | |
| 64 | - | |
| 65 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/MediaDescription.java deleted
100755 → 0
| 1 | -/* | |
| 2 | - This file is part of Peers, a java SIP softphone. | |
| 3 | - | |
| 4 | - This program is free software: you can redistribute it and/or modify | |
| 5 | - it under the terms of the GNU General Public License as published by | |
| 6 | - the Free Software Foundation, either version 3 of the License, or | |
| 7 | - any later version. | |
| 8 | - | |
| 9 | - This program is distributed in the hope that it will be useful, | |
| 10 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | - GNU General Public License for more details. | |
| 13 | - | |
| 14 | - You should have received a copy of the GNU General Public License | |
| 15 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | - | |
| 17 | - Copyright 2007, 2008, 2009, 2010 Yohann Martineau | |
| 18 | - */ | |
| 19 | - | |
| 20 | -package com.genersoft.iot.vmp.gb28181.sdp; | |
| 21 | - | |
| 22 | -import java.net.Inet4Address; | |
| 23 | -import java.net.Inet6Address; | |
| 24 | -import java.net.InetAddress; | |
| 25 | -import java.util.Hashtable; | |
| 26 | -import java.util.List; | |
| 27 | - | |
| 28 | -public class MediaDescription { | |
| 29 | - | |
| 30 | - private String type; | |
| 31 | - private InetAddress ipAddress; | |
| 32 | - // attributes not codec-related | |
| 33 | - private Hashtable<String, String> attributes; | |
| 34 | - private int port; | |
| 35 | - private List<Codec> codecs; | |
| 36 | - | |
| 37 | - public String getType() { | |
| 38 | - return type; | |
| 39 | - } | |
| 40 | - | |
| 41 | - public void setType(String type) { | |
| 42 | - this.type = type; | |
| 43 | - } | |
| 44 | - | |
| 45 | - public Hashtable<String, String> getAttributes() { | |
| 46 | - return attributes; | |
| 47 | - } | |
| 48 | - | |
| 49 | - public void setAttributes(Hashtable<String, String> attributes) { | |
| 50 | - this.attributes = attributes; | |
| 51 | - } | |
| 52 | - | |
| 53 | - public InetAddress getIpAddress() { | |
| 54 | - return ipAddress; | |
| 55 | - } | |
| 56 | - | |
| 57 | - public void setIpAddress(InetAddress ipAddress) { | |
| 58 | - this.ipAddress = ipAddress; | |
| 59 | - } | |
| 60 | - | |
| 61 | - public int getPort() { | |
| 62 | - return port; | |
| 63 | - } | |
| 64 | - | |
| 65 | - public void setPort(int port) { | |
| 66 | - this.port = port; | |
| 67 | - } | |
| 68 | - | |
| 69 | - public List<Codec> getCodecs() { | |
| 70 | - return codecs; | |
| 71 | - } | |
| 72 | - | |
| 73 | - public void setCodecs(List<Codec> codecs) { | |
| 74 | - this.codecs = codecs; | |
| 75 | - } | |
| 76 | - | |
| 77 | - @Override | |
| 78 | - public String toString() { | |
| 79 | - StringBuffer buf = new StringBuffer(); | |
| 80 | - buf.append(RFC4566_28181.TYPE_MEDIA).append(RFC4566_28181.SEPARATOR); | |
| 81 | - buf.append(type).append(" ").append(port); | |
| 82 | - buf.append(" RTP/AVP"); | |
| 83 | - if (codecs != null) { | |
| 84 | - for (Codec codec: codecs) { | |
| 85 | - buf.append(" "); | |
| 86 | - buf.append(codec.getPayloadType()); | |
| 87 | - } | |
| 88 | - buf.append("\r\n"); | |
| 89 | - } | |
| 90 | - if (ipAddress != null) { | |
| 91 | - int ipVersion; | |
| 92 | - if (ipAddress instanceof Inet4Address) { | |
| 93 | - ipVersion = 4; | |
| 94 | - } else if (ipAddress instanceof Inet6Address) { | |
| 95 | - ipVersion = 6; | |
| 96 | - } else { | |
| 97 | - throw new RuntimeException("unknown ip version: " + ipAddress); | |
| 98 | - } | |
| 99 | - buf.append(RFC4566_28181.TYPE_CONNECTION).append(RFC4566_28181.SEPARATOR); | |
| 100 | - buf.append("IN IP").append(ipVersion).append(" "); | |
| 101 | - buf.append(ipAddress.getHostAddress()).append("\r\n"); | |
| 102 | - } | |
| 103 | - if (codecs != null) { | |
| 104 | - for (Codec codec: codecs) { | |
| 105 | - buf.append(codec.toString()); | |
| 106 | - } | |
| 107 | - } | |
| 108 | - | |
| 109 | - if (attributes != null) { | |
| 110 | - for (String attributeName: attributes.keySet()) { | |
| 111 | - buf.append(RFC4566_28181.TYPE_ATTRIBUTE).append(RFC4566_28181.SEPARATOR); | |
| 112 | - buf.append(attributeName); | |
| 113 | - String attributeValue = attributes.get(attributeName); | |
| 114 | - if (attributeValue != null && !"".equals(attributeValue.trim())) { | |
| 115 | - buf.append(":").append(attributeValue); | |
| 116 | - } | |
| 117 | - buf.append("\r\n"); | |
| 118 | - } | |
| 119 | - } | |
| 120 | - return buf.toString(); | |
| 121 | - } | |
| 122 | - | |
| 123 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/RFC4566_28181.java deleted
100755 → 0
| 1 | -/* | |
| 2 | - This file is part of Peers, a java SIP softphone. | |
| 3 | - | |
| 4 | - This program is free software: you can redistribute it and/or modify | |
| 5 | - it under the terms of the GNU General Public License as published by | |
| 6 | - the Free Software Foundation, either version 3 of the License, or | |
| 7 | - any later version. | |
| 8 | - | |
| 9 | - This program is distributed in the hope that it will be useful, | |
| 10 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | - GNU General Public License for more details. | |
| 13 | - | |
| 14 | - You should have received a copy of the GNU General Public License | |
| 15 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | - | |
| 17 | - Copyright 2007, 2008, 2009, 2010 Yohann Martineau | |
| 18 | -*/ | |
| 19 | - | |
| 20 | -package com.genersoft.iot.vmp.gb28181.sdp; | |
| 21 | - | |
| 22 | -public class RFC4566_28181 { | |
| 23 | - | |
| 24 | - public static final char VERSION = '0'; | |
| 25 | - | |
| 26 | - public static final char TYPE_VERSION = 'v'; | |
| 27 | - public static final char TYPE_ORIGIN = 'o'; | |
| 28 | - public static final char TYPE_SUBJECT = 's'; | |
| 29 | - public static final char TYPE_INFO = 'i'; | |
| 30 | - public static final char TYPE_URI = 'u'; | |
| 31 | - public static final char TYPE_EMAIL = 'e'; | |
| 32 | - public static final char TYPE_PHONE = 'p'; | |
| 33 | - public static final char TYPE_CONNECTION = 'c'; | |
| 34 | - public static final char TYPE_BANDWITH = 'b'; | |
| 35 | - public static final char TYPE_TIME = 't'; | |
| 36 | - public static final char TYPE_REPEAT = 'r'; | |
| 37 | - public static final char TYPE_ZONE = 'z'; | |
| 38 | - public static final char TYPE_KEY = 'k'; | |
| 39 | - public static final char TYPE_ATTRIBUTE = 'a'; | |
| 40 | - public static final char TYPE_MEDIA = 'm'; | |
| 41 | - public static final char TYPE_SSRC = 'y'; | |
| 42 | - public static final char TYPE_MEDIA_DES = 'f'; | |
| 43 | - | |
| 44 | - public static final char SEPARATOR = '='; | |
| 45 | - public static final char ATTR_SEPARATOR = ':'; | |
| 46 | - | |
| 47 | - public static final String MEDIA_AUDIO = "audio"; | |
| 48 | - | |
| 49 | - public static final String ATTR_RTPMAP = "rtpmap"; | |
| 50 | - public static final String ATTR_SENDRECV = "sendrecv"; | |
| 51 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/SdpLine.java deleted
100755 → 0
| 1 | -/* | |
| 2 | - This file is part of Peers, a java SIP softphone. | |
| 3 | - | |
| 4 | - This program is free software: you can redistribute it and/or modify | |
| 5 | - it under the terms of the GNU General Public License as published by | |
| 6 | - the Free Software Foundation, either version 3 of the License, or | |
| 7 | - any later version. | |
| 8 | - | |
| 9 | - This program is distributed in the hope that it will be useful, | |
| 10 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | - GNU General Public License for more details. | |
| 13 | - | |
| 14 | - You should have received a copy of the GNU General Public License | |
| 15 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | - | |
| 17 | - Copyright 2007, 2008, 2009, 2010 Yohann Martineau | |
| 18 | -*/ | |
| 19 | - | |
| 20 | -package com.genersoft.iot.vmp.gb28181.sdp; | |
| 21 | - | |
| 22 | -public class SdpLine { | |
| 23 | - private char type; | |
| 24 | - private String value; | |
| 25 | - public char getType() { | |
| 26 | - return type; | |
| 27 | - } | |
| 28 | - public void setType(char type) { | |
| 29 | - this.type = type; | |
| 30 | - } | |
| 31 | - public String getValue() { | |
| 32 | - return value; | |
| 33 | - } | |
| 34 | - public void setValue(String value) { | |
| 35 | - this.value = value; | |
| 36 | - } | |
| 37 | - | |
| 38 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/SdpParser.java deleted
100755 → 0
| 1 | -/* | |
| 2 | - This file is part of Peers, a java SIP softphone. | |
| 3 | - | |
| 4 | - This program is free software: you can redistribute it and/or modify | |
| 5 | - it under the terms of the GNU General Public License as published by | |
| 6 | - the Free Software Foundation, either version 3 of the License, or | |
| 7 | - any later version. | |
| 8 | - | |
| 9 | - This program is distributed in the hope that it will be useful, | |
| 10 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | - GNU General Public License for more details. | |
| 13 | - | |
| 14 | - You should have received a copy of the GNU General Public License | |
| 15 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | - | |
| 17 | - Copyright 2007, 2008, 2009, 2010 Yohann Martineau | |
| 18 | -*/ | |
| 19 | - | |
| 20 | -package com.genersoft.iot.vmp.gb28181.sdp; | |
| 21 | - | |
| 22 | -import java.io.BufferedReader; | |
| 23 | -import java.io.ByteArrayInputStream; | |
| 24 | -import java.io.IOException; | |
| 25 | -import java.io.InputStreamReader; | |
| 26 | -import java.net.InetAddress; | |
| 27 | -import java.util.ArrayList; | |
| 28 | -import java.util.Hashtable; | |
| 29 | -import java.util.List; | |
| 30 | - | |
| 31 | -public class SdpParser { | |
| 32 | - | |
| 33 | - public SessionDescription parse(byte[] body) throws IOException { | |
| 34 | - if (body == null || body.length == 0) { | |
| 35 | - return null; | |
| 36 | - } | |
| 37 | - ByteArrayInputStream in = new ByteArrayInputStream(body); | |
| 38 | - InputStreamReader inputStreamReader = new InputStreamReader(in); | |
| 39 | - BufferedReader reader = new BufferedReader(inputStreamReader); | |
| 40 | - SessionDescription sessionDescription = new SessionDescription(); | |
| 41 | - | |
| 42 | - //version | |
| 43 | - | |
| 44 | - String line = reader.readLine(); | |
| 45 | - if (line.length() < 3) { | |
| 46 | - return null; | |
| 47 | - } | |
| 48 | - if (line.charAt(0) != RFC4566_28181.TYPE_VERSION | |
| 49 | - || line.charAt(1) != RFC4566_28181.SEPARATOR | |
| 50 | - || line.charAt(2) != RFC4566_28181.VERSION) { | |
| 51 | - return null; | |
| 52 | - } | |
| 53 | - | |
| 54 | - //origin | |
| 55 | - | |
| 56 | - line = reader.readLine(); | |
| 57 | - if (line.length() < 3) { | |
| 58 | - return null; | |
| 59 | - } | |
| 60 | - if (line.charAt(0) != RFC4566_28181.TYPE_ORIGIN | |
| 61 | - || line.charAt(1) != RFC4566_28181.SEPARATOR) { | |
| 62 | - return null; | |
| 63 | - } | |
| 64 | - line = line.substring(2); | |
| 65 | - String[] originArr = line.split(" "); | |
| 66 | - if (originArr == null || originArr.length != 6) { | |
| 67 | - return null; | |
| 68 | - } | |
| 69 | - sessionDescription.setUsername(originArr[0]); | |
| 70 | - sessionDescription.setId(Long.parseLong(originArr[1])); | |
| 71 | - sessionDescription.setVersion(Long.parseLong(originArr[2])); | |
| 72 | - sessionDescription.setIpAddress(InetAddress.getByName(originArr[5])); | |
| 73 | - | |
| 74 | - //name | |
| 75 | - | |
| 76 | - line = reader.readLine(); | |
| 77 | - if (line.length() < 3) { | |
| 78 | - return null; | |
| 79 | - } | |
| 80 | - if (line.charAt(0) != RFC4566_28181.TYPE_SUBJECT | |
| 81 | - || line.charAt(1) != RFC4566_28181.SEPARATOR) { | |
| 82 | - return null; | |
| 83 | - } | |
| 84 | - sessionDescription.setName(line.substring(2)); | |
| 85 | - | |
| 86 | - //session connection and attributes | |
| 87 | - Hashtable<String, String> sessionAttributes = new Hashtable<String, String>(); | |
| 88 | - sessionDescription.setAttributes(sessionAttributes); | |
| 89 | - | |
| 90 | - while ((line = reader.readLine()) != null | |
| 91 | - && line.charAt(0) != RFC4566_28181.TYPE_MEDIA) { | |
| 92 | - if (line.length() > 3 | |
| 93 | - && line.charAt(0) == RFC4566_28181.TYPE_CONNECTION | |
| 94 | - && line.charAt(1) == RFC4566_28181.SEPARATOR) { | |
| 95 | - String connection = parseConnection(line.substring(2)); | |
| 96 | - if (connection == null) { | |
| 97 | - continue; | |
| 98 | - } | |
| 99 | - sessionDescription.setIpAddress(InetAddress.getByName(connection)); | |
| 100 | - } else if (line.length() > 3 | |
| 101 | - && line.charAt(0) == RFC4566_28181.TYPE_ATTRIBUTE | |
| 102 | - && line.charAt(1) == RFC4566_28181.SEPARATOR) { | |
| 103 | - String value = line.substring(2); | |
| 104 | - int pos = value.indexOf(RFC4566_28181.ATTR_SEPARATOR); | |
| 105 | - if (pos > -1) { | |
| 106 | - sessionAttributes.put(value.substring(0, pos), | |
| 107 | - value.substring(pos + 1)); | |
| 108 | - } else { | |
| 109 | - sessionAttributes.put(value, ""); | |
| 110 | - } | |
| 111 | - } | |
| 112 | - } | |
| 113 | - if (line == null) { | |
| 114 | - return null; | |
| 115 | - } | |
| 116 | - //we are at the first media line | |
| 117 | - | |
| 118 | - ArrayList<SdpLine> mediaLines = new ArrayList<SdpLine>(); | |
| 119 | - do { | |
| 120 | - if (line.length() < 2) { | |
| 121 | - return null; | |
| 122 | - } | |
| 123 | - if (line.charAt(1) != RFC4566_28181.SEPARATOR) { | |
| 124 | - return null; | |
| 125 | - } | |
| 126 | - if (line.charAt(0) == RFC4566_28181.TYPE_SSRC) { | |
| 127 | - sessionDescription.setSsrc(line.length() >=2 ?line.substring(2):""); | |
| 128 | - }else if (line.charAt(0) == RFC4566_28181.TYPE_MEDIA_DES) { | |
| 129 | - sessionDescription.setGbMediaDescriptions(line.length() >=2 ?line.substring(2):""); | |
| 130 | - }else { | |
| 131 | - SdpLine mediaLine = new SdpLine(); | |
| 132 | - mediaLine.setType(line.charAt(0)); | |
| 133 | - mediaLine.setValue(line.substring(2)); | |
| 134 | - mediaLines.add(mediaLine); | |
| 135 | - } | |
| 136 | - | |
| 137 | - } | |
| 138 | - while ((line = reader.readLine()) != null ); | |
| 139 | - | |
| 140 | - ArrayList<MediaDescription> mediaDescriptions = new ArrayList<MediaDescription>(); | |
| 141 | - sessionDescription.setMediaDescriptions(mediaDescriptions); | |
| 142 | - | |
| 143 | - for (SdpLine sdpLine : mediaLines) { | |
| 144 | - MediaDescription mediaDescription; | |
| 145 | - if (sdpLine.getType() == RFC4566_28181.TYPE_MEDIA) { | |
| 146 | - String[] mediaArr = sdpLine.getValue().split(" "); | |
| 147 | - if (mediaArr == null || mediaArr.length < 4) { | |
| 148 | - return null; | |
| 149 | - } | |
| 150 | - mediaDescription = new MediaDescription(); | |
| 151 | - mediaDescription.setType(mediaArr[0]); | |
| 152 | - //TODO manage port range | |
| 153 | - mediaDescription.setPort(Integer.parseInt(mediaArr[1])); | |
| 154 | - mediaDescription.setAttributes(new Hashtable<String, String>()); | |
| 155 | - List<Codec> codecs = new ArrayList<Codec>(); | |
| 156 | - for (int i = 3; i < mediaArr.length; ++i) { | |
| 157 | - int payloadType = Integer.parseInt(mediaArr[i]); | |
| 158 | - Codec codec = new Codec(); | |
| 159 | - codec.setPayloadType(payloadType); | |
| 160 | - codec.setName("unsupported"); | |
| 161 | - codecs.add(codec); | |
| 162 | - } | |
| 163 | - mediaDescription.setCodecs(codecs); | |
| 164 | - mediaDescriptions.add(mediaDescription); | |
| 165 | - } else { | |
| 166 | - mediaDescription = mediaDescriptions.get(mediaDescriptions.size() - 1); | |
| 167 | - String sdpLineValue = sdpLine.getValue(); | |
| 168 | - if (sdpLine.getType() == RFC4566_28181.TYPE_CONNECTION) { | |
| 169 | - String ipAddress = parseConnection(sdpLineValue); | |
| 170 | - mediaDescription.setIpAddress(InetAddress.getByName(ipAddress)); | |
| 171 | - } else if (sdpLine.getType() == RFC4566_28181.TYPE_ATTRIBUTE) { | |
| 172 | - Hashtable<String, String> attributes = mediaDescription.getAttributes(); | |
| 173 | - int pos = sdpLineValue.indexOf(RFC4566_28181.ATTR_SEPARATOR); | |
| 174 | - if (pos > -1) { | |
| 175 | - String name = sdpLineValue.substring(0, pos); | |
| 176 | - String value = sdpLineValue.substring(pos + 1); | |
| 177 | - pos = value.indexOf(" "); | |
| 178 | - if (pos > -1) { | |
| 179 | - int payloadType; | |
| 180 | - try { | |
| 181 | - payloadType = Integer.parseInt(value.substring(0, pos)); | |
| 182 | - List<Codec> codecs = mediaDescription.getCodecs(); | |
| 183 | - for (Codec codec: codecs) { | |
| 184 | - if (codec.getPayloadType() == payloadType) { | |
| 185 | - value = value.substring(pos + 1); | |
| 186 | - pos = value.indexOf("/"); | |
| 187 | - if (pos > -1) { | |
| 188 | - value = value.substring(0, pos); | |
| 189 | - codec.setName(value); | |
| 190 | - } | |
| 191 | - break; | |
| 192 | - } | |
| 193 | - } | |
| 194 | - } catch (NumberFormatException e) { | |
| 195 | - attributes.put(name, value); | |
| 196 | - } | |
| 197 | - } else { | |
| 198 | - attributes.put(name, value); | |
| 199 | - } | |
| 200 | - } else { | |
| 201 | - attributes.put(sdpLineValue, ""); | |
| 202 | - } | |
| 203 | - } | |
| 204 | - } | |
| 205 | - } | |
| 206 | - sessionDescription.setMediaDescriptions(mediaDescriptions); | |
| 207 | - | |
| 208 | - for (MediaDescription description : mediaDescriptions) { | |
| 209 | - if (description.getIpAddress() == null) { | |
| 210 | - InetAddress sessionAddress = sessionDescription.getIpAddress(); | |
| 211 | - if (sessionAddress == null) { | |
| 212 | - return null; | |
| 213 | - } | |
| 214 | - description.setIpAddress(sessionAddress); | |
| 215 | - } | |
| 216 | - } | |
| 217 | - | |
| 218 | - | |
| 219 | - return sessionDescription; | |
| 220 | - } | |
| 221 | - | |
| 222 | - private String parseConnection(String line) { | |
| 223 | - String[] connectionArr = line.split(" "); | |
| 224 | - if (connectionArr == null || connectionArr.length != 3) { | |
| 225 | - return null; | |
| 226 | - } | |
| 227 | - return connectionArr[2]; | |
| 228 | - } | |
| 229 | - | |
| 230 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/sdp/SessionDescription.java deleted
100755 → 0
| 1 | -/* | |
| 2 | - This file is part of Peers, a java SIP softphone. | |
| 3 | - | |
| 4 | - This program is free software: you can redistribute it and/or modify | |
| 5 | - it under the terms of the GNU General Public License as published by | |
| 6 | - the Free Software Foundation, either version 3 of the License, or | |
| 7 | - any later version. | |
| 8 | - | |
| 9 | - This program is distributed in the hope that it will be useful, | |
| 10 | - but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | - GNU General Public License for more details. | |
| 13 | - | |
| 14 | - You should have received a copy of the GNU General Public License | |
| 15 | - along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | - | |
| 17 | - Copyright 2007, 2008, 2009, 2010 Yohann Martineau | |
| 18 | -*/ | |
| 19 | - | |
| 20 | -package com.genersoft.iot.vmp.gb28181.sdp; | |
| 21 | - | |
| 22 | -import java.net.Inet4Address; | |
| 23 | -import java.net.Inet6Address; | |
| 24 | -import java.net.InetAddress; | |
| 25 | -import java.util.Hashtable; | |
| 26 | -import java.util.List; | |
| 27 | - | |
| 28 | -public class SessionDescription { | |
| 29 | - | |
| 30 | - private long id; | |
| 31 | - private long version; | |
| 32 | - private String name; | |
| 33 | - private String username; | |
| 34 | - private InetAddress ipAddress; | |
| 35 | - private List<MediaDescription> mediaDescriptions; | |
| 36 | - private Hashtable<String, String> attributes; | |
| 37 | - private String ssrc; | |
| 38 | - private String gbMediaDescriptions; | |
| 39 | - | |
| 40 | - public SessionDescription() { | |
| 41 | - } | |
| 42 | - | |
| 43 | - public long getId() { | |
| 44 | - return id; | |
| 45 | - } | |
| 46 | - | |
| 47 | - public void setId(long id) { | |
| 48 | - this.id = id; | |
| 49 | - } | |
| 50 | - | |
| 51 | - public InetAddress getIpAddress() { | |
| 52 | - return ipAddress; | |
| 53 | - } | |
| 54 | - | |
| 55 | - public void setIpAddress(InetAddress ipAddress) { | |
| 56 | - this.ipAddress = ipAddress; | |
| 57 | - } | |
| 58 | - | |
| 59 | - public List<MediaDescription> getMediaDescriptions() { | |
| 60 | - return mediaDescriptions; | |
| 61 | - } | |
| 62 | - | |
| 63 | - public void setMediaDescriptions(List<MediaDescription> mediaDescriptions) { | |
| 64 | - this.mediaDescriptions = mediaDescriptions; | |
| 65 | - } | |
| 66 | - | |
| 67 | - public String getName() { | |
| 68 | - return name; | |
| 69 | - } | |
| 70 | - | |
| 71 | - public void setName(String name) { | |
| 72 | - this.name = name; | |
| 73 | - } | |
| 74 | - | |
| 75 | - public String getUsername() { | |
| 76 | - return username; | |
| 77 | - } | |
| 78 | - | |
| 79 | - public void setUsername(String username) { | |
| 80 | - this.username = username; | |
| 81 | - } | |
| 82 | - | |
| 83 | - public long getVersion() { | |
| 84 | - return version; | |
| 85 | - } | |
| 86 | - | |
| 87 | - public void setVersion(long version) { | |
| 88 | - this.version = version; | |
| 89 | - } | |
| 90 | - | |
| 91 | - public Hashtable<String, String> getAttributes() { | |
| 92 | - return attributes; | |
| 93 | - } | |
| 94 | - | |
| 95 | - public void setAttributes(Hashtable<String, String> attributes) { | |
| 96 | - this.attributes = attributes; | |
| 97 | - } | |
| 98 | - | |
| 99 | - public String getSsrc() { | |
| 100 | - return ssrc; | |
| 101 | - } | |
| 102 | - | |
| 103 | - public void setSsrc(String ssrc) { | |
| 104 | - this.ssrc = ssrc; | |
| 105 | - } | |
| 106 | - | |
| 107 | - public String getGbMediaDescriptions() { | |
| 108 | - return gbMediaDescriptions; | |
| 109 | - } | |
| 110 | - | |
| 111 | - public void setGbMediaDescriptions(String gbMediaDescriptions) { | |
| 112 | - this.gbMediaDescriptions = gbMediaDescriptions; | |
| 113 | - } | |
| 114 | - | |
| 115 | - @Override | |
| 116 | - public String toString() { | |
| 117 | - StringBuilder buf = new StringBuilder(); | |
| 118 | - buf.append("v=0\r\n"); | |
| 119 | - buf.append("o=").append(username).append(" ").append(id); | |
| 120 | - buf.append(" ").append(version); | |
| 121 | - int ipVersion; | |
| 122 | - if (ipAddress instanceof Inet4Address) { | |
| 123 | - ipVersion = 4; | |
| 124 | - } else if (ipAddress instanceof Inet6Address) { | |
| 125 | - ipVersion = 6; | |
| 126 | - } else { | |
| 127 | - throw new RuntimeException("unknown ip version: " + ipAddress); | |
| 128 | - } | |
| 129 | - buf.append(" IN IP").append(ipVersion).append(" "); | |
| 130 | - String hostAddress = ipAddress.getHostAddress(); | |
| 131 | - buf.append(hostAddress).append("\r\n"); | |
| 132 | - buf.append("s=").append(name).append("\r\n"); | |
| 133 | - buf.append("c=IN IP").append(ipVersion).append(" "); | |
| 134 | - buf.append(hostAddress).append("\r\n"); | |
| 135 | - buf.append("t=0 0\r\n"); | |
| 136 | - if (attributes != null){ | |
| 137 | - for (String attributeName: attributes.keySet()) { | |
| 138 | - String attributeValue = attributes.get(attributeName); | |
| 139 | - buf.append("a=").append(attributeName); | |
| 140 | - if (attributeValue != null && !"".equals(attributeValue.trim())) { | |
| 141 | - buf.append(":"); | |
| 142 | - buf.append(attributeValue); | |
| 143 | - buf.append("\r\n"); | |
| 144 | - } | |
| 145 | - } | |
| 146 | - } | |
| 147 | - if (mediaDescriptions != null){ | |
| 148 | - for (MediaDescription mediaDescription: mediaDescriptions) { | |
| 149 | - buf.append(mediaDescription.toString()); | |
| 150 | - } | |
| 151 | - } | |
| 152 | - | |
| 153 | - if (ssrc != null){ | |
| 154 | - buf.append("y=").append(ssrc).append("\r\n"); | |
| 155 | - } | |
| 156 | - if (gbMediaDescriptions != null){ | |
| 157 | - buf.append("f=").append(gbMediaDescriptions).append("\r\n"); | |
| 158 | - } | |
| 159 | - return buf.toString(); | |
| 160 | - } | |
| 161 | - | |
| 162 | -} |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| ... | ... | @@ -375,7 +375,6 @@ public class SIPCommander implements ISIPCommander { |
| 375 | 375 | content.append("a=setup:passive\r\n"); |
| 376 | 376 | content.append("a=connection:new\r\n"); |
| 377 | 377 | } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 |
| 378 | - } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式 | |
| 379 | 378 | content.append("a=setup:active\r\n"); |
| 380 | 379 | content.append("a=connection:new\r\n"); |
| 381 | 380 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java
| ... | ... | @@ -113,45 +113,84 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { |
| 113 | 113 | } |
| 114 | 114 | // 解析sdp消息, 使用jainsip 自带的sdp解析方式 |
| 115 | 115 | String contentString = new String(request.getRawContent()); |
| 116 | - SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(contentString); | |
| 117 | 116 | |
| 118 | - // TODO 区分TCP发流还是udp, 当前默认udp | |
| 117 | + // jainSip不支持y=字段, 移除移除以解析。 | |
| 118 | + int ssrcIndex = contentString.indexOf("y="); | |
| 119 | + String ssrc = contentString.substring(ssrcIndex + 2, contentString.length()) | |
| 120 | + .replace("\r\n", "").replace("\n", ""); | |
| 121 | + | |
| 122 | + String substring = contentString.substring(0, contentString.indexOf("y=")); | |
| 123 | + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); | |
| 124 | + | |
| 119 | 125 | // 获取支持的格式 |
| 120 | 126 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| 121 | 127 | // 查看是否支持PS 负载96 |
| 122 | 128 | String ip = null; |
| 123 | 129 | int port = -1; |
| 130 | + boolean recvonly = false; | |
| 131 | + boolean mediaTransmissionTCP = false; | |
| 132 | + Boolean tcpActive = null; | |
| 124 | 133 | for (int i = 0; i < mediaDescriptions.size(); i++) { |
| 125 | 134 | MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); |
| 126 | 135 | Media media = mediaDescription.getMedia(); |
| 127 | - port = media.getMediaPort(); | |
| 128 | - } | |
| 129 | -// for (MediaDescription mediaDescription : mediaDescriptions) { | |
| 130 | -// | |
| 131 | -// List<Codec> codecs = mediaDescription.getCodecs(); | |
| 132 | -// for (Codec codec : codecs) { | |
| 133 | -// if("96".equals(codec.getPayloadType()) || "PS".equals(codec.getName()) || "ps".equals(codec.getName())) { | |
| 134 | -// // TODO 这里很慢 | |
| 135 | -// ip = mediaDescription.getIpAddress().getHostName(); | |
| 136 | -// port = mediaDescription.getPort(); | |
| 137 | -// break; | |
| 138 | -// } | |
| 139 | -// } | |
| 140 | -// } | |
| 141 | -// if (ip == null || port == -1) { // TODO 没有合适的视频流格式, 可配置是否使用第一个media信息 | |
| 142 | -// if (mediaDescriptions.size() > 0) { | |
| 143 | -// ip = mediaDescriptions.get(0).getIpAddress().getHostName(); | |
| 144 | -// port = mediaDescriptions.get(0).getPort(); | |
| 145 | -// } | |
| 146 | -// } | |
| 147 | -// | |
| 148 | -// if (ip == null || port == -1) { | |
| 149 | -// response488Ack(evt); | |
| 150 | -// return; | |
| 151 | -// } | |
| 136 | + | |
| 137 | + Vector mediaFormats = media.getMediaFormats(false); | |
| 138 | + if (mediaFormats.contains("96")) { | |
| 139 | + port = media.getMediaPort(); | |
| 140 | + String mediaType = media.getMediaType(); | |
| 141 | + String protocol = media.getProtocol(); | |
| 142 | + | |
| 143 | + // 区分TCP发流还是udp, 当前默认udp | |
| 144 | + if ("TCP/RTP/AVP".equals(protocol)) { | |
| 145 | + String setup = mediaDescription.getAttribute("setup"); | |
| 146 | + if (setup != null) { | |
| 147 | + mediaTransmissionTCP = true; | |
| 148 | + if ("active".equals(setup)) { | |
| 149 | + tcpActive = true; | |
| 150 | + }else if ("passive".equals(setup)) { | |
| 151 | + tcpActive = false; | |
| 152 | + } | |
| 153 | + } | |
| 154 | + } | |
| 155 | +// Vector attributes = mediaDescription.getAttributes(false); | |
| 156 | +// for (Object attributeObj : attributes) { | |
| 157 | +// Attribute attribute = (Attribute)attributeObj; | |
| 158 | +// String name = attribute.getName(); | |
| 159 | +// switch (name){ | |
| 160 | +// case "recvonly": | |
| 161 | +// recvonly = true; | |
| 162 | +// break; | |
| 163 | +// case "rtpmap": | |
| 164 | +// case "connection": | |
| 165 | +// break; | |
| 166 | +// case "setup": | |
| 167 | +// mediaTransmissionTCP = true; | |
| 168 | +// if ("active".equals(attribute.getValue())) { // tcp主动模式 | |
| 169 | +// tcpActive = true; | |
| 170 | +// }else if ("passive".equals(attribute.getValue())){ // tcp被动模式 | |
| 171 | +// tcpActive = false; | |
| 172 | +// } | |
| 173 | +// break; | |
| 152 | 174 | // |
| 175 | +// } | |
| 176 | +// if ("recvonly".equals(name)) { | |
| 177 | +// recvonly = true; | |
| 178 | +// } | |
| 153 | 179 | // |
| 154 | -// String ssrc = sdp.getSsrc(); | |
| 180 | +// String value = attribute.getValue(); | |
| 181 | +// } | |
| 182 | + break; | |
| 183 | + } | |
| 184 | + } | |
| 185 | + if (port == -1) { | |
| 186 | + // 回复不支持的格式 | |
| 187 | + response415Ack(evt); // 不支持的格式,发415 | |
| 188 | + return; | |
| 189 | + } | |
| 190 | + String username = sdp.getOrigin().getUsername(); | |
| 191 | + String addressStr = sdp.getOrigin().getAddress(); | |
| 192 | + String sessionName = sdp.getSessionName().getValue(); | |
| 193 | + logger.info("[上级点播]用户:{}, 地址:{}:{}, ssrc:{}", username, addressStr, port, ssrc); | |
| 155 | 194 | // |
| 156 | 195 | // Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId); |
| 157 | 196 | // if (device == null) { |
| ... | ... | @@ -278,6 +317,18 @@ public class InviteRequestProcessor extends SIPRequestAbstractProcessor { |
| 278 | 317 | } |
| 279 | 318 | |
| 280 | 319 | /*** |
| 320 | + * 回复415 不支持的媒体类型 | |
| 321 | + * @param evt | |
| 322 | + * @throws SipException | |
| 323 | + * @throws InvalidArgumentException | |
| 324 | + * @throws ParseException | |
| 325 | + */ | |
| 326 | + private void response415Ack(RequestEvent evt) throws SipException, InvalidArgumentException, ParseException { | |
| 327 | + Response response = getMessageFactory().createResponse(Response.UNSUPPORTED_MEDIA_TYPE, evt.getRequest()); | |
| 328 | + getServerTransaction(evt).sendResponse(response); | |
| 329 | + } | |
| 330 | + | |
| 331 | + /*** | |
| 281 | 332 | * 回复488 |
| 282 | 333 | * @param evt |
| 283 | 334 | * @throws SipException | ... | ... |
web_src/.postcssrc.js