mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 11:03:01 +00:00
Backwards compatibility for video and control stream to GFE 2.1.x
This commit is contained in:
parent
daf7598774
commit
aee255a6ee
@ -119,6 +119,16 @@ public class NvConnection {
|
||||
context.connListener.displayTransientMessage("This version of GFE is not currently supported. You may experience issues until Limelight is updated");
|
||||
}
|
||||
|
||||
switch (majorVersion) {
|
||||
case 3:
|
||||
context.serverGeneration = ConnectionContext.SERVER_GENERATION_3;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
context.serverGeneration = ConnectionContext.SERVER_GENERATION_4;
|
||||
break;
|
||||
}
|
||||
|
||||
LimeLog.info("Server major version: "+majorVersion);
|
||||
} catch (NumberFormatException e) {
|
||||
context.connListener.displayMessage("Server version malformed: "+serverVersion);
|
||||
|
@ -3,7 +3,6 @@ package com.limelight.nvstream.av.audio;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.util.LinkedList;
|
||||
|
@ -4,7 +4,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
@ -179,10 +178,20 @@ public class VideoStream {
|
||||
startReceiveThread();
|
||||
}
|
||||
|
||||
// Open the first frame port connection on Gen 3 servers
|
||||
if (context.serverGeneration == ConnectionContext.SERVER_GENERATION_3) {
|
||||
connectFirstFrame();
|
||||
}
|
||||
|
||||
// Start pinging before reading the first frame
|
||||
// so GFE knows where to send UDP data
|
||||
startUdpPingThread();
|
||||
|
||||
// Read the first frame on Gen 3 servers
|
||||
if (context.serverGeneration == ConnectionContext.SERVER_GENERATION_3) {
|
||||
readFirstFrame();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -19,23 +19,55 @@ public class ControlStream implements ConnectionStatusListener {
|
||||
|
||||
public static final int CONTROL_TIMEOUT = 5000;
|
||||
|
||||
public static final short PTYPE_START_STREAM_A = 0x0606;
|
||||
public static final short PPAYLEN_START_STREAM_A = 2;
|
||||
public static final byte[] PPAYLOAD_START_STREAM_A = new byte[]{0, 0};
|
||||
private static final int IDX_START_A = 0;
|
||||
private static final int IDX_START_B = 1;
|
||||
private static final int IDX_RESYNC = 2;
|
||||
private static final int IDX_LOSS_STATS = 3;
|
||||
|
||||
public static final short PTYPE_START_STREAM_B = 0x0609;
|
||||
public static final short PPAYLEN_START_STREAM_B = 1;
|
||||
public static final byte[] PPAYLOAD_START_STREAM_B = new byte[]{0};
|
||||
private static final short packetTypesGen3[] = {
|
||||
0x140b, // Start A
|
||||
0x1410, // Start B
|
||||
0x1404, // Resync
|
||||
0x140c, // Loss Stats
|
||||
0x1417, // Frame Stats (unused)
|
||||
};
|
||||
private static final short packetTypesGen4[] = {
|
||||
0x0606, // Start A
|
||||
0x0609, // Start B
|
||||
0x0604, // Resync
|
||||
0x060a, // Loss Stats
|
||||
0x0611, // Frame Stats (unused)
|
||||
};
|
||||
|
||||
public static final short PTYPE_RESYNC = 0x0604;
|
||||
public static final short PPAYLEN_RESYNC = 24;
|
||||
private static final short payloadLengthsGen3[] = {
|
||||
-1, // Start A
|
||||
16, // Start B
|
||||
24, // Resync
|
||||
32, // Loss Stats
|
||||
64, // Frame Stats
|
||||
};
|
||||
private static final short payloadLengthsGen4[] = {
|
||||
-1, // Start A
|
||||
-1, // Start B
|
||||
24, // Resync
|
||||
32, // Loss Stats
|
||||
64, // Frame Stats
|
||||
};
|
||||
|
||||
public static final short PTYPE_LOSS_STATS = 0x060a;
|
||||
public static final short PPAYLEN_LOSS_STATS = 32;
|
||||
|
||||
// Currently unused
|
||||
public static final short PTYPE_FRAME_STATS = 0x0611;
|
||||
public static final short PPAYLEN_FRAME_STATS = 64;
|
||||
private static final byte[] precontructedPayloadsGen3[] = {
|
||||
new byte[]{0}, // Start A
|
||||
null, // Start B
|
||||
null, // Resync
|
||||
null, // Loss Stats
|
||||
null, // Frame Stats
|
||||
};
|
||||
private static final byte[] precontructedPayloadsGen4[] = {
|
||||
new byte[]{0, 0}, // Start A
|
||||
new byte[]{0}, // Start B
|
||||
null, // Resync
|
||||
null, // Loss Stats
|
||||
null, // Frame Stats
|
||||
};
|
||||
|
||||
public static final int LOSS_REPORT_INTERVAL_MS = 50;
|
||||
|
||||
@ -62,9 +94,28 @@ public class ControlStream implements ConnectionStatusListener {
|
||||
private LinkedBlockingQueue<int[]> invalidReferenceFrameTuples = new LinkedBlockingQueue<int[]>();
|
||||
private boolean aborting = false;
|
||||
|
||||
private final short[] packetTypes;
|
||||
private final short[] payloadLengths;
|
||||
private final byte[][] preconstructedPayloads;
|
||||
|
||||
public ControlStream(ConnectionContext context)
|
||||
{
|
||||
this.context = context;
|
||||
|
||||
switch (context.serverGeneration)
|
||||
{
|
||||
case ConnectionContext.SERVER_GENERATION_3:
|
||||
packetTypes = packetTypesGen3;
|
||||
payloadLengths = payloadLengthsGen3;
|
||||
preconstructedPayloads = precontructedPayloadsGen3;
|
||||
break;
|
||||
case ConnectionContext.SERVER_GENERATION_4:
|
||||
default:
|
||||
packetTypes = packetTypesGen4;
|
||||
payloadLengths = payloadLengthsGen4;
|
||||
preconstructedPayloads = precontructedPayloadsGen4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize() throws IOException
|
||||
@ -102,7 +153,8 @@ public class ControlStream implements ConnectionStatusListener {
|
||||
bb.putInt(0);
|
||||
bb.putInt(0x14);
|
||||
|
||||
sendPacket(new NvCtlPacket(PTYPE_LOSS_STATS, PPAYLEN_LOSS_STATS, bb.array()));
|
||||
sendPacket(new NvCtlPacket(packetTypes[IDX_LOSS_STATS],
|
||||
payloadLengths[IDX_LOSS_STATS], bb.array()));
|
||||
}
|
||||
|
||||
public void abort()
|
||||
@ -148,7 +200,7 @@ public class ControlStream implements ConnectionStatusListener {
|
||||
lossStatsThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(PPAYLEN_LOSS_STATS).order(ByteOrder.LITTLE_ENDIAN);
|
||||
ByteBuffer bb = ByteBuffer.allocate(payloadLengths[IDX_LOSS_STATS]).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
while (!isInterrupted())
|
||||
{
|
||||
@ -225,19 +277,33 @@ public class ControlStream implements ConnectionStatusListener {
|
||||
|
||||
private ControlStream.NvCtlResponse doStartA() throws IOException
|
||||
{
|
||||
return sendAndGetReply(new NvCtlPacket(PTYPE_START_STREAM_A,
|
||||
PPAYLEN_START_STREAM_A, PPAYLOAD_START_STREAM_A));
|
||||
return sendAndGetReply(new NvCtlPacket(packetTypes[IDX_START_A],
|
||||
(short) preconstructedPayloads[IDX_START_A].length,
|
||||
preconstructedPayloads[IDX_START_A]));
|
||||
}
|
||||
|
||||
private ControlStream.NvCtlResponse doStartB() throws IOException
|
||||
{
|
||||
return sendAndGetReply(new NvCtlPacket(PTYPE_START_STREAM_B,
|
||||
PPAYLEN_START_STREAM_B, PPAYLOAD_START_STREAM_B));
|
||||
if (context.serverGeneration == ConnectionContext.SERVER_GENERATION_3) {
|
||||
ByteBuffer payload = ByteBuffer.wrap(new byte[payloadLengths[IDX_START_B]]).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
payload.putInt(0);
|
||||
payload.putInt(0);
|
||||
payload.putInt(0);
|
||||
payload.putInt(0xa);
|
||||
|
||||
return sendAndGetReply(new NvCtlPacket(packetTypes[IDX_START_B],
|
||||
payloadLengths[IDX_START_B], payload.array()));
|
||||
}
|
||||
else {
|
||||
return sendAndGetReply(new NvCtlPacket(packetTypes[IDX_START_B],
|
||||
payloadLengths[IDX_START_B], preconstructedPayloads[IDX_START_B]));
|
||||
}
|
||||
}
|
||||
|
||||
private void sendResync(int firstLostFrame, int nextSuccessfulFrame) throws IOException
|
||||
{
|
||||
ByteBuffer conf = ByteBuffer.wrap(new byte[PPAYLEN_RESYNC]).order(ByteOrder.LITTLE_ENDIAN);
|
||||
ByteBuffer conf = ByteBuffer.wrap(new byte[payloadLengths[IDX_RESYNC]]).order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
//conf.putLong(firstLostFrame);
|
||||
//conf.putLong(nextSuccessfulFrame);
|
||||
@ -245,7 +311,8 @@ public class ControlStream implements ConnectionStatusListener {
|
||||
conf.putLong(0xFFFFF);
|
||||
conf.putLong(0);
|
||||
|
||||
sendAndGetReply(new NvCtlPacket(PTYPE_RESYNC, PPAYLEN_RESYNC, conf.array()));
|
||||
sendAndGetReply(new NvCtlPacket(packetTypes[IDX_RESYNC],
|
||||
payloadLengths[IDX_RESYNC], conf.array()));
|
||||
}
|
||||
|
||||
static class NvCtlPacket {
|
||||
|
Loading…
x
Reference in New Issue
Block a user