mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-17 17:05:50 +00:00
Update control connection for GFE 2.0.1+. Remove config and handshake code that isn't used on GFE 2.0.1+
This commit is contained in:
parent
929487249d
commit
ee96cccb51
@ -8,6 +8,15 @@ void BbInitializeWrappedBuffer(PBYTE_BUFFER buff, char* data, int offset, int le
|
||||
buff->byteOrder = byteOrder;
|
||||
}
|
||||
|
||||
static long long byteSwapLongLong(PBYTE_BUFFER buff, long long l) {
|
||||
if (buff->byteOrder == BYTE_ORDER_BIG) {
|
||||
return HTONLL(l);
|
||||
}
|
||||
else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
static int byteSwapInt(PBYTE_BUFFER buff, int i) {
|
||||
if (buff->byteOrder == BYTE_ORDER_BIG) {
|
||||
return htonl(i);
|
||||
@ -63,6 +72,19 @@ int BbGetInt(PBYTE_BUFFER buff, int *i) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BbGetLong(PBYTE_BUFFER buff, long long *l) {
|
||||
if (buff->position + sizeof(*l) > buff->length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(l, &buff->buffer[buff->position], sizeof(*l));
|
||||
buff->position += sizeof(*l);
|
||||
|
||||
*l = byteSwapInt(buff, *l);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BbPutInt(PBYTE_BUFFER buff, int i) {
|
||||
if (buff->position + sizeof(i) > buff->length) {
|
||||
return 0;
|
||||
@ -76,6 +98,19 @@ int BbPutInt(PBYTE_BUFFER buff, int i) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BbPutLong(PBYTE_BUFFER buff, long long l) {
|
||||
if (buff->position + sizeof(l) > buff->length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
l = byteSwapInt(buff, l);
|
||||
|
||||
memcpy(&buff->buffer[buff->position], &l, sizeof(l));
|
||||
buff->position += sizeof(l);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BbPutShort(PBYTE_BUFFER buff, short s) {
|
||||
if (buff->position + sizeof(s) > buff->length) {
|
||||
return 0;
|
||||
|
@ -5,6 +5,16 @@
|
||||
#define BYTE_ORDER_LITTLE 1
|
||||
#define BYTE_ORDER_BIG 2
|
||||
|
||||
#define HTONLL(x) \
|
||||
((((x) & 0xff00000000000000ull) >> 56) \
|
||||
| (((x) & 0x00ff000000000000ull) >> 40) \
|
||||
| (((x) & 0x0000ff0000000000ull) >> 24) \
|
||||
| (((x) & 0x000000ff00000000ull) >> 8) \
|
||||
| (((x) & 0x00000000ff000000ull) << 8) \
|
||||
| (((x) & 0x0000000000ff0000ull) << 24) \
|
||||
| (((x) & 0x000000000000ff00ull) << 40) \
|
||||
| (((x) & 0x00000000000000ffull) << 56))
|
||||
|
||||
typedef struct _BYTE_BUFFER {
|
||||
char* buffer;
|
||||
unsigned int offset;
|
||||
@ -18,7 +28,9 @@ void BbInitializeWrappedBuffer(PBYTE_BUFFER buff, char* data, int offset, int le
|
||||
int BbGet(PBYTE_BUFFER buff, char *c);
|
||||
int BbGetShort(PBYTE_BUFFER buff, short *s);
|
||||
int BbGetInt(PBYTE_BUFFER buff, int *i);
|
||||
int BbGetLong(PBYTE_BUFFER buff, long long *l);
|
||||
|
||||
int BbPutInt(PBYTE_BUFFER buff, int i);
|
||||
int BbPutShort(PBYTE_BUFFER buff, short s);
|
||||
int BbPut(PBYTE_BUFFER buff, char c);
|
||||
int BbPutLong(PBYTE_BUFFER buff, long long l);
|
||||
|
@ -1,135 +0,0 @@
|
||||
#include "Limelight-internal.h"
|
||||
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
static const int UNKNOWN_CONFIG[] = {
|
||||
70151,
|
||||
68291329,
|
||||
1280,
|
||||
68291584,
|
||||
1280,
|
||||
68291840,
|
||||
15360,
|
||||
68292096,
|
||||
25600,
|
||||
68292352,
|
||||
2048,
|
||||
68292608,
|
||||
1024,
|
||||
68289024,
|
||||
262144,
|
||||
17957632,
|
||||
302055424,
|
||||
134217729,
|
||||
16777490,
|
||||
70153,
|
||||
68293120,
|
||||
768000,
|
||||
17961216,
|
||||
303235072,
|
||||
335609857,
|
||||
838861842,
|
||||
352321536,
|
||||
1006634002,
|
||||
369098752,
|
||||
335545362,
|
||||
385875968,
|
||||
1042,
|
||||
402653184,
|
||||
134218770,
|
||||
419430400,
|
||||
167773202,
|
||||
436207616,
|
||||
855638290,
|
||||
266779,
|
||||
10000,
|
||||
266780,
|
||||
2000,
|
||||
266781,
|
||||
50,
|
||||
266782,
|
||||
3000,
|
||||
266783,
|
||||
2,
|
||||
266794,
|
||||
5000,
|
||||
266795,
|
||||
500,
|
||||
266784,
|
||||
75,
|
||||
266785,
|
||||
25,
|
||||
266786,
|
||||
10,
|
||||
266787,
|
||||
60,
|
||||
266788,
|
||||
30,
|
||||
266789,
|
||||
3,
|
||||
266790,
|
||||
1000,
|
||||
266791,
|
||||
5000,
|
||||
266792,
|
||||
5000,
|
||||
266793,
|
||||
5000,
|
||||
70190,
|
||||
68301063,
|
||||
10240,
|
||||
68301312,
|
||||
6400,
|
||||
68301568,
|
||||
768000,
|
||||
68299776,
|
||||
768,
|
||||
68300032,
|
||||
2560,
|
||||
68300544,
|
||||
0,
|
||||
34746368,
|
||||
(int) 0xFE000000
|
||||
};
|
||||
|
||||
static const int CONFIG_SIZE = sizeof(UNKNOWN_CONFIG) +(8 * 4) + 3;
|
||||
|
||||
int getConfigDataSize(PSTREAM_CONFIGURATION streamConfig) {
|
||||
return CONFIG_SIZE;
|
||||
}
|
||||
|
||||
char* allocateConfigDataForStreamConfig(PSTREAM_CONFIGURATION streamConfig) {
|
||||
BYTE_BUFFER bb;
|
||||
int i;
|
||||
char* config = (char *)malloc(CONFIG_SIZE);
|
||||
if (config == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BbInitializeWrappedBuffer(&bb, config, 0, CONFIG_SIZE, BYTE_ORDER_LITTLE);
|
||||
|
||||
BbPutShort(&bb, 0x1204);
|
||||
BbPutShort(&bb, 0x0004);
|
||||
BbPutInt(&bb, streamConfig->width);
|
||||
|
||||
BbPutShort(&bb, 0x1205);
|
||||
BbPutShort(&bb, 0x0004);
|
||||
BbPutInt(&bb, streamConfig->height);
|
||||
|
||||
BbPutShort(&bb, 0x1206);
|
||||
BbPutShort(&bb, 0x0004);
|
||||
BbPutInt(&bb, 1);
|
||||
|
||||
BbPutShort(&bb, 0x120A);
|
||||
BbPutShort(&bb, 0x0004);
|
||||
BbPutInt(&bb, streamConfig->fps);
|
||||
|
||||
for (i = 0; i < sizeof(UNKNOWN_CONFIG) / sizeof(int); i++) {
|
||||
BbPutInt(&bb, UNKNOWN_CONFIG[i]);
|
||||
}
|
||||
|
||||
BbPutShort(&bb, 0x0013);
|
||||
BbPut(&bb, 0x00);
|
||||
|
||||
return config;
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
#include "PlatformSockets.h"
|
||||
#include "PlatformThreads.h"
|
||||
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
typedef struct _NVCTL_PACKET_HEADER {
|
||||
unsigned short type;
|
||||
unsigned short payloadLength;
|
||||
@ -10,26 +12,31 @@ typedef struct _NVCTL_PACKET_HEADER {
|
||||
static IP_ADDRESS host;
|
||||
static SOCKET ctlSock = INVALID_SOCKET;
|
||||
static STREAM_CONFIGURATION streamConfig;
|
||||
static PLT_THREAD heartbeatThread;
|
||||
static PLT_THREAD jitterThread;
|
||||
static PLT_THREAD lossStatsThread;
|
||||
static PLT_THREAD resyncThread;
|
||||
static PLT_EVENT resyncEvent;
|
||||
static PCONNECTION_LISTENER_CALLBACKS listenerCallbacks;
|
||||
static int lossCountSinceLastReport = 0;
|
||||
static long currentFrame = 0;
|
||||
|
||||
static const short PTYPE_KEEPALIVE = 0x13ff;
|
||||
static const short PPAYLEN_KEEPALIVE = 0x0000;
|
||||
#define PTYPE_START_STREAM_A 0x140b
|
||||
#define PPAYLEN_START_STREAM_A 1
|
||||
static const char PPAYLOAD_START_STREAM_A[1] = { 0 };
|
||||
|
||||
static const short PTYPE_HEARTBEAT = 0x1401;
|
||||
static const short PPAYLEN_HEARTBEAT = 0x0000;
|
||||
#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
|
||||
|
||||
static const short PTYPE_1405 = 0x1405;
|
||||
static const short PPAYLEN_1405 = 0x0000;
|
||||
#define PTYPE_RESYNC 0x1404
|
||||
#define PPAYLEN_RESYNC 24
|
||||
|
||||
static const short PTYPE_RESYNC = 0x1404;
|
||||
static const short PPAYLEN_RESYNC = 16;
|
||||
#define PTYPE_LOSS_STATS 0x140c
|
||||
#define PPAYLEN_LOSS_STATS 20
|
||||
|
||||
static const short PTYPE_JITTER = 0x140c;
|
||||
static const short PPAYLEN_JITTER = 0x10;
|
||||
#define PTYPE_FRAME_STATS 0x1417
|
||||
#define PPAYLEN_FRAME_STATS 64
|
||||
|
||||
#define LOSS_REPORT_INTERVAL_MS 50
|
||||
|
||||
int initializeControlStream(IP_ADDRESS addr, PSTREAM_CONFIGURATION streamConfigPtr, PCONNECTION_LISTENER_CALLBACKS clCallbacks) {
|
||||
memcpy(&streamConfig, streamConfigPtr, sizeof(*streamConfigPtr));
|
||||
@ -56,6 +63,14 @@ void connectionDetectedFrameLoss(int startFrame, int endFrame) {
|
||||
PltSetEvent(&resyncEvent);
|
||||
}
|
||||
|
||||
void connectionReceivedFrame(int frameIndex) {
|
||||
currentFrame = frameIndex;
|
||||
}
|
||||
|
||||
void connectionLostPackets(int lastReceivedPacket, int nextReceivedPacket) {
|
||||
lossCountSinceLastReport += (nextReceivedPacket - lastReceivedPacket) - 1;
|
||||
}
|
||||
|
||||
static PNVCTL_PACKET_HEADER readNvctlPacket(void) {
|
||||
NVCTL_PACKET_HEADER staticHeader;
|
||||
PNVCTL_PACKET_HEADER fullPacket;
|
||||
@ -83,7 +98,7 @@ static PNVCTL_PACKET_HEADER readNvctlPacket(void) {
|
||||
return fullPacket;
|
||||
}
|
||||
|
||||
static PNVCTL_PACKET_HEADER sendNoPayloadAndReceive(short ptype, short paylen) {
|
||||
static int sendMessageAndForget(short ptype, short paylen, const void* payload) {
|
||||
NVCTL_PACKET_HEADER header;
|
||||
int err;
|
||||
|
||||
@ -91,105 +106,86 @@ static PNVCTL_PACKET_HEADER sendNoPayloadAndReceive(short ptype, short paylen) {
|
||||
header.payloadLength = paylen;
|
||||
err = send(ctlSock, (char*) &header, sizeof(header), 0);
|
||||
if (err != sizeof(header)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (payload != NULL) {
|
||||
err = send(ctlSock, payload, paylen, 0);
|
||||
if (err != paylen) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static PNVCTL_PACKET_HEADER sendMessage(short ptype, short paylen, const void* payload) {
|
||||
int success;
|
||||
|
||||
success = sendMessageAndForget(ptype, paylen, payload);
|
||||
if (!success) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return readNvctlPacket();
|
||||
}
|
||||
|
||||
static void heartbeatThreadFunc(void* context) {
|
||||
int err;
|
||||
NVCTL_PACKET_HEADER header;
|
||||
static void lossStatsThreadFunc(void* context) {
|
||||
char lossStatsPayload[PPAYLEN_LOSS_STATS];
|
||||
BYTE_BUFFER byteBuffer;
|
||||
|
||||
header.type = PTYPE_HEARTBEAT;
|
||||
header.payloadLength = PPAYLEN_HEARTBEAT;
|
||||
while (!PltIsThreadInterrupted(&heartbeatThread)) {
|
||||
err = send(ctlSock, (char*) &header, sizeof(header), 0);
|
||||
if (err != sizeof(header)) {
|
||||
Limelog("Heartbeat thread terminating #1\n");
|
||||
listenerCallbacks->connectionTerminated(err);
|
||||
while (!PltIsThreadInterrupted(&lossStatsThread)) {
|
||||
// Construct the payload
|
||||
BbInitializeWrappedBuffer(&byteBuffer, lossStatsPayload, 0, PPAYLEN_LOSS_STATS, BYTE_ORDER_LITTLE);
|
||||
BbPutInt(&byteBuffer, lossCountSinceLastReport);
|
||||
BbPutInt(&byteBuffer, LOSS_REPORT_INTERVAL_MS);
|
||||
BbPutInt(&byteBuffer, 1000);
|
||||
BbPutLong(&byteBuffer, currentFrame);
|
||||
|
||||
// Send the message (and don't expect a response)
|
||||
if (!sendMessageAndForget(PTYPE_LOSS_STATS,
|
||||
PPAYLEN_LOSS_STATS, lossStatsPayload)) {
|
||||
Limelog("Loss stats thread terminating #1\n");
|
||||
return;
|
||||
}
|
||||
|
||||
PltSleepMs(3000);
|
||||
}
|
||||
}
|
||||
// Clear the transient state
|
||||
lossCountSinceLastReport = 0;
|
||||
|
||||
static void jitterThreadFunc(void* context) {
|
||||
int payload[4];
|
||||
NVCTL_PACKET_HEADER header;
|
||||
int err;
|
||||
|
||||
header.type = PTYPE_JITTER;
|
||||
header.payloadLength = PPAYLEN_JITTER;
|
||||
while (!PltIsThreadInterrupted(&jitterThread)) {
|
||||
err = send(ctlSock, (char*) &header, sizeof(header), 0);
|
||||
if (err != sizeof(header)) {
|
||||
Limelog("Jitter thread terminating #1\n");
|
||||
listenerCallbacks->connectionTerminated(err);
|
||||
return;
|
||||
}
|
||||
|
||||
payload[0] = 0;
|
||||
payload[1] = 77;
|
||||
payload[2] = 888;
|
||||
payload[3] = 0; // FIXME: Sequence number?
|
||||
|
||||
err = send(ctlSock, (char*) payload, sizeof(payload), 0);
|
||||
if (err != sizeof(payload)) {
|
||||
Limelog("Jitter thread terminating #2\n");
|
||||
listenerCallbacks->connectionTerminated(err);
|
||||
return;
|
||||
}
|
||||
|
||||
PltSleepMs(100);
|
||||
// Wait a bit
|
||||
PltSleepMs(LOSS_REPORT_INTERVAL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void resyncThreadFunc(void* context) {
|
||||
long long payload[2];
|
||||
NVCTL_PACKET_HEADER header;
|
||||
long long payload[3];
|
||||
PNVCTL_PACKET_HEADER response;
|
||||
int err;
|
||||
|
||||
header.type = PTYPE_RESYNC;
|
||||
header.payloadLength = PPAYLEN_RESYNC;
|
||||
while (!PltIsThreadInterrupted(&resyncThread)) {
|
||||
// Wait for a resync request
|
||||
PltWaitForEvent(&resyncEvent);
|
||||
|
||||
err = send(ctlSock, (char*) &header, sizeof(header), 0);
|
||||
if (err != sizeof(header)) {
|
||||
Limelog("Resync thread terminating #1\n");
|
||||
listenerCallbacks->connectionTerminated(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// Form the payload
|
||||
payload[0] = 0;
|
||||
payload[1] = 0xFFFFF;
|
||||
payload[2] = 0;
|
||||
|
||||
Limelog("Sending resync packet\n");
|
||||
err = send(ctlSock, (char*) payload, sizeof(payload), 0);
|
||||
if (err != sizeof(payload)) {
|
||||
Limelog("Resync thread terminating #2\n");
|
||||
listenerCallbacks->connectionTerminated(err);
|
||||
return;
|
||||
}
|
||||
// Done capturing the parameters
|
||||
PltClearEvent(&resyncEvent);
|
||||
|
||||
response = readNvctlPacket();
|
||||
// Send the resync request and read the response
|
||||
response = sendMessage(PTYPE_RESYNC, PPAYLEN_RESYNC, payload);
|
||||
if (response == NULL) {
|
||||
Limelog("Resync thread terminating #3\n");
|
||||
Limelog("Resync thread terminating #1\n");
|
||||
listenerCallbacks->connectionTerminated(LastSocketError());
|
||||
return;
|
||||
}
|
||||
Limelog("Resync complete\n");
|
||||
|
||||
PltClearEvent(&resyncEvent);
|
||||
}
|
||||
}
|
||||
|
||||
int stopControlStream(void) {
|
||||
PltInterruptThread(&heartbeatThread);
|
||||
PltInterruptThread(&jitterThread);
|
||||
PltInterruptThread(&lossStatsThread);
|
||||
PltInterruptThread(&resyncThread);
|
||||
|
||||
if (ctlSock != INVALID_SOCKET) {
|
||||
@ -197,12 +193,10 @@ int stopControlStream(void) {
|
||||
ctlSock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
PltJoinThread(&heartbeatThread);
|
||||
PltJoinThread(&jitterThread);
|
||||
PltJoinThread(&lossStatsThread);
|
||||
PltJoinThread(&resyncThread);
|
||||
|
||||
PltCloseThread(&heartbeatThread);
|
||||
PltCloseThread(&jitterThread);
|
||||
PltCloseThread(&lossStatsThread);
|
||||
PltCloseThread(&resyncThread);
|
||||
|
||||
return 0;
|
||||
@ -210,8 +204,6 @@ int stopControlStream(void) {
|
||||
|
||||
int startControlStream(void) {
|
||||
int err;
|
||||
char* config;
|
||||
int configSize;
|
||||
PNVCTL_PACKET_HEADER response;
|
||||
|
||||
ctlSock = connectTcpSocket(host, 47995);
|
||||
@ -221,39 +213,21 @@ int startControlStream(void) {
|
||||
|
||||
enableNoDelay(ctlSock);
|
||||
|
||||
configSize = getConfigDataSize(&streamConfig);
|
||||
config = allocateConfigDataForStreamConfig(&streamConfig);
|
||||
if (config == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Send config
|
||||
err = send(ctlSock, config, configSize, 0);
|
||||
free(config);
|
||||
if (err != configSize) {
|
||||
return LastSocketError();
|
||||
}
|
||||
|
||||
// Ping pong
|
||||
response = sendNoPayloadAndReceive(PTYPE_KEEPALIVE, PPAYLEN_KEEPALIVE);
|
||||
// Send START A
|
||||
response = sendMessage(PTYPE_START_STREAM_A,
|
||||
PPAYLEN_START_STREAM_A, PPAYLOAD_START_STREAM_A);
|
||||
if (response == NULL) {
|
||||
return LastSocketError();
|
||||
}
|
||||
free(response);
|
||||
|
||||
// 1405
|
||||
response = sendNoPayloadAndReceive(PTYPE_1405, PPAYLEN_1405);
|
||||
// Send START B
|
||||
response = sendMessage(PTYPE_START_STREAM_B,
|
||||
PPAYLEN_START_STREAM_B, PPAYLOAD_START_STREAM_B);
|
||||
if (response == NULL) {
|
||||
return LastSocketError();
|
||||
}
|
||||
free(response);
|
||||
|
||||
err = PltCreateThread(heartbeatThreadFunc, NULL, &heartbeatThread);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = PltCreateThread(jitterThreadFunc, NULL, &jitterThread);
|
||||
err = PltCreateThread(lossStatsThreadFunc, NULL, &lossStatsThread);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
@ -1,97 +0,0 @@
|
||||
#include "Limelight.h"
|
||||
#include "PlatformSockets.h"
|
||||
#include "PlatformThreads.h"
|
||||
|
||||
static const char HELLO [] = {
|
||||
0x07, 0x00, 0x00, 0x00,
|
||||
0x61, 0x6e, 0x64, 0x72,
|
||||
0x6f, 0x69, 0x64, 0x03,
|
||||
0x01, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const char PACKET2 [] = {
|
||||
0x01, 0x03, 0x02, 0x00,
|
||||
0x08, 0x00
|
||||
};
|
||||
|
||||
static const char PACKET3 [] = {
|
||||
0x04, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const char PACKET4 [] = {
|
||||
0x01, 0x01, 0x00, 0x0
|
||||
};
|
||||
|
||||
static SOCKET sock = INVALID_SOCKET;
|
||||
|
||||
static int waitAndDiscardResponse(SOCKET sock) {
|
||||
char temp[256];
|
||||
return recv(sock, temp, sizeof(temp), 0);
|
||||
}
|
||||
|
||||
void terminateHandshake(void) {
|
||||
if (sock != INVALID_SOCKET) {
|
||||
closesocket(sock);
|
||||
sock = INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int performHandshake(IP_ADDRESS host) {
|
||||
int err;
|
||||
|
||||
sock = connectTcpSocket(host, 47991);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
return LastSocketError();
|
||||
}
|
||||
|
||||
enableNoDelay(sock);
|
||||
|
||||
err = send(sock, HELLO, sizeof(HELLO), 0);
|
||||
if (err == SOCKET_ERROR) {
|
||||
goto CleanupError;
|
||||
}
|
||||
|
||||
err = waitAndDiscardResponse(sock);
|
||||
if (err == SOCKET_ERROR) {
|
||||
goto CleanupError;
|
||||
}
|
||||
|
||||
err = send(sock, PACKET2, sizeof(PACKET2), 0);
|
||||
if (err == SOCKET_ERROR) {
|
||||
goto CleanupError;
|
||||
}
|
||||
|
||||
err = waitAndDiscardResponse(sock);
|
||||
if (err == SOCKET_ERROR) {
|
||||
goto CleanupError;
|
||||
}
|
||||
|
||||
err = send(sock, PACKET3, sizeof(PACKET3), 0);
|
||||
if (err == SOCKET_ERROR) {
|
||||
goto CleanupError;
|
||||
}
|
||||
|
||||
err = waitAndDiscardResponse(sock);
|
||||
if (err == SOCKET_ERROR) {
|
||||
goto CleanupError;
|
||||
}
|
||||
|
||||
err = send(sock, PACKET4, sizeof(PACKET4), 0);
|
||||
if (err == SOCKET_ERROR) {
|
||||
goto CleanupError;
|
||||
}
|
||||
|
||||
closesocket(sock);
|
||||
sock = INVALID_SOCKET;
|
||||
|
||||
return 0;
|
||||
|
||||
CleanupError:
|
||||
closesocket(sock);
|
||||
sock = INVALID_SOCKET;
|
||||
|
||||
return LastSocketError();
|
||||
}
|
@ -6,18 +6,14 @@
|
||||
#include "PlatformThreads.h"
|
||||
#include "Video.h"
|
||||
|
||||
char* allocateConfigDataForStreamConfig(PSTREAM_CONFIGURATION streamConfig);
|
||||
int getConfigDataSize(PSTREAM_CONFIGURATION streamConfig);
|
||||
|
||||
int initializeControlStream(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks);
|
||||
int startControlStream(void);
|
||||
int stopControlStream(void);
|
||||
void destroyControlStream(void);
|
||||
void connectionSinkTooSlow(int startFrame, int endFrame);
|
||||
void connectionDetectedFrameLoss(int startFrame, int endFrame);
|
||||
|
||||
int performHandshake(IP_ADDRESS host);
|
||||
void terminateHandshake(void);
|
||||
void connectionReceivedFrame(int frameIndex);
|
||||
void connectionLostPackets(int lastReceivedPacket, int nextReceivedPacket);
|
||||
|
||||
void initializeVideoDepacketizer(void);
|
||||
void destroyVideoDepacketizer(void);
|
||||
|
@ -9,7 +9,8 @@ typedef struct _NV_VIDEO_PACKET {
|
||||
int totalPackets;
|
||||
int flags;
|
||||
int payloadLength;
|
||||
char reserved2[36];
|
||||
int streamPacketIndex;
|
||||
char reserved2[32];
|
||||
} NV_VIDEO_PACKET, *PNV_VIDEO_PACKET;
|
||||
|
||||
typedef struct _RTP_PACKET {
|
||||
|
@ -12,6 +12,7 @@ static int nextPacketNumber;
|
||||
static int startFrameNumber = 1;
|
||||
static int waitingForNextSuccessfulFrame;
|
||||
static int gotNextFrameStart;
|
||||
static int lastPacketInStream = 0;
|
||||
|
||||
static LINKED_BLOCKING_QUEUE decodeUnitQueue;
|
||||
|
||||
@ -124,6 +125,9 @@ static void reassembleFrame(int frameNumber) {
|
||||
// FIXME: Get proper lower bound
|
||||
connectionSinkTooSlow(0, frameNumber);
|
||||
}
|
||||
|
||||
// Notify the control connection
|
||||
connectionReceivedFrame(frameNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,6 +336,13 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
||||
}
|
||||
}
|
||||
|
||||
int streamPacketIndex = videoPacket->streamPacketIndex;
|
||||
if (streamPacketIndex != (int) (lastPacketInStream + 1)) {
|
||||
// Packets were lost so report this to the server
|
||||
connectionLostPackets(lastPacketInStream, streamPacketIndex);
|
||||
}
|
||||
lastPacketInStream = streamPacketIndex;
|
||||
|
||||
nextPacketNumber++;
|
||||
|
||||
// Remove extra padding
|
||||
|
@ -129,10 +129,8 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AudioStream.c" />
|
||||
<ClCompile Include="ByteBuffer.c" />
|
||||
<ClCompile Include="Config.c" />
|
||||
<ClCompile Include="Connection.c" />
|
||||
<ClCompile Include="ControlStream.c" />
|
||||
<ClCompile Include="Handshake.c" />
|
||||
<ClCompile Include="InputStream.c" />
|
||||
<ClCompile Include="LinkedBlockingQueue.c" />
|
||||
<ClCompile Include="PlatformSockets.c" />
|
||||
|
@ -18,15 +18,9 @@
|
||||
<ClCompile Include="ByteBuffer.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Config.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Connection.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Handshake.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ControlStream.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
Loading…
x
Reference in New Issue
Block a user