From 41d823923b75a4e4c1d16657b75e7f41c335d2df Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 22 Jan 2015 16:55:08 -0500 Subject: [PATCH] Update for GFE 2.2.2+ --- limelight-common/ControlStream.c | 18 +++++----- limelight-common/Limelight-internal.h | 4 +++ limelight-common/RtspConnection.c | 4 --- limelight-common/SdpGenerator.c | 47 ++++--------------------- limelight-common/VideoStream.c | 49 --------------------------- 5 files changed, 20 insertions(+), 102 deletions(-) diff --git a/limelight-common/ControlStream.c b/limelight-common/ControlStream.c index 2166925..2a1bc91 100644 --- a/limelight-common/ControlStream.c +++ b/limelight-common/ControlStream.c @@ -20,21 +20,21 @@ static PCONNECTION_LISTENER_CALLBACKS listenerCallbacks; static int lossCountSinceLastReport = 0; static long currentFrame = 0; -#define PTYPE_START_STREAM_A 0x140b -#define PPAYLEN_START_STREAM_A 1 -static const char PPAYLOAD_START_STREAM_A[1] = { 0 }; +#define PTYPE_START_STREAM_A 0x0606 +#define PPAYLEN_START_STREAM_A 2 +static const char PPAYLOAD_START_STREAM_A[PPAYLEN_START_STREAM_A] = { 0, 0 }; -#define PTYPE_START_STREAM_B 0x1410 -#define PPAYLEN_START_STREAM_B 16 -static const int PPAYLOAD_START_STREAM_B[4] = { 0, 0, 0, 0xa }; // FIXME: Little endian +#define PTYPE_START_STREAM_B 0x0609 +#define PPAYLEN_START_STREAM_B 1 +static const char PPAYLOAD_START_STREAM_B[PPAYLEN_START_STREAM_B] = { 0 }; -#define PTYPE_RESYNC 0x1404 +#define PTYPE_RESYNC 0x0604 #define PPAYLEN_RESYNC 24 -#define PTYPE_LOSS_STATS 0x140c +#define PTYPE_LOSS_STATS 0x060a #define PPAYLEN_LOSS_STATS 32 -#define PTYPE_FRAME_STATS 0x1417 +#define PTYPE_FRAME_STATS 0x0611 #define PPAYLEN_FRAME_STATS 64 #define LOSS_REPORT_INTERVAL_MS 50 diff --git a/limelight-common/Limelight-internal.h b/limelight-common/Limelight-internal.h index c04b2a7..3490ae1 100644 --- a/limelight-common/Limelight-internal.h +++ b/limelight-common/Limelight-internal.h @@ -6,6 +6,10 @@ #include "PlatformThreads.h" #include "Video.h" +/* GFE 2.2.2+ RTSP/SDP version code */ +#define RTSP_CLIENT_VERSION 11 +#define RTSP_CLIENT_VERSION_S "11" + char* getSdpPayloadForStreamConfig(PSTREAM_CONFIGURATION streamConfig, struct in_addr targetAddress, int *length); int initializeControlStream(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks); diff --git a/limelight-common/RtspConnection.c b/limelight-common/RtspConnection.c index 7fb73d2..e651e4e 100644 --- a/limelight-common/RtspConnection.c +++ b/limelight-common/RtspConnection.c @@ -11,10 +11,6 @@ static char sessionIdString[16]; static int hasSessionId; static char responseBuffer[RTSP_MAX_RESP_SIZE]; -/* GFE 2.1.1 */ -#define RTSP_CLIENT_VERSION 10 -#define RTSP_CLIENT_VERSION_S "10" - /* Create RTSP Option */ static POPTION_ITEM createOptionItem(char* option, char* content) { diff --git a/limelight-common/SdpGenerator.c b/limelight-common/SdpGenerator.c index fbcb8d1..04edb23 100644 --- a/limelight-common/SdpGenerator.c +++ b/limelight-common/SdpGenerator.c @@ -5,8 +5,6 @@ #define MAX_SDP_HEADER_LEN 128 #define MAX_SDP_TAIL_LEN 128 -#define RTSP_CLIENT_VERSION_S "10" - typedef struct _SDP_OPTION { char name[MAX_OPTION_NAME_LEN+1]; void* payload; @@ -92,19 +90,14 @@ static int addAttributeString(PSDP_OPTION *head, char* name, const char* payload static PSDP_OPTION getAttributesList(PSTREAM_CONFIGURATION streamConfig, struct in_addr targetAddress) { PSDP_OPTION optionHead; - int payloadInt; - char payloadStr[64]; + char payloadStr[92]; int err; optionHead = NULL; - err = 0; - err |= addAttributeString(&optionHead, "x-nv-general.serverAddress", - inet_ntoa(targetAddress)); - - payloadInt = htonl(0x42774141); - err |= addAttributeBinary(&optionHead, - "x-nv-general.featureFlags", &payloadInt, sizeof(payloadInt)); + + sprintf(payloadStr, "rtsp://%s:48010", inet_ntoa(targetAddress)); + err |= addAttributeString(&optionHead, "x-nv-general.serverAddress", payloadStr); sprintf(payloadStr, "%d", streamConfig->width); err |= addAttributeString(&optionHead, "x-nv-video[0].clientViewportWd", payloadStr); @@ -117,26 +110,7 @@ static PSDP_OPTION getAttributesList(PSTREAM_CONFIGURATION streamConfig, struct sprintf(payloadStr, "%d", streamConfig->packetSize); err |= addAttributeString(&optionHead, "x-nv-video[0].packetSize", payloadStr); - payloadInt = htonl(0x41514141); - err |= addAttributeBinary(&optionHead, - "x-nv-video[0].transferProtocol", &payloadInt, sizeof(payloadInt)); - err |= addAttributeBinary(&optionHead, - "x-nv-video[1].transferProtocol", &payloadInt, sizeof(payloadInt)); - err |= addAttributeBinary(&optionHead, - "x-nv-video[2].transferProtocol", &payloadInt, sizeof(payloadInt)); - err |= addAttributeBinary(&optionHead, - "x-nv-video[3].transferProtocol", &payloadInt, sizeof(payloadInt)); - - payloadInt = htonl(0x42414141); - err |= addAttributeBinary(&optionHead, - "x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt)); - payloadInt = htonl(0x42514141); - err |= addAttributeBinary(&optionHead, - "x-nv-video[1].rateControlMode", &payloadInt, sizeof(payloadInt)); - err |= addAttributeBinary(&optionHead, - "x-nv-video[2].rateControlMode", &payloadInt, sizeof(payloadInt)); - err |= addAttributeBinary(&optionHead, - "x-nv-video[3].rateControlMode", &payloadInt, sizeof(payloadInt)); + err |= addAttributeString(&optionHead, "x-nv-video[0].rateControlMode", "4"); // FIXME: Remote optimizations if (streamConfig->bitrate <= 13000) { @@ -148,7 +122,7 @@ static PSDP_OPTION getAttributesList(PSTREAM_CONFIGURATION streamConfig, struct err |= addAttributeString(&optionHead, "x-nv-video[0].framesWithInvalidRefThreshold", "0"); // This flags value will mean that resolution won't change as bitrate falls - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.flags", "14083"); + err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.flags", "51"); // Lock the bitrate since we're not scaling resolution so the picture doesn't get too bad if (streamConfig->height >= 1080 && streamConfig->fps >= 60) { @@ -192,13 +166,6 @@ static PSDP_OPTION getAttributesList(PSTREAM_CONFIGURATION streamConfig, struct // FIXME: Remote optimizations err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "5"); - - err |= addAttributeString(&optionHead, "x-nv-vqos[0].videoQosMaxConsecutiveDrops", "0"); - err |= addAttributeString(&optionHead, "x-nv-vqos[1].videoQosMaxConsecutiveDrops", "0"); - err |= addAttributeString(&optionHead, "x-nv-vqos[2].videoQosMaxConsecutiveDrops", "0"); - err |= addAttributeString(&optionHead, "x-nv-vqos[3].videoQosMaxConsecutiveDrops", "0"); - - // FIXME: Remote optimizations err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4"); if (err == 0) { @@ -221,7 +188,7 @@ static int fillSdpHeader(char* buffer, struct in_addr targetAddress) { static int fillSdpTail(char* buffer) { return sprintf(buffer, "t=0 0\r\n" - "m=video 47996 \r\n"); + "m=video 47998 \r\n"); } /* Get the SDP attributes for the stream config */ diff --git a/limelight-common/VideoStream.c b/limelight-common/VideoStream.c index 55c5072..18f70fe 100644 --- a/limelight-common/VideoStream.c +++ b/limelight-common/VideoStream.c @@ -6,7 +6,6 @@ #define FIRST_FRAME_MAX 1500 #define RTP_PORT 47998 -#define FIRST_FRAME_PORT 47996 static DECODER_RENDERER_CALLBACKS callbacks; static STREAM_CONFIGURATION configuration; @@ -14,7 +13,6 @@ static IP_ADDRESS remoteHost; static PCONNECTION_LISTENER_CALLBACKS listenerCallbacks; static SOCKET rtpSocket = INVALID_SOCKET; -static SOCKET firstFrameSocket = INVALID_SOCKET; static PLT_THREAD udpPingThread; static PLT_THREAD receiveThread; @@ -110,37 +108,6 @@ static void DecoderThreadProc(void* context) { } } -/* Read the first frame of the video stream */ -int readFirstFrame(void) { - char* firstFrame; - SOCK_RET err; - int offset = 0; - - firstFrame = (char*) malloc(FIRST_FRAME_MAX); - if (firstFrame == NULL) { - return -1; - } - - Limelog("Waiting for first frame\n"); - for (;;) { - err = recv(firstFrameSocket, &firstFrame[offset], FIRST_FRAME_MAX - offset, 0); - if (err <= 0) { - break; - } - - offset += err; - } - Limelog("Read %d bytes\n", offset); - - // We can just ignore this data for now. It's the act of reading - // it that matters. If this changes, we'll need to move this call before - // starting the receive thread to avoid state corruption in the depacketizer. - - free(firstFrame); - - return 0; -} - /* Terminate the video stream */ void stopVideoStream(void) { callbacks.stop(); @@ -149,10 +116,6 @@ void stopVideoStream(void) { PltInterruptThread(&receiveThread); PltInterruptThread(&decoderThread); - if (firstFrameSocket != INVALID_SOCKET) { - closesocket(firstFrameSocket); - firstFrameSocket = INVALID_SOCKET; - } if (rtpSocket != INVALID_SOCKET) { closesocket(rtpSocket); rtpSocket = INVALID_SOCKET; @@ -193,21 +156,9 @@ int startVideoStream(void* rendererContext, int drFlags) { return err; } - // Connect this socket to open port 47998 for our ping thread - firstFrameSocket = connectTcpSocket(remoteHost, FIRST_FRAME_PORT); - if (firstFrameSocket == INVALID_SOCKET) { - return LastSocketError(); - } - // Start pinging before reading the first frame so GFE knows where // to send UDP data err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread); - if (err != 0) { - return err; - } - - // Read the first frame to start the flow of video - err = readFirstFrame(); if (err != 0) { return err; }