mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-18 01:15:46 +00:00
API update to provide enough information to support GFE 3.0.7
This commit is contained in:
parent
ed2c4e716b
commit
f57bd745b4
@ -11,7 +11,7 @@ static long terminationCallbackErrorCode;
|
||||
char* RemoteAddrString;
|
||||
struct sockaddr_storage RemoteAddr;
|
||||
SOCKADDR_LEN RemoteAddrLen;
|
||||
int ServerMajorVersion;
|
||||
int AppVersionQuad[4];
|
||||
STREAM_CONFIGURATION StreamConfig;
|
||||
CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
|
||||
DECODER_RENDERER_CALLBACKS VideoCallbacks;
|
||||
@ -206,15 +206,20 @@ static int resolveHostName(const char* host)
|
||||
}
|
||||
|
||||
// Starts the connection to the streaming machine
|
||||
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) {
|
||||
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 err;
|
||||
|
||||
NegotiatedVideoFormat = 0;
|
||||
ServerMajorVersion = _serverMajorVersion;
|
||||
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
|
||||
fixupMissingCallbacks(&drCallbacks, &arCallbacks, &clCallbacks);
|
||||
@ -244,7 +249,7 @@ int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCON
|
||||
|
||||
Limelog("Resolving host name...");
|
||||
ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION);
|
||||
err = resolveHostName(host);
|
||||
err = resolveHostName(serverInfo->address);
|
||||
if (err != 0) {
|
||||
Limelog("failed: %d\n", err);
|
||||
ListenerCallbacks.stageFailed(STAGE_NAME_RESOLUTION, err);
|
||||
|
@ -151,17 +151,17 @@ int initializeControlStream(void) {
|
||||
PltCreateEvent(&invalidateRefFramesEvent);
|
||||
LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20);
|
||||
|
||||
if (ServerMajorVersion == 3) {
|
||||
if (AppVersionQuad[0] == 3) {
|
||||
packetTypes = (short*)packetTypesGen3;
|
||||
payloadLengths = (short*)payloadLengthsGen3;
|
||||
preconstructedPayloads = (char**)preconstructedPayloadsGen3;
|
||||
}
|
||||
else if (ServerMajorVersion == 4) {
|
||||
else if (AppVersionQuad[0] == 4) {
|
||||
packetTypes = (short*)packetTypesGen4;
|
||||
payloadLengths = (short*)payloadLengthsGen4;
|
||||
preconstructedPayloads = (char**)preconstructedPayloadsGen4;
|
||||
}
|
||||
else if (ServerMajorVersion == 5) {
|
||||
else if (AppVersionQuad[0] == 5) {
|
||||
packetTypes = (short*)packetTypesGen5;
|
||||
payloadLengths = (short*)payloadLengthsGen5;
|
||||
preconstructedPayloads = (char**)preconstructedPayloadsGen5;
|
||||
@ -290,7 +290,7 @@ static int sendMessageEnet(short ptype, short paylen, const void* payload) {
|
||||
ENetEvent event;
|
||||
int err;
|
||||
|
||||
LC_ASSERT(ServerMajorVersion >= 5);
|
||||
LC_ASSERT(AppVersionQuad[0] >= 5);
|
||||
|
||||
// We may be trying to disconnect, so our peer could be gone.
|
||||
// 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;
|
||||
SOCK_RET err;
|
||||
|
||||
LC_ASSERT(ServerMajorVersion < 5);
|
||||
LC_ASSERT(AppVersionQuad[0] < 5);
|
||||
|
||||
packet = malloc(sizeof(*packet) + paylen);
|
||||
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
|
||||
// threads at once. We have to synchronize them with a lock.
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
PltLockMutex(&enetMutex);
|
||||
ret = sendMessageEnet(ptype, paylen, payload);
|
||||
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) {
|
||||
// Discard the response
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
ENetEvent event;
|
||||
|
||||
PltLockMutex(&enetMutex);
|
||||
@ -469,7 +469,7 @@ static void lossStatsThreadFunc(void* context) {
|
||||
static void requestIdrFrame(void) {
|
||||
long long payload[3];
|
||||
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
// Form the payload
|
||||
if (lastSeenFrame < 0x20) {
|
||||
payload[0] = 0;
|
||||
@ -610,7 +610,7 @@ int stopControlStream(void) {
|
||||
|
||||
// Called by the input stream to send a packet for Gen 5+ servers
|
||||
int sendInputPacketOnControlStream(unsigned char* data, int length) {
|
||||
LC_ASSERT(ServerMajorVersion >= 5);
|
||||
LC_ASSERT(AppVersionQuad[0] >= 5);
|
||||
|
||||
// Send the input data (no reply expected)
|
||||
if (sendMessageAndForget(packetTypes[IDX_INPUT_DATA], length, data) == 0) {
|
||||
@ -626,7 +626,7 @@ int startControlStream(void) {
|
||||
|
||||
PltCreateMutex(&enetMutex);
|
||||
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
ENetAddress address;
|
||||
ENetEvent event;
|
||||
|
||||
|
@ -116,7 +116,7 @@ static int encryptData(const unsigned char* plaintext, int plaintextLen,
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
if (ServerMajorVersion >= 7) {
|
||||
if (AppVersionQuad[0] >= 7) {
|
||||
EVP_CIPHER_CTX_init(&cipherContext);
|
||||
|
||||
// Gen 7 servers use 128-bit AES GCM
|
||||
@ -332,7 +332,7 @@ static void inputSendThreadProc(void* context) {
|
||||
encryptedLengthPrefix = htonl((unsigned long)encryptedSize);
|
||||
memcpy(&encryptedBuffer[0], &encryptedLengthPrefix, 4);
|
||||
|
||||
if (ServerMajorVersion < 5) {
|
||||
if (AppVersionQuad[0] < 5) {
|
||||
// Send the encrypted payload
|
||||
err = send(inputSock, (const char*) encryptedBuffer,
|
||||
(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
|
||||
// future encryption. I think it may be a buffer overrun on their end but we'll have
|
||||
// to mimic it to work correctly.
|
||||
if (ServerMajorVersion >= 7 && encryptedSize >= 16 + sizeof(currentAesIv)) {
|
||||
if (AppVersionQuad[0] >= 7 && encryptedSize >= 16 + sizeof(currentAesIv)) {
|
||||
memcpy(currentAesIv,
|
||||
&encryptedBuffer[4 + encryptedSize - sizeof(currentAesIv)],
|
||||
sizeof(currentAesIv));
|
||||
@ -369,7 +369,7 @@ int startInputStream(void) {
|
||||
int err;
|
||||
|
||||
// After Gen 5, we send input on the control stream
|
||||
if (ServerMajorVersion < 5) {
|
||||
if (AppVersionQuad[0] < 5) {
|
||||
inputSock = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
|
||||
35043, INPUT_STREAM_TIMEOUT_SEC);
|
||||
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.magic = MOUSE_MOVE_MAGIC;
|
||||
// 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.deltaX = htons(deltaX);
|
||||
@ -457,7 +457,7 @@ int LiSendMouseButtonEvent(char action, int button) {
|
||||
holder->packetLength = sizeof(NV_MOUSE_BUTTON_PACKET);
|
||||
holder->packet.mouseButton.header.packetType = htonl(PACKET_TYPE_MOUSE_BUTTON);
|
||||
holder->packet.mouseButton.action = action;
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
holder->packet.mouseButton.action++;
|
||||
}
|
||||
holder->packet.mouseButton.button = htonl(button);
|
||||
@ -515,7 +515,7 @@ static int sendControllerEventInternal(short controllerNumber, short buttonFlags
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ServerMajorVersion == 3) {
|
||||
if (AppVersionQuad[0] == 3) {
|
||||
// Generation 3 servers don't support multiple controllers so we send
|
||||
// the legacy 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.headerA = MC_HEADER_A;
|
||||
// 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.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.magicA = MAGIC_A;
|
||||
// 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.zero1 = 0;
|
||||
|
@ -12,7 +12,7 @@
|
||||
extern char* RemoteAddrString;
|
||||
extern struct sockaddr_storage RemoteAddr;
|
||||
extern SOCKADDR_LEN RemoteAddrLen;
|
||||
extern int ServerMajorVersion;
|
||||
extern int AppVersionQuad[4];
|
||||
extern STREAM_CONFIGURATION StreamConfig;
|
||||
extern CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
|
||||
extern DECODER_RENDERER_CALLBACKS VideoCallbacks;
|
||||
@ -21,6 +21,7 @@ extern int NegotiatedVideoFormat;
|
||||
|
||||
int isBeforeSignedInt(int numA, int numB, int ambiguousCase);
|
||||
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,
|
||||
PCONNECTION_LISTENER_CALLBACKS* clCallbacks);
|
||||
|
@ -214,15 +214,28 @@ typedef struct _CONNECTION_LISTENER_CALLBACKS {
|
||||
// Use this function to zero the connection callbacks when allocated on the stack or heap
|
||||
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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// _serverMajorVersion is the major version number of the 'appversion' tag in the /serverinfo request
|
||||
//
|
||||
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);
|
||||
int LiStartConnection(PSERVER_INFORMATION serverInfo, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
||||
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags);
|
||||
|
||||
// This function stops streaming.
|
||||
void LiStopConnection(void);
|
||||
|
38
src/Misc.c
38
src/Misc.c
@ -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) {
|
||||
memset(streamConfig, 0, sizeof(*streamConfig));
|
||||
}
|
||||
@ -51,4 +83,8 @@ void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks) {
|
||||
|
||||
void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks) {
|
||||
memset(clCallbacks, 0, sizeof(*clCallbacks));
|
||||
}
|
||||
}
|
||||
|
||||
void LiInitializeServerInformation(PSERVER_INFORMATION serverInfo) {
|
||||
memset(serverInfo, 0, sizeof(*serverInfo));
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ Exit:
|
||||
|
||||
static int transactRtspMessage(PRTSP_MESSAGE request, PRTSP_MESSAGE response, int expectingPayload, int* error) {
|
||||
// Gen 5+ does RTSP over ENet not TCP
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
return transactRtspMessageEnet(request, response, expectingPayload, error);
|
||||
}
|
||||
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
|
||||
// we need to give it some port to successfully complete the
|
||||
// handshake process.
|
||||
@ -446,7 +446,7 @@ int performRtspHandshake(void) {
|
||||
currentSeqNumber = 1;
|
||||
hasSessionId = 0;
|
||||
|
||||
switch (ServerMajorVersion) {
|
||||
switch (AppVersionQuad[0]) {
|
||||
case 3:
|
||||
rtspClientVersion = 10;
|
||||
break;
|
||||
@ -467,7 +467,7 @@ int performRtspHandshake(void) {
|
||||
}
|
||||
|
||||
// Gen 5 servers use ENet to do the RTSP handshake
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
ENetAddress address;
|
||||
ENetEvent event;
|
||||
|
||||
@ -562,7 +562,7 @@ int performRtspHandshake(void) {
|
||||
int error = -1;
|
||||
|
||||
if (!setupStream(&response,
|
||||
ServerMajorVersion >= 5 ? "streamid=audio/0/0" : "streamid=audio",
|
||||
AppVersionQuad[0] >= 5 ? "streamid=audio/0/0" : "streamid=audio",
|
||||
&error)) {
|
||||
Limelog("RTSP SETUP streamid=audio request failed: %d\n", error);
|
||||
ret = error;
|
||||
@ -594,7 +594,7 @@ int performRtspHandshake(void) {
|
||||
int error = -1;
|
||||
|
||||
if (!setupStream(&response,
|
||||
ServerMajorVersion >= 5 ? "streamid=video/0/0" : "streamid=video",
|
||||
AppVersionQuad[0] >= 5 ? "streamid=video/0/0" : "streamid=video",
|
||||
&error)) {
|
||||
Limelog("RTSP SETUP streamid=video request failed: %d\n", error);
|
||||
ret = error;
|
||||
@ -611,7 +611,7 @@ int performRtspHandshake(void) {
|
||||
freeMessage(&response);
|
||||
}
|
||||
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
RTSP_MESSAGE response;
|
||||
int error = -1;
|
||||
|
||||
@ -695,7 +695,7 @@ int performRtspHandshake(void) {
|
||||
|
||||
Exit:
|
||||
// Cleanup the ENet stuff
|
||||
if (ServerMajorVersion >= 5) {
|
||||
if (AppVersionQuad[0] >= 5) {
|
||||
if (peer != NULL) {
|
||||
enet_peer_disconnect_now(peer, 0);
|
||||
peer = NULL;
|
||||
|
@ -185,7 +185,7 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
err |= addAttributeString(&optionHead, "x-nv-video[0].framesWithInvalidRefThreshold", "0");
|
||||
|
||||
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.maximumBitrateKbps", payloadStr);
|
||||
}
|
||||
@ -219,17 +219,17 @@ static PSDP_OPTION getAttributesList(char*urlSafeAddr) {
|
||||
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4");
|
||||
}
|
||||
|
||||
if (ServerMajorVersion == 3) {
|
||||
if (AppVersionQuad[0] == 3) {
|
||||
err |= addGen3Options(&optionHead, urlSafeAddr);
|
||||
}
|
||||
else if (ServerMajorVersion == 4) {
|
||||
else if (AppVersionQuad[0] == 4) {
|
||||
err |= addGen4Options(&optionHead, urlSafeAddr);
|
||||
}
|
||||
else {
|
||||
err |= addGen5Options(&optionHead);
|
||||
}
|
||||
|
||||
if (ServerMajorVersion >= 4) {
|
||||
if (AppVersionQuad[0] >= 4) {
|
||||
if (NegotiatedVideoFormat == VIDEO_FORMAT_H265) {
|
||||
err |= addAttributeString(&optionHead, "x-nv-clientSupportHevc", "1");
|
||||
err |= addAttributeString(&optionHead, "x-nv-vqos[0].bitStreamFormat", "1");
|
||||
@ -298,7 +298,7 @@ static int fillSdpTail(char* buffer) {
|
||||
return sprintf(buffer,
|
||||
"t=0 0\r\n"
|
||||
"m=video %d \r\n",
|
||||
ServerMajorVersion < 4 ? 47996 : 47998);
|
||||
AppVersionQuad[0] < 4 ? 47996 : 47998);
|
||||
}
|
||||
|
||||
// Get the SDP attributes for the stream config
|
||||
|
@ -507,7 +507,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
||||
lastPacketInStream = streamPacketIndex;
|
||||
|
||||
// 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.length -= 8;
|
||||
}
|
||||
|
@ -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
|
||||
firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen,
|
||||
FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC);
|
||||
@ -234,7 +234,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ServerMajorVersion == 3) {
|
||||
if (AppVersionQuad[0] == 3) {
|
||||
// Read the first frame to start the flow of video
|
||||
err = readFirstFrame();
|
||||
if (err != 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user