API update to provide enough information to support GFE 3.0.7

This commit is contained in:
Cameron Gutman 2016-10-05 17:23:59 -07:00
parent ed2c4e716b
commit f57bd745b4
10 changed files with 103 additions and 48 deletions

View File

@ -11,7 +11,7 @@ static long terminationCallbackErrorCode;
char* RemoteAddrString; char* RemoteAddrString;
struct sockaddr_storage RemoteAddr; struct sockaddr_storage RemoteAddr;
SOCKADDR_LEN RemoteAddrLen; SOCKADDR_LEN RemoteAddrLen;
int ServerMajorVersion; int AppVersionQuad[4];
STREAM_CONFIGURATION StreamConfig; STREAM_CONFIGURATION StreamConfig;
CONNECTION_LISTENER_CALLBACKS ListenerCallbacks; CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
DECODER_RENDERER_CALLBACKS VideoCallbacks; DECODER_RENDERER_CALLBACKS VideoCallbacks;
@ -206,15 +206,20 @@ static int resolveHostName(const char* host)
} }
// Starts the connection to the streaming machine // Starts the connection to the streaming machine
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks, int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags) {
void* renderContext, int drFlags, int _serverMajorVersion) {
int err; int err;
NegotiatedVideoFormat = 0; NegotiatedVideoFormat = 0;
ServerMajorVersion = _serverMajorVersion;
memcpy(&StreamConfig, streamConfig, sizeof(StreamConfig)); memcpy(&StreamConfig, streamConfig, sizeof(StreamConfig));
RemoteAddrString = strdup(host); RemoteAddrString = strdup(serverInfo->address);
// Extract the appversion from the supplied string
if (extractVersionQuadFromString(serverInfo->serverInfoAppVersion,
AppVersionQuad) < 0) {
Limelog("Invalid appversion string: %s\n", serverInfo->serverInfoAppVersion);
return -1;
}
// Replace missing callbacks with placeholders // Replace missing callbacks with placeholders
fixupMissingCallbacks(&drCallbacks, &arCallbacks, &clCallbacks); fixupMissingCallbacks(&drCallbacks, &arCallbacks, &clCallbacks);
@ -244,7 +249,7 @@ int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCON
Limelog("Resolving host name..."); Limelog("Resolving host name...");
ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION); ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION);
err = resolveHostName(host); err = resolveHostName(serverInfo->address);
if (err != 0) { if (err != 0) {
Limelog("failed: %d\n", err); Limelog("failed: %d\n", err);
ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err); ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err);

View File

@ -151,17 +151,17 @@ int initializeControlStream(void) {
PltCreateEvent(&invalidateRefFramesEvent); PltCreateEvent(&invalidateRefFramesEvent);
LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20); LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20);
if (ServerMajorVersion == 3) { if (AppVersionQuad[0] == 3) {
packetTypes = (short*)packetTypesGen3; packetTypes = (short*)packetTypesGen3;
payloadLengths = (short*)payloadLengthsGen3; payloadLengths = (short*)payloadLengthsGen3;
preconstructedPayloads = (char**)preconstructedPayloadsGen3; preconstructedPayloads = (char**)preconstructedPayloadsGen3;
} }
else if (ServerMajorVersion == 4) { else if (AppVersionQuad[0] == 4) {
packetTypes = (short*)packetTypesGen4; packetTypes = (short*)packetTypesGen4;
payloadLengths = (short*)payloadLengthsGen4; payloadLengths = (short*)payloadLengthsGen4;
preconstructedPayloads = (char**)preconstructedPayloadsGen4; preconstructedPayloads = (char**)preconstructedPayloadsGen4;
} }
else if (ServerMajorVersion == 5) { else if (AppVersionQuad[0] == 5) {
packetTypes = (short*)packetTypesGen5; packetTypes = (short*)packetTypesGen5;
payloadLengths = (short*)payloadLengthsGen5; payloadLengths = (short*)payloadLengthsGen5;
preconstructedPayloads = (char**)preconstructedPayloadsGen5; preconstructedPayloads = (char**)preconstructedPayloadsGen5;
@ -290,7 +290,7 @@ static int sendMessageEnet(short ptype, short paylen, const void* payload) {
ENetEvent event; ENetEvent event;
int err; int err;
LC_ASSERT(ServerMajorVersion >= 5); LC_ASSERT(AppVersionQuad[0] >= 5);
// We may be trying to disconnect, so our peer could be gone. // We may be trying to disconnect, so our peer could be gone.
// This check is safe because we're guaranteed to be holding enetMutex. // This check is safe because we're guaranteed to be holding enetMutex.
@ -347,7 +347,7 @@ static int sendMessageTcp(short ptype, short paylen, const void* payload) {
PNVCTL_TCP_PACKET_HEADER packet; PNVCTL_TCP_PACKET_HEADER packet;
SOCK_RET err; SOCK_RET err;
LC_ASSERT(ServerMajorVersion < 5); LC_ASSERT(AppVersionQuad[0] < 5);
packet = malloc(sizeof(*packet) + paylen); packet = malloc(sizeof(*packet) + paylen);
if (packet == NULL) { if (packet == NULL) {
@ -373,7 +373,7 @@ static int sendMessageAndForget(short ptype, short paylen, const void* payload)
// Unlike regular sockets, ENet sockets aren't safe to invoke from multiple // Unlike regular sockets, ENet sockets aren't safe to invoke from multiple
// threads at once. We have to synchronize them with a lock. // threads at once. We have to synchronize them with a lock.
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
PltLockMutex(&enetMutex); PltLockMutex(&enetMutex);
ret = sendMessageEnet(ptype, paylen, payload); ret = sendMessageEnet(ptype, paylen, payload);
PltUnlockMutex(&enetMutex); PltUnlockMutex(&enetMutex);
@ -387,7 +387,7 @@ static int sendMessageAndForget(short ptype, short paylen, const void* payload)
static int sendMessageAndDiscardReply(short ptype, short paylen, const void* payload) { static int sendMessageAndDiscardReply(short ptype, short paylen, const void* payload) {
// Discard the response // Discard the response
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
ENetEvent event; ENetEvent event;
PltLockMutex(&enetMutex); PltLockMutex(&enetMutex);
@ -469,7 +469,7 @@ static void lossStatsThreadFunc(void* context) {
static void requestIdrFrame(void) { static void requestIdrFrame(void) {
long long payload[3]; long long payload[3];
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
// Form the payload // Form the payload
if (lastSeenFrame < 0x20) { if (lastSeenFrame < 0x20) {
payload[0] = 0; payload[0] = 0;
@ -610,7 +610,7 @@ int stopControlStream(void) {
// Called by the input stream to send a packet for Gen 5+ servers // Called by the input stream to send a packet for Gen 5+ servers
int sendInputPacketOnControlStream(unsigned char* data, int length) { int sendInputPacketOnControlStream(unsigned char* data, int length) {
LC_ASSERT(ServerMajorVersion >= 5); LC_ASSERT(AppVersionQuad[0] >= 5);
// Send the input data (no reply expected) // Send the input data (no reply expected)
if (sendMessageAndForget(packetTypes[IDX_INPUT_DATA], length, data) == 0) { if (sendMessageAndForget(packetTypes[IDX_INPUT_DATA], length, data) == 0) {
@ -626,7 +626,7 @@ int startControlStream(void) {
PltCreateMutex(&enetMutex); PltCreateMutex(&enetMutex);
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
ENetAddress address; ENetAddress address;
ENetEvent event; ENetEvent event;

View File

@ -116,7 +116,7 @@ static int encryptData(const unsigned char* plaintext, int plaintextLen,
int ret; int ret;
int len; int len;
if (ServerMajorVersion >= 7) { if (AppVersionQuad[0] >= 7) {
EVP_CIPHER_CTX_init(&cipherContext); EVP_CIPHER_CTX_init(&cipherContext);
// Gen 7 servers use 128-bit AES GCM // Gen 7 servers use 128-bit AES GCM
@ -332,7 +332,7 @@ static void inputSendThreadProc(void* context) {
encryptedLengthPrefix = htonl((unsigned long)encryptedSize); encryptedLengthPrefix = htonl((unsigned long)encryptedSize);
memcpy(&encryptedBuffer[0], &encryptedLengthPrefix, 4); memcpy(&encryptedBuffer[0], &encryptedLengthPrefix, 4);
if (ServerMajorVersion < 5) { if (AppVersionQuad[0] < 5) {
// Send the encrypted payload // Send the encrypted payload
err = send(inputSock, (const char*) encryptedBuffer, err = send(inputSock, (const char*) encryptedBuffer,
(int) (encryptedSize + sizeof(encryptedLengthPrefix)), 0); (int) (encryptedSize + sizeof(encryptedLengthPrefix)), 0);
@ -347,7 +347,7 @@ static void inputSendThreadProc(void* context) {
// bytes of ciphertext in the most recent game controller packet as the IV for // bytes of ciphertext in the most recent game controller packet as the IV for
// future encryption. I think it may be a buffer overrun on their end but we'll have // future encryption. I think it may be a buffer overrun on their end but we'll have
// to mimic it to work correctly. // to mimic it to work correctly.
if (ServerMajorVersion >= 7 && encryptedSize >= 16 + sizeof(currentAesIv)) { if (AppVersionQuad[0] >= 7 && encryptedSize >= 16 + sizeof(currentAesIv)) {
memcpy(currentAesIv, memcpy(currentAesIv,
&encryptedBuffer[4 + encryptedSize - sizeof(currentAesIv)], &encryptedBuffer[4 + encryptedSize - sizeof(currentAesIv)],
sizeof(currentAesIv)); sizeof(currentAesIv));
@ -369,7 +369,7 @@ int startInputStream(void) {
int err; int err;
// After Gen 5, we send input on the control stream // After Gen 5, we send input on the control stream
if (ServerMajorVersion < 5) { if (AppVersionQuad[0] < 5) {
inputSock = connectTcpSocket(&RemoteAddr, RemoteAddrLen, inputSock = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
35043, INPUT_STREAM_TIMEOUT_SEC); 35043, INPUT_STREAM_TIMEOUT_SEC);
if (inputSock == INVALID_SOCKET) { if (inputSock == INVALID_SOCKET) {
@ -426,7 +426,7 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) {
holder->packet.mouseMove.header.packetType = htonl(PACKET_TYPE_MOUSE_MOVE); holder->packet.mouseMove.header.packetType = htonl(PACKET_TYPE_MOUSE_MOVE);
holder->packet.mouseMove.magic = MOUSE_MOVE_MAGIC; holder->packet.mouseMove.magic = MOUSE_MOVE_MAGIC;
// On Gen 5 servers, the header code is incremented by one // On Gen 5 servers, the header code is incremented by one
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
holder->packet.mouseMove.magic++; holder->packet.mouseMove.magic++;
} }
holder->packet.mouseMove.deltaX = htons(deltaX); holder->packet.mouseMove.deltaX = htons(deltaX);
@ -457,7 +457,7 @@ int LiSendMouseButtonEvent(char action, int button) {
holder->packetLength = sizeof(NV_MOUSE_BUTTON_PACKET); holder->packetLength = sizeof(NV_MOUSE_BUTTON_PACKET);
holder->packet.mouseButton.header.packetType = htonl(PACKET_TYPE_MOUSE_BUTTON); holder->packet.mouseButton.header.packetType = htonl(PACKET_TYPE_MOUSE_BUTTON);
holder->packet.mouseButton.action = action; holder->packet.mouseButton.action = action;
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
holder->packet.mouseButton.action++; holder->packet.mouseButton.action++;
} }
holder->packet.mouseButton.button = htonl(button); holder->packet.mouseButton.button = htonl(button);
@ -515,7 +515,7 @@ static int sendControllerEventInternal(short controllerNumber, short buttonFlags
return -1; return -1;
} }
if (ServerMajorVersion == 3) { if (AppVersionQuad[0] == 3) {
// Generation 3 servers don't support multiple controllers so we send // Generation 3 servers don't support multiple controllers so we send
// the legacy packet // the legacy packet
holder->packetLength = sizeof(NV_CONTROLLER_PACKET); holder->packetLength = sizeof(NV_CONTROLLER_PACKET);
@ -538,7 +538,7 @@ static int sendControllerEventInternal(short controllerNumber, short buttonFlags
holder->packet.multiController.header.packetType = htonl(PACKET_TYPE_MULTI_CONTROLLER); holder->packet.multiController.header.packetType = htonl(PACKET_TYPE_MULTI_CONTROLLER);
holder->packet.multiController.headerA = MC_HEADER_A; holder->packet.multiController.headerA = MC_HEADER_A;
// On Gen 5 servers, the header code is decremented by one // On Gen 5 servers, the header code is decremented by one
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
holder->packet.multiController.headerA--; holder->packet.multiController.headerA--;
} }
holder->packet.multiController.headerB = MC_HEADER_B; holder->packet.multiController.headerB = MC_HEADER_B;
@ -598,7 +598,7 @@ int LiSendScrollEvent(signed char scrollClicks) {
holder->packet.scroll.header.packetType = htonl(PACKET_TYPE_SCROLL); holder->packet.scroll.header.packetType = htonl(PACKET_TYPE_SCROLL);
holder->packet.scroll.magicA = MAGIC_A; holder->packet.scroll.magicA = MAGIC_A;
// On Gen 5 servers, the header code is incremented by one // On Gen 5 servers, the header code is incremented by one
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
holder->packet.scroll.magicA++; holder->packet.scroll.magicA++;
} }
holder->packet.scroll.zero1 = 0; holder->packet.scroll.zero1 = 0;

View File

@ -12,7 +12,7 @@
extern char* RemoteAddrString; extern char* RemoteAddrString;
extern struct sockaddr_storage RemoteAddr; extern struct sockaddr_storage RemoteAddr;
extern SOCKADDR_LEN RemoteAddrLen; extern SOCKADDR_LEN RemoteAddrLen;
extern int ServerMajorVersion; extern int AppVersionQuad[4];
extern STREAM_CONFIGURATION StreamConfig; extern STREAM_CONFIGURATION StreamConfig;
extern CONNECTION_LISTENER_CALLBACKS ListenerCallbacks; extern CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
extern DECODER_RENDERER_CALLBACKS VideoCallbacks; extern DECODER_RENDERER_CALLBACKS VideoCallbacks;
@ -21,6 +21,7 @@ extern int NegotiatedVideoFormat;
int isBeforeSignedInt(int numA, int numB, int ambiguousCase); int isBeforeSignedInt(int numA, int numB, int ambiguousCase);
int serviceEnetHost(ENetHost* client, ENetEvent* event, enet_uint32 timeoutMs); int serviceEnetHost(ENetHost* client, ENetEvent* event, enet_uint32 timeoutMs);
int extractVersionQuadFromString(const char* string, int* quad);
void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks, void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS* drCallbacks, PAUDIO_RENDERER_CALLBACKS* arCallbacks,
PCONNECTION_LISTENER_CALLBACKS* clCallbacks); PCONNECTION_LISTENER_CALLBACKS* clCallbacks);

View File

@ -214,15 +214,28 @@ typedef struct _CONNECTION_LISTENER_CALLBACKS {
// Use this function to zero the connection callbacks when allocated on the stack or heap // Use this function to zero the connection callbacks when allocated on the stack or heap
void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks); void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks);
typedef struct _SERVER_INFORMATION {
// Server host name or IP address in text form
const char* address;
// Text inside 'appversion' tag in /serverinfo
const char* serverInfoAppVersion;
// Text inside 'GfeVersion' tag in /serverinfo (if present)
const char* serverInfoGfeVersion;
} SERVER_INFORMATION, *PSERVER_INFORMATION;
// Use this function to zero the server information when allocated on the stack or heap
void LiInitializeServerInformation(PSERVER_INFORMATION serverInfo);
// This function begins streaming. // This function begins streaming.
// //
// Callbacks are all optional. Pass NULL for individual callbacks within each struct or pass NULL for the entire struct // Callbacks are all optional. Pass NULL for individual callbacks within each struct or pass NULL for the entire struct
// to use the defaults for all callbacks. // to use the defaults for all callbacks.
// //
// _serverMajorVersion is the major version number of the 'appversion' tag in the /serverinfo request int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
// PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags);
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags, int _serverMajorVersion);
// This function stops streaming. // This function stops streaming.
void LiStopConnection(void); void LiStopConnection(void);

View File

@ -37,6 +37,38 @@ int isBeforeSignedInt(int numA, int numB, int ambiguousCase) {
} }
} }
int extractVersionQuadFromString(const char* string, int* quad) {
char versionString[128];
char* nextDot;
char* nextNumber;
int i;
strcpy(versionString, string);
nextNumber = versionString;
for (i = 0; i < 4; i++) {
if (i == 3) {
nextDot = strchr(nextNumber, '\0');
}
else {
nextDot = strchr(nextNumber, '.');
}
if (nextDot == NULL) {
return -1;
}
// Cut the string off at the next dot
*nextDot = '\0';
quad[i] = atoi(nextNumber);
// Move on to the next segment
nextNumber = nextDot + 1;
}
return 0;
}
void LiInitializeStreamConfiguration(PSTREAM_CONFIGURATION streamConfig) { void LiInitializeStreamConfiguration(PSTREAM_CONFIGURATION streamConfig) {
memset(streamConfig, 0, sizeof(*streamConfig)); memset(streamConfig, 0, sizeof(*streamConfig));
} }
@ -52,3 +84,7 @@ void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks) {
void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks) { void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks) {
memset(clCallbacks, 0, sizeof(*clCallbacks)); memset(clCallbacks, 0, sizeof(*clCallbacks));
} }
void LiInitializeServerInformation(PSERVER_INFORMATION serverInfo) {
memset(serverInfo, 0, sizeof(*serverInfo));
}

View File

@ -273,7 +273,7 @@ Exit:
static int transactRtspMessage(PRTSP_MESSAGE request, PRTSP_MESSAGE response, int expectingPayload, int* error) { static int transactRtspMessage(PRTSP_MESSAGE request, PRTSP_MESSAGE response, int expectingPayload, int* error) {
// Gen 5+ does RTSP over ENet not TCP // Gen 5+ does RTSP over ENet not TCP
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
return transactRtspMessageEnet(request, response, expectingPayload, error); return transactRtspMessageEnet(request, response, expectingPayload, error);
} }
else { else {
@ -349,7 +349,7 @@ static int setupStream(PRTSP_MESSAGE response, char* target, int* error) {
} }
} }
if (ServerMajorVersion >= 6) { if (AppVersionQuad[0] >= 6) {
// It looks like GFE doesn't care what we say our port is but // 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 // we need to give it some port to successfully complete the
// handshake process. // handshake process.
@ -446,7 +446,7 @@ int performRtspHandshake(void) {
currentSeqNumber = 1; currentSeqNumber = 1;
hasSessionId = 0; hasSessionId = 0;
switch (ServerMajorVersion) { switch (AppVersionQuad[0]) {
case 3: case 3:
rtspClientVersion = 10; rtspClientVersion = 10;
break; break;
@ -467,7 +467,7 @@ int performRtspHandshake(void) {
} }
// Gen 5 servers use ENet to do the RTSP handshake // Gen 5 servers use ENet to do the RTSP handshake
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
ENetAddress address; ENetAddress address;
ENetEvent event; ENetEvent event;
@ -562,7 +562,7 @@ int performRtspHandshake(void) {
int error = -1; int error = -1;
if (!setupStream(&response, if (!setupStream(&response,
ServerMajorVersion >= 5 ? "streamid=audio/0/0" : "streamid=audio", AppVersionQuad[0] >= 5 ? "streamid=audio/0/0" : "streamid=audio",
&error)) { &error)) {
Limelog("RTSP SETUP streamid=audio request failed: %d\n", error); Limelog("RTSP SETUP streamid=audio request failed: %d\n", error);
ret = error; ret = error;
@ -594,7 +594,7 @@ int performRtspHandshake(void) {
int error = -1; int error = -1;
if (!setupStream(&response, if (!setupStream(&response,
ServerMajorVersion >= 5 ? "streamid=video/0/0" : "streamid=video", AppVersionQuad[0] >= 5 ? "streamid=video/0/0" : "streamid=video",
&error)) { &error)) {
Limelog("RTSP SETUP streamid=video request failed: %d\n", error); Limelog("RTSP SETUP streamid=video request failed: %d\n", error);
ret = error; ret = error;
@ -611,7 +611,7 @@ int performRtspHandshake(void) {
freeMessage(&response); freeMessage(&response);
} }
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
RTSP_MESSAGE response; RTSP_MESSAGE response;
int error = -1; int error = -1;
@ -695,7 +695,7 @@ int performRtspHandshake(void) {
Exit: Exit:
// Cleanup the ENet stuff // Cleanup the ENet stuff
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
if (peer != NULL) { if (peer != NULL) {
enet_peer_disconnect_now(peer, 0); enet_peer_disconnect_now(peer, 0);
peer = NULL; peer = NULL;

View File

@ -185,7 +185,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
err |= addAttributeString(&optionHead, "x-nv-video[0].framesWithInvalidRefThreshold", "0"); err |= addAttributeString(&optionHead, "x-nv-video[0].framesWithInvalidRefThreshold", "0");
sprintf(payloadStr, "%d", StreamConfig.bitrate); sprintf(payloadStr, "%d", StreamConfig.bitrate);
if (ServerMajorVersion >= 5) { if (AppVersionQuad[0] >= 5) {
err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.minimumBitrateKbps", payloadStr); err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.minimumBitrateKbps", payloadStr);
err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.maximumBitrateKbps", payloadStr); err |= addAttributeString(&optionHead, "x-nv-vqos[0].bw.maximumBitrateKbps", payloadStr);
} }
@ -219,17 +219,17 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4"); err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4");
} }
if (ServerMajorVersion == 3) { if (AppVersionQuad[0] == 3) {
err |= addGen3Options(&optionHead, urlSafeAddr); err |= addGen3Options(&optionHead, urlSafeAddr);
} }
else if (ServerMajorVersion == 4) { else if (AppVersionQuad[0] == 4) {
err |= addGen4Options(&optionHead, urlSafeAddr); err |= addGen4Options(&optionHead, urlSafeAddr);
} }
else { else {
err |= addGen5Options(&optionHead); err |= addGen5Options(&optionHead);
} }
if (ServerMajorVersion >= 4) { if (AppVersionQuad[0] >= 4) {
if (NegotiatedVideoFormat == VIDEO_FORMAT_H265) { if (NegotiatedVideoFormat == VIDEO_FORMAT_H265) {
err |= addAttributeString(&optionHead, "x-nv-clientSupportHevc", "1"); err |= addAttributeString(&optionHead, "x-nv-clientSupportHevc", "1");
err |= addAttributeString(&optionHead, "x-nv-vqos[0].bitStreamFormat", "1"); err |= addAttributeString(&optionHead, "x-nv-vqos[0].bitStreamFormat", "1");
@ -298,7 +298,7 @@ static int fillSdpTail(char* buffer) {
return sprintf(buffer, return sprintf(buffer,
"t=0 0\r\n" "t=0 0\r\n"
"m=video %d \r\n", "m=video %d \r\n",
ServerMajorVersion < 4 ? 47996 : 47998); AppVersionQuad[0] < 4 ? 47996 : 47998);
} }
// Get the SDP attributes for the stream config // Get the SDP attributes for the stream config

View File

@ -507,7 +507,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
lastPacketInStream = streamPacketIndex; lastPacketInStream = streamPacketIndex;
// If this is the first packet, skip the frame header (if one exists) // If this is the first packet, skip the frame header (if one exists)
if (firstPacket && ServerMajorVersion >= 5) { if (firstPacket && AppVersionQuad[0] >= 5) {
currentPos.offset += 8; currentPos.offset += 8;
currentPos.length -= 8; currentPos.length -= 8;
} }

View File

@ -218,7 +218,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
} }
} }
if (ServerMajorVersion == 3) { if (AppVersionQuad[0] == 3) {
// Connect this socket to open port 47998 for our ping thread // Connect this socket to open port 47998 for our ping thread
firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen, firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC); FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC);
@ -234,7 +234,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
return err; return err;
} }
if (ServerMajorVersion == 3) { if (AppVersionQuad[0] == 3) {
// Read the first frame to start the flow of video // Read the first frame to start the flow of video
err = readFirstFrame(); err = readFirstFrame();
if (err != 0) { if (err != 0) {