diff --git a/limelight-common/SdpGenerator.c b/limelight-common/SdpGenerator.c index 9b71658..af93517 100644 --- a/limelight-common/SdpGenerator.c +++ b/limelight-common/SdpGenerator.c @@ -5,30 +5,7 @@ #define MAX_SDP_HEADER_LEN 128 #define MAX_SDP_TAIL_LEN 128 -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4996) -#endif - -static const char ATTRIB_X_NV_CALLBACKS [] = { - 0x50, 0x51, 0x49, 0x4a, 0x0d, - 0xad, 0x30, 0x4a, 0xf1, 0xbd, 0x30, 0x4a, 0xd5, - 0xac, 0x30, 0x4a, 0x21, 0xbc, 0x30, 0x4a, 0xc1, - 0xbb, 0x30, 0x4a, 0x7d, 0xbb, 0x30, 0x4a, 0x19, - 0xbb, 0x30, 0x4a, 0x00, 0x00, 0x00, 0x00 -}; - -static const char ATTRIB_X_NV_VIDEO_DECODER [] = { - 0x50, 0x51, 0x49, 0x4a, 0x65, 0xad, 0x30, 0x4a, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xac, 0x30, - 0x4a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4d, 0xad, 0x30, 0x4a -}; - -static const char ATTRIB_X_NV_AUDIO_RENDERER [] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; +#define RTSP_CLIENT_VERSION_S "10" static const int ATTRIB_X_NV_GENERAL_SERVERPORTS [] = { 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, @@ -146,193 +123,67 @@ static PSDP_OPTION getAttributesList(PSTREAM_CONFIGURATION streamConfig, struct PSDP_OPTION optionHead; int payloadInt; char payloadStr[64]; - void* payloadBinary; int err; optionHead = NULL; err = 0; - err |= addAttributeBinary(&optionHead, "x-nv-callbacks", - ATTRIB_X_NV_CALLBACKS, sizeof(ATTRIB_X_NV_CALLBACKS)); - err |= addAttributeBinary(&optionHead, "x-nv-videoDecoder", - ATTRIB_X_NV_VIDEO_DECODER, sizeof(ATTRIB_X_NV_VIDEO_DECODER)); - err |= addAttributeBinary(&optionHead, "x-nv-audioRenderer", - ATTRIB_X_NV_AUDIO_RENDERER, sizeof(ATTRIB_X_NV_AUDIO_RENDERER)); err |= addAttributeString(&optionHead, "x-nv-general.serverAddress", inet_ntoa(targetAddress)); err |= addAttributeBinary(&optionHead, "x-nv-general.serverPorts", ATTRIB_X_NV_GENERAL_SERVERPORTS, sizeof(ATTRIB_X_NV_GENERAL_SERVERPORTS)); - err |= addAttributeString(&optionHead, "x-nv-general.videoSyncAudioDelayAdjust", "10000"); - err |= addAttributeString(&optionHead, "x-nv-general.startTime", "0"); - payloadInt = 0xFFFFFFFF; + payloadInt = 0x42774141; err |= addAttributeBinary(&optionHead, "x-nv-general.featureFlags", &payloadInt, sizeof(payloadInt)); - err |= addAttributeString(&optionHead, "x-nv-general.userIdleWarningTimeout", "0"); - err |= addAttributeString(&optionHead, "x-nv-general.userIdleSessionTimeout", "0"); - err |= addAttributeString(&optionHead, "x-nv-general.serverCapture", "0"); - err |= addAttributeString(&optionHead, "x-nv-general.clientCapture", "0"); - err |= addAttributeString(&optionHead, "x-nv-general.rtpQueueMaxPackets", "16"); - err |= addAttributeString(&optionHead, "x-nv-general.rtpQueueMaxDurationMs", "40"); - err |= addAttributeString(&optionHead, "x-nv-general.useRtspClient", "257"); sprintf(payloadStr, "%d", streamConfig->width); err |= addAttributeString(&optionHead, "x-nv-video[0].clientViewportWd", payloadStr); sprintf(payloadStr, "%d", streamConfig->height); err |= addAttributeString(&optionHead, "x-nv-video[0].clientViewportHt", payloadStr); - err |= addAttributeString(&optionHead, "x-nv-video[0].adapterNumber", "0"); - sprintf(payloadStr, "%d", streamConfig->fps); err |= addAttributeString(&optionHead, "x-nv-video[0].maxFPS", payloadStr); - err |= addAttributeString(&optionHead, "x-nv-video[0].iFrameOnDemand", "1"); - - payloadInt = 1; + payloadInt = 0x41514120; err |= addAttributeBinary(&optionHead, - "x-nv-video[0].transferProtocol", &payloadInt, sizeof(payloadInt)); - if (streamConfig->height >= 1080 && streamConfig->fps >= 60) { - payloadInt = 4; - err |= addAttributeBinary(&optionHead, - "x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt)); - err |= addAttributeString(&optionHead, "x-nv-video[0].averageBitrate", "30"); - err |= addAttributeString(&optionHead, "x-nv-video[0].peakBitrate", "30"); - } - else { - payloadInt = 5; - err |= addAttributeBinary(&optionHead, - "x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt)); - err |= addAttributeString(&optionHead, "x-nv-video[0].averageBitrate", "7"); - err |= addAttributeString(&optionHead, "x-nv-video[0].peakBitrate", "7"); - } + "x-nv-video[1].transferProtocol", &payloadInt, sizeof(payloadInt)); + err |= addAttributeBinary(&optionHead, + "x-nv-video[2].transferProtocol", &payloadInt, sizeof(payloadInt)); + + payloadInt = 0x42414141; + err |= addAttributeBinary(&optionHead, + "x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt)); + err |= addAttributeBinary(&optionHead, + "x-nv-video[2].rateControlMode", &payloadInt, sizeof(payloadInt)); - err |= addAttributeString(&optionHead, "x-nv-video[0].gopLength", "60"); - err |= addAttributeString(&optionHead, "x-nv-video[0].vbvMultiplier", "100"); - err |= addAttributeString(&optionHead, "x-nv-video[0].slicesPerFrame", "4"); - err |= addAttributeString(&optionHead, "x-nv-video[0].numTemporalLayers", "0"); - sprintf(payloadStr, "%d", streamConfig->packetSize); - err |= addAttributeString(&optionHead, "x-nv-video[0].packetSize", payloadStr); - err |= addAttributeString(&optionHead, "x-nv-video[0].enableSubframeEncoding", "0"); - err |= addAttributeString(&optionHead, "x-nv-video[0].refPicInvalidation", "1"); - err |= addAttributeString(&optionHead, "x-nv-video[0].pingBackIntervalMs", "3000"); - err |= addAttributeString(&optionHead, "x-nv-video[0].pingBackTimeoutMs", "10000"); err |= addAttributeString(&optionHead, "x-nv-video[0].timeoutLengthMs", "7000"); - err |= addAttributeString(&optionHead, "x-nv-video[0].fullFrameAssembly", "1"); - err |= addAttributeString(&optionHead, "x-nv-video[0].decodeIncompleteFrames", "0"); - err |= addAttributeString(&optionHead, "x-nv-video[0].enableIntraRefresh", "0"); - err |= addAttributeString(&optionHead, "x-nv-video[0].enableLongTermReferences", "0"); - err |= addAttributeString(&optionHead, "x-nv-video[0].enableFrameRateCtrl", "0"); - err |= addAttributeString(&optionHead, "x-nv-video[0].rtpDynamicPort", "0"); err |= addAttributeString(&optionHead, "x-nv-video[0].framesWithInvalidRefThreshold", "0"); - err |= addAttributeString(&optionHead, "x-nv-video[0].consecutiveFrameLostThreshold", "0"); + - err |= addAttributeString(&optionHead, "x-nv-vqos[0].ts.enable", "0"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].ts.averageBitrate", "8"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].ts.maximumBitrate", "10"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.flags", "819"); // Bit 2 being set causes picture problems (should be 823) + // The low nibble of the high byte should be 0x9 but that causes video issues + // The bit 0x80 enables video scaling on packet loss which we can't support (for now) + err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.flags", "7011"); - // We clamp to min = max so manual bitrate settings take effect without time to scale up sprintf(payloadStr, "%d", streamConfig->bitrate); err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.maximumBitrate", payloadStr); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.minimumBitrate", payloadStr); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.statsTime", "50"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.zeroLossCount", "3000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.lossThreshold", "2"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.owdThreshold", "5000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.owdReference", "500"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.lossWaitTime", "75"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.rateDropMultiplier", "25"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.rateGainMultiplier", "10"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.maxFps", "60"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.minFps", "30"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.fpsThreshold", "3"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.jitterThreshold", "1000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.jitterWaitTime", "5000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.noJitterWaitTime", "5000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionEnableBitRatePercentThreshold", "110"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionEnableL1Threshold", "10"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionEnableL0Threshold", "6"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionDisableThreshold", "4"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionDisableWaitTime", "20000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionDisableWaitPercent", "100"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionLowerBoundRate", "1000"); - - if (streamConfig->height >= 1080) { - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionLowerBoundWidth", "1280"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionLowerBoundHeight", "720"); - } - else { - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionLowerBoundWidth", "720"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.earlyDetectionLowerBoundHeight", "480"); - } - - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.enableFlags", "3"); - - if (streamConfig->height >= 1080 && streamConfig->fps >= 60) { - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.lowBitrate30FpsThreshold", "5000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.lowBitrate60FpsThreshold", "5000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.highBitrateThreshold", "7000"); - } - else { - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.lowBitrate30FpsThreshold", "4000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.lowBitrate60FpsThreshold", "5000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.highBitrateThreshold", "6000"); - } - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.pf.bitrateStepSize", "1000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bn.notifyUpBoundThreshold", "40"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bn.notifyLowBoundThreshold", "25"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].bn.notifyWaitTime", "3000"); + // Since we can only deal with FEC data on a 1 packet frame, + // restrict FEC repair percentage to minimum so we get only 1 + // FEC packet per frame err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.enable", "1"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.numSrcPackets", "50"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.numOutPackets", "60"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.repairPercent", "20"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].pictureRefreshIntervalMs", "0"); + err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.repairPercent", "1"); + err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.repairMaxPercent", "1"); + err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.repairMinPercent", "1"); + err |= addAttributeString(&optionHead, "x-nv-vqos[0].videoQualityScoreUpdateTime", "5000"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].invalidateThreshold", "3"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].invalidateSkipPercentage", "10"); err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "7"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].videoQoSMaxRoundTripLatencyFrames", "12"); - err |= addAttributeString(&optionHead, "x-nv-vqos[0].videoQoSMaxConsecutiveDrops", "3"); - payloadInt = 1; - err |= addAttributeBinary(&optionHead, "x-nv-vqos[0].profile", &payloadInt, sizeof(payloadInt)); - - payloadInt = 1; - err |= addAttributeBinary(&optionHead, "x-nv-aqos.mode", &payloadInt, sizeof(payloadInt)); - err |= addAttributeString(&optionHead, "x-nv-aqos.enableAudioStats", "1"); - err |= addAttributeString(&optionHead, "x-nv-aqos.audioStatsUpdateIntervalMs", "70"); - err |= addAttributeString(&optionHead, "x-nv-aqos.enablePacketLossPercentage", "1"); - err |= addAttributeString(&optionHead, "x-nv-aqos.bitRate", "96000"); - err |= addAttributeString(&optionHead, "x-nv-aqos.packetDuration", "5"); - err |= addAttributeString(&optionHead, "x-nv-aqos.packetLossPercentageUpdateIntervalMs", "100"); - err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4"); - - err |= addAttributeString(&optionHead, "x-nv-runtime.recordClientStats", "8"); - err |= addAttributeString(&optionHead, "x-nv-runtime.recordServerStats", "0"); - err |= addAttributeString(&optionHead, "x-nv-runtime.clientNetworkCapture", "0"); - err |= addAttributeString(&optionHead, "x-nv-runtime.clientTraceCapture", "0"); - err |= addAttributeString(&optionHead, "x-nv-runtime.serverNetworkCapture", "0"); - err |= addAttributeString(&optionHead, "x-nv-runtime.serverTraceCapture", "0"); - - payloadInt = 0; - err |= addAttributeBinary(&optionHead, "x-nv-ri.protocol", &payloadInt, sizeof(payloadInt)); - err |= addAttributeString(&optionHead, "x-nv-ri.sendStatus", "0"); - payloadInt = 0; - err |= addAttributeBinary(&optionHead, "x-nv-ri.securityProtocol", &payloadInt, sizeof(payloadInt)); - payloadBinary = calloc(1, 0x20a); - if (payloadBinary == NULL) { - goto ExitFailure; - } - err |= addAttributeBinary(&optionHead, "x-nv-ri.secInfo", payloadBinary, 0x20a); - free(payloadBinary); - err |= addAttributeString(&optionHead, "x-nv-videoFrameDropIntervalNumber", "0"); - err |= addAttributeString(&optionHead, "x-nv-videoFrameDropContinualNumber", "0"); + err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "8"); if (err == 0) { return optionHead; } -ExitFailure: freeAttributeList(optionHead); return NULL; } @@ -340,7 +191,7 @@ ExitFailure: static int fillSdpHeader(char* buffer, struct in_addr targetAddress) { return sprintf(buffer, "v=0\r\n" - "o=android 0 9 IN IPv4 %s\r\n" + "o=android 0 "RTSP_CLIENT_VERSION_S" IN IPv4 %s\r\n" "s=NVIDIA Streaming Client\r\n", inet_ntoa(targetAddress)); } @@ -374,8 +225,4 @@ char* getSdpPayloadForStreamConfig(PSTREAM_CONFIGURATION streamConfig, struct in freeAttributeList(attributeList); *length = offset; return payload; -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif \ No newline at end of file +} \ No newline at end of file