Fixed incorrect RTSP packets and options query
This commit is contained in:
parent
37692613bf
commit
1b25915c33
2 changed files with 81 additions and 18 deletions
|
|
@ -23,14 +23,20 @@
|
||||||
*/
|
*/
|
||||||
package zutil.net.media;
|
package zutil.net.media;
|
||||||
|
|
||||||
|
import zutil.ObjectUtil;
|
||||||
|
import zutil.converter.Converter;
|
||||||
import zutil.io.IOUtil;
|
import zutil.io.IOUtil;
|
||||||
|
import zutil.log.LogUtil;
|
||||||
import zutil.net.http.HttpClient;
|
import zutil.net.http.HttpClient;
|
||||||
import zutil.net.http.HttpHeader;
|
import zutil.net.http.HttpHeader;
|
||||||
|
import zutil.net.http.HttpURL;
|
||||||
import zutil.parser.sdp.SessionDescription;
|
import zutil.parser.sdp.SessionDescription;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static zutil.net.media.RTSPClient.RTSPRequestType.*;
|
import static zutil.net.media.RTSPClient.RTSPRequestType.*;
|
||||||
|
|
||||||
|
|
@ -40,6 +46,8 @@ import static zutil.net.media.RTSPClient.RTSPRequestType.*;
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc2326">RFC2326</a>
|
* @see <a href="https://tools.ietf.org/html/rfc2326">RFC2326</a>
|
||||||
*/
|
*/
|
||||||
public class RTSPClient {
|
public class RTSPClient {
|
||||||
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
public enum RTSPRequestType {
|
public enum RTSPRequestType {
|
||||||
DESCRIBE, // RFC Section 10.2
|
DESCRIBE, // RFC Section 10.2
|
||||||
ANNOUNCE, // RFC Section 10.3
|
ANNOUNCE, // RFC Section 10.3
|
||||||
|
|
@ -57,11 +65,14 @@ public class RTSPClient {
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
private static final String PARAMETER_SESSION = "Session";
|
private static final String PARAMETER_SESSION = "Session";
|
||||||
|
private static final String PARAMETER_PUBLIC = "Public";
|
||||||
|
|
||||||
// Current media variables
|
// Current media variables
|
||||||
|
|
||||||
private final URL url;
|
private final HttpURL url;
|
||||||
|
|
||||||
|
private RTSPRequestType[] supportedOptions;
|
||||||
|
private int sequenceId;
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
private String transport;
|
private String transport;
|
||||||
|
|
||||||
|
|
@ -69,7 +80,8 @@ public class RTSPClient {
|
||||||
public RTSPClient(String strUrl) throws MalformedURLException {
|
public RTSPClient(String strUrl) throws MalformedURLException {
|
||||||
if (strUrl.startsWith("rtsp://"))
|
if (strUrl.startsWith("rtsp://"))
|
||||||
strUrl = strUrl.substring(7);
|
strUrl = strUrl.substring(7);
|
||||||
this.url = new URL("http://" + strUrl);
|
this.url = new HttpURL(new URL("http://" + strUrl));
|
||||||
|
url.setProtocol("rtsp");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
|
@ -106,19 +118,18 @@ public class RTSPClient {
|
||||||
*/
|
*/
|
||||||
public String getDescription() throws IOException {
|
public String getDescription() throws IOException {
|
||||||
HttpClient http = getHttpClient(DESCRIBE);
|
HttpClient http = getHttpClient(DESCRIBE);
|
||||||
HttpHeader resp = http.send();
|
|
||||||
|
ResponseData resp = sendRequest(http);
|
||||||
// TODO: parse response
|
// TODO: parse response
|
||||||
|
|
||||||
http.close();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDescription(SessionDescription description) throws IOException {
|
public void setDescription(SessionDescription description) throws IOException {
|
||||||
HttpClient http = getHttpClient(ANNOUNCE);
|
HttpClient http = getHttpClient(ANNOUNCE);
|
||||||
http.setContent(description.toString());
|
http.setContent(description.toString());
|
||||||
http.send();
|
|
||||||
|
|
||||||
http.close();
|
sendRequest(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -126,9 +137,8 @@ public class RTSPClient {
|
||||||
HttpClient http = getHttpClient(GET_PARAMETER);
|
HttpClient http = getHttpClient(GET_PARAMETER);
|
||||||
http.setHeader(HttpHeader.HEADER_CONTENT_TYPE, "text/parameters");
|
http.setHeader(HttpHeader.HEADER_CONTENT_TYPE, "text/parameters");
|
||||||
http.setContent(key);
|
http.setContent(key);
|
||||||
http.send();
|
|
||||||
|
|
||||||
String response = IOUtil.readContentAsString(http.getResponseInputStream());
|
ResponseData resp = sendRequest(http);
|
||||||
// TODO: parse response
|
// TODO: parse response
|
||||||
|
|
||||||
http.close();
|
http.close();
|
||||||
|
|
@ -139,9 +149,9 @@ public class RTSPClient {
|
||||||
HttpClient http = getHttpClient(SET_PARAMETER);
|
HttpClient http = getHttpClient(SET_PARAMETER);
|
||||||
http.setHeader("Content-Type", "text/parameters");
|
http.setHeader("Content-Type", "text/parameters");
|
||||||
http.setContent(key + ": " + value);
|
http.setContent(key + ": " + value);
|
||||||
http.send();
|
|
||||||
|
|
||||||
http.close();
|
ResponseData resp = sendRequest(http);
|
||||||
|
// TODO: parse response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -162,33 +172,81 @@ public class RTSPClient {
|
||||||
* This function will only initiate the resources once any other call
|
* This function will only initiate the resources once any other call
|
||||||
* will only return without any action.
|
* will only return without any action.
|
||||||
*/
|
*/
|
||||||
private void setup() throws IOException {
|
protected void setup() throws IOException {
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
|
supportedOptions = getOptions();
|
||||||
|
|
||||||
HttpClient http = getHttpClient(SETUP);
|
HttpClient http = getHttpClient(SETUP);
|
||||||
http.setHeader("Transport", "RTP/AVP;unicast;client_port=4588-4589");
|
http.setHeader("Transport", "RTP/AVP;unicast;client_port=4588-4589");
|
||||||
HttpHeader resp = http.send();
|
|
||||||
|
|
||||||
sessionId = resp.getHeader(PARAMETER_SESSION);
|
ResponseData resp = sendRequest(http);
|
||||||
transport = resp.getHeader("Transport");
|
sessionId = resp.header.getHeader(PARAMETER_SESSION);
|
||||||
http.close();
|
transport = resp.header.getHeader("Transport");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will check what request types are supported by the server
|
||||||
|
*
|
||||||
|
* @return an array of RTSP request types that are supported by the server.
|
||||||
|
*/
|
||||||
|
protected RTSPRequestType[] getOptions() throws IOException {
|
||||||
|
HttpClient http = getHttpClient(OPTIONS);
|
||||||
|
ResponseData resp = sendRequest(http);
|
||||||
|
|
||||||
|
String options = resp.header.getHeader(PARAMETER_PUBLIC);
|
||||||
|
if (!ObjectUtil.isEmpty(options)) {
|
||||||
|
String[] arr = options.split(",");
|
||||||
|
RTSPRequestType[] ret = new RTSPRequestType[arr.length];
|
||||||
|
|
||||||
|
// Convert received options to the enum type
|
||||||
|
for (int i=0; i<arr.length; i++) {
|
||||||
|
ret[i] = RTSPRequestType.valueOf(arr[i].trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.fine("Received supported options: " + Arrays.toString(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RTSPRequestType[]{};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the stream and release any associated resources on the server.
|
* Stop the stream and release any associated resources on the server.
|
||||||
*/
|
*/
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
HttpClient http = getHttpClient(TEARDOWN);
|
HttpClient http = getHttpClient(TEARDOWN);
|
||||||
http.send();
|
sendRequest(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private HttpClient getHttpClient(RTSPRequestType type) {
|
private HttpClient getHttpClient(RTSPRequestType type) {
|
||||||
HttpClient http = new HttpClient(type.toString());
|
HttpClient http = new HttpClient(type.toString());
|
||||||
http.setURL(url); // TODO: Request line is required to contain the whole URL and not tha path
|
http.setProtocol("RTSP");
|
||||||
|
http.setURL(url);
|
||||||
|
http.setAbsoluteURL(true);
|
||||||
http.setHeader("Accept", "application/sdp");
|
http.setHeader("Accept", "application/sdp");
|
||||||
http.setHeader(PARAMETER_SESSION, sessionId);
|
http.setHeader("CSeq", "" + sequenceId++);
|
||||||
|
if (sessionId != null)
|
||||||
|
http.setHeader(PARAMETER_SESSION, sessionId);
|
||||||
|
|
||||||
return http;
|
return http;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ResponseData sendRequest(HttpClient http) throws IOException {
|
||||||
|
ResponseData resp = new ResponseData();
|
||||||
|
|
||||||
|
logger.finest("RTSP Request: " + http);
|
||||||
|
resp.header = http.send();
|
||||||
|
logger.finest("RTSP Response: " + resp.header);
|
||||||
|
|
||||||
|
resp.content = IOUtil.readContentAsString(http.getResponseInputStream());
|
||||||
|
http.close();
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ResponseData {
|
||||||
|
HttpHeader header;
|
||||||
|
String content;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,19 @@
|
||||||
|
|
||||||
package zutil.net.media;
|
package zutil.net.media;
|
||||||
|
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
|
||||||
public class RTSPClientTest {
|
public class RTSPClientTest {
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
|
LogUtil.setGlobalLevel(Level.FINEST);
|
||||||
|
|
||||||
RTSPClient rtsp = new RTSPClient("rtsp://192.168.10.249:8554/unicast");
|
RTSPClient rtsp = new RTSPClient("rtsp://192.168.10.249:8554/unicast");
|
||||||
rtsp.play();
|
rtsp.play();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue