diff --git a/limelight-common/ControlStream.c b/limelight-common/ControlStream.c index 2c80a98..c891caa 100644 --- a/limelight-common/ControlStream.c +++ b/limelight-common/ControlStream.c @@ -43,6 +43,7 @@ static LINKED_BLOCKING_QUEUE invalidReferenceFrameTuples; #define IDX_START_B 1 #define IDX_INVALIDATE_REF_FRAMES 2 #define IDX_LOSS_STATS 3 +#define IDX_INPUT_DATA 5 #define CONTROL_STREAM_TIMEOUT_SEC 10 @@ -52,6 +53,7 @@ static const short packetTypesGen3[] = { 0x1404, // Invalidate reference frames 0x140c, // Loss Stats 0x1417, // Frame Stats (unused) + -1, // Input data (unused) }; static const short packetTypesGen4[] = { 0x0606, // Request IDR frame @@ -59,6 +61,7 @@ static const short packetTypesGen4[] = { 0x0604, // Invalidate reference frames 0x060a, // Loss Stats 0x0611, // Frame Stats (unused) + -1, // Input data (unused) }; static const short packetTypesGen5[] = { 0x0305, // Start A @@ -66,6 +69,15 @@ static const short packetTypesGen5[] = { 0x0301, // Invalidate reference frames 0x0201, // Loss Stats 0x0204, // Frame Stats (unused) + 0x0207, // Input data +}; +static const short packetTypesGen7[] = { + 0x0305, // Start A + 0x0307, // Start B + 0x0301, // Invalidate reference frames + 0x0201, // Loss Stats + 0x0204, // Frame Stats (unused) + 0x0206, // Input data }; static const char startAGen3[] = { 0 }; @@ -83,6 +95,7 @@ static const short payloadLengthsGen3[] = { 24, // Invalidate reference frames 32, // Loss Stats 64, // Frame Stats + -1, // Input data }; static const short payloadLengthsGen4[] = { sizeof(requestIdrFrameGen4), // Request IDR frame @@ -90,6 +103,7 @@ static const short payloadLengthsGen4[] = { 24, // Invalidate reference frames 32, // Loss Stats 64, // Frame Stats + -1, // Input data }; static const short payloadLengthsGen5[] = { sizeof(startAGen5), // Start A @@ -97,6 +111,15 @@ static const short payloadLengthsGen5[] = { 24, // Invalidate reference frames 32, // Loss Stats 80, // Frame Stats + -1, // Input data +}; +static const short payloadLengthsGen7[] = { + sizeof(startAGen5), // Start A + sizeof(startBGen5), // Start B + 24, // Invalidate reference frames + 32, // Loss Stats + 80, // Frame Stats + -1, // Input data }; static const char* preconstructedPayloadsGen3[] = { @@ -111,6 +134,10 @@ static const char* preconstructedPayloadsGen5[] = { startAGen5, startBGen5 }; +static const char* preconstructedPayloadsGen7[] = { + startAGen5, + startBGen5 +}; static short* packetTypes; static short* payloadLengths; @@ -134,11 +161,16 @@ int initializeControlStream(void) { payloadLengths = (short*)payloadLengthsGen4; preconstructedPayloads = (char**)preconstructedPayloadsGen4; } - else { + else if (ServerMajorVersion == 5) { packetTypes = (short*)packetTypesGen5; payloadLengths = (short*)payloadLengthsGen5; preconstructedPayloads = (char**)preconstructedPayloadsGen5; } + else { + packetTypes = (short*)packetTypesGen7; + payloadLengths = (short*)payloadLengthsGen7; + preconstructedPayloads = (char**)preconstructedPayloadsGen7; + } idrFrameRequired = 0; lastGoodFrame = 0; @@ -575,7 +607,7 @@ int sendInputPacketOnControlStream(unsigned char* data, int length) { LC_ASSERT(ServerMajorVersion >= 5); // Send the input data (no reply expected) - if (sendMessageAndForget(0x0207, length, data) == 0) { + if (sendMessageAndForget(packetTypes[IDX_INPUT_DATA], length, data) == 0) { return -1; } diff --git a/limelight-common/RtspConnection.c b/limelight-common/RtspConnection.c index d5dcc55..90eb624 100644 --- a/limelight-common/RtspConnection.c +++ b/limelight-common/RtspConnection.c @@ -337,6 +337,7 @@ static int requestDescribe(PRTSP_MESSAGE response, int* error) { static int setupStream(PRTSP_MESSAGE response, char* target, int* error) { RTSP_MESSAGE request; int ret; + char* transportValue; *error = -1; @@ -349,7 +350,17 @@ static int setupStream(PRTSP_MESSAGE response, char* target, int* error) { } } - if (addOption(&request, "Transport", " ") && + if (ServerMajorVersion >= 6) { + // It looks like GFE doesn't care what we say our port is but + // we need to give it some port to successfully complete the + // handshake process. + transportValue = "unicast;X-GS-ClientPort=50000-50001"; + } + else { + transportValue = " "; + } + + if (addOption(&request, "Transport", transportValue) && addOption(&request, "If-Modified-Since", "Thu, 01 Jan 1970 00:00:00 GMT")) { ret = transactRtspMessage(&request, response, 0, error); @@ -436,14 +447,24 @@ int performRtspHandshake(void) { currentSeqNumber = 1; hasSessionId = 0; - if (ServerMajorVersion == 3) { - rtspClientVersion = 10; - } - else if (ServerMajorVersion == 4) { - rtspClientVersion = 11; - } - else { - rtspClientVersion = 12; + switch (ServerMajorVersion) { + case 3: + rtspClientVersion = 10; + break; + case 4: + rtspClientVersion = 11; + break; + case 5: + rtspClientVersion = 12; + break; + case 6: + // Gen 6 has never been seen in the wild + rtspClientVersion = 13; + break; + case 7: + default: + rtspClientVersion = 14; + break; } // Gen 5 servers use ENet to do the RTSP handshake @@ -544,7 +565,9 @@ int performRtspHandshake(void) { char* sessionId; int error = -1; - if (!setupStream(&response, "streamid=audio", &error)) { + if (!setupStream(&response, + ServerMajorVersion >= 5 ? "streamid=audio/0/0" : "streamid=audio", + &error)) { Limelog("RTSP SETUP streamid=audio request failed: %d\n", error); ret = error; goto Exit; @@ -574,7 +597,9 @@ int performRtspHandshake(void) { RTSP_MESSAGE response; int error = -1; - if (!setupStream(&response, "streamid=video", &error)) { + if (!setupStream(&response, + ServerMajorVersion >= 5 ? "streamid=video/0/0" : "streamid=video", + &error)) { Limelog("RTSP SETUP streamid=video request failed: %d\n", error); ret = error; goto Exit; @@ -589,6 +614,26 @@ int performRtspHandshake(void) { freeMessage(&response); } + + if (ServerMajorVersion >= 5) { + RTSP_MESSAGE response; + int error = -1; + + if (!setupStream(&response, "streamid=control/1/0", &error)) { + Limelog("RTSP SETUP streamid=control request failed: %d\n", error); + ret = error; + goto Exit; + } + + if (response.message.response.statusCode != 200) { + Limelog("RTSP SETUP streamid=control request failed: %d\n", + response.message.response.statusCode); + ret = response.message.response.statusCode; + goto Exit; + } + + freeMessage(&response); + } { RTSP_MESSAGE response;