mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-21 12:03:02 +00:00
Implement RTSP over ENet
This commit is contained in:
parent
b3042312f6
commit
c06a4ab76d
Binary file not shown.
@ -4,13 +4,16 @@ import java.io.IOException;
|
|||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import com.limelight.nvstream.ConnectionContext;
|
import com.limelight.nvstream.ConnectionContext;
|
||||||
import com.limelight.nvstream.av.video.VideoDecoderRenderer.VideoFormat;
|
import com.limelight.nvstream.av.video.VideoDecoderRenderer.VideoFormat;
|
||||||
|
import com.limelight.nvstream.enet.EnetConnection;
|
||||||
import com.tinyrtsp.rtsp.message.RtspMessage;
|
import com.tinyrtsp.rtsp.message.RtspMessage;
|
||||||
import com.tinyrtsp.rtsp.message.RtspRequest;
|
import com.tinyrtsp.rtsp.message.RtspRequest;
|
||||||
import com.tinyrtsp.rtsp.message.RtspResponse;
|
import com.tinyrtsp.rtsp.message.RtspResponse;
|
||||||
|
import com.tinyrtsp.rtsp.parser.RtspParser;
|
||||||
import com.tinyrtsp.rtsp.parser.RtspStream;
|
import com.tinyrtsp.rtsp.parser.RtspStream;
|
||||||
|
|
||||||
public class RtspConnection {
|
public class RtspConnection {
|
||||||
@ -19,6 +22,7 @@ public class RtspConnection {
|
|||||||
|
|
||||||
private int sequenceNumber = 1;
|
private int sequenceNumber = 1;
|
||||||
private int sessionId = 0;
|
private int sessionId = 0;
|
||||||
|
private EnetConnection enetConnection;
|
||||||
|
|
||||||
private ConnectionContext context;
|
private ConnectionContext context;
|
||||||
private String hostStr;
|
private String hostStr;
|
||||||
@ -54,7 +58,45 @@ public class RtspConnection {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RtspResponse transactRtspMessage(RtspMessage m) throws IOException {
|
private String byteBufferToString(byte[] bytes, int length) {
|
||||||
|
StringBuilder message = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
message.append((char) bytes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return message.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RtspResponse transactRtspMessageEnet(RtspMessage m) throws IOException {
|
||||||
|
byte[] header, payload;
|
||||||
|
|
||||||
|
header = m.toWireNoPayload();
|
||||||
|
payload = m.toWirePayloadOnly();
|
||||||
|
|
||||||
|
// Send the RTSP header
|
||||||
|
enetConnection.writePacket(ByteBuffer.wrap(header));
|
||||||
|
|
||||||
|
// Send payload in a separate packet if there's payload on this
|
||||||
|
if (payload != null) {
|
||||||
|
enetConnection.writePacket(ByteBuffer.wrap(payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for a response
|
||||||
|
ByteBuffer responseHeader = enetConnection.readPacket(2048, RTSP_TIMEOUT);
|
||||||
|
|
||||||
|
// Parse the response and determine whether it has a payload
|
||||||
|
RtspResponse message = (RtspResponse) RtspParser.parseMessageNoPayload(byteBufferToString(responseHeader.array(), responseHeader.limit()));
|
||||||
|
if (message.getOption("Content-Length") != null) {
|
||||||
|
// The payload should immediately follow the header, so only wait another second
|
||||||
|
ByteBuffer responsePayload = enetConnection.readPacket(65536, 1000);
|
||||||
|
message.setPayload(byteBufferToString(responsePayload.array(), responsePayload.limit()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RtspResponse transactRtspMessageTcp(RtspMessage m) throws IOException {
|
||||||
Socket s = new Socket();
|
Socket s = new Socket();
|
||||||
try {
|
try {
|
||||||
s.setTcpNoDelay(true);
|
s.setTcpNoDelay(true);
|
||||||
@ -73,6 +115,15 @@ public class RtspConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RtspResponse transactRtspMessage(RtspMessage m) throws IOException {
|
||||||
|
if (context.serverGeneration >= ConnectionContext.SERVER_GENERATION_5) {
|
||||||
|
return transactRtspMessageEnet(m);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return transactRtspMessageTcp(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private RtspResponse requestOptions() throws IOException {
|
private RtspResponse requestOptions() throws IOException {
|
||||||
RtspRequest m = createRtspRequest("OPTIONS", "rtsp://"+hostStr);
|
RtspRequest m = createRtspRequest("OPTIONS", "rtsp://"+hostStr);
|
||||||
return transactRtspMessage(m);
|
return transactRtspMessage(m);
|
||||||
@ -138,6 +189,12 @@ public class RtspConnection {
|
|||||||
public void doRtspHandshake() throws IOException {
|
public void doRtspHandshake() throws IOException {
|
||||||
RtspResponse r;
|
RtspResponse r;
|
||||||
|
|
||||||
|
// Gen 5+ servers do RTSP over ENet instead of TCP
|
||||||
|
if (context.serverGeneration >= ConnectionContext.SERVER_GENERATION_5) {
|
||||||
|
enetConnection = EnetConnection.connect(context.serverAddress.getHostAddress(), PORT, RTSP_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
r = requestOptions();
|
r = requestOptions();
|
||||||
if (r.getStatusCode() != 200) {
|
if (r.getStatusCode() != 200) {
|
||||||
throw new IOException("RTSP OPTIONS request failed: "+r.getStatusCode());
|
throw new IOException("RTSP OPTIONS request failed: "+r.getStatusCode());
|
||||||
@ -177,5 +234,11 @@ public class RtspConnection {
|
|||||||
if (r.getStatusCode() != 200) {
|
if (r.getStatusCode() != 200) {
|
||||||
throw new IOException("RTSP PLAY request failed: "+r.getStatusCode());
|
throw new IOException("RTSP PLAY request failed: "+r.getStatusCode());
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
if (enetConnection != null) {
|
||||||
|
enetConnection.close();
|
||||||
|
enetConnection = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user