├── .gitignore ├── build.gradle └── src └── main └── java └── br └── com └── voicetechnology └── rtspclient ├── HeaderMismatchException.java ├── IncompleteMessageException.java ├── InvalidMessageException.java ├── MissingHeaderException.java ├── RTSPClient.java ├── RTSPEntityMessage.java ├── RTSPMessage.java ├── RTSPMessageFactory.java ├── RTSPRequest.java ├── RTSPResponse.java ├── concepts ├── Client.java ├── ClientListener.java ├── Content.java ├── EntityMessage.java ├── Header.java ├── Message.java ├── MessageBuffer.java ├── MessageFactory.java ├── Request.java ├── Response.java ├── Transport.java └── TransportListener.java ├── headers ├── BaseIntegerHeader.java ├── BaseStringHeader.java ├── CSeqHeader.java ├── ContentEncodingHeader.java ├── ContentLengthHeader.java ├── ContentTypeHeader.java ├── SessionHeader.java └── TransportHeader.java ├── messages ├── RTSPDescribeRequest.java ├── RTSPOptionsRequest.java ├── RTSPPlayRequest.java ├── RTSPSetupRequest.java └── RTSPTeardownRequest.java ├── test ├── OPTIONSTest.java ├── PLAYTest.java ├── ReadH264.java ├── SETUPandTEARDOWNTest.java └── Server.java ├── transport ├── PlainTCP.java └── SafeTransportListener.java └── util ├── RTPPacket.java ├── UnsignedByte.java ├── UnsignedInt.java ├── UnsignedNumber.java └── UnsignedShort.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # Gradle Files # 9 | .gradle/* 10 | 11 | # Build Files # 12 | build/* 13 | 14 | # Eclipse Files# 15 | .settings/* 16 | .classpath 17 | .project 18 | 19 | # Idea Files # 20 | *.iml 21 | *.ipr 22 | *.iws 23 | /bin 24 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "java" 2 | 3 | apply plugin: "eclipse" 4 | apply plugin: "idea" 5 | 6 | sourceCompatibility = 1.7 7 | version = '1.0' 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies{ 14 | compile( 15 | "org.slf4j:slf4j-log4j12:1.7.5", 16 | "log4j:log4j:1.2.16" 17 | ) 18 | testCompile( 19 | "junit:junit:4.11" 20 | ) 21 | } 22 | 23 | tasks.withType(JavaCompile){ 24 | options.encoding ="utf-8" 25 | } 26 | tasks.withType(Javadoc){ 27 | options.encoding = "utf-8" 28 | options.charSet = "utf-8" 29 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/HeaderMismatchException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | /** 23 | * Exception thrown when a class is initialized with a header name different 24 | * than expected. 25 | * 26 | * @author paulo 27 | * 28 | */ 29 | public class HeaderMismatchException extends RuntimeException 30 | { 31 | /** 32 | * 33 | */ 34 | private static final long serialVersionUID = 6316852391642646327L; 35 | 36 | public HeaderMismatchException(String expected, String current) 37 | { 38 | super("expected " + expected + " but got " + current); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/IncompleteMessageException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | public class IncompleteMessageException extends InvalidMessageException 23 | { 24 | 25 | /** 26 | * 27 | */ 28 | private static final long serialVersionUID = -2965559263580173275L; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/InvalidMessageException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | import java.io.IOException; 23 | 24 | public class InvalidMessageException extends IOException 25 | { 26 | 27 | /** 28 | * 29 | */ 30 | private static final long serialVersionUID = -1500523453819730537L; 31 | 32 | public InvalidMessageException() 33 | { 34 | } 35 | 36 | public InvalidMessageException(Throwable cause) 37 | { 38 | super(cause); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/MissingHeaderException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | public class MissingHeaderException extends Exception 23 | { 24 | 25 | /** 26 | * 27 | */ 28 | private static final long serialVersionUID = -3027257996891420069L; 29 | 30 | public MissingHeaderException(String header) 31 | { 32 | super("Header " + header + " wasn't found."); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/RTSPClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | import java.io.IOException; 23 | import java.net.SocketException; 24 | import java.net.URI; 25 | import java.net.URISyntaxException; 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | 29 | import br.com.voicetechnology.rtspclient.concepts.Client; 30 | import br.com.voicetechnology.rtspclient.concepts.ClientListener; 31 | import br.com.voicetechnology.rtspclient.concepts.Header; 32 | import br.com.voicetechnology.rtspclient.concepts.Message; 33 | import br.com.voicetechnology.rtspclient.concepts.MessageBuffer; 34 | import br.com.voicetechnology.rtspclient.concepts.MessageFactory; 35 | import br.com.voicetechnology.rtspclient.concepts.Request; 36 | import br.com.voicetechnology.rtspclient.concepts.Response; 37 | import br.com.voicetechnology.rtspclient.concepts.Transport; 38 | import br.com.voicetechnology.rtspclient.concepts.TransportListener; 39 | import br.com.voicetechnology.rtspclient.concepts.Request.Method; 40 | import br.com.voicetechnology.rtspclient.headers.SessionHeader; 41 | import br.com.voicetechnology.rtspclient.headers.TransportHeader; 42 | import br.com.voicetechnology.rtspclient.headers.TransportHeader.LowerTransport; 43 | import br.com.voicetechnology.rtspclient.messages.RTSPOptionsRequest; 44 | 45 | public class RTSPClient implements Client, TransportListener 46 | { 47 | private Transport transport; 48 | 49 | private MessageFactory messageFactory; 50 | 51 | private MessageBuffer messageBuffer; 52 | 53 | private volatile int cseq; 54 | 55 | private SessionHeader session; 56 | 57 | /** 58 | * URI kept from last setup. 59 | */ 60 | private URI uri; 61 | 62 | private Map outstanding; 63 | 64 | private ClientListener clientListener; 65 | 66 | public RTSPClient() 67 | { 68 | messageFactory = new RTSPMessageFactory(); 69 | cseq = 0; 70 | outstanding = new HashMap(); 71 | messageBuffer = new MessageBuffer(); 72 | } 73 | 74 | @Override 75 | public Transport getTransport() 76 | { 77 | return transport; 78 | } 79 | 80 | @Override 81 | public void setSession(SessionHeader session) 82 | { 83 | this.session = session; 84 | } 85 | 86 | @Override 87 | public MessageFactory getMessageFactory() 88 | { 89 | return messageFactory; 90 | } 91 | 92 | @Override 93 | public URI getURI() 94 | { 95 | return uri; 96 | } 97 | 98 | @Override 99 | public void options(String uri, URI endpoint) throws URISyntaxException, 100 | IOException 101 | { 102 | try 103 | { 104 | RTSPOptionsRequest message = (RTSPOptionsRequest) messageFactory 105 | .outgoingRequest(uri, Method.OPTIONS, nextCSeq()); 106 | if(!getTransport().isConnected()) 107 | message.addHeader(new Header("Connection", "close")); 108 | send(message, endpoint); 109 | } catch(MissingHeaderException e) 110 | { 111 | if(clientListener != null) 112 | clientListener.generalError(this, e); 113 | } 114 | } 115 | 116 | @Override 117 | public void play() throws IOException 118 | { 119 | try 120 | { 121 | send(messageFactory.outgoingRequest(uri.toString(), Method.PLAY, 122 | nextCSeq(), session)); 123 | } catch(Exception e) 124 | { 125 | if(clientListener != null) 126 | clientListener.generalError(this, e); 127 | } 128 | } 129 | 130 | @Override 131 | public void record() throws IOException 132 | { 133 | throw new UnsupportedOperationException( 134 | "Recording is not supported in current version."); 135 | } 136 | 137 | @Override 138 | public void setClientListener(ClientListener listener) 139 | { 140 | clientListener = listener; 141 | } 142 | 143 | @Override 144 | public ClientListener getClientListener() 145 | { 146 | return clientListener; 147 | } 148 | 149 | @Override 150 | public void setTransport(Transport transport) 151 | { 152 | this.transport = transport; 153 | transport.setTransportListener(this); 154 | } 155 | 156 | @Override 157 | public void describe(URI uri) throws IOException 158 | { 159 | this.uri = uri; 160 | try 161 | { 162 | send(messageFactory.outgoingRequest(uri.toString(), Method.DESCRIBE, 163 | nextCSeq(), new Header("Accept", "application/sdp"))); 164 | } catch(Exception e) 165 | { 166 | if(clientListener != null) 167 | clientListener.generalError(this, e); 168 | } 169 | } 170 | 171 | @Override 172 | public void setup(URI uri, int localPort) throws IOException 173 | { 174 | this.uri = uri; 175 | try 176 | { 177 | String portParam = "client_port=" + localPort + "-" + (1 + localPort); 178 | 179 | send(getSetup(uri.toString(), localPort, new TransportHeader( 180 | LowerTransport.DEFAULT, "unicast", portParam), session)); 181 | } catch(Exception e) 182 | { 183 | if(clientListener != null) 184 | clientListener.generalError(this, e); 185 | } 186 | } 187 | 188 | @Override 189 | public void setup(URI uri, int localPort, String resource) throws IOException 190 | { 191 | this.uri = uri; 192 | try 193 | { 194 | String portParam = "client_port=" + localPort + "-" + (1 + localPort); 195 | String finalURI = uri.toString(); 196 | if(resource != null && resource.length() != 0 && !resource.equals("*")) 197 | finalURI += '/' + resource; 198 | send(getSetup(finalURI, localPort, new TransportHeader( 199 | LowerTransport.DEFAULT, "unicast", portParam), session)); 200 | } catch(Exception e) 201 | { 202 | if(clientListener != null) 203 | clientListener.generalError(this, e); 204 | } 205 | } 206 | 207 | @Override 208 | public void teardown() 209 | { 210 | if(session == null) 211 | return; 212 | try 213 | { 214 | send(messageFactory.outgoingRequest(uri.toString(), Method.TEARDOWN, 215 | nextCSeq(), session, new Header("Connection", "close"))); 216 | } catch(Exception e) 217 | { 218 | if(clientListener != null) 219 | clientListener.generalError(this, e); 220 | } 221 | } 222 | 223 | @Override 224 | public void connected(Transport t) throws Throwable 225 | { 226 | } 227 | 228 | @Override 229 | public void dataReceived(Transport t, byte[] data, int size) throws Throwable 230 | { 231 | messageBuffer.addData(data, size); 232 | while(messageBuffer.getLength() > 0) 233 | try 234 | { 235 | messageFactory.incomingMessage(messageBuffer); 236 | messageBuffer.discardData(); 237 | Message message = messageBuffer.getMessage(); 238 | if(message instanceof Request) 239 | send(messageFactory.outgoingResponse(405, "Method Not Allowed", 240 | message.getCSeq().getValue())); 241 | else 242 | { 243 | Request request = null; 244 | synchronized(outstanding) 245 | { 246 | request = outstanding.remove(message.getCSeq().getValue()); 247 | } 248 | Response response = (Response) message; 249 | request.handleResponse(this, response); 250 | clientListener.response(this, request, response); 251 | } 252 | } catch(IncompleteMessageException ie) 253 | { 254 | break; 255 | } catch(InvalidMessageException e) 256 | { 257 | messageBuffer.discardData(); 258 | if(clientListener != null) 259 | clientListener.generalError(this, e.getCause()); 260 | } 261 | } 262 | 263 | @Override 264 | public void dataSent(Transport t) throws Throwable 265 | { 266 | } 267 | 268 | @Override 269 | public void error(Transport t, Throwable error) 270 | { 271 | clientListener.generalError(this, error); 272 | } 273 | 274 | @Override 275 | public void error(Transport t, Message message, Throwable error) 276 | { 277 | clientListener.requestFailed(this, (Request) message, error); 278 | } 279 | 280 | @Override 281 | public void remoteDisconnection(Transport t) throws Throwable 282 | { 283 | synchronized(outstanding) 284 | { 285 | for(Map.Entry request : outstanding.entrySet()) 286 | clientListener.requestFailed(this, request.getValue(), 287 | new SocketException("Socket has been closed")); 288 | } 289 | } 290 | 291 | @Override 292 | public int nextCSeq() 293 | { 294 | return cseq++; 295 | } 296 | 297 | @Override 298 | public void send(Message message) throws IOException, MissingHeaderException 299 | { 300 | send(message, uri); 301 | } 302 | 303 | private void send(Message message, URI endpoint) throws IOException, 304 | MissingHeaderException 305 | { 306 | if(!transport.isConnected()) 307 | transport.connect(endpoint); 308 | 309 | if(message instanceof Request) 310 | { 311 | Request request = (Request) message; 312 | synchronized(outstanding) 313 | { 314 | outstanding.put(message.getCSeq().getValue(), request); 315 | } 316 | try 317 | { 318 | transport.sendMessage(message); 319 | } catch(IOException e) 320 | { 321 | clientListener.requestFailed(this, request, e); 322 | } 323 | } else 324 | transport.sendMessage(message); 325 | } 326 | 327 | private Request getSetup(String uri, int localPort, Header... headers) 328 | throws URISyntaxException 329 | { 330 | return getMessageFactory().outgoingRequest(uri, Method.SETUP, nextCSeq(), 331 | headers); 332 | } 333 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/RTSPEntityMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | import br.com.voicetechnology.rtspclient.concepts.Content; 23 | import br.com.voicetechnology.rtspclient.concepts.EntityMessage; 24 | import br.com.voicetechnology.rtspclient.concepts.Message; 25 | import br.com.voicetechnology.rtspclient.headers.ContentEncodingHeader; 26 | import br.com.voicetechnology.rtspclient.headers.ContentLengthHeader; 27 | import br.com.voicetechnology.rtspclient.headers.ContentTypeHeader; 28 | 29 | public class RTSPEntityMessage implements EntityMessage 30 | { 31 | private Content content; 32 | 33 | private final Message message; 34 | 35 | public RTSPEntityMessage(Message message) 36 | { 37 | this.message = message; 38 | } 39 | 40 | public RTSPEntityMessage(Message message, Content body) 41 | { 42 | this(message); 43 | setContent(body); 44 | } 45 | 46 | @Override 47 | public Message getMessage() 48 | { 49 | return message; 50 | }; 51 | 52 | public byte[] getBytes() throws MissingHeaderException 53 | { 54 | message.getHeader(ContentTypeHeader.NAME); 55 | message.getHeader(ContentLengthHeader.NAME); 56 | return content.getBytes(); 57 | } 58 | 59 | @Override 60 | public Content getContent() 61 | { 62 | return content; 63 | } 64 | 65 | @Override 66 | public void setContent(Content content) 67 | { 68 | if(content == null) throw new NullPointerException(); 69 | this.content = content; 70 | message.addHeader(new ContentTypeHeader(content.getType())); 71 | if(content.getEncoding() != null) 72 | message.addHeader(new ContentEncodingHeader(content.getEncoding())); 73 | message.addHeader(new ContentLengthHeader(content.getBytes().length)); 74 | } 75 | 76 | @Override 77 | public boolean isEntity() 78 | { 79 | return content != null; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/RTSPMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | import br.com.voicetechnology.rtspclient.concepts.EntityMessage; 26 | import br.com.voicetechnology.rtspclient.concepts.Header; 27 | import br.com.voicetechnology.rtspclient.concepts.Message; 28 | import br.com.voicetechnology.rtspclient.headers.CSeqHeader; 29 | 30 | public abstract class RTSPMessage implements Message 31 | { 32 | private String line; 33 | 34 | private List
headers; 35 | 36 | private CSeqHeader cseq; 37 | 38 | private EntityMessage entity; 39 | 40 | public RTSPMessage() 41 | { 42 | headers = new ArrayList
(); 43 | } 44 | 45 | @Override 46 | public byte[] getBytes() throws MissingHeaderException 47 | { 48 | getHeader(CSeqHeader.NAME); 49 | addHeader(new Header("User-Agent", "RTSPClientLib/Java")); 50 | byte[] message = toString().getBytes(); 51 | if(getEntityMessage() != null) 52 | { 53 | byte[] body = entity.getBytes(); 54 | byte[] full = new byte[message.length + body.length]; 55 | System.arraycopy(message, 0, full, 0, message.length); 56 | System.arraycopy(body, 0, full, message.length, body.length); 57 | message = full; 58 | } 59 | return message; 60 | } 61 | 62 | @Override 63 | public Header getHeader(final String name) throws MissingHeaderException 64 | { 65 | int index = headers.indexOf(new Object() { 66 | @Override 67 | public boolean equals(Object obj) 68 | { 69 | return name.equalsIgnoreCase(((Header) obj).getName()); 70 | } 71 | }); 72 | if(index == -1) 73 | throw new MissingHeaderException(name); 74 | return headers.get(index); 75 | } 76 | 77 | @Override 78 | public Header[] getHeaders() 79 | { 80 | return headers.toArray(new Header[headers.size()]); 81 | } 82 | 83 | @Override 84 | public CSeqHeader getCSeq() 85 | { 86 | return cseq; 87 | } 88 | 89 | @Override 90 | public String getLine() 91 | { 92 | return line; 93 | } 94 | 95 | public void setLine(String line) 96 | { 97 | this.line = line; 98 | } 99 | 100 | @Override 101 | public void addHeader(Header header) 102 | { 103 | if(header == null) return; 104 | if(header instanceof CSeqHeader) 105 | cseq = (CSeqHeader) header; 106 | int index = headers.indexOf(header); 107 | if(index > -1) 108 | headers.remove(index); 109 | else 110 | index = headers.size(); 111 | headers.add(index, header); 112 | } 113 | 114 | @Override 115 | public EntityMessage getEntityMessage() 116 | { 117 | return entity; 118 | } 119 | 120 | @Override 121 | public Message setEntityMessage(EntityMessage entity) 122 | { 123 | this.entity = entity; 124 | return this; 125 | } 126 | 127 | @Override 128 | public String toString() 129 | { 130 | StringBuilder buffer = new StringBuilder(); 131 | buffer.append(getLine()).append("\r\n"); 132 | for(Header header : headers) 133 | buffer.append(header).append("\r\n"); 134 | buffer.append("\r\n"); 135 | return buffer.toString(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/RTSPMessageFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | import java.io.ByteArrayInputStream; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.lang.reflect.Constructor; 26 | import java.net.URISyntaxException; 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | import br.com.voicetechnology.rtspclient.concepts.Content; 31 | import br.com.voicetechnology.rtspclient.concepts.Header; 32 | import br.com.voicetechnology.rtspclient.concepts.Message; 33 | import br.com.voicetechnology.rtspclient.concepts.MessageBuffer; 34 | import br.com.voicetechnology.rtspclient.concepts.MessageFactory; 35 | import br.com.voicetechnology.rtspclient.concepts.Request; 36 | import br.com.voicetechnology.rtspclient.concepts.Response; 37 | import br.com.voicetechnology.rtspclient.concepts.Request.Method; 38 | import br.com.voicetechnology.rtspclient.headers.CSeqHeader; 39 | import br.com.voicetechnology.rtspclient.headers.ContentEncodingHeader; 40 | import br.com.voicetechnology.rtspclient.headers.ContentLengthHeader; 41 | import br.com.voicetechnology.rtspclient.headers.ContentTypeHeader; 42 | import br.com.voicetechnology.rtspclient.headers.SessionHeader; 43 | import br.com.voicetechnology.rtspclient.messages.RTSPDescribeRequest; 44 | import br.com.voicetechnology.rtspclient.messages.RTSPOptionsRequest; 45 | import br.com.voicetechnology.rtspclient.messages.RTSPPlayRequest; 46 | import br.com.voicetechnology.rtspclient.messages.RTSPSetupRequest; 47 | import br.com.voicetechnology.rtspclient.messages.RTSPTeardownRequest; 48 | 49 | public class RTSPMessageFactory implements MessageFactory 50 | { 51 | private static Map> headerMap; 52 | private static Map> requestMap; 53 | 54 | static 55 | { 56 | headerMap = new HashMap>(); 57 | requestMap = new HashMap>(); 58 | 59 | try 60 | { 61 | putHeader(CSeqHeader.class); 62 | putHeader(ContentEncodingHeader.class); 63 | putHeader(ContentLengthHeader.class); 64 | putHeader(ContentTypeHeader.class); 65 | putHeader(SessionHeader.class); 66 | 67 | requestMap.put(Method.OPTIONS, RTSPOptionsRequest.class); 68 | requestMap.put(Method.SETUP, RTSPSetupRequest.class); 69 | requestMap.put(Method.TEARDOWN, RTSPTeardownRequest.class); 70 | requestMap.put(Method.DESCRIBE, RTSPDescribeRequest.class); 71 | requestMap.put(Method.PLAY, RTSPPlayRequest.class); 72 | } catch(Exception e) 73 | { 74 | // TODO Auto-generated catch block 75 | e.printStackTrace(); 76 | } 77 | } 78 | 79 | private static void putHeader(Class cls) throws Exception 80 | { 81 | headerMap.put(cls.getDeclaredField("NAME").get(null).toString() 82 | .toLowerCase(), cls.getConstructor(String.class)); 83 | } 84 | 85 | @Override 86 | public void incomingMessage(MessageBuffer buffer) 87 | throws InvalidMessageException 88 | { 89 | ByteArrayInputStream in = new ByteArrayInputStream(buffer.getData(), buffer 90 | .getOffset(), buffer.getLength()); 91 | int initial = in.available(); 92 | Message message = null; 93 | 94 | try 95 | { 96 | // message line. 97 | String line = readLine(in); 98 | if(line.startsWith(Message.RTSP_TOKEN)) 99 | { 100 | message = new RTSPResponse(line); 101 | } else 102 | { 103 | Method method = Method.valueOf(line.substring(0, line.indexOf(' '))); 104 | Class cls = requestMap.get(method); 105 | if(cls != null) 106 | message = cls.getConstructor(String.class).newInstance(line); 107 | else 108 | message = new RTSPRequest(line); 109 | } 110 | 111 | while(true) 112 | { 113 | line = readLine(in); 114 | if(in == null) 115 | throw new IncompleteMessageException(); 116 | if(line.length() == 0) 117 | break; 118 | Constructor c = headerMap.get(line.substring(0, 119 | line.indexOf(':')).toLowerCase()); 120 | if(c != null) 121 | message.addHeader(c.newInstance(line)); 122 | else 123 | message.addHeader(new Header(line)); 124 | } 125 | buffer.setMessage(message); 126 | 127 | try 128 | { 129 | int length = ((ContentLengthHeader) message 130 | .getHeader(ContentLengthHeader.NAME)).getValue(); 131 | if(in.available() < length) 132 | throw new IncompleteMessageException(); 133 | Content content = new Content(); 134 | content.setDescription(message); 135 | byte[] data = new byte[length]; 136 | in.read(data); 137 | content.setBytes(data); 138 | System.out.println(data.length); 139 | message.setEntityMessage(new RTSPEntityMessage(message, content)); 140 | } catch(MissingHeaderException e) 141 | { 142 | } 143 | 144 | } catch(Exception e) 145 | { 146 | throw new InvalidMessageException(e); 147 | } finally 148 | { 149 | buffer.setused(initial - in.available()); 150 | try 151 | { 152 | in.close(); 153 | } catch(IOException e) 154 | { 155 | } 156 | } 157 | } 158 | 159 | @Override 160 | public Request outgoingRequest(String uri, Method method, int cseq, 161 | Header... extras) throws URISyntaxException 162 | { 163 | Class cls = requestMap.get(method); 164 | Request message; 165 | try 166 | { 167 | message = cls != null ? cls.newInstance() : new RTSPRequest(); 168 | } catch(Exception e) 169 | { 170 | throw new RuntimeException(e); 171 | } 172 | message.setLine(uri, method); 173 | fillMessage(message, cseq, extras); 174 | 175 | return message; 176 | } 177 | 178 | @Override 179 | public Request outgoingRequest(Content body, String uri, Method method, 180 | int cseq, Header... extras) throws URISyntaxException 181 | { 182 | Message message = outgoingRequest(uri, method, cseq, extras); 183 | return (Request) message.setEntityMessage(new RTSPEntityMessage(message, 184 | body)); 185 | } 186 | 187 | @Override 188 | public Response outgoingResponse(int code, String text, int cseq, 189 | Header... extras) 190 | { 191 | RTSPResponse message = new RTSPResponse(); 192 | message.setLine(code, text); 193 | fillMessage(message, cseq, extras); 194 | 195 | return message; 196 | } 197 | 198 | @Override 199 | public Response outgoingResponse(Content body, int code, String text, 200 | int cseq, Header... extras) 201 | { 202 | Message message = outgoingResponse(code, text, cseq, extras); 203 | return (Response) message.setEntityMessage(new RTSPEntityMessage(message, body)); 204 | } 205 | 206 | private void fillMessage(Message message, int cseq, Header[] extras) 207 | { 208 | message.addHeader(new CSeqHeader(cseq)); 209 | 210 | for(Header h : extras) 211 | message.addHeader(h); 212 | } 213 | 214 | private String readLine(InputStream in) throws IOException 215 | { 216 | int ch = 0; 217 | StringBuilder b = new StringBuilder(); 218 | for(ch = in.read(); ch != -1 && ch != 0x0d && ch != 0x0a; ch = in.read()) 219 | b.append((char) ch); 220 | if(ch == -1) 221 | return null; 222 | in.read(); 223 | return b.toString(); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/RTSPRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | import java.net.URI; 23 | import java.net.URISyntaxException; 24 | 25 | import br.com.voicetechnology.rtspclient.concepts.Client; 26 | import br.com.voicetechnology.rtspclient.concepts.Message; 27 | import br.com.voicetechnology.rtspclient.concepts.Request; 28 | import br.com.voicetechnology.rtspclient.concepts.Response; 29 | 30 | public class RTSPRequest extends RTSPMessage implements Request 31 | { 32 | private Method method; 33 | 34 | private String uri; 35 | 36 | public RTSPRequest() 37 | { 38 | } 39 | 40 | public RTSPRequest(String messageLine) throws URISyntaxException 41 | { 42 | String[] parts = messageLine.split(" "); 43 | setLine(parts[0], Method.valueOf(parts[1])); 44 | } 45 | 46 | @Override 47 | public void setLine(String uri, Method method) throws URISyntaxException 48 | { 49 | this.method = method; 50 | this.uri = new URI(uri).toString(); 51 | 52 | super.setLine(method.toString() + ' ' + uri + ' ' + RTSP_VERSION_TOKEN); 53 | } 54 | 55 | @Override 56 | public Method getMethod() 57 | { 58 | return method; 59 | } 60 | 61 | @Override 62 | public String getURI() 63 | { 64 | return uri; 65 | } 66 | 67 | @Override 68 | public void handleResponse(Client client, Response response) 69 | { 70 | if(testForClose(client, this) || testForClose(client, response)) 71 | client.getTransport().disconnect(); 72 | } 73 | 74 | protected void setURI(String uri) 75 | { 76 | this.uri = uri; 77 | } 78 | 79 | protected void setMethod(Method method) 80 | { 81 | this.method = method; 82 | } 83 | 84 | private boolean testForClose(Client client, Message message) 85 | { 86 | try 87 | { 88 | return message.getHeader("Connection").getRawValue().equalsIgnoreCase("close"); 89 | } catch(MissingHeaderException e) 90 | { 91 | } catch(Exception e) 92 | { 93 | client.getClientListener().generalError(client, e); 94 | } 95 | return false; 96 | } 97 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/RTSPResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient; 21 | 22 | import br.com.voicetechnology.rtspclient.concepts.Response; 23 | 24 | public class RTSPResponse extends RTSPMessage implements Response 25 | { 26 | private int status; 27 | 28 | private String text; 29 | 30 | public RTSPResponse() 31 | { 32 | } 33 | 34 | public RTSPResponse(String line) 35 | { 36 | setLine(line); 37 | line = line.substring(line.indexOf(' ') + 1); 38 | status = Integer.parseInt(line.substring(0, line.indexOf(' '))); 39 | text = line.substring(line.indexOf(' ') + 1); 40 | } 41 | 42 | @Override 43 | public int getStatusCode() 44 | { 45 | return status; 46 | } 47 | 48 | @Override 49 | public String getStatusText() 50 | { 51 | return text; 52 | } 53 | 54 | @Override 55 | public void setLine(int statusCode, String statusText) 56 | { 57 | status = statusCode; 58 | text = statusText; 59 | super.setLine(RTSP_VERSION_TOKEN + ' ' + status + ' ' + text); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import java.io.IOException; 23 | import java.net.URI; 24 | import java.net.URISyntaxException; 25 | 26 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 27 | import br.com.voicetechnology.rtspclient.headers.SessionHeader; 28 | 29 | /** 30 | * Models a simple RTSPClient.
31 | * it MUST keep track of CSeq to match requests and responses. 32 | * 33 | * @author paulo 34 | * 35 | */ 36 | public interface Client 37 | { 38 | 39 | void setTransport(Transport transport); 40 | 41 | Transport getTransport(); 42 | 43 | void setClientListener(ClientListener listener); 44 | 45 | ClientListener getClientListener(); 46 | 47 | void setSession(SessionHeader session); 48 | 49 | MessageFactory getMessageFactory(); 50 | 51 | URI getURI(); 52 | 53 | void describe(URI uri) throws IOException; 54 | 55 | /** 56 | * Sets up a session 57 | * 58 | * @param uri 59 | * base URI for the request. 60 | * @param localPort 61 | * Port for RTP stream. RTCP port is derived by adding 1 to this 62 | * port. 63 | */ 64 | void setup(URI uri, int localPort) throws IOException; 65 | 66 | /** 67 | * Sets up a session with a specific resource. If a session has been 68 | * previously established, a call to this method will set up a different 69 | * resource with the same session identifier as the previous one. 70 | * 71 | * @see #setup(URI, int) 72 | * @param resource 73 | * resource derived from SDP (via control: attribute). the final URI 74 | * will be uri + '/' + resource. 75 | */ 76 | void setup(URI uri, int localPort, String resource) throws IOException; 77 | 78 | void teardown(); 79 | 80 | void play() throws IOException; 81 | 82 | void record() throws IOException; 83 | 84 | void options(String uri, URI endpoint) throws URISyntaxException, IOException; 85 | 86 | /** 87 | * Sends a message and, if message is a {@link Request}, store it as an 88 | * outstanding request. 89 | * 90 | * @param message 91 | * @throws IOException 92 | * @throws MissingHeaderException 93 | * Malformed message, lacking mandatory header. 94 | */ 95 | void send(Message message) throws IOException, MissingHeaderException; 96 | 97 | /** 98 | * 99 | * @return value of CSeq for next packet. 100 | */ 101 | int nextCSeq(); 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/ClientListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | /** 23 | * Listener for {@link Client} events, such as a {@link Response} that arrives. 24 | * 25 | * @author paulo 26 | * 27 | */ 28 | public interface ClientListener 29 | { 30 | void generalError(Client client, Throwable error); 31 | 32 | /** 33 | * this method is called when a client obtains a session descriptor, such as 34 | * SDP from a DESCRIBE. 35 | * 36 | * @param client 37 | * @param descriptor 38 | */ 39 | void mediaDescriptor(Client client, String descriptor); 40 | 41 | void requestFailed(Client client, Request request, Throwable cause); 42 | 43 | void response(Client client, Request request, Response response); 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/Content.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 23 | import br.com.voicetechnology.rtspclient.headers.ContentEncodingHeader; 24 | import br.com.voicetechnology.rtspclient.headers.ContentTypeHeader; 25 | 26 | public class Content 27 | { 28 | private String type; 29 | 30 | private String encoding; 31 | 32 | private byte[] content; 33 | 34 | public void setDescription(Message message) throws MissingHeaderException 35 | { 36 | type = message.getHeader(ContentTypeHeader.NAME).getRawValue(); 37 | try 38 | { 39 | encoding = message.getHeader(ContentEncodingHeader.NAME).getRawValue(); 40 | } catch(MissingHeaderException e) 41 | { 42 | } 43 | } 44 | 45 | public String getType() 46 | { 47 | return type; 48 | } 49 | 50 | public void setType(String type) 51 | { 52 | this.type = type; 53 | } 54 | 55 | public String getEncoding() 56 | { 57 | return encoding; 58 | } 59 | 60 | public void setEncoding(String encoding) 61 | { 62 | this.encoding = encoding; 63 | } 64 | 65 | public byte[] getBytes() 66 | { 67 | return content; 68 | } 69 | 70 | public void setBytes(byte[] content) 71 | { 72 | this.content = content; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/EntityMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 23 | 24 | public interface EntityMessage 25 | { 26 | Content getContent(); 27 | 28 | void setContent(Content content); 29 | 30 | Message getMessage(); 31 | 32 | byte[] getBytes() throws MissingHeaderException; 33 | 34 | boolean isEntity(); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/Header.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import br.com.voicetechnology.rtspclient.HeaderMismatchException; 23 | 24 | public class Header 25 | { 26 | private String name; 27 | 28 | private String value; 29 | 30 | /** 31 | * Constructs a new header. 32 | * 33 | * @param header 34 | * if the character ':' (colon) is not found, it will be the name of 35 | * the header. Otherwise, this constructor parses the header line. 36 | */ 37 | public Header(String header) 38 | { 39 | int colon = header.indexOf(':'); 40 | if(colon == -1) 41 | name = header; 42 | else 43 | { 44 | name = header.substring(0, colon); 45 | value = header.substring(++colon).trim(); 46 | } 47 | } 48 | 49 | public Header(String name, String value) 50 | { 51 | this.name = name; 52 | this.value = value; 53 | } 54 | 55 | public String getName() 56 | { 57 | return name; 58 | } 59 | 60 | public String getRawValue() 61 | { 62 | return value; 63 | } 64 | 65 | public void setRawValue(String value) 66 | { 67 | this.value = value; 68 | } 69 | 70 | @Override 71 | public String toString() 72 | { 73 | return name + ": " + value; 74 | } 75 | 76 | @Override 77 | public boolean equals(Object obj) 78 | { 79 | if(super.equals(obj)) 80 | return true; 81 | if(obj instanceof String) 82 | return getName().equals(obj); 83 | if(obj instanceof Header) 84 | return getName().equals(((Header) obj).getName()); 85 | return false; 86 | } 87 | 88 | protected final void checkName(String expected) 89 | { 90 | if(!expected.equalsIgnoreCase(getName())) 91 | throw new HeaderMismatchException(expected, getName()); 92 | } 93 | 94 | protected final void setName(String name) 95 | { 96 | value = this.name; 97 | this.name = name; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/Message.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 23 | import br.com.voicetechnology.rtspclient.headers.CSeqHeader; 24 | 25 | /** 26 | * Models a RTSP Message 27 | * 28 | * @author paulo 29 | * 30 | */ 31 | public interface Message 32 | { 33 | static String RTSP_TOKEN = "RTSP/"; 34 | 35 | static String RTSP_VERSION = "1.0"; 36 | 37 | static String RTSP_VERSION_TOKEN = RTSP_TOKEN + RTSP_VERSION; 38 | 39 | /** 40 | * 41 | * @return the Message line (the first line of the message) 42 | */ 43 | String getLine(); 44 | 45 | /** 46 | * Returns a header, if exists 47 | * 48 | * @param name 49 | * Name of the header to be searched 50 | * @return value of that header 51 | * @throws MissingHeaderException 52 | */ 53 | Header getHeader(String name) throws MissingHeaderException; 54 | 55 | /** 56 | * Convenience method to get CSeq. 57 | * 58 | * @return 59 | */ 60 | CSeqHeader getCSeq(); 61 | 62 | /** 63 | * 64 | * @return all headers in the message, except CSeq 65 | */ 66 | Header[] getHeaders(); 67 | 68 | /** 69 | * Adds a new header or replaces if one already exists. If header to be added 70 | * is a CSeq, implementation MUST keep reference of this header. 71 | * 72 | * @param header 73 | */ 74 | void addHeader(Header header); 75 | 76 | /** 77 | * 78 | * @return message as a byte array, ready for transmission. 79 | */ 80 | byte[] getBytes() throws MissingHeaderException; 81 | 82 | /** 83 | * 84 | * @return Entity part of message, it exists. 85 | */ 86 | EntityMessage getEntityMessage(); 87 | 88 | /** 89 | * 90 | * @param entity 91 | * adds an entity part to the message. 92 | * @return this, for easier construction. 93 | */ 94 | Message setEntityMessage(EntityMessage entity); 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/MessageBuffer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | public class MessageBuffer 23 | { 24 | /** 25 | * buffer for received data 26 | */ 27 | private byte[] data; 28 | 29 | /** 30 | * offset for starting useful area 31 | */ 32 | private int offset; 33 | 34 | /** 35 | * length of useful portion. 36 | */ 37 | private int length; 38 | 39 | /** 40 | * Used (read) buffer. 41 | */ 42 | private int used; 43 | 44 | /** 45 | * {@link Message} created during last parsing. 46 | */ 47 | private Message message; 48 | 49 | /** 50 | * Adds more data to buffer and ensures the sequence [data, newData] is 51 | * contiguous. 52 | * 53 | * @param newData data to be added to the buffer. 54 | */ 55 | public void addData(byte[] newData, int newLength) 56 | { 57 | if(data == null) 58 | { 59 | data = newData; 60 | length = newLength; 61 | offset = 0; 62 | } else 63 | { 64 | // buffer seems to be small. 65 | if((data.length - offset - length) < newLength) 66 | { 67 | // try to sequeeze data at the beginning of the buffer only if current 68 | // buffer does not overlap 69 | if(offset >= length && (data.length - length) >= newLength) 70 | { 71 | System.arraycopy(data, offset, data, 0, length); 72 | offset = 0; 73 | } else 74 | { // worst-case scenario, a new buffer will have to be created 75 | byte[] temp = new byte[data.length + newLength]; 76 | System.arraycopy(data, offset, temp, 0, length); 77 | offset = 0; 78 | data = temp; 79 | } 80 | } 81 | // there's room for everything - just copy 82 | System.arraycopy(newData, 0, data, offset + length, newLength); 83 | length += newLength; 84 | } 85 | } 86 | 87 | /** 88 | * Discards used portions of the buffer. 89 | */ 90 | public void discardData() 91 | { 92 | offset += used; 93 | length -= used; 94 | } 95 | 96 | public byte[] getData() 97 | { 98 | return data; 99 | } 100 | 101 | public int getOffset() 102 | { 103 | return offset; 104 | } 105 | 106 | public int getLength() 107 | { 108 | return length; 109 | } 110 | 111 | public void setMessage(Message message) 112 | { 113 | this.message = message; 114 | } 115 | 116 | public Message getMessage() 117 | { 118 | return message; 119 | } 120 | 121 | public void setused(int used) 122 | { 123 | this.used = used; 124 | } 125 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/MessageFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import java.net.URISyntaxException; 23 | 24 | import br.com.voicetechnology.rtspclient.InvalidMessageException; 25 | 26 | /** 27 | * A RTSP message factory to build objects from incoming messages or to 28 | * initialize outgoing messages correctly. 29 | * 30 | * 31 | * @author paulo 32 | * 33 | */ 34 | public interface MessageFactory 35 | { 36 | 37 | /** 38 | * 39 | * @param message 40 | */ 41 | void incomingMessage(MessageBuffer message) throws InvalidMessageException; 42 | 43 | Request outgoingRequest(String uri, Request.Method method, int cseq, 44 | Header... extras) throws URISyntaxException; 45 | 46 | Request outgoingRequest(Content body, String uri, Request.Method method, 47 | int cseq, Header... extras) throws URISyntaxException; 48 | 49 | Response outgoingResponse(int code, String message, int cseq, Header... extras); 50 | 51 | Response outgoingResponse(Content body, int code, String text, int cseq, 52 | Header... extras); 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import java.net.URISyntaxException; 23 | 24 | public interface Request extends Message 25 | { 26 | enum Method 27 | { 28 | OPTIONS, DESCRIBE, SETUP, PLAY, RECORD, TEARDOWN 29 | }; 30 | 31 | void setLine(String uri, Method method) throws URISyntaxException; 32 | 33 | Method getMethod(); 34 | 35 | String getURI(); 36 | 37 | void handleResponse(Client client, Response response); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/Response.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | public interface Response extends Message 23 | { 24 | void setLine(int statusCode, String statusPhrase); 25 | 26 | int getStatusCode(); 27 | 28 | String getStatusText(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/Transport.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | import java.io.IOException; 23 | import java.net.URI; 24 | 25 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 26 | 27 | /** 28 | * This interface defines a transport protocol (TCP, UDP) or method (HTTP 29 | * tunneling). Transport also MUST enqueue a command if a connection is busy at 30 | * the moment it is issued. 31 | * 32 | * @author paulo 33 | */ 34 | public interface Transport 35 | { 36 | void connect(URI to) throws IOException; 37 | 38 | void disconnect(); 39 | 40 | void sendMessage(Message message) throws IOException, MissingHeaderException; 41 | 42 | void setTransportListener(TransportListener listener); 43 | 44 | void setUserData(Object data); 45 | 46 | boolean isConnected(); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/concepts/TransportListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.concepts; 21 | 22 | /** 23 | * Listener for transport events. Implementations of {@link Transport}, when 24 | * calling a listener method, must catch all errors and submit them to the 25 | * error() method. 26 | * 27 | * @author paulo 28 | * 29 | */ 30 | public interface TransportListener 31 | { 32 | void connected(Transport t) throws Throwable; 33 | 34 | void error(Transport t, Throwable error); 35 | 36 | void error(Transport t, Message message, Throwable error); 37 | 38 | void remoteDisconnection(Transport t) throws Throwable; 39 | 40 | void dataReceived(Transport t, byte[] data, int size) throws Throwable; 41 | 42 | void dataSent(Transport t) throws Throwable; 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/BaseIntegerHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | import br.com.voicetechnology.rtspclient.concepts.Header; 23 | 24 | public class BaseIntegerHeader extends Header 25 | { 26 | 27 | private int value; 28 | 29 | public BaseIntegerHeader(String name) 30 | { 31 | super(name); 32 | String text = getRawValue(); 33 | if(text != null) value = Integer.parseInt(text); 34 | } 35 | 36 | public BaseIntegerHeader(String name, int value) 37 | { 38 | super(name); 39 | setValue(value); 40 | } 41 | 42 | public BaseIntegerHeader(String name, String header) 43 | { 44 | super(header); 45 | checkName(name); 46 | value = Integer.parseInt(getRawValue()); 47 | } 48 | 49 | public final void setValue(int newValue) 50 | { 51 | value = newValue; 52 | setRawValue(String.valueOf(value)); 53 | } 54 | 55 | public final int getValue() 56 | { 57 | return value; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/BaseStringHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | import br.com.voicetechnology.rtspclient.HeaderMismatchException; 23 | import br.com.voicetechnology.rtspclient.concepts.Header; 24 | 25 | public class BaseStringHeader extends Header 26 | { 27 | public BaseStringHeader(String name) 28 | { 29 | super(name); 30 | } 31 | 32 | public BaseStringHeader(String name, String header) 33 | { 34 | super(header); 35 | try 36 | { 37 | checkName(name); 38 | } catch(HeaderMismatchException e) 39 | { 40 | setName(name); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/CSeqHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | 23 | public class CSeqHeader extends BaseIntegerHeader 24 | { 25 | public static final String NAME = "CSeq"; 26 | 27 | public CSeqHeader() 28 | { 29 | super(NAME); 30 | } 31 | 32 | public CSeqHeader(int cseq) 33 | { 34 | super(NAME, cseq); 35 | } 36 | 37 | public CSeqHeader(String line) 38 | { 39 | super(line); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/ContentEncodingHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | 23 | public class ContentEncodingHeader extends BaseStringHeader 24 | { 25 | public static final String NAME = "Content-Encoding"; 26 | 27 | public ContentEncodingHeader() 28 | { 29 | super(NAME); 30 | } 31 | 32 | public ContentEncodingHeader(String header) 33 | { 34 | super(NAME, header); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/ContentLengthHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | 23 | public class ContentLengthHeader extends BaseIntegerHeader 24 | { 25 | public static final String NAME = "Content-Length"; 26 | 27 | public ContentLengthHeader() 28 | { 29 | super(NAME); 30 | } 31 | 32 | public ContentLengthHeader(int value) 33 | { 34 | super(NAME, value); 35 | } 36 | 37 | public ContentLengthHeader(String header) 38 | { 39 | super(NAME, header); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/ContentTypeHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | 23 | public class ContentTypeHeader extends BaseStringHeader 24 | { 25 | public static final String NAME = "Content-Type"; 26 | 27 | public ContentTypeHeader() 28 | { 29 | super(NAME); 30 | } 31 | 32 | public ContentTypeHeader(String header) 33 | { 34 | super(NAME, header); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/SessionHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | public class SessionHeader extends BaseStringHeader 23 | { 24 | public static final String NAME = "Session"; 25 | 26 | public SessionHeader() 27 | { 28 | super(NAME); 29 | } 30 | 31 | public SessionHeader(String header) 32 | { 33 | super(NAME, header); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/headers/TransportHeader.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.headers; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | import br.com.voicetechnology.rtspclient.concepts.Header; 26 | 27 | /** 28 | * Models a "Transport" header from RFC 2326. According to specification, there may be parameters, which will be inserted as a list of strings, which follow below: 29 | * 30 | parameter = ( "unicast" | "multicast" ) 31 | | ";" "destination" [ "=" address ] 32 | | ";" "interleaved" "=" channel [ "-" channel ] 33 | | ";" "append" 34 | | ";" "ttl" "=" ttl 35 | | ";" "layers" "=" 1*DIGIT 36 | | ";" "port" "=" port [ "-" port ] 37 | | ";" "client_port" "=" port [ "-" port ] 38 | | ";" "server_port" "=" port [ "-" port ] 39 | | ";" "ssrc" "=" ssrc 40 | | ";" "mode" = <"> 1\#mode <"> 41 | ttl = 1*3(DIGIT) 42 | port = 1*5(DIGIT) 43 | ssrc = 8*8(HEX) 44 | channel = 1*3(DIGIT) 45 | address = host 46 | mode = <"> *Method <"> | Method 47 | 48 | * @author paulo 49 | * 50 | */ 51 | public class TransportHeader extends Header 52 | { 53 | public static final String NAME = "Transport"; 54 | 55 | public static enum LowerTransport { 56 | TCP, UDP, DEFAULT 57 | }; 58 | 59 | private LowerTransport transport; 60 | 61 | private List parameters; 62 | 63 | public TransportHeader(String header) 64 | { 65 | super(header); 66 | String value = getRawValue(); 67 | if(!value.startsWith("RTP/AVP")) 68 | throw new IllegalArgumentException("Missing RTP/AVP"); 69 | int index = 7; 70 | if(value.charAt(index) == '/') 71 | { 72 | switch(value.charAt(++index)) 73 | { 74 | case 'T': 75 | transport = LowerTransport.TCP; 76 | break; 77 | case 'U': 78 | transport = LowerTransport.UDP; 79 | break; 80 | default: 81 | throw new IllegalArgumentException("Invalid Transport: " 82 | + value.substring(7)); 83 | } 84 | index += 2; 85 | } else 86 | transport = LowerTransport.DEFAULT; 87 | ++index; 88 | if(value.charAt(index) != ';' || index != value.length()) 89 | throw new IllegalArgumentException("Parameter block expected"); 90 | addParameters(value.substring(++index).split(";")); 91 | } 92 | 93 | public TransportHeader(LowerTransport transport, String... parameters) 94 | { 95 | super(NAME); 96 | this.transport = transport; 97 | addParameters(parameters); 98 | } 99 | 100 | void addParameters(String[] parameterList) 101 | { 102 | if(parameters == null) 103 | parameters = Arrays.asList(parameterList); 104 | else 105 | parameters.addAll(Arrays.asList(parameterList)); 106 | } 107 | 108 | LowerTransport getTransport() 109 | { 110 | return transport; 111 | } 112 | 113 | String getParameter(String part) 114 | { 115 | for(String parameter : parameters) 116 | if(parameter.startsWith(part)) 117 | return parameter; 118 | throw new IllegalArgumentException("No such parameter named " + part); 119 | } 120 | 121 | @Override 122 | public String toString() 123 | { 124 | StringBuilder buffer = new StringBuilder(NAME).append(": ").append("RTP/AVP"); 125 | if(transport != LowerTransport.DEFAULT) 126 | buffer.append('/').append(transport); 127 | for(String parameter : parameters) 128 | buffer.append(';').append(parameter); 129 | return buffer.toString(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/messages/RTSPDescribeRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.messages; 21 | 22 | import java.net.URISyntaxException; 23 | 24 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 25 | import br.com.voicetechnology.rtspclient.RTSPRequest; 26 | import br.com.voicetechnology.rtspclient.concepts.Client; 27 | import br.com.voicetechnology.rtspclient.concepts.Response; 28 | 29 | public class RTSPDescribeRequest extends RTSPRequest 30 | { 31 | 32 | public RTSPDescribeRequest() 33 | { 34 | super(); 35 | } 36 | 37 | public RTSPDescribeRequest(String messageLine) throws URISyntaxException 38 | { 39 | super(messageLine); 40 | } 41 | 42 | @Override 43 | public byte[] getBytes() throws MissingHeaderException 44 | { 45 | getHeader("Accept"); 46 | return super.getBytes(); 47 | } 48 | 49 | @Override 50 | public void handleResponse(Client client, Response response) 51 | { 52 | super.handleResponse(client, response); 53 | try 54 | { 55 | client.getClientListener().mediaDescriptor(client, 56 | new String(response.getEntityMessage().getContent().getBytes())); 57 | } catch(Exception e) 58 | { 59 | client.getClientListener().generalError(client, e); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/messages/RTSPOptionsRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.messages; 21 | 22 | import java.net.URI; 23 | import java.net.URISyntaxException; 24 | 25 | import br.com.voicetechnology.rtspclient.RTSPRequest; 26 | 27 | public class RTSPOptionsRequest extends RTSPRequest 28 | { 29 | public RTSPOptionsRequest() 30 | { 31 | } 32 | 33 | public RTSPOptionsRequest(String line) throws URISyntaxException 34 | { 35 | super(line); 36 | } 37 | 38 | @Override 39 | public void setLine(String uri, Method method) throws URISyntaxException 40 | { 41 | setMethod(method); 42 | setURI("*".equals(uri) ? uri : new URI(uri).toString()); 43 | 44 | super.setLine(method.toString() + ' ' + uri + ' ' + RTSP_VERSION_TOKEN); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/messages/RTSPPlayRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.messages; 21 | 22 | import java.net.URISyntaxException; 23 | 24 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 25 | import br.com.voicetechnology.rtspclient.RTSPRequest; 26 | import br.com.voicetechnology.rtspclient.headers.SessionHeader; 27 | 28 | /** 29 | * 30 | * @author paulo 31 | * 32 | */ 33 | public class RTSPPlayRequest extends RTSPRequest 34 | { 35 | 36 | public RTSPPlayRequest() 37 | { 38 | } 39 | 40 | public RTSPPlayRequest(String messageLine) throws URISyntaxException 41 | { 42 | super(messageLine); 43 | } 44 | 45 | @Override 46 | public byte[] getBytes() throws MissingHeaderException 47 | { 48 | getHeader(SessionHeader.NAME); 49 | return super.getBytes(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/messages/RTSPSetupRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.messages; 21 | 22 | import java.net.URISyntaxException; 23 | 24 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 25 | import br.com.voicetechnology.rtspclient.RTSPRequest; 26 | import br.com.voicetechnology.rtspclient.concepts.Client; 27 | import br.com.voicetechnology.rtspclient.concepts.Response; 28 | import br.com.voicetechnology.rtspclient.headers.SessionHeader; 29 | 30 | public class RTSPSetupRequest extends RTSPRequest 31 | { 32 | public RTSPSetupRequest() 33 | { 34 | } 35 | 36 | public RTSPSetupRequest(String line) throws URISyntaxException 37 | { 38 | super(line); 39 | } 40 | 41 | @Override 42 | public byte[] getBytes() throws MissingHeaderException 43 | { 44 | getHeader("Transport"); 45 | return super.getBytes(); 46 | } 47 | 48 | @Override 49 | public void handleResponse(Client client, Response response) 50 | { 51 | super.handleResponse(client, response); 52 | try 53 | { 54 | if(response.getStatusCode() == 200) 55 | client.setSession((SessionHeader) response 56 | .getHeader(SessionHeader.NAME)); 57 | } catch(MissingHeaderException e) 58 | { 59 | client.getClientListener().generalError(client, e); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/messages/RTSPTeardownRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.messages; 21 | 22 | import java.net.URISyntaxException; 23 | 24 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 25 | import br.com.voicetechnology.rtspclient.RTSPRequest; 26 | import br.com.voicetechnology.rtspclient.concepts.Client; 27 | import br.com.voicetechnology.rtspclient.concepts.Response; 28 | import br.com.voicetechnology.rtspclient.headers.SessionHeader; 29 | 30 | public class RTSPTeardownRequest extends RTSPRequest 31 | { 32 | 33 | public RTSPTeardownRequest() 34 | { 35 | super(); 36 | } 37 | 38 | public RTSPTeardownRequest(String messageLine) throws URISyntaxException 39 | { 40 | super(messageLine); 41 | } 42 | 43 | @Override 44 | public byte[] getBytes() throws MissingHeaderException 45 | { 46 | getHeader(SessionHeader.NAME); 47 | return super.getBytes(); 48 | } 49 | 50 | @Override 51 | public void handleResponse(Client client, Response response) 52 | { 53 | super.handleResponse(client, response); 54 | if(response.getStatusCode() == 200) client.setSession(null); 55 | client.getTransport().disconnect(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/test/OPTIONSTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.test; 21 | 22 | import java.net.URI; 23 | 24 | import br.com.voicetechnology.rtspclient.RTSPClient; 25 | import br.com.voicetechnology.rtspclient.concepts.Client; 26 | import br.com.voicetechnology.rtspclient.concepts.ClientListener; 27 | import br.com.voicetechnology.rtspclient.concepts.Request; 28 | import br.com.voicetechnology.rtspclient.concepts.Response; 29 | import br.com.voicetechnology.rtspclient.transport.PlainTCP; 30 | 31 | public class OPTIONSTest implements ClientListener 32 | { 33 | public static void main(String[] args) throws Throwable 34 | { 35 | new OPTIONSTest(); 36 | } 37 | 38 | private OPTIONSTest() throws Exception 39 | { 40 | RTSPClient client = new RTSPClient(); 41 | 42 | client.setTransport(new PlainTCP()); 43 | client.setClientListener(this); 44 | //client.options("*", new URI("rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov")); 45 | client.options("*", new URI("rtsp://admin:gxtw2217@172.19.170.66/mpeg4/ch33/main/av_stream")); 46 | } 47 | 48 | @Override 49 | public void requestFailed(Client client, Request request, Throwable cause) 50 | { 51 | System.out.println("Request failed \n" + request); 52 | } 53 | 54 | @Override 55 | public void response(Client client, Request request, Response response) 56 | { 57 | System.out.println("Got response: \n" + response); 58 | System.out.println("for the request: \n" + request); 59 | } 60 | 61 | @Override 62 | public void generalError(Client client, Throwable error) 63 | { 64 | error.printStackTrace(); 65 | } 66 | 67 | @Override 68 | public void mediaDescriptor(Client client, String descriptor) 69 | { 70 | // TODO Auto-generated method stub 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/test/PLAYTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.test; 21 | 22 | import java.io.IOException; 23 | 24 | import br.com.voicetechnology.rtspclient.concepts.Client; 25 | import br.com.voicetechnology.rtspclient.concepts.Request; 26 | import br.com.voicetechnology.rtspclient.concepts.Response; 27 | import br.com.voicetechnology.rtspclient.concepts.Request.Method; 28 | 29 | /** 30 | * Testing the PLAY message. RTP Stream can be checked with Wireshark or a play 31 | * with RTP only capability. 32 | * 33 | * @author paulo 34 | * 35 | */ 36 | public class PLAYTest extends SETUPandTEARDOWNTest { 37 | 38 | public static void main(String[] args) throws Throwable { 39 | new PLAYTest(); 40 | } 41 | 42 | protected PLAYTest() throws Exception { 43 | super(); 44 | } 45 | 46 | @Override 47 | public void response(Client client, Request request, Response response) { 48 | try { 49 | super.response(client, request, response); 50 | 51 | if (request.getMethod() == Method.PLAY 52 | && response.getStatusCode() == 200) { 53 | Thread.sleep(60000); 54 | client.teardown(); 55 | } 56 | } catch (Throwable t) { 57 | generalError(client, t); 58 | } 59 | } 60 | 61 | @Override 62 | protected void sessionSet(Client client) throws IOException { 63 | client.play(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/test/ReadH264.java: -------------------------------------------------------------------------------- 1 | package br.com.voicetechnology.rtspclient.test; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | 7 | 8 | public class ReadH264 { 9 | 10 | /** 11 | * @param args 12 | * @throws IOException 13 | */ 14 | public static void main(String[] args) throws IOException { 15 | // TODO Auto-generated method stub 16 | File file = new File("F:/aa.h264"); 17 | FileInputStream input = new FileInputStream(file); 18 | byte[] buffer = new byte[1024]; 19 | int i = 0; 20 | System.out.println("start"); 21 | int count = 0; 22 | while((i = input.read(buffer, 0, buffer.length)) >= 0){ 23 | StringBuilder builder = new StringBuilder(); 24 | for (int j = 0; j < i; j++) { 25 | String string = String.format("%08d", Integer.valueOf(Integer.toBinaryString(buffer[j] & 0xff))); 26 | builder.append(string); 27 | } 28 | int length = Math.min(300, builder.length()); 29 | System.out.println(builder.toString().substring(0, length)); 30 | count++; 31 | if(count > 100){ 32 | break; 33 | } 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/test/SETUPandTEARDOWNTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.test; 21 | 22 | import java.io.IOException; 23 | import java.net.URI; 24 | import java.util.Collections; 25 | import java.util.LinkedList; 26 | import java.util.List; 27 | 28 | import br.com.voicetechnology.rtspclient.RTSPClient; 29 | import br.com.voicetechnology.rtspclient.concepts.Client; 30 | import br.com.voicetechnology.rtspclient.concepts.ClientListener; 31 | import br.com.voicetechnology.rtspclient.concepts.Request; 32 | import br.com.voicetechnology.rtspclient.concepts.Response; 33 | import br.com.voicetechnology.rtspclient.transport.PlainTCP; 34 | 35 | public class SETUPandTEARDOWNTest implements ClientListener 36 | { 37 | //private final static String TARGET_URI = "rtsp://192.168.0.102/sample_50kbit.3gp"; 38 | //private final static String TARGET_URI = "rtsp://admin:gxtw2217@172.19.170.66/mpeg4/ch33/main/av_stream"; 39 | //private final static String TARGET_URI = "rtsp://admin:lyjjits1@172.17.5.26/h264/ch1/main/av_stream"; 40 | private final static String TARGET_URI = "rtsp://172.18.1.172/media/video"; 41 | public static void main(String[] args) throws Throwable 42 | { 43 | new SETUPandTEARDOWNTest(); 44 | } 45 | 46 | private final List resourceList; 47 | 48 | private String controlURI; 49 | 50 | private int port; 51 | 52 | protected SETUPandTEARDOWNTest() throws Exception 53 | { 54 | RTSPClient client = new RTSPClient(); 55 | 56 | client.setTransport(new PlainTCP()); 57 | client.setClientListener(this); 58 | client.describe(new URI(TARGET_URI)); 59 | resourceList = Collections.synchronizedList(new LinkedList()); 60 | port = 2000; 61 | } 62 | 63 | @Override 64 | public void requestFailed(Client client, Request request, Throwable cause) 65 | { 66 | System.out.println("Request failed \n" + request); 67 | cause.printStackTrace(); 68 | } 69 | 70 | @Override 71 | public void response(Client client, Request request, Response response) 72 | { 73 | try 74 | { 75 | System.out.println("Got response: \n" + response); 76 | System.out.println("for the request: \n" + request); 77 | if(response.getStatusCode() == 200) 78 | { 79 | switch(request.getMethod()) 80 | { 81 | case DESCRIBE: 82 | System.out.println(resourceList); 83 | if(resourceList.get(0).equals("*")) 84 | { 85 | controlURI = request.getURI(); 86 | resourceList.remove(0); 87 | }else{ 88 | controlURI = resourceList.remove(0); 89 | for(int i = 0; i < resourceList.size(); i++){ 90 | resourceList.set(i, resourceList.get(i).substring(controlURI.length())); 91 | } 92 | } 93 | if(resourceList.size() > 0) 94 | client.setup(new URI(controlURI), nextPort(), resourceList 95 | .remove(0)); 96 | else 97 | client.setup(new URI(controlURI), nextPort()); 98 | break; 99 | 100 | case SETUP: 101 | //sets up next session or ends everything. 102 | if(resourceList.size() > 0) 103 | client.setup(new URI(controlURI), nextPort(), resourceList 104 | .remove(0)); 105 | else{ 106 | sessionSet(client); 107 | } 108 | 109 | break; 110 | } 111 | 112 | } else 113 | client.teardown(); 114 | } catch(Throwable t) 115 | { 116 | generalError(client, t); 117 | } 118 | } 119 | 120 | @Override 121 | public void generalError(Client client, Throwable error) 122 | { 123 | error.printStackTrace(); 124 | try { 125 | Thread.sleep(1000); 126 | } catch (InterruptedException e) { 127 | // TODO Auto-generated catch block 128 | e.printStackTrace(); 129 | } 130 | } 131 | 132 | @Override 133 | public void mediaDescriptor(Client client, String descriptor) 134 | { 135 | // searches for control: session and media arguments. 136 | final String target = "control:"; 137 | System.out.println("Session Descriptor\n" + descriptor); 138 | int position = -1; 139 | while((position = descriptor.indexOf(target)) > -1) 140 | { 141 | descriptor = descriptor.substring(position + target.length()); 142 | resourceList.add(descriptor.substring(0, descriptor.indexOf('\r'))); 143 | } 144 | } 145 | 146 | protected void sessionSet(Client client) throws IOException 147 | { 148 | client.teardown(); 149 | } 150 | 151 | private int nextPort() 152 | { 153 | return (port += 2) - 2; 154 | } 155 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/test/Server.java: -------------------------------------------------------------------------------- 1 | package br.com.voicetechnology.rtspclient.test; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.FileNotFoundException; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.net.DatagramPacket; 10 | import java.net.DatagramSocket; 11 | 12 | 13 | import br.com.voicetechnology.rtspclient.util.RTPPacket; 14 | 15 | 16 | public class Server { 17 | 18 | private static final int PORT = 2000; 19 | private DatagramSocket dataSocket; 20 | private DatagramPacket dataPacket; 21 | private byte buffer[]; 22 | private String receiveStr; 23 | private static byte[] startCode = {(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01}; 24 | 25 | public Server() { 26 | Init(); 27 | } 28 | 29 | public void Init() { 30 | try { 31 | dataSocket = new DatagramSocket(PORT); 32 | buffer = new byte[2048]; 33 | dataPacket = new DatagramPacket(buffer, buffer.length); 34 | receiveStr = ""; 35 | int i = 0; 36 | H264Handler handler = new H264Handler(); 37 | int count = 0; 38 | System.out.println("start"); 39 | while (i == 0)// 无数据,则循环 40 | { 41 | dataSocket.receive(dataPacket); 42 | i = dataPacket.getLength(); 43 | // 接收数据 44 | if (i > 0) { 45 | StringBuilder builder = new StringBuilder(); 46 | for (int j = 12; j < Math.min(50, buffer.length); j++) { 47 | String string = String.format("%08d", Integer.valueOf(Integer.toBinaryString(buffer[j] & 0xff))); 48 | builder.append(string); 49 | } 50 | RTPPacket rtpPacket = new RTPPacket(buffer, 0, i); 51 | count++; 52 | if(count < 300){ 53 | System.out.println(builder.toString() + " " + rtpPacket.getTimestamp().longValue()); 54 | } 55 | handler.handle(rtpPacket.getPayload(), 0, rtpPacket.getPayload().length); 56 | i = 0;// 循环接收 57 | } else { 58 | //System.out.println("a paket end " + i); 59 | } 60 | } 61 | } catch (Exception e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | 66 | public static void main(String args[]) { 67 | new Server(); 68 | } 69 | 70 | static class H264Handler extends Thread { 71 | private File file; 72 | private FileOutputStream output; 73 | private ByteArrayOutputStream buffer; 74 | private boolean start = false; 75 | public H264Handler(){ 76 | file = new File("F:/aa.h264"); 77 | try { 78 | output = new FileOutputStream(file); 79 | } catch (FileNotFoundException e) { 80 | // TODO Auto-generated catch block 81 | e.printStackTrace(); 82 | } 83 | buffer = new ByteArrayOutputStream(); 84 | } 85 | 86 | public void handle(byte[] bs, int off, int len) throws Exception{ 87 | if(getType(bs, off, len) == 7){ 88 | start = true; 89 | } 90 | if(!start){ 91 | return; 92 | } 93 | if(isSingle(bs, off, len)){ 94 | output.write(startCode); 95 | output.write(bs, off, len); 96 | output.flush(); 97 | }else if(isPice(bs, off, len)){ 98 | if(isBegan(bs, off, len)){ 99 | //System.out.println("get began " + buffer.size()); 100 | if(buffer.size() != 0){ 101 | save(); 102 | //buffer.reset(); 103 | } 104 | bs[off + 1] = (byte)((bs[off] & 0xE0) ^ (bs[off + 1] & 0x1F)); 105 | buffer.write(bs, off + 1, len - 1); 106 | }else if(isMiddle(bs, off, len)){ 107 | //System.out.println("get middle " + buffer.toByteArray().length); 108 | if(buffer.size() != 0){ 109 | buffer.write(bs, off + 2, len - 2); 110 | }else{ 111 | bs[off + 1] = (byte)((bs[off] & 0xE0) ^ (bs[off + 1] & 0x1F)); 112 | buffer.write(bs, off + 1, len - 1); 113 | } 114 | }else if(isEnd(bs, off, len)){ 115 | //System.out.println("get end " + buffer.size()); 116 | if(buffer.size() != 0){ 117 | buffer.write(bs, off + 2, len - 2); 118 | }else{ 119 | bs[off + 1] = (byte)((bs[off] & 0xE0) ^ (bs[off + 1] & 0x1F)); 120 | buffer.write(bs, off + 1, len - 1); 121 | } 122 | save(); 123 | } 124 | } 125 | } 126 | 127 | public void save() throws IOException{ 128 | output.write(startCode); 129 | output.write(buffer.toByteArray()); 130 | output.flush(); 131 | buffer.reset(); 132 | } 133 | 134 | private int getType(byte[] bs, int off, int len) throws Exception{ 135 | if(bs == null || bs.length - off < len || len < 1){ 136 | throw new Exception(); 137 | } 138 | int type = bs[off] & 0x1F; 139 | return type; 140 | } 141 | 142 | private boolean isSingle(byte[] bs, int off, int len) throws Exception{ 143 | if(bs == null || bs.length - off < len || len < 1){ 144 | throw new Exception(); 145 | } 146 | int type = bs[off] & 0x1F; 147 | if(type < 24 && type > 0){ 148 | return true; 149 | }else{ 150 | return false; 151 | } 152 | } 153 | 154 | private boolean isPice(byte[] bs, int off, int len) throws Exception{ 155 | if(bs == null || bs.length - off < len || len < 1){ 156 | throw new Exception(); 157 | } 158 | int type = bs[off] & 0x1F; 159 | if(type == 28 || type == 29){ 160 | return true; 161 | }else{ 162 | return false; 163 | } 164 | } 165 | 166 | private boolean isBegan(byte[] bs, int off, int len) throws Exception{ 167 | if(bs == null || bs.length - off < len || len < 2){ 168 | throw new Exception(); 169 | } 170 | int type = bs[off + 1] & 0xE0; 171 | if(type == 128){ 172 | return true; 173 | }else{ 174 | return false; 175 | } 176 | } 177 | 178 | private boolean isMiddle(byte[] bs, int off, int len) throws Exception{ 179 | if(bs == null || bs.length - off < len || len < 2){ 180 | throw new Exception(); 181 | } 182 | int type = bs[off + 1] & 0xE0; 183 | if(type == 0){ 184 | return true; 185 | }else{ 186 | return false; 187 | } 188 | } 189 | 190 | private boolean isEnd(byte[] bs, int off, int len) throws Exception{ 191 | if(bs == null || bs.length - off < len || len < 2){ 192 | throw new Exception(); 193 | } 194 | int type = bs[off + 1] & 0xE0; 195 | if(type == 64){ 196 | return true; 197 | }else{ 198 | return false; 199 | } 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/transport/PlainTCP.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.transport; 21 | 22 | import java.io.IOException; 23 | import java.net.Socket; 24 | import java.net.URI; 25 | 26 | import br.com.voicetechnology.rtspclient.MissingHeaderException; 27 | import br.com.voicetechnology.rtspclient.concepts.Message; 28 | import br.com.voicetechnology.rtspclient.concepts.Transport; 29 | import br.com.voicetechnology.rtspclient.concepts.TransportListener; 30 | 31 | class TransportThread extends Thread 32 | { 33 | private final PlainTCP transport; 34 | 35 | private volatile SafeTransportListener listener; 36 | 37 | public TransportThread(PlainTCP transport, TransportListener listener) 38 | { 39 | this.transport = transport; 40 | this.listener = new SafeTransportListener(listener); 41 | } 42 | 43 | public SafeTransportListener getListener() 44 | { 45 | return listener; 46 | } 47 | 48 | public void setListener(TransportListener listener) 49 | { 50 | listener = new SafeTransportListener(listener); 51 | } 52 | 53 | @Override 54 | public void run() 55 | { 56 | listener.connected(transport); 57 | byte[] buffer = new byte[2048]; 58 | int read = -1; 59 | while(transport.isConnected()) 60 | { 61 | try 62 | { 63 | read = transport.receive(buffer); 64 | if(read == -1) 65 | { 66 | transport.setConnected(false); 67 | listener.remoteDisconnection(transport); 68 | } else 69 | listener.dataReceived(transport, buffer, read); 70 | } catch(IOException e) 71 | { 72 | listener.error(transport, e); 73 | } 74 | } 75 | } 76 | } 77 | 78 | public class PlainTCP implements Transport 79 | { 80 | private Socket socket; 81 | 82 | private TransportThread thread; 83 | 84 | private TransportListener transportListener; 85 | 86 | private volatile boolean connected; 87 | 88 | public PlainTCP() 89 | { 90 | } 91 | 92 | @Override 93 | public void connect(URI to) throws IOException 94 | { 95 | if(connected) 96 | throw new IllegalStateException("Socket is still open. Close it first"); 97 | int port = to.getPort(); 98 | if(port == -1) port = 554; 99 | System.out.println(to.getHost() + " " + port); 100 | socket = new Socket(to.getHost(), port); 101 | setConnected(true); 102 | thread = new TransportThread(this, transportListener); 103 | thread.start(); 104 | System.out.println("****************************************************8"); 105 | } 106 | 107 | @Override 108 | public void disconnect() 109 | { 110 | setConnected(false); 111 | try 112 | { 113 | socket.close(); 114 | } catch(IOException e) 115 | { 116 | } 117 | } 118 | 119 | @Override 120 | public boolean isConnected() 121 | { 122 | return connected; 123 | } 124 | 125 | @Override 126 | public synchronized void sendMessage(Message message) throws IOException, 127 | MissingHeaderException 128 | { 129 | socket.getOutputStream().write(message.getBytes()); 130 | thread.getListener().dataSent(this); 131 | } 132 | 133 | @Override 134 | public void setTransportListener(TransportListener listener) 135 | { 136 | transportListener = listener; 137 | if(thread != null) 138 | thread.setListener(listener); 139 | } 140 | 141 | @Override 142 | public void setUserData(Object data) 143 | { 144 | } 145 | 146 | int receive(byte[] data) throws IOException 147 | { 148 | return socket.getInputStream().read(data); 149 | } 150 | 151 | void setConnected(boolean connected) 152 | { 153 | this.connected = connected; 154 | } 155 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/transport/SafeTransportListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Voice Technology Ind. e Com. Ltda. 3 | 4 | This file is part of RTSPClientLib. 5 | 6 | RTSPClientLib is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RTSPClientLib is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public License 17 | along with RTSPClientLib. If not, see . 18 | 19 | */ 20 | package br.com.voicetechnology.rtspclient.transport; 21 | 22 | import br.com.voicetechnology.rtspclient.concepts.Message; 23 | import br.com.voicetechnology.rtspclient.concepts.Transport; 24 | import br.com.voicetechnology.rtspclient.concepts.TransportListener; 25 | 26 | /** 27 | * Auxiliary class to make listener calls. 28 | * 29 | * @author paulo 30 | * 31 | */ 32 | class SafeTransportListener implements TransportListener 33 | { 34 | private final TransportListener behaviour; 35 | 36 | public SafeTransportListener(TransportListener theBehaviour) 37 | { 38 | behaviour = theBehaviour; 39 | } 40 | 41 | @Override 42 | public void connected(Transport t) 43 | { 44 | if(behaviour != null) 45 | try 46 | { 47 | behaviour.connected(t); 48 | } catch(Throwable error) 49 | { 50 | behaviour.error(t, error); 51 | } 52 | } 53 | 54 | @Override 55 | public void dataReceived(Transport t, byte[] data, int size) 56 | { 57 | if(behaviour != null) 58 | try 59 | { 60 | behaviour.dataReceived(t, data, size); 61 | } catch(Throwable error) 62 | { 63 | behaviour.error(t, error); 64 | } 65 | } 66 | 67 | @Override 68 | public void dataSent(Transport t) 69 | { 70 | // TODO Auto-generated method stub 71 | if(behaviour != null) 72 | try 73 | { 74 | behaviour.dataSent(t); 75 | } catch(Throwable error) 76 | { 77 | behaviour.error(t, error); 78 | } 79 | 80 | } 81 | 82 | @Override 83 | public void error(Transport t, Throwable error) 84 | { 85 | if(behaviour != null) 86 | behaviour.error(t, error); 87 | } 88 | 89 | @Override 90 | public void error(Transport t, Message message, Throwable error) 91 | { 92 | if(behaviour != null) 93 | behaviour.error(t, message, error); 94 | } 95 | 96 | @Override 97 | public void remoteDisconnection(Transport t) 98 | { 99 | if(behaviour != null) 100 | try 101 | { 102 | behaviour.remoteDisconnection(t); 103 | } catch(Throwable error) 104 | { 105 | behaviour.error(t, error); 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/util/RTPPacket.java: -------------------------------------------------------------------------------- 1 | package br.com.voicetechnology.rtspclient.util; 2 | 3 | /* 4 | * RED5 Open Source Flash Server - http://www.osflash.org/red5 5 | * 6 | * Copyright (c) 2006-2008 by respective authors (see below). All rights reserved. 7 | * 8 | * This library is free software; you can redistribute it and/or modify it under the 9 | * terms of the GNU Lesser General Public License as published by the Free Software 10 | * Foundation; either version 2.1 of the License, or (at your option) any later 11 | * version. 12 | * 13 | * This library is distributed in the hope that it will be useful, but WITHOUT ANY 14 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 15 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License along 18 | * with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | 22 | /*************************************************************************** 23 | * * 24 | * This program is free software; you can redistribute it and/or modify * 25 | * it under the terms of the GNU General Public License as published by * 26 | * the Free Software Foundation; either version 2 of the License, or * 27 | * (at your option) any later version. * 28 | * * 29 | * Copyright (C) 2005 - Matteo Merli - matteo.merli@gmail.com * 30 | * * 31 | ***************************************************************************/ 32 | 33 | 34 | /** 35 | * This class wraps a RTP packet providing method to convert from and to a 36 | * {@link IoBuffer}. 37 | *

38 | * A RTP packet is composed of an header and the subsequent payload. 39 | *

40 | * The RTP header has the following format: 41 | * 42 | *

 43 |  *        0                   1                   2                   3
 44 |  *        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 45 |  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 46 |  *        |V=2|P|X|  CC   |M|     PT      |       sequence number         |
 47 |  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 48 |  *        |                           timestamp                           |
 49 |  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 50 |  *        |           synchronization source (SSRC) identifier            |
 51 |  *        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 52 |  *        |            contributing source (CSRC) identifiers             |
 53 |  *        |                             ....                              |
 54 |  *        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 55 |  * 
56 | * 57 | * The first twelve octets are present in every RTP packet, while the list of 58 | * CSRC identifiers is present only when inserted by a mixer. 59 | * 60 | * @author Matteo Merli 61 | */ 62 | public class RTPPacket { 63 | 64 | /** 65 | * This field identifies the version of RTP. The version defined by this 66 | * specification is two (2). (The value 1 is used by the first draft version 67 | * of RTP and the value 0 is used by the protocol initially implemented in 68 | * the "vat" audio tool.) 69 | */ 70 | private byte version; 71 | 72 | /** 73 | * Padding flag. If the padding bit is set, the packet contains one or more 74 | * additional padding octets at the end which are not part of the payload. 75 | * The last octet of the padding contains a count of how many padding octets 76 | * should be ignored, including itself. Padding may be needed by some 77 | * encryption algorithms with fixed block sizes or for carrying several RTP 78 | * packets in a lower-layer protocol data unit. 79 | */ 80 | private boolean padding; 81 | 82 | /** 83 | * Extension Flag. If the extension bit is set, the fixed header MUST be 84 | * followed by exactly one header extension, with a format defined in 85 | * Section 5.3.1 of the RFC. 86 | */ 87 | private boolean extension; 88 | 89 | /** 90 | * The CSRC count contains the number of CSRC identifiers that follow the 91 | * fixed header. 92 | */ 93 | private byte csrcCount; 94 | 95 | /** 96 | * The interpretation of the marker is defined by a profile. It is intended 97 | * to allow significant events such as frame boundaries to be marked in the 98 | * packet stream. A profile MAY define additional marker bits or specify 99 | * that there is no marker bit by changing the number of bits in the payload 100 | * type field (see Section 5.3). 101 | */ 102 | private boolean marker; 103 | 104 | /** 105 | * This field identifies the format of the RTP payload and determines its 106 | * interpretation by the application. A profile MAY specify a default static 107 | * mapping of payload type codes to payload formats. Additional payload type 108 | * codes MAY be defined dynamically through non-RTP means (see Section 3). 109 | *

110 | * A set of default mappings for audio and video is specified in the 111 | * companion RFC 3551 [1]. An RTP source MAY change the payload type during 112 | * a session, but this field SHOULD NOT be used for multiplexing separate 113 | * media streams (see Section 5.2). 114 | */ 115 | private UnsignedByte payloadType; 116 | 117 | /** 118 | * The sequence number increments by one for each RTP data packet sent, and 119 | * may be used by the receiver to detect packet loss and to restore packet 120 | * sequence. The initial value of the sequence number SHOULD be random 121 | * (unpredictable) to make known-plaintext attacks on encryption more 122 | * difficult, even if the source itself does not encrypt according to the 123 | * method in Section 9.1, because the packets may flow through a translator 124 | * that does. 125 | */ 126 | private UnsignedShort sequence; 127 | 128 | /** 129 | * The timestamp reflects the sampling instant of the first octet in the RTP 130 | * data packet. The sampling instant MUST be derived from a clock that 131 | * increments monotonically and linearly in time to allow synchronization 132 | * and jitter calculations (see Section 6.4.1). 133 | */ 134 | private UnsignedInt timestamp; 135 | 136 | /** 137 | * The SSRC field identifies the synchronization source. This identifier 138 | * SHOULD be chosen randomly, with the intent that no two synchronization 139 | * sources within the same RTP session will have the same SSRC identifier. 140 | */ 141 | private UnsignedInt ssrc; 142 | 143 | /** 144 | * The CSRC list identifies the contributing sources for the payload 145 | * contained in this packet. The number of identifiers is given by the CC 146 | * field. If there are more than 15 contributing sources, only 15 can be 147 | * identified. 148 | */ 149 | private UnsignedInt[] csrc = {}; 150 | 151 | private short profileExtension; 152 | 153 | private byte[] headerExtension = {}; 154 | 155 | /** 156 | * Content of the packet. 157 | */ 158 | private byte[] payload = {}; 159 | 160 | /** 161 | * Construct a new RTPPacket reading the fields from a IoBuffer 162 | * 163 | * @param buffer 164 | * the buffer containing the packet 165 | */ 166 | public RTPPacket(byte[] buffer, int off, int len) { 167 | // Read the packet header 168 | byte c = buffer[off++]; 169 | // |V=2|P=1|X=1| CC=4 | 170 | this.version = (byte) ((c & 0xC0) >> 6); 171 | this.padding = ((c & 0x20) >> 5) == 1; 172 | this.extension = ((c & 0x10) >> 4) == 1; 173 | this.csrcCount = (byte) (c & 0x0F); 174 | 175 | c = buffer[off++]; 176 | // |M=1| PT=7 | 177 | this.marker = ((c & 0x80) >> 7) == 1; 178 | this.payloadType = new UnsignedByte(c & 0x7F); 179 | 180 | this.sequence = UnsignedShort.fromBytes(buffer, off); 181 | off+=2; 182 | this.timestamp = UnsignedInt.fromBytes(buffer, off); 183 | off+=4; 184 | this.ssrc = UnsignedInt.fromBytes(buffer, off); 185 | off+=4; 186 | 187 | // CSRC list 188 | csrc = new UnsignedInt[csrcCount]; 189 | for (int i = 0; i < csrcCount; i++) { 190 | csrc[i] = UnsignedInt.fromBytes(buffer, off); 191 | off+=4; 192 | } 193 | 194 | // Read the extension header if present 195 | if (extension) { 196 | this.profileExtension = UnsignedShort.fromBytes(buffer, off).shortValue(); 197 | off+=2; 198 | int length = UnsignedShort.fromBytes(buffer, off).intValue(); 199 | off+=2; 200 | this.headerExtension = new byte[length]; 201 | System.arraycopy(buffer, off, headerExtension, 0, length); 202 | off+=length; 203 | } 204 | 205 | // Read the payload 206 | int payloadSize = len - off; 207 | if(padding){ 208 | payloadSize -= buffer[len - 1]; 209 | } 210 | this.payload = new byte[payloadSize]; 211 | System.arraycopy(buffer, off, payload, 0, payloadSize); 212 | if (version != 2) { 213 | //log.debug("Packet Version is not 2."); 214 | } 215 | } 216 | 217 | protected RTPPacket() { 218 | // Creates an empty packet 219 | } 220 | 221 | /** 222 | * @return Returns the csrc. 223 | */ 224 | public UnsignedInt[] getCsrc() { 225 | return csrc; 226 | } 227 | 228 | /** 229 | * @param csrc 230 | * The csrc to set. 231 | */ 232 | public void setCsrc(UnsignedInt[] csrc) { 233 | this.csrc = csrc; 234 | } 235 | 236 | /** 237 | * @return Returns the csrcCount. 238 | */ 239 | public byte getCsrcCount() { 240 | return csrcCount; 241 | } 242 | 243 | /** 244 | * @param csrcCount 245 | * The csrcCount to set. 246 | */ 247 | public void setCsrcCount(byte csrcCount) { 248 | this.csrcCount = csrcCount; 249 | } 250 | 251 | /** 252 | * @return Returns the extension. 253 | */ 254 | public boolean isExtension() { 255 | return extension; 256 | } 257 | 258 | /** 259 | * @param extension 260 | * The extension to set. 261 | */ 262 | public void setExtension(boolean extension) { 263 | this.extension = extension; 264 | } 265 | 266 | /** 267 | * @return Returns the marker. 268 | */ 269 | public boolean isMarker() { 270 | return marker; 271 | } 272 | 273 | /** 274 | * @param marker 275 | * The marker to set. 276 | */ 277 | public void setMarker(boolean marker) { 278 | this.marker = marker; 279 | } 280 | 281 | /** 282 | * @return Returns the padding. 283 | */ 284 | public boolean isPadding() { 285 | return padding; 286 | } 287 | 288 | /** 289 | * @param padding 290 | * The padding to set. 291 | */ 292 | public void setPadding(boolean padding) { 293 | this.padding = padding; 294 | } 295 | 296 | /** 297 | * @return Returns the payload. 298 | */ 299 | public byte[] getPayload() { 300 | return payload; 301 | } 302 | 303 | /** 304 | * @param payload 305 | * The payload to set. 306 | */ 307 | public void setPayload(byte[] payload) { 308 | this.payload = payload; 309 | } 310 | 311 | /** 312 | * @return Returns the payloadType. 313 | */ 314 | public UnsignedByte getPayloadType() { 315 | return payloadType; 316 | } 317 | 318 | /** 319 | * @param payloadType 320 | * The payloadType to set. 321 | */ 322 | public void setPayloadType(UnsignedByte payloadType) { 323 | this.payloadType = payloadType; 324 | } 325 | 326 | /** 327 | * @return Returns the sequence. 328 | */ 329 | public UnsignedShort getSequence() { 330 | return sequence; 331 | } 332 | 333 | /** 334 | * @param sequence 335 | * The sequence to set. 336 | */ 337 | public void setSequence(UnsignedShort sequence) { 338 | this.sequence = sequence; 339 | } 340 | 341 | /** 342 | * @return Returns the ssrc. 343 | */ 344 | public UnsignedInt getSsrc() { 345 | return ssrc; 346 | } 347 | 348 | /** 349 | * @param ssrc 350 | * The ssrc to set. 351 | */ 352 | public void setSsrc(UnsignedInt ssrc) { 353 | this.ssrc = ssrc; 354 | } 355 | 356 | /** 357 | * @return Returns the timestamp. 358 | */ 359 | public UnsignedInt getTimestamp() { 360 | return timestamp; 361 | } 362 | 363 | /** 364 | * @param timestamp 365 | * The timestamp to set. 366 | */ 367 | public void setTimestamp(UnsignedInt timestamp) { 368 | this.timestamp = timestamp; 369 | } 370 | 371 | /** 372 | * @return Returns the version. 373 | */ 374 | public byte getVersion() { 375 | return version; 376 | } 377 | 378 | /** 379 | * @param version 380 | * The version to set. 381 | */ 382 | public void setVersion(byte version) { 383 | this.version = version; 384 | } 385 | 386 | } 387 | -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/util/UnsignedByte.java: -------------------------------------------------------------------------------- 1 | /* 2 | * RED5 Open Source Flash Server - https://github.com/Red5/ 3 | * 4 | * Copyright 2006-2015 by respective authors (see below). All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package br.com.voicetechnology.rtspclient.util; 19 | 20 | 21 | /** 22 | * The UnsignedByte class wraps a value of and unsigned 8 bits number. 23 | * 24 | * @author Matteo Merli (matteo.merli@gmail.com) 25 | */ 26 | public final class UnsignedByte extends UnsignedNumber { 27 | static final long serialVersionUID = 1L; 28 | 29 | private short value; 30 | 31 | public UnsignedByte(byte c) { 32 | value = c; 33 | } 34 | 35 | public UnsignedByte(short c) { 36 | value = (short) (c & 0xFF); 37 | } 38 | 39 | public UnsignedByte(int c) { 40 | value = (short) (c & 0xFF); 41 | } 42 | 43 | public UnsignedByte(long c) { 44 | value = (short) (c & 0xFFL); 45 | } 46 | 47 | private UnsignedByte() { 48 | value = 0; 49 | } 50 | 51 | public static UnsignedByte fromBytes(byte[] c) { 52 | return fromBytes(c, 0); 53 | } 54 | 55 | public static UnsignedByte fromBytes(byte[] c, int idx) { 56 | UnsignedByte number = new UnsignedByte(); 57 | if ((c.length - idx) < 1) 58 | throw new IllegalArgumentException("An UnsignedByte number is composed of 1 byte."); 59 | 60 | number.value = (short) (c[idx] & 0xFF); 61 | return number; 62 | } 63 | 64 | public static UnsignedByte fromString(String c) { 65 | return fromString(c, 10); 66 | } 67 | 68 | public static UnsignedByte fromString(String c, int radix) { 69 | UnsignedByte number = new UnsignedByte(); 70 | 71 | short v = Short.parseShort(c, radix); 72 | number.value = (short) (v & 0x0F); 73 | return number; 74 | } 75 | 76 | @Override 77 | public double doubleValue() { 78 | return value; 79 | } 80 | 81 | @Override 82 | public float floatValue() { 83 | return value; 84 | } 85 | 86 | @Override 87 | public short shortValue() { 88 | return (short) (value & 0xFF); 89 | } 90 | 91 | @Override 92 | public int intValue() { 93 | return value & 0xFF; 94 | } 95 | 96 | @Override 97 | public long longValue() { 98 | return value & 0xFFL; 99 | } 100 | 101 | @Override 102 | public byte[] getBytes() { 103 | byte[] c = { (byte) (value & 0xFF) }; 104 | return c; 105 | } 106 | 107 | @Override 108 | public int compareTo(UnsignedNumber other) { 109 | short otherValue = other.shortValue(); 110 | if (value > otherValue) { 111 | return +1; 112 | } else if (value < otherValue) { 113 | return -1; 114 | } 115 | return 0; 116 | } 117 | 118 | @Override 119 | public boolean equals(Object other) { 120 | if (other != null && other instanceof Number) { 121 | return value == ((Number) other).shortValue(); 122 | } else { 123 | return false; 124 | } 125 | } 126 | 127 | @Override 128 | public int hashCode() { 129 | return value; 130 | } 131 | 132 | @Override 133 | public String toString() { 134 | return Short.toString(value); 135 | } 136 | 137 | @Override 138 | public void shiftRight(int nBits) { 139 | if (Math.abs(nBits) > 8) { 140 | throw new IllegalArgumentException("Cannot right shift " + nBits + " an UnsignedByte."); 141 | } 142 | value >>>= nBits; 143 | } 144 | 145 | @Override 146 | public void shiftLeft(int nBits) { 147 | if (Math.abs(nBits) > 8) { 148 | throw new IllegalArgumentException("Cannot left shift " + nBits + " an UnsignedByte."); 149 | } 150 | value <<= nBits; 151 | } 152 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/util/UnsignedInt.java: -------------------------------------------------------------------------------- 1 | /* 2 | * RED5 Open Source Flash Server - https://github.com/Red5/ 3 | * 4 | * Copyright 2006-2015 by respective authors (see below). All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package br.com.voicetechnology.rtspclient.util; 20 | 21 | 22 | /** 23 | * The UnsignedInt class wraps a value of an unsigned 32 bits number. 24 | * 25 | * @author Matteo Merli (matteo.merli@gmail.com) 26 | */ 27 | public final class UnsignedInt extends UnsignedNumber { 28 | static final long serialVersionUID = 1L; 29 | 30 | private long value; 31 | 32 | public UnsignedInt(byte c) { 33 | value = c; 34 | } 35 | 36 | public UnsignedInt(short c) { 37 | value = c; 38 | } 39 | 40 | public UnsignedInt(int c) { 41 | value = c; 42 | } 43 | 44 | public UnsignedInt(long c) { 45 | value = c & 0xFFFFFFFFL; 46 | } 47 | 48 | private UnsignedInt() { 49 | value = 0; 50 | } 51 | 52 | public static UnsignedInt fromBytes(byte[] c) { 53 | return fromBytes(c, 0); 54 | } 55 | 56 | public static UnsignedInt fromBytes(byte[] c, int idx) { 57 | UnsignedInt number = new UnsignedInt(); 58 | if ((c.length - idx) < 4) { 59 | throw new IllegalArgumentException("An UnsignedInt number is composed of 4 bytes."); 60 | } 61 | number.value = (((c[idx] << 24) & 0xFF000000L) 62 | | ((c[idx + 1] << 16) & 0xFF0000L) 63 | | (c[idx + 2] << 8 & 0xFF00L) 64 | | (c[idx + 3] & 0xFFL)); 65 | return number; 66 | } 67 | 68 | public static UnsignedInt fromString(String c) { 69 | return fromString(c, 10); 70 | } 71 | 72 | public static UnsignedInt fromString(String c, int radix) { 73 | UnsignedInt number = new UnsignedInt(); 74 | long v = Long.parseLong(c, radix); 75 | number.value = v & 0xFFFFFFFFL; 76 | return number; 77 | } 78 | 79 | @Override 80 | public double doubleValue() { 81 | return value; 82 | } 83 | 84 | @Override 85 | public float floatValue() { 86 | return value; 87 | } 88 | 89 | @Override 90 | public int intValue() { 91 | return (int) (value & 0xFFFFFFFFL); 92 | } 93 | 94 | @Override 95 | public long longValue() { 96 | return value & 0xFFFFFFFFL; 97 | } 98 | 99 | @Override 100 | public byte[] getBytes() { 101 | byte[] c = new byte[4]; 102 | c[0] = (byte) ((value >> 24) & 0xFF); 103 | c[1] = (byte) ((value >> 16) & 0xFF); 104 | c[2] = (byte) ((value >> 8) & 0xFF); 105 | c[3] = (byte) ((value >> 0) & 0xFF); 106 | return c; 107 | } 108 | 109 | @Override 110 | public int compareTo(UnsignedNumber other) { 111 | long otherValue = other.longValue(); 112 | if (value > otherValue) 113 | return +1; 114 | else if (value < otherValue) 115 | return -1; 116 | return 0; 117 | } 118 | 119 | @Override 120 | public boolean equals(Object other) { 121 | if (!(other instanceof Number)) 122 | return false; 123 | return value == ((Number) other).longValue(); 124 | } 125 | 126 | @Override 127 | public String toString() { 128 | return Long.toString(value & 0xFFFFFFFFL); 129 | } 130 | 131 | @Override 132 | public int hashCode() { 133 | return (int) (value ^ (value >>> 32)); 134 | } 135 | 136 | @Override 137 | public void shiftRight(int nBits) { 138 | if (Math.abs(nBits) > 32) 139 | throw new IllegalArgumentException("Cannot right shift " + nBits + " an UnsignedInt."); 140 | 141 | value >>>= nBits; 142 | } 143 | 144 | @Override 145 | public void shiftLeft(int nBits) { 146 | if (Math.abs(nBits) > 32) 147 | throw new IllegalArgumentException("Cannot left shift " + nBits + " an UnsignedInt."); 148 | 149 | value <<= nBits; 150 | } 151 | 152 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/util/UnsignedNumber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * RED5 Open Source Flash Server - https://github.com/Red5/ 3 | * 4 | * Copyright 2006-2015 by respective authors (see below). All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | package br.com.voicetechnology.rtspclient.util; 19 | 20 | /** 21 | * @author Matteo Merli (matteo.merli@gmail.com) 22 | */ 23 | public abstract class UnsignedNumber extends Number { 24 | 25 | private static final long serialVersionUID = -6404256963187584919L; 26 | 27 | /** 28 | * Get a byte array representation of the number. The order will be MSB first (Big Endian). 29 | * 30 | * @return the serialized number 31 | */ 32 | public abstract byte[] getBytes(); 33 | 34 | /** 35 | * Perform a bit right shift of the value. 36 | * 37 | * @param nBits 38 | * the number of positions to shift 39 | */ 40 | public abstract void shiftRight(int nBits); 41 | 42 | /** 43 | * Perform a bit left shift of the value. 44 | * 45 | * @param nBits 46 | * the number of positions to shift 47 | */ 48 | public abstract void shiftLeft(int nBits); 49 | 50 | public abstract String toString(); 51 | 52 | public abstract int compareTo(UnsignedNumber other); 53 | 54 | public abstract boolean equals(Object other); 55 | 56 | public abstract int hashCode(); 57 | 58 | public String toHexString() { 59 | return toHexString(false); 60 | } 61 | 62 | public String toHexString(boolean pad) { 63 | StringBuilder sb = new StringBuilder(); 64 | boolean started = false; 65 | for (byte b : getBytes()) { 66 | if (!started && b == 0) { 67 | if (pad) { 68 | sb.append("00"); 69 | } 70 | } else { 71 | sb.append(hexLetters[(byte) ((b >> 4) & 0x0F)]).append(hexLetters[b & 0x0F]); 72 | started = true; 73 | } 74 | } 75 | if (sb.length() == 0) { 76 | return "0"; 77 | } 78 | return sb.toString(); 79 | } 80 | 81 | protected static final char[] hexLetters = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 82 | } -------------------------------------------------------------------------------- /src/main/java/br/com/voicetechnology/rtspclient/util/UnsignedShort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * RED5 Open Source Flash Server - https://github.com/Red5/ 3 | * 4 | * Copyright 2006-2015 by respective authors (see below). All rights reserved. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package br.com.voicetechnology.rtspclient.util; 20 | 21 | import java.util.Arrays; 22 | 23 | 24 | /** 25 | * The UnsignedByte class wraps a value of an unsigned 16 bits number. 26 | * 27 | * @author Matteo Merli (matteo.merli@gmail.com) 28 | */ 29 | public final class UnsignedShort extends UnsignedNumber { 30 | static final long serialVersionUID = 1L; 31 | 32 | private int value; 33 | 34 | public UnsignedShort(byte c) { 35 | value = c; 36 | } 37 | 38 | public UnsignedShort(short c) { 39 | value = c; 40 | } 41 | 42 | public UnsignedShort(int c) { 43 | value = c & 0xFFFF; 44 | } 45 | 46 | public UnsignedShort(long c) { 47 | value = (int) (c & 0xFFFFL); 48 | } 49 | 50 | private UnsignedShort() { 51 | value = 0; 52 | } 53 | 54 | public static UnsignedShort fromBytes(byte[] c) { 55 | return fromBytes(c, 0); 56 | } 57 | 58 | public static UnsignedShort fromBytes(byte[] c, int idx) { 59 | UnsignedShort number = new UnsignedShort(); 60 | if ((c.length - idx) < 2) { 61 | throw new IllegalArgumentException("An UnsignedShort number is composed of 2 bytes."); 62 | } 63 | number.value = (((c[idx] << 8) & 0xFF00) | (c[idx+1] & 0xFF)); 64 | return number; 65 | } 66 | 67 | public static UnsignedShort fromString(String c) { 68 | return fromString(c, 10); 69 | } 70 | 71 | public static UnsignedShort fromString(String c, int radix) { 72 | UnsignedShort number = new UnsignedShort(); 73 | long v = Integer.parseInt(c, radix); 74 | number.value = (int) (v & 0xFFFF); 75 | return number; 76 | } 77 | 78 | @Override 79 | public double doubleValue() { 80 | return value; 81 | } 82 | 83 | @Override 84 | public float floatValue() { 85 | return value; 86 | } 87 | 88 | @Override 89 | public short shortValue() { 90 | return (short) (value & 0xFFFF); 91 | } 92 | 93 | @Override 94 | public int intValue() { 95 | return value & 0xFFFF; 96 | } 97 | 98 | @Override 99 | public long longValue() { 100 | return value & 0xFFFFL; 101 | } 102 | 103 | @Override 104 | public byte[] getBytes() { 105 | return new byte[] { (byte) ((value >> 8) & 0xFF), (byte) (value & 0xFF) }; 106 | } 107 | 108 | @Override 109 | public int compareTo(UnsignedNumber other) { 110 | int otherValue = other.intValue(); 111 | if (value > otherValue) { 112 | return 1; 113 | } else if (value < otherValue) { 114 | return -1; 115 | } 116 | return 0; 117 | } 118 | 119 | @Override 120 | public boolean equals(Object other) { 121 | if (other instanceof Number) { 122 | return Arrays.equals(getBytes(), ((UnsignedNumber) other).getBytes()); 123 | } else { 124 | return false; 125 | } 126 | } 127 | 128 | @Override 129 | public int hashCode() { 130 | return value; 131 | } 132 | 133 | @Override 134 | public String toString() { 135 | return Integer.toString(value); 136 | } 137 | 138 | @Override 139 | public void shiftRight(int nBits) { 140 | if (Math.abs(nBits) > 16) { 141 | throw new IllegalArgumentException("Cannot right shift " + nBits + " an UnsignedShort."); 142 | } 143 | value >>>= nBits; 144 | } 145 | 146 | @Override 147 | public void shiftLeft(int nBits) { 148 | if (Math.abs(nBits) > 16) { 149 | throw new IllegalArgumentException("Cannot left shift " + nBits + " an UnsignedShort."); 150 | } 151 | value <<= nBits; 152 | } 153 | 154 | } 155 | --------------------------------------------------------------------------------