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
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 List38 | * 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 | --------------------------------------------------------------------------------