Major code cleanup: comment style & run CodeMaid

This commit is contained in:
Michelle Bergeron
2016-02-13 13:01:24 -06:00
parent baa8106dd8
commit c8bad4ed2f
18 changed files with 452 additions and 453 deletions
+14 -12
View File
@@ -133,8 +133,8 @@ static int queuePacketToLbq(PQUEUED_AUDIO_PACKET *packet) {
static void decodeInputData(PQUEUED_AUDIO_PACKET packet) { static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
PRTP_PACKET rtp; PRTP_PACKET rtp;
rtp = (PRTP_PACKET) &packet->data[0]; rtp = (PRTP_PACKET)&packet->data[0];
if (lastSeq != 0 && (unsigned short) (lastSeq + 1) != rtp->sequenceNumber) { if (lastSeq != 0 && (unsigned short)(lastSeq + 1) != rtp->sequenceNumber) {
Limelog("Received OOS audio data (expected %d, but got %d)\n", lastSeq + 1, rtp->sequenceNumber); Limelog("Received OOS audio data (expected %d, but got %d)\n", lastSeq + 1, rtp->sequenceNumber);
AudioCallbacks.decodeAndPlaySample(NULL, 0); AudioCallbacks.decodeAndPlaySample(NULL, 0);
@@ -142,7 +142,7 @@ static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
lastSeq = rtp->sequenceNumber; lastSeq = rtp->sequenceNumber;
AudioCallbacks.decodeAndPlaySample((char *) (rtp + 1), packet->size - sizeof(*rtp)); AudioCallbacks.decodeAndPlaySample((char *)(rtp + 1), packet->size - sizeof(*rtp));
} }
static void ReceiveThreadProc(void* context) { static void ReceiveThreadProc(void* context) {
@@ -154,7 +154,7 @@ static void ReceiveThreadProc(void* context) {
while (!PltIsThreadInterrupted(&receiveThread)) { while (!PltIsThreadInterrupted(&receiveThread)) {
if (packet == NULL) { if (packet == NULL) {
packet = (PQUEUED_AUDIO_PACKET) malloc(sizeof(*packet)); packet = (PQUEUED_AUDIO_PACKET)malloc(sizeof(*packet));
if (packet == NULL) { if (packet == NULL) {
Limelog("Audio Receive: malloc() failed\n"); Limelog("Audio Receive: malloc() failed\n");
ListenerCallbacks.connectionTerminated(-1); ListenerCallbacks.connectionTerminated(-1);
@@ -162,7 +162,7 @@ static void ReceiveThreadProc(void* context) {
} }
} }
packet->size = (int) recv(rtpSocket, &packet->data[0], MAX_PACKET_SIZE, 0); packet->size = (int)recv(rtpSocket, &packet->data[0], MAX_PACKET_SIZE, 0);
if (packet->size <= 0) { if (packet->size <= 0) {
Limelog("Audio Receive: recv() failed: %d\n", (int)LastSocketError()); Limelog("Audio Receive: recv() failed: %d\n", (int)LastSocketError());
free(packet); free(packet);
@@ -175,23 +175,24 @@ static void ReceiveThreadProc(void* context) {
continue; continue;
} }
rtp = (PRTP_PACKET) &packet->data[0]; rtp = (PRTP_PACKET)&packet->data[0];
if (rtp->packetType != 97) { if (rtp->packetType != 97) {
// Not audio // Not audio
continue; continue;
} }
// RTP sequence number must be in host order for the RTP queue // RTP sequence number must be in host order for the RTP queue
rtp->sequenceNumber = htons(rtp->sequenceNumber); rtp->sequenceNumber = htons(rtp->sequenceNumber);
queueStatus = RtpqAddPacket(&rtpReorderQueue, (PRTP_PACKET) packet, &packet->q.rentry); queueStatus = RtpqAddPacket(&rtpReorderQueue, (PRTP_PACKET)packet, &packet->q.rentry);
if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) { if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) {
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
if (!queuePacketToLbq(&packet)) { if (!queuePacketToLbq(&packet)) {
// An exit signal was received // An exit signal was received
return; return;
} }
} else { }
else {
decodeInputData(packet); decodeInputData(packet);
} }
} }
@@ -203,13 +204,14 @@ static void ReceiveThreadProc(void* context) {
if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) { if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) {
// If packets are ready, pull them and send them to the decoder // If packets are ready, pull them and send them to the decoder
while ((packet = (PQUEUED_AUDIO_PACKET) RtpqGetQueuedPacket(&rtpReorderQueue)) != NULL) { while ((packet = (PQUEUED_AUDIO_PACKET)RtpqGetQueuedPacket(&rtpReorderQueue)) != NULL) {
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
if (!queuePacketToLbq(&packet)) { if (!queuePacketToLbq(&packet)) {
// An exit signal was received // An exit signal was received
return; return;
} }
} else { }
else {
decodeInputData(packet); decodeInputData(packet);
} }
} }
@@ -223,7 +225,7 @@ static void DecoderThreadProc(void* context) {
PQUEUED_AUDIO_PACKET packet; PQUEUED_AUDIO_PACKET packet;
while (!PltIsThreadInterrupted(&decoderThread)) { while (!PltIsThreadInterrupted(&decoderThread)) {
err = LbqWaitForQueueElement(&packetQueue, (void**) &packet); err = LbqWaitForQueueElement(&packetQueue, (void**)&packet);
if (err != LBQ_SUCCESS) { if (err != LBQ_SUCCESS) {
// An exit signal was received // An exit signal was received
return; return;
+2 -2
View File
@@ -142,6 +142,6 @@ int BbPut(PBYTE_BUFFER buff, char c) {
memcpy(&buff->buffer[buff->position], &c, sizeof(c)); memcpy(&buff->buffer[buff->position], &c, sizeof(c));
buff->position += sizeof(c); buff->position += sizeof(c);
return 1; return 1;
} }
+12 -12
View File
@@ -16,7 +16,7 @@ CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
DECODER_RENDERER_CALLBACKS VideoCallbacks; DECODER_RENDERER_CALLBACKS VideoCallbacks;
AUDIO_RENDERER_CALLBACKS AudioCallbacks; AUDIO_RENDERER_CALLBACKS AudioCallbacks;
/* Connection stages */ // Connection stages
static const char* stageNames[STAGE_MAX] = { static const char* stageNames[STAGE_MAX] = {
"none", "none",
"platform initialization", "platform initialization",
@@ -32,16 +32,16 @@ static const char* stageNames[STAGE_MAX] = {
"input stream establishment" "input stream establishment"
}; };
/* Get the name of the current stage based on its number */ // Get the name of the current stage based on its number
const char* LiGetStageName(int stage) { const char* LiGetStageName(int stage) {
return stageNames[stage]; return stageNames[stage];
} }
/* Stop the connection by undoing the step at the current stage and those before it */ // Stop the connection by undoing the step at the current stage and those before it
void LiStopConnection(void) { void LiStopConnection(void) {
// Disable termination callbacks now // Disable termination callbacks now
alreadyTerminated = 1; alreadyTerminated = 1;
if (stage == STAGE_INPUT_STREAM_START) { if (stage == STAGE_INPUT_STREAM_START) {
Limelog("Stopping input stream..."); Limelog("Stopping input stream...");
stopInputStream(); stopInputStream();
@@ -148,7 +148,7 @@ static int resolveHostName(const char *host)
{ {
struct addrinfo hints, *res; struct addrinfo hints, *res;
int err; int err;
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG; hints.ai_flags = AI_ADDRCONFIG;
@@ -157,21 +157,21 @@ static int resolveHostName(const char *host)
Limelog("getaddrinfo() failed: %d\n", err); Limelog("getaddrinfo() failed: %d\n", err);
return err; return err;
} }
if (res == NULL) { if (res == NULL) {
Limelog("getaddrinfo() returned success without addresses\n"); Limelog("getaddrinfo() returned success without addresses\n");
return -1; return -1;
} }
// Use the first address in the list // Use the first address in the list
memcpy(&RemoteAddr, res->ai_addr, res->ai_addrlen); memcpy(&RemoteAddr, res->ai_addr, res->ai_addrlen);
RemoteAddrLen = res->ai_addrlen; RemoteAddrLen = res->ai_addrlen;
freeaddrinfo(res); freeaddrinfo(res);
return 0; return 0;
} }
/* 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(const char* host, 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, int _serverMajorVersion) { void* renderContext, int drFlags, int _serverMajorVersion) {
@@ -190,7 +190,7 @@ int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCON
originalTerminationCallback = clCallbacks->connectionTerminated; originalTerminationCallback = clCallbacks->connectionTerminated;
memcpy(&ListenerCallbacks, clCallbacks, sizeof(ListenerCallbacks)); memcpy(&ListenerCallbacks, clCallbacks, sizeof(ListenerCallbacks));
ListenerCallbacks.connectionTerminated = ClInternalConnectionTerminated; ListenerCallbacks.connectionTerminated = ClInternalConnectionTerminated;
alreadyTerminated = 0; alreadyTerminated = 0;
Limelog("Initializing platform..."); Limelog("Initializing platform...");
@@ -205,7 +205,7 @@ int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCON
LC_ASSERT(stage == STAGE_PLATFORM_INIT); LC_ASSERT(stage == STAGE_PLATFORM_INIT);
ListenerCallbacks.stageComplete(STAGE_PLATFORM_INIT); ListenerCallbacks.stageComplete(STAGE_PLATFORM_INIT);
Limelog("done\n"); Limelog("done\n");
Limelog("Resolving host name..."); Limelog("Resolving host name...");
ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION); ListenerCallbacks.stageStarting(STAGE_NAME_RESOLUTION);
err = resolveHostName(host); err = resolveHostName(host);
@@ -326,4 +326,4 @@ int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCON
Cleanup: Cleanup:
return err; return err;
} }
+32 -32
View File
@@ -4,7 +4,7 @@
#include "ByteBuffer.h" #include "ByteBuffer.h"
/* NV control stream packet header */ // NV control stream packet header
typedef struct _NVCTL_PACKET_HEADER { typedef struct _NVCTL_PACKET_HEADER {
unsigned short type; unsigned short type;
unsigned short payloadLength; unsigned short payloadLength;
@@ -47,11 +47,11 @@ static const short packetTypesGen4[] = {
0x0611, // Frame Stats (unused) 0x0611, // Frame Stats (unused)
}; };
static const char startAGen3[] = {0}; static const char startAGen3[] = { 0 };
static const int startBGen3[] = {0, 0, 0, 0xa}; static const int startBGen3[] = { 0, 0, 0, 0xa };
static const char requestIdrFrameGen4[] = {0, 0}; static const char requestIdrFrameGen4[] = { 0, 0 };
static const char startBGen4[] = {0}; static const char startBGen4[] = { 0 };
static const short payloadLengthsGen3[] = { static const short payloadLengthsGen3[] = {
sizeof(startAGen3), // Start A sizeof(startAGen3), // Start A
@@ -83,11 +83,11 @@ static char **preconstructedPayloads;
#define LOSS_REPORT_INTERVAL_MS 50 #define LOSS_REPORT_INTERVAL_MS 50
/* Initializes the control stream */ // Initializes the control stream
int initializeControlStream(void) { int initializeControlStream(void) {
PltCreateEvent(&invalidateRefFramesEvent); PltCreateEvent(&invalidateRefFramesEvent);
LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20); LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20);
if (ServerMajorVersion == 3) { if (ServerMajorVersion == 3) {
packetTypes = (short*)packetTypesGen3; packetTypes = (short*)packetTypesGen3;
payloadLengths = (short*)payloadLengthsGen3; payloadLengths = (short*)payloadLengthsGen3;
@@ -116,19 +116,18 @@ void freeFrameInvalidationList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
} }
} }
/* Cleans up control stream */ // Cleans up control stream
void destroyControlStream(void) { void destroyControlStream(void) {
PltCloseEvent(&invalidateRefFramesEvent); PltCloseEvent(&invalidateRefFramesEvent);
freeFrameInvalidationList(LbqDestroyLinkedBlockingQueue(&invalidReferenceFrameTuples)); freeFrameInvalidationList(LbqDestroyLinkedBlockingQueue(&invalidReferenceFrameTuples));
} }
int getNextFrameInvalidationTuple(PQUEUED_FRAME_INVALIDATION_TUPLE *qfit) { int getNextFrameInvalidationTuple(PQUEUED_FRAME_INVALIDATION_TUPLE *qfit) {
int err = LbqPollQueueElement(&invalidReferenceFrameTuples, (void**) qfit); int err = LbqPollQueueElement(&invalidReferenceFrameTuples, (void**)qfit);
return (err == LBQ_SUCCESS); return (err == LBQ_SUCCESS);
} }
void queueFrameInvalidationTuple(int startFrame, int endFrame) { void queueFrameInvalidationTuple(int startFrame, int endFrame) {
if (VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION) { if (VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION) {
PQUEUED_FRAME_INVALIDATION_TUPLE qfit; PQUEUED_FRAME_INVALIDATION_TUPLE qfit;
qfit = malloc(sizeof(*qfit)); qfit = malloc(sizeof(*qfit));
@@ -152,51 +151,51 @@ void queueFrameInvalidationTuple(int startFrame, int endFrame) {
PltSetEvent(&invalidateRefFramesEvent); PltSetEvent(&invalidateRefFramesEvent);
} }
/* Request an IDR frame on demand by the decoder */ // Request an IDR frame on demand by the decoder
void requestIdrOnDemand(void) { void requestIdrOnDemand(void) {
idrFrameRequired = 1; idrFrameRequired = 1;
PltSetEvent(&invalidateRefFramesEvent); PltSetEvent(&invalidateRefFramesEvent);
} }
/* Invalidate reference frames if the decoder is too slow */ // Invalidate reference frames if the decoder is too slow
void connectionSinkTooSlow(int startFrame, int endFrame) { void connectionSinkTooSlow(int startFrame, int endFrame) {
queueFrameInvalidationTuple(startFrame, endFrame); queueFrameInvalidationTuple(startFrame, endFrame);
} }
/* Invalidate reference frames lost by the network */ // Invalidate reference frames lost by the network
void connectionDetectedFrameLoss(int startFrame, int endFrame) { void connectionDetectedFrameLoss(int startFrame, int endFrame) {
queueFrameInvalidationTuple(startFrame, endFrame); queueFrameInvalidationTuple(startFrame, endFrame);
} }
/* When we receive a frame, update the number of our current frame */ // When we receive a frame, update the number of our current frame
void connectionReceivedFrame(int frameIndex) { void connectionReceivedFrame(int frameIndex) {
currentFrame = frameIndex; currentFrame = frameIndex;
} }
/* When we lose packets, update our packet loss count */ // When we lose packets, update our packet loss count
void connectionLostPackets(int lastReceivedPacket, int nextReceivedPacket) { void connectionLostPackets(int lastReceivedPacket, int nextReceivedPacket) {
lossCountSinceLastReport += (nextReceivedPacket - lastReceivedPacket) - 1; lossCountSinceLastReport += (nextReceivedPacket - lastReceivedPacket) - 1;
} }
/* Reads an NV control stream packet */ // Reads an NV control stream packet
static PNVCTL_PACKET_HEADER readNvctlPacket(void) { static PNVCTL_PACKET_HEADER readNvctlPacket(void) {
NVCTL_PACKET_HEADER staticHeader; NVCTL_PACKET_HEADER staticHeader;
PNVCTL_PACKET_HEADER fullPacket; PNVCTL_PACKET_HEADER fullPacket;
SOCK_RET err; SOCK_RET err;
err = recv(ctlSock, (char*) &staticHeader, sizeof(staticHeader), 0); err = recv(ctlSock, (char*)&staticHeader, sizeof(staticHeader), 0);
if (err != sizeof(staticHeader)) { if (err != sizeof(staticHeader)) {
return NULL; return NULL;
} }
fullPacket = (PNVCTL_PACKET_HEADER) malloc(staticHeader.payloadLength + sizeof(staticHeader)); fullPacket = (PNVCTL_PACKET_HEADER)malloc(staticHeader.payloadLength + sizeof(staticHeader));
if (fullPacket == NULL) { if (fullPacket == NULL) {
return NULL; return NULL;
} }
memcpy(fullPacket, &staticHeader, sizeof(staticHeader)); memcpy(fullPacket, &staticHeader, sizeof(staticHeader));
if (staticHeader.payloadLength != 0) { if (staticHeader.payloadLength != 0) {
err = recv(ctlSock, (char*) (fullPacket + 1), staticHeader.payloadLength, 0); err = recv(ctlSock, (char*)(fullPacket + 1), staticHeader.payloadLength, 0);
if (err != staticHeader.payloadLength) { if (err != staticHeader.payloadLength) {
free(fullPacket); free(fullPacket);
return NULL; return NULL;
@@ -219,7 +218,7 @@ static int sendMessageAndForget(short ptype, short paylen, const void* payload)
packet->payloadLength = paylen; packet->payloadLength = paylen;
memcpy(&packet[1], payload, paylen); memcpy(&packet[1], payload, paylen);
err = send(ctlSock, (char*) packet, sizeof(*packet) + paylen, 0); err = send(ctlSock, (char*)packet, sizeof(*packet) + paylen, 0);
free(packet); free(packet);
if (err != sizeof(*packet) + paylen) { if (err != sizeof(*packet) + paylen) {
@@ -239,12 +238,12 @@ static PNVCTL_PACKET_HEADER sendMessage(short ptype, short paylen, const void* p
static int sendMessageAndDiscardReply(short ptype, short paylen, const void* payload) { static int sendMessageAndDiscardReply(short ptype, short paylen, const void* payload) {
PNVCTL_PACKET_HEADER reply; PNVCTL_PACKET_HEADER reply;
reply = sendMessage(ptype, paylen, payload); reply = sendMessage(ptype, paylen, payload);
if (reply == NULL) { if (reply == NULL) {
return 0; return 0;
} }
free(reply); free(reply);
return 1; return 1;
} }
@@ -302,7 +301,7 @@ static void requestIdrFrame(void) {
// Send the reference frame invalidation request and read the response // Send the reference frame invalidation request and read the response
if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES], if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES],
payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) { payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) {
Limelog("Request IDR Frame: Transaction failed: %d\n", (int) LastSocketError()); Limelog("Request IDR Frame: Transaction failed: %d\n", (int)LastSocketError());
ListenerCallbacks.connectionTerminated(LastSocketError()); ListenerCallbacks.connectionTerminated(LastSocketError());
return; return;
} }
@@ -311,7 +310,7 @@ static void requestIdrFrame(void) {
// Send IDR frame request and read the response // Send IDR frame request and read the response
if (!sendMessageAndDiscardReply(packetTypes[IDX_REQUEST_IDR_FRAME], if (!sendMessageAndDiscardReply(packetTypes[IDX_REQUEST_IDR_FRAME],
payloadLengths[IDX_REQUEST_IDR_FRAME], preconstructedPayloads[IDX_REQUEST_IDR_FRAME])) { payloadLengths[IDX_REQUEST_IDR_FRAME], preconstructedPayloads[IDX_REQUEST_IDR_FRAME])) {
Limelog("Request IDR Frame: Transaction failed: %d\n", (int) LastSocketError()); Limelog("Request IDR Frame: Transaction failed: %d\n", (int)LastSocketError());
ListenerCallbacks.connectionTerminated(LastSocketError()); ListenerCallbacks.connectionTerminated(LastSocketError());
return; return;
} }
@@ -346,7 +345,7 @@ static void requestInvalidateReferenceFrames(void) {
// Send the reference frame invalidation request and read the response // Send the reference frame invalidation request and read the response
if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES], if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES],
payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) { payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) {
Limelog("Request Invaldiate Reference Frames: Transaction failed: %d\n", (int) LastSocketError()); Limelog("Request Invaldiate Reference Frames: Transaction failed: %d\n", (int)LastSocketError());
ListenerCallbacks.connectionTerminated(LastSocketError()); ListenerCallbacks.connectionTerminated(LastSocketError());
return; return;
} }
@@ -371,14 +370,15 @@ static void invalidateRefFramesFunc(void* context) {
// Send an IDR frame request // Send an IDR frame request
idrFrameRequired = 0; idrFrameRequired = 0;
requestIdrFrame(); requestIdrFrame();
} else { }
else {
// Otherwise invalidate reference frames // Otherwise invalidate reference frames
requestInvalidateReferenceFrames(); requestInvalidateReferenceFrames();
} }
} }
} }
/* Stops the control stream */ // Stops the control stream
int stopControlStream(void) { int stopControlStream(void) {
PltInterruptThread(&lossStatsThread); PltInterruptThread(&lossStatsThread);
PltInterruptThread(&invalidateRefFramesThread); PltInterruptThread(&invalidateRefFramesThread);
@@ -397,7 +397,7 @@ int stopControlStream(void) {
return 0; return 0;
} }
/* Starts the control stream */ // Starts the control stream
int startControlStream(void) { int startControlStream(void) {
int err; int err;
@@ -410,16 +410,16 @@ int startControlStream(void) {
// Send START A // Send START A
if (!sendMessageAndDiscardReply(packetTypes[IDX_START_A], if (!sendMessageAndDiscardReply(packetTypes[IDX_START_A],
payloadLengths[IDX_START_A], payloadLengths[IDX_START_A],
preconstructedPayloads[IDX_START_A])) { preconstructedPayloads[IDX_START_A])) {
Limelog("Start A failed: %d\n", (int)LastSocketError()); Limelog("Start A failed: %d\n", (int)LastSocketError());
return LastSocketFail(); return LastSocketFail();
} }
// Send START B // Send START B
if (!sendMessageAndDiscardReply(packetTypes[IDX_START_B], if (!sendMessageAndDiscardReply(packetTypes[IDX_START_B],
payloadLengths[IDX_START_B], payloadLengths[IDX_START_B],
preconstructedPayloads[IDX_START_B])) { preconstructedPayloads[IDX_START_B])) {
Limelog("Start B failed: %d\n", (int)LastSocketError()); Limelog("Start B failed: %d\n", (int)LastSocketError());
return LastSocketFail(); return LastSocketFail();
} }
+49 -49
View File
@@ -16,7 +16,7 @@ static OAES_CTX* oaesContext;
#define MAX_INPUT_PACKET_SIZE 128 #define MAX_INPUT_PACKET_SIZE 128
/* Contains input stream packets */ // Contains input stream packets
typedef struct _PACKET_HOLDER { typedef struct _PACKET_HOLDER {
int packetLength; int packetLength;
union { union {
@@ -30,9 +30,9 @@ typedef struct _PACKET_HOLDER {
LINKED_BLOCKING_QUEUE_ENTRY entry; LINKED_BLOCKING_QUEUE_ENTRY entry;
} PACKET_HOLDER, *PPACKET_HOLDER; } PACKET_HOLDER, *PPACKET_HOLDER;
/* Initializes the input stream */ // Initializes the input stream
int initializeInputStream(char* aesKeyData, int aesKeyDataLength, int initializeInputStream(char* aesKeyData, int aesKeyDataLength,
char* aesIv, int aesIvLength) { char* aesIv, int aesIvLength) {
if (aesIvLength != OAES_BLOCK_SIZE) if (aesIvLength != OAES_BLOCK_SIZE)
{ {
Limelog("AES IV is incorrect length. Should be %d\n", aesIvLength); Limelog("AES IV is incorrect length. Should be %d\n", aesIvLength);
@@ -64,7 +64,7 @@ int initializeInputStream(char* aesKeyData, int aesKeyDataLength,
return 0; return 0;
} }
/* Destroys and cleans up the input stream */ // Destroys and cleans up the input stream
void destroyInputStream(void) { void destroyInputStream(void) {
PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry; PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry;
@@ -94,12 +94,12 @@ static int checkDirs(short currentVal, short newVal, int* dir) {
if (currentVal == newVal) { if (currentVal == newVal) {
return 1; return 1;
} }
// We want to send a new packet if we've now zeroed an axis // We want to send a new packet if we've now zeroed an axis
if (newVal == 0) { if (newVal == 0) {
return 0; return 0;
} }
if (*dir == 0) { if (*dir == 0) {
if (newVal < currentVal) { if (newVal < currentVal) {
*dir = -1; *dir = -1;
@@ -114,13 +114,13 @@ static int checkDirs(short currentVal, short newVal, int* dir) {
else if (newVal < currentVal) { else if (newVal < currentVal) {
return 0; return 0;
} }
return 1; return 1;
} }
#define OAES_DATA_OFFSET 32 #define OAES_DATA_OFFSET 32
/* Input thread proc */ // Input thread proc
static void inputSendThreadProc(void* context) { static void inputSendThreadProc(void* context) {
SOCK_RET err; SOCK_RET err;
PPACKET_HOLDER holder; PPACKET_HOLDER holder;
@@ -130,33 +130,33 @@ static void inputSendThreadProc(void* context) {
while (!PltIsThreadInterrupted(&inputSendThread)) { while (!PltIsThreadInterrupted(&inputSendThread)) {
int encryptedLengthPrefix; int encryptedLengthPrefix;
err = LbqWaitForQueueElement(&packetQueue, (void**) &holder); err = LbqWaitForQueueElement(&packetQueue, (void**)&holder);
if (err != LBQ_SUCCESS) { if (err != LBQ_SUCCESS) {
return; return;
} }
// If it's a multi-controller packet we can do batching // If it's a multi-controller packet we can do batching
if (holder->packet.multiController.header.packetType == htonl(PACKET_TYPE_MULTI_CONTROLLER)) { if (holder->packet.multiController.header.packetType == htonl(PACKET_TYPE_MULTI_CONTROLLER)) {
PPACKET_HOLDER controllerBatchHolder; PPACKET_HOLDER controllerBatchHolder;
PNV_MULTI_CONTROLLER_PACKET origPkt; PNV_MULTI_CONTROLLER_PACKET origPkt;
int dirs[6]; int dirs[6];
memset(dirs, 0, sizeof(dirs)); memset(dirs, 0, sizeof(dirs));
origPkt = &holder->packet.multiController; origPkt = &holder->packet.multiController;
for (;;) { for (;;) {
PNV_MULTI_CONTROLLER_PACKET newPkt; PNV_MULTI_CONTROLLER_PACKET newPkt;
// Peek at the next packet // Peek at the next packet
if (LbqPeekQueueElement(&packetQueue, (void**)&controllerBatchHolder) != LBQ_SUCCESS) { if (LbqPeekQueueElement(&packetQueue, (void**)&controllerBatchHolder) != LBQ_SUCCESS) {
break; break;
} }
// If it's not a controller packet, we're done // If it's not a controller packet, we're done
if (controllerBatchHolder->packet.multiController.header.packetType != htonl(PACKET_TYPE_MULTI_CONTROLLER)) { if (controllerBatchHolder->packet.multiController.header.packetType != htonl(PACKET_TYPE_MULTI_CONTROLLER)) {
break; break;
} }
// Check if it's able to be batched // Check if it's able to be batched
newPkt = &controllerBatchHolder->packet.multiController; newPkt = &controllerBatchHolder->packet.multiController;
if (newPkt->buttonFlags != origPkt->buttonFlags || if (newPkt->buttonFlags != origPkt->buttonFlags ||
@@ -170,12 +170,12 @@ static void inputSendThreadProc(void* context) {
// Batching not allowed // Batching not allowed
break; break;
} }
// Remove the batchable controller packet // Remove the batchable controller packet
if (LbqPollQueueElement(&packetQueue, (void**)&controllerBatchHolder) != LBQ_SUCCESS) { if (LbqPollQueueElement(&packetQueue, (void**)&controllerBatchHolder) != LBQ_SUCCESS) {
break; break;
} }
// Update the original packet // Update the original packet
origPkt->leftTrigger = newPkt->leftTrigger; origPkt->leftTrigger = newPkt->leftTrigger;
origPkt->rightTrigger = newPkt->rightTrigger; origPkt->rightTrigger = newPkt->rightTrigger;
@@ -183,7 +183,7 @@ static void inputSendThreadProc(void* context) {
origPkt->leftStickY = newPkt->leftStickY; origPkt->leftStickY = newPkt->leftStickY;
origPkt->rightStickX = newPkt->rightStickX; origPkt->rightStickX = newPkt->rightStickX;
origPkt->rightStickY = newPkt->rightStickY; origPkt->rightStickY = newPkt->rightStickY;
// Free the batched packet holder // Free the batched packet holder
free(controllerBatchHolder); free(controllerBatchHolder);
} }
@@ -193,24 +193,24 @@ static void inputSendThreadProc(void* context) {
PPACKET_HOLDER mouseBatchHolder; PPACKET_HOLDER mouseBatchHolder;
int totalDeltaX = (short)htons(holder->packet.mouseMove.deltaX); int totalDeltaX = (short)htons(holder->packet.mouseMove.deltaX);
int totalDeltaY = (short)htons(holder->packet.mouseMove.deltaY); int totalDeltaY = (short)htons(holder->packet.mouseMove.deltaY);
for (;;) { for (;;) {
int partialDeltaX; int partialDeltaX;
int partialDeltaY; int partialDeltaY;
// Peek at the next packet // Peek at the next packet
if (LbqPeekQueueElement(&packetQueue, (void**)&mouseBatchHolder) != LBQ_SUCCESS) { if (LbqPeekQueueElement(&packetQueue, (void**)&mouseBatchHolder) != LBQ_SUCCESS) {
break; break;
} }
// If it's not a mouse move packet, we're done // If it's not a mouse move packet, we're done
if (mouseBatchHolder->packet.mouseMove.header.packetType != htonl(PACKET_TYPE_MOUSE_MOVE)) { if (mouseBatchHolder->packet.mouseMove.header.packetType != htonl(PACKET_TYPE_MOUSE_MOVE)) {
break; break;
} }
partialDeltaX = (short)htons(mouseBatchHolder->packet.mouseMove.deltaX); partialDeltaX = (short)htons(mouseBatchHolder->packet.mouseMove.deltaX);
partialDeltaY = (short)htons(mouseBatchHolder->packet.mouseMove.deltaY); partialDeltaY = (short)htons(mouseBatchHolder->packet.mouseMove.deltaY);
// Check for overflow // Check for overflow
if (partialDeltaX + totalDeltaX > INT16_MAX || if (partialDeltaX + totalDeltaX > INT16_MAX ||
partialDeltaX + totalDeltaX < INT16_MIN || partialDeltaX + totalDeltaX < INT16_MIN ||
@@ -219,27 +219,27 @@ static void inputSendThreadProc(void* context) {
// Total delta would overflow our 16-bit short // Total delta would overflow our 16-bit short
break; break;
} }
// Remove the batchable mouse move packet // Remove the batchable mouse move packet
if (LbqPollQueueElement(&packetQueue, (void**)&mouseBatchHolder) != LBQ_SUCCESS) { if (LbqPollQueueElement(&packetQueue, (void**)&mouseBatchHolder) != LBQ_SUCCESS) {
break; break;
} }
totalDeltaX += partialDeltaX; totalDeltaX += partialDeltaX;
totalDeltaY += partialDeltaY; totalDeltaY += partialDeltaY;
// Free the batched packet holder // Free the batched packet holder
free(mouseBatchHolder); free(mouseBatchHolder);
} }
// Update the original packet // Update the original packet
holder->packet.mouseMove.deltaX = htons((short)totalDeltaX); holder->packet.mouseMove.deltaX = htons((short)totalDeltaX);
holder->packet.mouseMove.deltaY = htons((short)totalDeltaY); holder->packet.mouseMove.deltaY = htons((short)totalDeltaY);
} }
encryptedSize = sizeof(encryptedBuffer); encryptedSize = sizeof(encryptedBuffer);
err = oaes_encrypt(oaesContext, (const unsigned char*) &holder->packet, holder->packetLength, err = oaes_encrypt(oaesContext, (const unsigned char*)&holder->packet, holder->packetLength,
(unsigned char*) encryptedBuffer, &encryptedSize); (unsigned char*)encryptedBuffer, &encryptedSize);
free(holder); free(holder);
if (err != OAES_RET_SUCCESS) { if (err != OAES_RET_SUCCESS) {
Limelog("Input: Encryption failed: %d\n", (int)err); Limelog("Input: Encryption failed: %d\n", (int)err);
@@ -253,12 +253,12 @@ static void inputSendThreadProc(void* context) {
// Overwrite the last 4 bytes before the encrypted data with the length so // Overwrite the last 4 bytes before the encrypted data with the length so
// we can send the message all at once. GFE can choke if it gets the header // we can send the message all at once. GFE can choke if it gets the header
// before the rest of the message. // before the rest of the message.
encryptedLengthPrefix = htonl((unsigned long) encryptedSize); encryptedLengthPrefix = htonl((unsigned long)encryptedSize);
memcpy(&encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)], memcpy(&encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)],
&encryptedLengthPrefix, sizeof(encryptedLengthPrefix)); &encryptedLengthPrefix, sizeof(encryptedLengthPrefix));
// Send the encrypted payload // Send the encrypted payload
err = send(inputSock, (const char*) &encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)], err = send(inputSock, (const char*)&encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)],
(int)(encryptedSize + sizeof(encryptedLengthPrefix)), 0); (int)(encryptedSize + sizeof(encryptedLengthPrefix)), 0);
if (err <= 0) { if (err <= 0) {
Limelog("Input: send() failed: %d\n", (int)LastSocketError()); Limelog("Input: send() failed: %d\n", (int)LastSocketError());
@@ -268,7 +268,7 @@ static void inputSendThreadProc(void* context) {
} }
} }
/* Begin the input stream */ // Begin the input stream
int startInputStream(void) { int startInputStream(void) {
int err; int err;
@@ -287,7 +287,7 @@ int startInputStream(void) {
return err; return err;
} }
/* Stops the input stream */ // Stops the input stream
int stopInputStream(void) { int stopInputStream(void) {
PltInterruptThread(&inputSendThread); PltInterruptThread(&inputSendThread);
@@ -302,7 +302,7 @@ int stopInputStream(void) {
return 0; return 0;
} }
/* Send a mouse move event to the streaming machine */ // Send a mouse move event to the streaming machine
int LiSendMouseMoveEvent(short deltaX, short deltaY) { int LiSendMouseMoveEvent(short deltaX, short deltaY) {
PPACKET_HOLDER holder; PPACKET_HOLDER holder;
int err; int err;
@@ -330,7 +330,7 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) {
return err; return err;
} }
/* Send a mouse button event to the streaming machine */ // Send a mouse button event to the streaming machine
int LiSendMouseButtonEvent(char action, int button) { int LiSendMouseButtonEvent(char action, int button) {
PPACKET_HOLDER holder; PPACKET_HOLDER holder;
int err; int err;
@@ -357,7 +357,7 @@ int LiSendMouseButtonEvent(char action, int button) {
return err; return err;
} }
/* Send a key press event to the streaming machine */ // Send a key press event to the streaming machine
int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) { int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
PPACKET_HOLDER holder; PPACKET_HOLDER holder;
int err; int err;
@@ -388,20 +388,20 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
} }
static int sendControllerEventInternal(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger, static int sendControllerEventInternal(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
short leftStickX, short leftStickY, short rightStickX, short rightStickY) short leftStickX, short leftStickY, short rightStickX, short rightStickY)
{ {
PPACKET_HOLDER holder; PPACKET_HOLDER holder;
int err; int err;
if (!initialized) { if (!initialized) {
return -2; return -2;
} }
holder = malloc(sizeof(*holder)); holder = malloc(sizeof(*holder));
if (holder == NULL) { if (holder == NULL) {
return -1; return -1;
} }
if (ServerMajorVersion == 3) { if (ServerMajorVersion == 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
@@ -438,32 +438,32 @@ static int sendControllerEventInternal(short controllerNumber, short buttonFlags
holder->packet.multiController.tailA = MC_TAIL_A; holder->packet.multiController.tailA = MC_TAIL_A;
holder->packet.multiController.tailB = MC_TAIL_B; holder->packet.multiController.tailB = MC_TAIL_B;
} }
err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry); err = LbqOfferQueueItem(&packetQueue, holder, &holder->entry);
if (err != LBQ_SUCCESS) { if (err != LBQ_SUCCESS) {
free(holder); free(holder);
} }
return err; return err;
} }
/* Send a controller event to the streaming machine */ // Send a controller event to the streaming machine
int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger, int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
short leftStickX, short leftStickY, short rightStickX, short rightStickY) short leftStickX, short leftStickY, short rightStickX, short rightStickY)
{ {
return sendControllerEventInternal(0, buttonFlags, leftTrigger, rightTrigger, return sendControllerEventInternal(0, buttonFlags, leftTrigger, rightTrigger,
leftStickX, leftStickY, rightStickX, rightStickY); leftStickX, leftStickY, rightStickX, rightStickY);
} }
/* Send a controller event to the streaming machine */ // Send a controller event to the streaming machine
int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger, int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
short leftStickX, short leftStickY, short rightStickX, short rightStickY) short leftStickX, short leftStickY, short rightStickX, short rightStickY)
{ {
return sendControllerEventInternal(controllerNumber, buttonFlags, leftTrigger, rightTrigger, return sendControllerEventInternal(controllerNumber, buttonFlags, leftTrigger, rightTrigger,
leftStickX, leftStickY, rightStickX, rightStickY); leftStickX, leftStickY, rightStickX, rightStickY);
} }
/* Send a scroll event to the streaming machine */ // Send a scroll event to the streaming machine
int LiSendScrollEvent(signed char scrollClicks) { int LiSendScrollEvent(signed char scrollClicks) {
PPACKET_HOLDER holder; PPACKET_HOLDER holder;
int err; int err;
@@ -492,4 +492,4 @@ int LiSendScrollEvent(signed char scrollClicks) {
} }
return err; return err;
} }
+153 -153
View File
@@ -8,62 +8,62 @@
extern "C" { extern "C" {
#endif #endif
// Enable this definition during debugging to enable assertions // Enable this definition during debugging to enable assertions
//#define LC_DEBUG //#define LC_DEBUG
typedef struct _STREAM_CONFIGURATION { typedef struct _STREAM_CONFIGURATION {
// Dimensions in pixels of the desired video stream // Dimensions in pixels of the desired video stream
int width; int width;
int height; int height;
// FPS of the desired video stream // FPS of the desired video stream
int fps; int fps;
// Bitrate of the desired video stream (audio adds another ~1 Mbps) // Bitrate of the desired video stream (audio adds another ~1 Mbps)
int bitrate; int bitrate;
// Max video packet size in bytes (use 1024 if unsure) // Max video packet size in bytes (use 1024 if unsure)
int packetSize; int packetSize;
// Set to non-zero value to enable remote (over the Internet) // Set to non-zero value to enable remote (over the Internet)
// streaming optimizations. If unsure, set to 0. // streaming optimizations. If unsure, set to 0.
int streamingRemotely; int streamingRemotely;
// Specifies the channel configuration of the audio stream. // Specifies the channel configuration of the audio stream.
// See AUDIO_CONFIGURATION_XXX constants below. // See AUDIO_CONFIGURATION_XXX constants below.
int audioConfiguration; int audioConfiguration;
// AES encryption data for the remote input stream. This must be // AES encryption data for the remote input stream. This must be
// the same as what was passed as rikey and rikeyid // the same as what was passed as rikey and rikeyid
// in /launch and /resume requests. // in /launch and /resume requests.
char remoteInputAesKey[16]; char remoteInputAesKey[16];
char remoteInputAesIv[16]; char remoteInputAesIv[16];
} STREAM_CONFIGURATION, *PSTREAM_CONFIGURATION; } STREAM_CONFIGURATION, *PSTREAM_CONFIGURATION;
// Use this function to zero the stream configuration when allocated on the stack or heap // Use this function to zero the stream configuration when allocated on the stack or heap
void LiInitializeStreamConfiguration(PSTREAM_CONFIGURATION streamConfig); void LiInitializeStreamConfiguration(PSTREAM_CONFIGURATION streamConfig);
typedef struct _LENTRY { typedef struct _LENTRY {
// Pointer to the next entry or NULL if this is the last entry // Pointer to the next entry or NULL if this is the last entry
struct _LENTRY *next; struct _LENTRY *next;
// Pointer to data (never NULL) // Pointer to data (never NULL)
char* data; char* data;
// Size of data in bytes (never <= 0) // Size of data in bytes (never <= 0)
int length; int length;
} LENTRY, *PLENTRY; } LENTRY, *PLENTRY;
// A decode unit describes a buffer chain of H264 data from multiple packets // A decode unit describes a buffer chain of H264 data from multiple packets
typedef struct _DECODE_UNIT { typedef struct _DECODE_UNIT {
// Length of the entire buffer chain in bytes // Length of the entire buffer chain in bytes
int fullLength; int fullLength;
// Head of the buffer chain (never NULL) // Head of the buffer chain (never NULL)
PLENTRY bufferList; PLENTRY bufferList;
} DECODE_UNIT, *PDECODE_UNIT; } DECODE_UNIT, *PDECODE_UNIT;
// Specifies that the audio stream should be encoded in stereo (default) // Specifies that the audio stream should be encoded in stereo (default)
#define AUDIO_CONFIGURATION_STEREO 0 #define AUDIO_CONFIGURATION_STEREO 0
// Specifies that the audio stream should be in 5.1 surround sound if the PC is able // Specifies that the audio stream should be in 5.1 surround sound if the PC is able
@@ -85,73 +85,73 @@ typedef struct _DECODE_UNIT {
#define CAPABILITY_SLICES_PER_FRAME(x) (((unsigned char)(x)) << 24) #define CAPABILITY_SLICES_PER_FRAME(x) (((unsigned char)(x)) << 24)
// This callback is invoked to provide details about the video stream and allow configuration of the decoder // This callback is invoked to provide details about the video stream and allow configuration of the decoder
typedef void(*DecoderRendererSetup)(int width, int height, int redrawRate, void* context, int drFlags); typedef void(*DecoderRendererSetup)(int width, int height, int redrawRate, void* context, int drFlags);
// This callback performs the teardown of the video decoder // This callback performs the teardown of the video decoder
typedef void(*DecoderRendererCleanup)(void); typedef void(*DecoderRendererCleanup)(void);
// This callback provides Annex B formatted H264 elementary stream data to the // This callback provides Annex B formatted H264 elementary stream data to the
// decoder. If the decoder is unable to process the submitted data for some reason, // decoder. If the decoder is unable to process the submitted data for some reason,
// it must return DR_NEED_IDR to generate a keyframe. // it must return DR_NEED_IDR to generate a keyframe.
#define DR_OK 0 #define DR_OK 0
#define DR_NEED_IDR -1 #define DR_NEED_IDR -1
typedef int(*DecoderRendererSubmitDecodeUnit)(PDECODE_UNIT decodeUnit); typedef int(*DecoderRendererSubmitDecodeUnit)(PDECODE_UNIT decodeUnit);
typedef struct _DECODER_RENDERER_CALLBACKS { typedef struct _DECODER_RENDERER_CALLBACKS {
DecoderRendererSetup setup; DecoderRendererSetup setup;
DecoderRendererCleanup cleanup; DecoderRendererCleanup cleanup;
DecoderRendererSubmitDecodeUnit submitDecodeUnit; DecoderRendererSubmitDecodeUnit submitDecodeUnit;
int capabilities; int capabilities;
} DECODER_RENDERER_CALLBACKS, *PDECODER_RENDERER_CALLBACKS; } DECODER_RENDERER_CALLBACKS, *PDECODER_RENDERER_CALLBACKS;
// Use this function to zero the video callbacks when allocated on the stack or heap // Use this function to zero the video callbacks when allocated on the stack or heap
void LiInitializeVideoCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks); void LiInitializeVideoCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks);
// This structure provides the Opus multistream decoder parameters required to successfully // This structure provides the Opus multistream decoder parameters required to successfully
// decode the audio stream being sent from the computer. See opus_multistream_decoder_init docs // decode the audio stream being sent from the computer. See opus_multistream_decoder_init docs
// for details about these fields. // for details about these fields.
// //
// The supplied mapping array is indexed according to the following output channel order: // The supplied mapping array is indexed according to the following output channel order:
// 0 - Front Left // 0 - Front Left
// 1 - Front Right // 1 - Front Right
// 2 - Center // 2 - Center
// 3 - LFE // 3 - LFE
// 4 - Surround Left // 4 - Surround Left
// 5 - Surround Right // 5 - Surround Right
// //
// If the mapping order does not match the channel order of the audio renderer, you may swap // If the mapping order does not match the channel order of the audio renderer, you may swap
// the values in the mismatched indices until the mapping array matches the desired channel order. // the values in the mismatched indices until the mapping array matches the desired channel order.
typedef struct _OPUS_MULTISTREAM_CONFIGURATION { typedef struct _OPUS_MULTISTREAM_CONFIGURATION {
int sampleRate; int sampleRate;
int channelCount; int channelCount;
int streams; int streams;
int coupledStreams; int coupledStreams;
const unsigned char mapping[6]; const unsigned char mapping[6];
} OPUS_MULTISTREAM_CONFIGURATION, *POPUS_MULTISTREAM_CONFIGURATION; } OPUS_MULTISTREAM_CONFIGURATION, *POPUS_MULTISTREAM_CONFIGURATION;
// This callback initializes the audio renderer. The audio configuration parameter // This callback initializes the audio renderer. The audio configuration parameter
// provides the negotiated audio configuration. This may differ from the one // provides the negotiated audio configuration. This may differ from the one
// specified in the stream configuration. // specified in the stream configuration.
typedef void(*AudioRendererInit)(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig); typedef void(*AudioRendererInit)(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig);
// This callback performs the final teardown of the audio decoder // This callback performs the final teardown of the audio decoder
typedef void(*AudioRendererCleanup)(void); typedef void(*AudioRendererCleanup)(void);
// This callback provides Opus audio data to be decoded and played. sampleLength is in bytes. // This callback provides Opus audio data to be decoded and played. sampleLength is in bytes.
typedef void(*AudioRendererDecodeAndPlaySample)(char* sampleData, int sampleLength); typedef void(*AudioRendererDecodeAndPlaySample)(char* sampleData, int sampleLength);
typedef struct _AUDIO_RENDERER_CALLBACKS { typedef struct _AUDIO_RENDERER_CALLBACKS {
AudioRendererInit init; AudioRendererInit init;
AudioRendererCleanup cleanup; AudioRendererCleanup cleanup;
AudioRendererDecodeAndPlaySample decodeAndPlaySample; AudioRendererDecodeAndPlaySample decodeAndPlaySample;
int capabilities; int capabilities;
} AUDIO_RENDERER_CALLBACKS, *PAUDIO_RENDERER_CALLBACKS; } AUDIO_RENDERER_CALLBACKS, *PAUDIO_RENDERER_CALLBACKS;
// Use this function to zero the audio callbacks when allocated on the stack or heap // Use this function to zero the audio callbacks when allocated on the stack or heap
void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks); void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks);
// Subject to change in future releases // Subject to change in future releases
// Use LiGetStageName() for stable stage names // Use LiGetStageName() for stable stage names
#define STAGE_NONE 0 #define STAGE_NONE 0
#define STAGE_PLATFORM_INIT 1 #define STAGE_PLATFORM_INIT 1
#define STAGE_NAME_RESOLUTION 2 #define STAGE_NAME_RESOLUTION 2
@@ -167,78 +167,78 @@ void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks);
#define STAGE_MAX 12 #define STAGE_MAX 12
// This callback is invoked to indicate that a stage of initialization is about to begin // This callback is invoked to indicate that a stage of initialization is about to begin
typedef void(*ConnListenerStageStarting)(int stage); typedef void(*ConnListenerStageStarting)(int stage);
// This callback is invoked to indicate that a stage of initialization has completed // This callback is invoked to indicate that a stage of initialization has completed
typedef void(*ConnListenerStageComplete)(int stage); typedef void(*ConnListenerStageComplete)(int stage);
// This callback is invoked to indicate that a stage of initialization has failed // This callback is invoked to indicate that a stage of initialization has failed
typedef void(*ConnListenerStageFailed)(int stage, long errorCode); typedef void(*ConnListenerStageFailed)(int stage, long errorCode);
// This callback is invoked after initialization has finished // This callback is invoked after initialization has finished
typedef void(*ConnListenerConnectionStarted)(void); typedef void(*ConnListenerConnectionStarted)(void);
// This callback is invoked when a connection failure occurs. It will not // This callback is invoked when a connection failure occurs. It will not
// occur as a result of a call to LiStopConnection() // occur as a result of a call to LiStopConnection()
typedef void(*ConnListenerConnectionTerminated)(long errorCode); typedef void(*ConnListenerConnectionTerminated)(long errorCode);
// This callback is invoked to display a dialog-type message to the user // This callback is invoked to display a dialog-type message to the user
typedef void(*ConnListenerDisplayMessage)(char* message); typedef void(*ConnListenerDisplayMessage)(char* message);
// This callback is invoked to display a transient message for the user // This callback is invoked to display a transient message for the user
// while streaming // while streaming
typedef void(*ConnListenerDisplayTransientMessage)(char* message); typedef void(*ConnListenerDisplayTransientMessage)(char* message);
typedef struct _CONNECTION_LISTENER_CALLBACKS { typedef struct _CONNECTION_LISTENER_CALLBACKS {
ConnListenerStageStarting stageStarting; ConnListenerStageStarting stageStarting;
ConnListenerStageComplete stageComplete; ConnListenerStageComplete stageComplete;
ConnListenerStageFailed stageFailed; ConnListenerStageFailed stageFailed;
ConnListenerConnectionStarted connectionStarted; ConnListenerConnectionStarted connectionStarted;
ConnListenerConnectionTerminated connectionTerminated; ConnListenerConnectionTerminated connectionTerminated;
ConnListenerDisplayMessage displayMessage; ConnListenerDisplayMessage displayMessage;
ConnListenerDisplayTransientMessage displayTransientMessage; ConnListenerDisplayTransientMessage displayTransientMessage;
} CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS; } CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_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);
// 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 // _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, 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); 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);
// Use to get a user-visible string to display initialization progress // Use to get a user-visible string to display initialization progress
// from the integer passed to the ConnListenerStageXXX callbacks // from the integer passed to the ConnListenerStageXXX callbacks
const char* LiGetStageName(int stage); const char* LiGetStageName(int stage);
// This function queues a mouse move event to be sent to the remote server. // This function queues a mouse move event to be sent to the remote server.
int LiSendMouseMoveEvent(short deltaX, short deltaY); int LiSendMouseMoveEvent(short deltaX, short deltaY);
// This function queues a mouse button event to be sent to the remote server. // This function queues a mouse button event to be sent to the remote server.
#define BUTTON_ACTION_PRESS 0x07 #define BUTTON_ACTION_PRESS 0x07
#define BUTTON_ACTION_RELEASE 0x08 #define BUTTON_ACTION_RELEASE 0x08
#define BUTTON_LEFT 0x01 #define BUTTON_LEFT 0x01
#define BUTTON_MIDDLE 0x02 #define BUTTON_MIDDLE 0x02
#define BUTTON_RIGHT 0x03 #define BUTTON_RIGHT 0x03
int LiSendMouseButtonEvent(char action, int button); int LiSendMouseButtonEvent(char action, int button);
// This function queues a keyboard event to be sent to the remote server. // This function queues a keyboard event to be sent to the remote server.
#define KEY_ACTION_DOWN 0x03 #define KEY_ACTION_DOWN 0x03
#define KEY_ACTION_UP 0x04 #define KEY_ACTION_UP 0x04
#define MODIFIER_SHIFT 0x01 #define MODIFIER_SHIFT 0x01
#define MODIFIER_CTRL 0x02 #define MODIFIER_CTRL 0x02
#define MODIFIER_ALT 0x04 #define MODIFIER_ALT 0x04
int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers); int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers);
// Button flags // Button flags
#define A_FLAG 0x1000 #define A_FLAG 0x1000
#define B_FLAG 0x2000 #define B_FLAG 0x2000
#define X_FLAG 0x4000 #define X_FLAG 0x4000
@@ -257,18 +257,18 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers);
// This function queues a controller event to be sent to the remote server. It will // This function queues a controller event to be sent to the remote server. It will
// be seen by the computer as the first controller. // be seen by the computer as the first controller.
int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger, int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
short leftStickX, short leftStickY, short rightStickX, short rightStickY); short leftStickX, short leftStickY, short rightStickX, short rightStickY);
// This function queues a controller event to be sent to the remote server. The controllerNumber // This function queues a controller event to be sent to the remote server. The controllerNumber
// parameter is a zero-based index of which controller this event corresponds to. The largest legal // parameter is a zero-based index of which controller this event corresponds to. The largest legal
// controller number is 3 (for a total of 4 controllers, the Xinput maximum). On generation 3 servers (GFE 2.1.x), // controller number is 3 (for a total of 4 controllers, the Xinput maximum). On generation 3 servers (GFE 2.1.x),
// these will be sent as controller 0 regardless of the controllerNumber parameter. // these will be sent as controller 0 regardless of the controllerNumber parameter.
int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger, int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
short leftStickX, short leftStickY, short rightStickX, short rightStickY); short leftStickX, short leftStickY, short rightStickX, short rightStickY);
// This function queues a vertical scroll event to the remote server. // This function queues a vertical scroll event to the remote server.
int LiSendScrollEvent(signed char scrollClicks); int LiSendScrollEvent(signed char scrollClicks);
#ifdef __cplusplus #ifdef __cplusplus
} }
+19 -19
View File
@@ -1,17 +1,17 @@
#include "LinkedBlockingQueue.h" #include "LinkedBlockingQueue.h"
/* Destroy the linked blocking queue and associated mutex and event */ // Destroy the linked blocking queue and associated mutex and event
PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead) { PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead) {
PltDeleteMutex(&queueHead->mutex); PltDeleteMutex(&queueHead->mutex);
PltCloseEvent(&queueHead->containsDataEvent); PltCloseEvent(&queueHead->containsDataEvent);
return queueHead->head; return queueHead->head;
} }
/* Flush the queue */ // Flush the queue
PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead) { PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead) {
PLINKED_BLOCKING_QUEUE_ENTRY head; PLINKED_BLOCKING_QUEUE_ENTRY head;
PltLockMutex(&queueHead->mutex); PltLockMutex(&queueHead->mutex);
// Save the old head // Save the old head
@@ -28,10 +28,10 @@ PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead
return head; return head;
} }
/* Linked blocking queue init */ // Linked blocking queue init
int LbqInitializeLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead, int sizeBound) { int LbqInitializeLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead, int sizeBound) {
int err; int err;
err = PltCreateEvent(&queueHead->containsDataEvent); err = PltCreateEvent(&queueHead->containsDataEvent);
if (err != 0) { if (err != 0) {
return err; return err;
@@ -90,35 +90,35 @@ int LbqPeekQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) {
if (queueHead->head == NULL) { if (queueHead->head == NULL) {
return LBQ_NO_ELEMENT; return LBQ_NO_ELEMENT;
} }
PltLockMutex(&queueHead->mutex); PltLockMutex(&queueHead->mutex);
if (queueHead->head == NULL) { if (queueHead->head == NULL) {
PltUnlockMutex(&queueHead->mutex); PltUnlockMutex(&queueHead->mutex);
return LBQ_NO_ELEMENT; return LBQ_NO_ELEMENT;
} }
*data = queueHead->head->data; *data = queueHead->head->data;
PltUnlockMutex(&queueHead->mutex); PltUnlockMutex(&queueHead->mutex);
return LBQ_SUCCESS; return LBQ_SUCCESS;
} }
int LbqPollQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) { int LbqPollQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) {
PLINKED_BLOCKING_QUEUE_ENTRY entry; PLINKED_BLOCKING_QUEUE_ENTRY entry;
if (queueHead->head == NULL) { if (queueHead->head == NULL) {
return LBQ_NO_ELEMENT; return LBQ_NO_ELEMENT;
} }
PltLockMutex(&queueHead->mutex); PltLockMutex(&queueHead->mutex);
if (queueHead->head == NULL) { if (queueHead->head == NULL) {
PltUnlockMutex(&queueHead->mutex); PltUnlockMutex(&queueHead->mutex);
return LBQ_NO_ELEMENT; return LBQ_NO_ELEMENT;
} }
entry = queueHead->head; entry = queueHead->head;
queueHead->head = entry->flink; queueHead->head = entry->flink;
queueHead->currentSize--; queueHead->currentSize--;
@@ -131,11 +131,11 @@ int LbqPollQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) {
LC_ASSERT(queueHead->currentSize != 0); LC_ASSERT(queueHead->currentSize != 0);
queueHead->head->blink = NULL; queueHead->head->blink = NULL;
} }
*data = entry->data; *data = entry->data;
PltUnlockMutex(&queueHead->mutex); PltUnlockMutex(&queueHead->mutex);
return LBQ_SUCCESS; return LBQ_SUCCESS;
} }
@@ -178,4 +178,4 @@ int LbqWaitForQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data) {
} }
return LBQ_SUCCESS; return LBQ_SUCCESS;
} }
+1 -1
View File
@@ -31,4 +31,4 @@ 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));
} }
+3 -4
View File
@@ -35,9 +35,9 @@ void* ThreadProc(void* context) {
struct thread_context *ctx = (struct thread_context *)context; struct thread_context *ctx = (struct thread_context *)context;
ctx->entry(ctx->context); ctx->entry(ctx->context);
free(ctx); free(ctx);
return NULL; return NULL;
} }
#endif #endif
@@ -102,7 +102,7 @@ void PltJoinThread(PLT_THREAD *thread) {
void PltCloseThread(PLT_THREAD *thread) { void PltCloseThread(PLT_THREAD *thread) {
#if defined(LC_WINDOWS) #if defined(LC_WINDOWS)
PLT_THREAD *current_thread; PLT_THREAD *current_thread;
PltLockMutex(&thread_list_lock); PltLockMutex(&thread_list_lock);
if (thread_head == thread) if (thread_head == thread)
@@ -195,7 +195,6 @@ int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
err = 0; err = 0;
} }
} }
#else #else
{ {
+13 -13
View File
@@ -39,21 +39,21 @@ void LimelogWindows(char* Format, ...);
#endif #endif
#if defined(LC_WINDOWS) #if defined(LC_WINDOWS)
#include <crtdbg.h> #include <crtdbg.h>
#ifdef LC_DEBUG #ifdef LC_DEBUG
#define LC_ASSERT(x) __analysis_assume(x); \ #define LC_ASSERT(x) __analysis_assume(x); \
_ASSERTE(x) _ASSERTE(x)
#else
#define LC_ASSERT(x)
#endif
#else #else
#ifndef LC_DEBUG #define LC_ASSERT(x)
#ifndef NDEBUG #endif
#define NDEBUG #else
#endif #ifndef LC_DEBUG
#endif #ifndef NDEBUG
#include <assert.h> #define NDEBUG
#define LC_ASSERT(x) assert(x) #endif
#endif
#include <assert.h>
#define LC_ASSERT(x) assert(x)
#endif #endif
int initializePlatform(void); int initializePlatform(void);
+12 -12
View File
@@ -8,14 +8,14 @@ void addrToUrlSafeString(struct sockaddr_storage *addr, char* string)
if (addr->ss_family == AF_INET6) { if (addr->ss_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
inet_ntop(addr->ss_family, &sin6->sin6_addr, addrstr, sizeof(addrstr)); inet_ntop(addr->ss_family, &sin6->sin6_addr, addrstr, sizeof(addrstr));
// IPv6 addresses need to be enclosed in brackets for URLs // IPv6 addresses need to be enclosed in brackets for URLs
sprintf(string, "[%s]", addrstr); sprintf(string, "[%s]", addrstr);
} }
else { else {
struct sockaddr_in *sin = (struct sockaddr_in *)addr; struct sockaddr_in *sin = (struct sockaddr_in *)addr;
inet_ntop(addr->ss_family, &sin->sin_addr, addrstr, sizeof(addrstr)); inet_ntop(addr->ss_family, &sin->sin_addr, addrstr, sizeof(addrstr));
// IPv4 addresses are returned without changes // IPv4 addresses are returned without changes
sprintf(string, "%s", addrstr); sprintf(string, "%s", addrstr);
} }
@@ -30,7 +30,7 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
int err; int err;
LC_ASSERT(addrfamily == AF_INET || addrfamily == AF_INET6); LC_ASSERT(addrfamily == AF_INET || addrfamily == AF_INET6);
s = socket(addrfamily, SOCK_DGRAM, IPPROTO_UDP); s = socket(addrfamily, SOCK_DGRAM, IPPROTO_UDP);
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
Limelog("socket() failed: %d\n", (int)LastSocketError()); Limelog("socket() failed: %d\n", (int)LastSocketError());
@@ -40,23 +40,23 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.ss_family = addrfamily; addr.ss_family = addrfamily;
if (bind(s, (struct sockaddr*) &addr, if (bind(s, (struct sockaddr*) &addr,
addrfamily == AF_INET ? addrfamily == AF_INET ?
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6)) == SOCKET_ERROR) { sizeof(struct sockaddr_in6)) == SOCKET_ERROR) {
err = LastSocketError(); err = LastSocketError();
Limelog("bind() failed: %d\n", err); Limelog("bind() failed: %d\n", err);
closesocket(s); closesocket(s);
SetLastSocketError(err); SetLastSocketError(err);
return INVALID_SOCKET; return INVALID_SOCKET;
} }
#ifdef LC_DARWIN #ifdef LC_DARWIN
// Disable SIGPIPE on iOS // Disable SIGPIPE on iOS
val = 1; val = 1;
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char* )&val, sizeof(val)); setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
#endif #endif
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*) &bufferSize, sizeof(bufferSize)); setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(bufferSize));
return s; return s;
} }
@@ -74,11 +74,11 @@ SOCKET connectTcpSocket(struct sockaddr_storage *dstaddr, SOCKADDR_LEN addrlen,
Limelog("socket() failed: %d\n", (int)LastSocketError()); Limelog("socket() failed: %d\n", (int)LastSocketError());
return INVALID_SOCKET; return INVALID_SOCKET;
} }
#ifdef LC_DARWIN #ifdef LC_DARWIN
// Disable SIGPIPE on iOS // Disable SIGPIPE on iOS
val = 1; val = 1;
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char* )&val, sizeof(val)); setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
#endif #endif
memcpy(&addr, dstaddr, sizeof(addr)); memcpy(&addr, dstaddr, sizeof(addr));
@@ -133,4 +133,4 @@ void cleanupPlatformSockets(void) {
WSACleanup(); WSACleanup();
#else #else
#endif #endif
} }
+1 -1
View File
@@ -3,7 +3,7 @@
#include "Limelight.h" #include "Limelight.h"
#include "Platform.h" #include "Platform.h"
typedef void (*ThreadEntry)(void *context); typedef void(*ThreadEntry)(void *context);
struct thread_context { struct thread_context {
ThreadEntry entry; ThreadEntry entry;
+2 -2
View File
@@ -94,7 +94,7 @@ static void updateOldestQueued(PRTP_REORDER_QUEUE queue) {
static PRTP_QUEUE_ENTRY getEntryByLowestSeq(PRTP_REORDER_QUEUE queue) { static PRTP_QUEUE_ENTRY getEntryByLowestSeq(PRTP_REORDER_QUEUE queue) {
PRTP_QUEUE_ENTRY lowestSeqEntry, entry; PRTP_QUEUE_ENTRY lowestSeqEntry, entry;
lowestSeqEntry = queue->queueHead; lowestSeqEntry = queue->queueHead;
entry = queue->queueHead; entry = queue->queueHead;
while (entry != NULL) { while (entry != NULL) {
@@ -225,7 +225,7 @@ int RtpqAddPacket(PRTP_REORDER_QUEUE queue, PRTP_PACKET packet, PRTP_QUEUE_ENTRY
} }
else { else {
// Constraint validation may have changed the oldest packet to one that // Constraint validation may have changed the oldest packet to one that
// matches the next sequence number // matches the next sequence number
return (lowestEntry != NULL) ? RTPQ_RET_QUEUED_PACKETS_READY : return (lowestEntry != NULL) ? RTPQ_RET_QUEUED_PACKETS_READY :
RTPQ_RET_QUEUED_NOTHING_READY; RTPQ_RET_QUEUED_NOTHING_READY;
} }
+8 -8
View File
@@ -65,7 +65,7 @@ static int initializeRtspRequest(PRTSP_MESSAGE msg, char* command, char* target)
// FIXME: Hacked CSeq attribute due to RTSP parser bug // FIXME: Hacked CSeq attribute due to RTSP parser bug
createRtspRequest(msg, NULL, 0, command, target, "RTSP/1.0", createRtspRequest(msg, NULL, 0, command, target, "RTSP/1.0",
0, NULL, NULL, 0); 0, NULL, NULL, 0);
sprintf(sequenceNumberStr, "%d", currentSeqNumber++); sprintf(sequenceNumberStr, "%d", currentSeqNumber++);
sprintf(clientVersionStr, "%d", rtspClientVersion); sprintf(clientVersionStr, "%d", rtspClientVersion);
if (!addOption(msg, "CSeq", sequenceNumberStr) || if (!addOption(msg, "CSeq", sequenceNumberStr) ||
@@ -84,7 +84,7 @@ static int transactRtspMessage(PRTSP_MESSAGE request, PRTSP_MESSAGE response, in
int offset; int offset;
char* serializedMessage = NULL; char* serializedMessage = NULL;
int messageLen; int messageLen;
*error = -1; *error = -1;
sock = connectTcpSocket(&RemoteAddr, RemoteAddrLen, 48010); sock = connectTcpSocket(&RemoteAddr, RemoteAddrLen, 48010);
@@ -156,7 +156,7 @@ void terminateRtspHandshake(void) {
static int requestOptions(PRTSP_MESSAGE response, int* error) { static int requestOptions(PRTSP_MESSAGE response, int* error) {
RTSP_MESSAGE request; RTSP_MESSAGE request;
int ret; int ret;
*error = -1; *error = -1;
ret = initializeRtspRequest(&request, "OPTIONS", rtspTargetUrl); ret = initializeRtspRequest(&request, "OPTIONS", rtspTargetUrl);
@@ -172,13 +172,13 @@ static int requestOptions(PRTSP_MESSAGE response, int* error) {
static int requestDescribe(PRTSP_MESSAGE response, int* error) { static int requestDescribe(PRTSP_MESSAGE response, int* error) {
RTSP_MESSAGE request; RTSP_MESSAGE request;
int ret; int ret;
*error = -1; *error = -1;
ret = initializeRtspRequest(&request, "DESCRIBE", rtspTargetUrl); ret = initializeRtspRequest(&request, "DESCRIBE", rtspTargetUrl);
if (ret != 0) { if (ret != 0) {
if (addOption(&request, "Accept", if (addOption(&request, "Accept",
"application/sdp") && "application/sdp") &&
addOption(&request, "If-Modified-Since", addOption(&request, "If-Modified-Since",
"Thu, 01 Jan 1970 00:00:00 GMT")) { "Thu, 01 Jan 1970 00:00:00 GMT")) {
ret = transactRtspMessage(&request, response, error); ret = transactRtspMessage(&request, response, error);
@@ -196,7 +196,7 @@ static int requestDescribe(PRTSP_MESSAGE response, int* error) {
static int setupStream(PRTSP_MESSAGE response, char* target, int* error) { static int setupStream(PRTSP_MESSAGE response, char* target, int* error) {
RTSP_MESSAGE request; RTSP_MESSAGE request;
int ret; int ret;
*error = -1; *error = -1;
ret = initializeRtspRequest(&request, "SETUP", target); ret = initializeRtspRequest(&request, "SETUP", target);
@@ -228,7 +228,7 @@ static int setupStream(PRTSP_MESSAGE response, char* target, int* error) {
static int playStream(PRTSP_MESSAGE response, char* target, int* error) { static int playStream(PRTSP_MESSAGE response, char* target, int* error) {
RTSP_MESSAGE request; RTSP_MESSAGE request;
int ret; int ret;
*error = -1; *error = -1;
ret = initializeRtspRequest(&request, "PLAY", target); ret = initializeRtspRequest(&request, "PLAY", target);
@@ -251,7 +251,7 @@ static int sendVideoAnnounce(PRTSP_MESSAGE response, int* error) {
int ret; int ret;
int payloadLength; int payloadLength;
char payloadLengthStr[16]; char payloadLengthStr[16];
*error = -1; *error = -1;
ret = initializeRtspRequest(&request, "ANNOUNCE", "streamid=video"); ret = initializeRtspRequest(&request, "ANNOUNCE", "streamid=video");
+31 -34
View File
@@ -1,8 +1,7 @@
#include "Rtsp.h" #include "Rtsp.h"
// Check if String s begins with the given prefix // Check if String s begins with the given prefix
static int startsWith(const char* s, const char* prefix) { static int startsWith(const char* s, const char* prefix) {
if (strncmp(s, prefix, strlen(prefix)) == 0) { if (strncmp(s, prefix, strlen(prefix)) == 0) {
return 1; return 1;
} }
@@ -29,26 +28,26 @@ static int getMessageLength(PRTSP_MESSAGE msg) {
// Add 4 for the two spaces and \r\n // Add 4 for the two spaces and \r\n
count += 4; count += 4;
} }
// Add length of response-specific strings // Add length of response-specific strings
else { else {
char statusCodeStr[16]; char statusCodeStr[16];
sprintf(statusCodeStr, "%d", msg->message.response.statusCode); sprintf(statusCodeStr, "%d", msg->message.response.statusCode);
count += strlen(statusCodeStr); count += strlen(statusCodeStr);
count += strlen(msg->message.response.statusString); count += strlen(msg->message.response.statusString);
// Add 4 for two spaces and \r\n // Add 4 for two spaces and \r\n
count += 4; count += 4;
} }
// Count the size of the options // Count the size of the options
current = msg->options; current = msg->options;
while (current != NULL) { while (current != NULL) {
count += strlen(current->option); count += strlen(current->option);
count += strlen(current->content); count += strlen(current->content);
// Add 4 because of :[space] and \r\n // Add 4 because of :[space] and \r\n
count += 4; count += 4;
current = current->next; current = current->next;
} }
// Add 2 more for extra /r/n ending // Add 2 more for extra /r/n ending
count += 2; count += 2;
count += msg->payloadLength; count += msg->payloadLength;
@@ -64,13 +63,13 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
POPTION_ITEM options = NULL; POPTION_ITEM options = NULL;
POPTION_ITEM newOpt; POPTION_ITEM newOpt;
// Delimeter sets for strtok() // Delimeter sets for strtok()
char* delim = " \r\n"; char* delim = " \r\n";
char* end = "\r\n"; char* end = "\r\n";
char* optDelim = " :\r\n"; char* optDelim = " :\r\n";
char typeFlag = TOKEN_OPTION; char typeFlag = TOKEN_OPTION;
// Put the raw message into a string we can use // Put the raw message into a string we can use
char* messageBuffer = malloc(length + 1); char* messageBuffer = malloc(length + 1);
if (messageBuffer == NULL) { if (messageBuffer == NULL) {
exitCode = RTSP_ERROR_NO_MEMORY; exitCode = RTSP_ERROR_NO_MEMORY;
@@ -88,13 +87,13 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
goto ExitFailure; goto ExitFailure;
} }
// The message is a response // The message is a response
if (startsWith(token, "RTSP")) { if (startsWith(token, "RTSP")) {
flag = TYPE_RESPONSE; flag = TYPE_RESPONSE;
// The current token is the protocol // The current token is the protocol
protocol = token; protocol = token;
// Get the status code // Get the status code
token = strtok(NULL, delim); token = strtok(NULL, delim);
statusCode = atoi(token); statusCode = atoi(token);
if (token == NULL) { if (token == NULL) {
@@ -102,19 +101,19 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
goto ExitFailure; goto ExitFailure;
} }
// Get the status string // Get the status string
statusStr = strtok(NULL, end); statusStr = strtok(NULL, end);
if (statusStr == NULL) { if (statusStr == NULL) {
exitCode = RTSP_ERROR_MALFORMED; exitCode = RTSP_ERROR_MALFORMED;
goto ExitFailure; goto ExitFailure;
} }
// Request fields - we don't care about them here // Request fields - we don't care about them here
target = NULL; target = NULL;
command = NULL; command = NULL;
} }
// The message is a request // The message is a request
else { else {
flag = TYPE_REQUEST; flag = TYPE_REQUEST;
command = token; command = token;
@@ -128,7 +127,7 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
exitCode = RTSP_ERROR_MALFORMED; exitCode = RTSP_ERROR_MALFORMED;
goto ExitFailure; goto ExitFailure;
} }
// Response field - we don't care about it here // Response field - we don't care about it here
statusStr = NULL; statusStr = NULL;
} }
if (strcmp(protocol, "RTSP/1.0")) { if (strcmp(protocol, "RTSP/1.0")) {
@@ -140,13 +139,12 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
{ {
token = strtok(NULL, typeFlag == TOKEN_OPTION ? optDelim : end); token = strtok(NULL, typeFlag == TOKEN_OPTION ? optDelim : end);
if (token != NULL) { if (token != NULL) {
if (typeFlag == TOKEN_OPTION) { if (typeFlag == TOKEN_OPTION) {
opt = token; opt = token;
} }
// The token is content // The token is content
else { else {
// Create a new node containing the option and content // Create a new node containing the option and content
newOpt = (POPTION_ITEM)malloc(sizeof(OPTION_ITEM)); newOpt = (POPTION_ITEM)malloc(sizeof(OPTION_ITEM));
if (newOpt == NULL) { if (newOpt == NULL) {
freeOptionList(options); freeOptionList(options);
@@ -160,16 +158,15 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
insertOption(&options, newOpt); insertOption(&options, newOpt);
// Check if we're at the end of the message portion marked by \r\n\r\n // Check if we're at the end of the message portion marked by \r\n\r\n
//endCheck points to the remainder of messageBuffer after the token // endCheck points to the remainder of messageBuffer after the token
endCheck = &token[0] + strlen(token) + 1; endCheck = &token[0] + strlen(token) + 1;
// See if we've hit the end of the message. The first \r is missing because it's been tokenized // See if we've hit the end of the message. The first \r is missing because it's been tokenized
if (startsWith(endCheck, "\n\r\n")) { if (startsWith(endCheck, "\n\r\n")) {
// We've encountered the end of the message - mark it thus
// We've encountered the end of the message - mark it thus
messageEnded = 1; messageEnded = 1;
// The payload is the remainder of messageBuffer. If none, then payload = null // The payload is the remainder of messageBuffer. If none, then payload = null
if (endCheck[3] != '\0') if (endCheck[3] != '\0')
payload = &endCheck[3]; payload = &endCheck[3];
@@ -179,13 +176,13 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
} }
typeFlag ^= 1; // flip the flag typeFlag ^= 1; // flip the flag
} }
// If we never encountered the double CRLF, then the message is malformed! // If we never encountered the double CRLF, then the message is malformed!
if (!messageEnded) { if (!messageEnded) {
exitCode = RTSP_ERROR_MALFORMED; exitCode = RTSP_ERROR_MALFORMED;
goto ExitFailure; goto ExitFailure;
} }
// Get sequence number as an integer // Get sequence number as an integer
sequence = getOptionContent(options, "CSeq"); sequence = getOptionContent(options, "CSeq");
if (sequence != NULL) { if (sequence != NULL) {
sequenceNum = atoi(sequence); sequenceNum = atoi(sequence);
@@ -193,7 +190,7 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
else { else {
sequenceNum = SEQ_INVALID; sequenceNum = SEQ_INVALID;
} }
// Package the new parsed message into the struct // Package the new parsed message into the struct
if (flag == TYPE_REQUEST) { if (flag == TYPE_REQUEST) {
createRtspRequest(msg, messageBuffer, FLAG_ALLOCATED_MESSAGE_BUFFER | FLAG_ALLOCATED_OPTION_ITEMS, command, target, createRtspRequest(msg, messageBuffer, FLAG_ALLOCATED_MESSAGE_BUFFER | FLAG_ALLOCATED_OPTION_ITEMS, command, target,
protocol, sequenceNum, options, payload, payload ? length - (int)(messageBuffer - payload) : 0); protocol, sequenceNum, options, payload, payload ? length - (int)(messageBuffer - payload) : 0);
@@ -248,7 +245,7 @@ void createRtspRequest(PRTSP_MESSAGE msg, char* message, int flags,
char* getOptionContent(POPTION_ITEM optionsHead, char* option) { char* getOptionContent(POPTION_ITEM optionsHead, char* option) {
OPTION_ITEM *current = optionsHead; OPTION_ITEM *current = optionsHead;
while (current != NULL) { while (current != NULL) {
// Check if current node is what we're looking for // Check if current node is what we're looking for
if (!strcmp(current->option, option)) { if (!strcmp(current->option, option)) {
return current->content; return current->content;
} }
@@ -263,15 +260,15 @@ void insertOption(POPTION_ITEM *optionsHead, POPTION_ITEM opt) {
OPTION_ITEM *current = *optionsHead; OPTION_ITEM *current = *optionsHead;
opt->next = NULL; opt->next = NULL;
// Empty options list // Empty options list
if (*optionsHead == NULL) { if (*optionsHead == NULL) {
*optionsHead = opt; *optionsHead = opt;
return; return;
} }
// Traverse the list and insert the new option at the end // Traverse the list and insert the new option at the end
while (current != NULL) { while (current != NULL) {
// Check for duplicate option; if so, replace the option currently there // Check for duplicate option; if so, replace the option currently there
if (!strcmp(current->option, opt->option)) { if (!strcmp(current->option, opt->option)) {
current->content = opt->content; current->content = opt->content;
return; return;
@@ -284,7 +281,7 @@ void insertOption(POPTION_ITEM *optionsHead, POPTION_ITEM opt) {
} }
} }
// Free every node in the message's option list // Free every node in the message's option list
void freeOptionList(POPTION_ITEM optionsHead) { void freeOptionList(POPTION_ITEM optionsHead) {
POPTION_ITEM current = optionsHead; POPTION_ITEM current = optionsHead;
POPTION_ITEM temp; POPTION_ITEM temp;
@@ -299,7 +296,7 @@ void freeOptionList(POPTION_ITEM optionsHead) {
} }
} }
// Serialize the message struct into a string containing the RTSP message // Serialize the message struct into a string containing the RTSP message
char* serializeRtspMessage(PRTSP_MESSAGE msg, int *serializedLength) { char* serializeRtspMessage(PRTSP_MESSAGE msg, int *serializedLength) {
int size = getMessageLength(msg); int size = getMessageLength(msg);
char* serializedMessage; char* serializedMessage;
@@ -345,7 +342,7 @@ char* serializeRtspMessage(PRTSP_MESSAGE msg, int *serializedLength) {
// Final \r\n // Final \r\n
strcat(serializedMessage, "\r\n"); strcat(serializedMessage, "\r\n");
// payload // payload
if (msg->payload != NULL) { if (msg->payload != NULL) {
int offset; int offset;
+39 -39
View File
@@ -12,13 +12,13 @@
#define CHANNEL_MASK_51_SURROUND 0xFC #define CHANNEL_MASK_51_SURROUND 0xFC
typedef struct _SDP_OPTION { typedef struct _SDP_OPTION {
char name[MAX_OPTION_NAME_LEN+1]; char name[MAX_OPTION_NAME_LEN + 1];
void* payload; void* payload;
int payloadLen; int payloadLen;
struct _SDP_OPTION *next; struct _SDP_OPTION *next;
} SDP_OPTION, *PSDP_OPTION; } SDP_OPTION, *PSDP_OPTION;
/* Cleanup the attribute list */ // Cleanup the attribute list
static void freeAttributeList(PSDP_OPTION head) { static void freeAttributeList(PSDP_OPTION head) {
PSDP_OPTION next; PSDP_OPTION next;
while (head != NULL) { while (head != NULL) {
@@ -28,7 +28,7 @@ static void freeAttributeList(PSDP_OPTION head) {
} }
} }
/* Get the size of the attribute list */ // Get the size of the attribute list
static int getSerializedAttributeListSize(PSDP_OPTION head) { static int getSerializedAttributeListSize(PSDP_OPTION head) {
PSDP_OPTION currentEntry = head; PSDP_OPTION currentEntry = head;
size_t size = 0; size_t size = 0;
@@ -44,7 +44,7 @@ static int getSerializedAttributeListSize(PSDP_OPTION head) {
return (int)size; return (int)size;
} }
/* Populate the serialized attribute list into a string */ // Populate the serialized attribute list into a string
static int fillSerializedAttributeList(char* buffer, PSDP_OPTION head) { static int fillSerializedAttributeList(char* buffer, PSDP_OPTION head) {
PSDP_OPTION currentEntry = head; PSDP_OPTION currentEntry = head;
int offset = 0; int offset = 0;
@@ -59,7 +59,7 @@ static int fillSerializedAttributeList(char* buffer, PSDP_OPTION head) {
return offset; return offset;
} }
/* Add an attribute */ // Add an attribute
static int addAttributeBinary(PSDP_OPTION *head, char* name, const void* payload, int payloadLen) { static int addAttributeBinary(PSDP_OPTION *head, char* name, const void* payload, int payloadLen) {
PSDP_OPTION option, currentOption; PSDP_OPTION option, currentOption;
@@ -88,7 +88,7 @@ static int addAttributeBinary(PSDP_OPTION *head, char* name, const void* payload
return 0; return 0;
} }
/* Add an attribute string */ // Add an attribute string
static int addAttributeString(PSDP_OPTION *head, char* name, const char* payload) { static int addAttributeString(PSDP_OPTION *head, char* name, const char* payload) {
// We purposefully omit the null terminating character // We purposefully omit the null terminating character
return addAttributeBinary(head, name, payload, (int)strlen(payload)); return addAttributeBinary(head, name, payload, (int)strlen(payload));
@@ -97,42 +97,41 @@ static int addAttributeString(PSDP_OPTION *head, char* name, const char* payload
static int addGen3Options(PSDP_OPTION *head, char* addrStr) { static int addGen3Options(PSDP_OPTION *head, char* addrStr) {
int payloadInt; int payloadInt;
int err = 0; int err = 0;
err |= addAttributeString(head, "x-nv-general.serverAddress", addrStr); err |= addAttributeString(head, "x-nv-general.serverAddress", addrStr);
payloadInt = htonl(0x42774141); payloadInt = htonl(0x42774141);
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-general.featureFlags", &payloadInt, sizeof(payloadInt)); "x-nv-general.featureFlags", &payloadInt, sizeof(payloadInt));
payloadInt = htonl(0x41514141); payloadInt = htonl(0x41514141);
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[0].transferProtocol", &payloadInt, sizeof(payloadInt)); "x-nv-video[0].transferProtocol", &payloadInt, sizeof(payloadInt));
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[1].transferProtocol", &payloadInt, sizeof(payloadInt)); "x-nv-video[1].transferProtocol", &payloadInt, sizeof(payloadInt));
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[2].transferProtocol", &payloadInt, sizeof(payloadInt)); "x-nv-video[2].transferProtocol", &payloadInt, sizeof(payloadInt));
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[3].transferProtocol", &payloadInt, sizeof(payloadInt)); "x-nv-video[3].transferProtocol", &payloadInt, sizeof(payloadInt));
payloadInt = htonl(0x42414141); payloadInt = htonl(0x42414141);
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt)); "x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt));
payloadInt = htonl(0x42514141); payloadInt = htonl(0x42514141);
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[1].rateControlMode", &payloadInt, sizeof(payloadInt)); "x-nv-video[1].rateControlMode", &payloadInt, sizeof(payloadInt));
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[2].rateControlMode", &payloadInt, sizeof(payloadInt)); "x-nv-video[2].rateControlMode", &payloadInt, sizeof(payloadInt));
err |= addAttributeBinary(head, err |= addAttributeBinary(head,
"x-nv-video[3].rateControlMode", &payloadInt, sizeof(payloadInt)); "x-nv-video[3].rateControlMode", &payloadInt, sizeof(payloadInt));
err |= addAttributeString(head, "x-nv-vqos[0].bw.flags", "14083"); err |= addAttributeString(head, "x-nv-vqos[0].bw.flags", "14083");
err |= addAttributeString(head, "x-nv-vqos[0].videoQosMaxConsecutiveDrops", "0"); err |= addAttributeString(head, "x-nv-vqos[0].videoQosMaxConsecutiveDrops", "0");
err |= addAttributeString(head, "x-nv-vqos[1].videoQosMaxConsecutiveDrops", "0"); err |= addAttributeString(head, "x-nv-vqos[1].videoQosMaxConsecutiveDrops", "0");
err |= addAttributeString(head, "x-nv-vqos[2].videoQosMaxConsecutiveDrops", "0"); err |= addAttributeString(head, "x-nv-vqos[2].videoQosMaxConsecutiveDrops", "0");
err |= addAttributeString(head, "x-nv-vqos[3].videoQosMaxConsecutiveDrops", "0"); err |= addAttributeString(head, "x-nv-vqos[3].videoQosMaxConsecutiveDrops", "0");
return err; return err;
} }
@@ -142,14 +141,14 @@ static int addGen4Options(PSDP_OPTION *head, char* addrStr) {
unsigned char slicesPerFrame; unsigned char slicesPerFrame;
int audioChannelCount; int audioChannelCount;
int audioChannelMask; int audioChannelMask;
sprintf(payloadStr, "rtsp://%s:48010", addrStr); sprintf(payloadStr, "rtsp://%s:48010", addrStr);
err |= addAttributeString(head, "x-nv-general.serverAddress", payloadStr); err |= addAttributeString(head, "x-nv-general.serverAddress", payloadStr);
err |= addAttributeString(head, "x-nv-video[0].rateControlMode", "4"); err |= addAttributeString(head, "x-nv-video[0].rateControlMode", "4");
// Use slicing for increased performance on some decoders // Use slicing for increased performance on some decoders
slicesPerFrame = (unsigned char) (VideoCallbacks.capabilities >> 24); slicesPerFrame = (unsigned char)(VideoCallbacks.capabilities >> 24);
if (slicesPerFrame == 0) { if (slicesPerFrame == 0) {
// If not using slicing, we request 1 slice per frame // If not using slicing, we request 1 slice per frame
slicesPerFrame = 1; slicesPerFrame = 1;
@@ -176,7 +175,7 @@ static int addGen4Options(PSDP_OPTION *head, char* addrStr) {
else { else {
err |= addAttributeString(head, "x-nv-audio.surround.enable", "0"); err |= addAttributeString(head, "x-nv-audio.surround.enable", "0");
} }
return err; return err;
} }
@@ -195,7 +194,7 @@ static PSDP_OPTION getAttributesList(char *urlSafeAddr) {
sprintf(payloadStr, "%d", StreamConfig.fps); sprintf(payloadStr, "%d", StreamConfig.fps);
err |= addAttributeString(&optionHead, "x-nv-video[0].maxFPS", payloadStr); err |= addAttributeString(&optionHead, "x-nv-video[0].maxFPS", payloadStr);
sprintf(payloadStr, "%d", StreamConfig.packetSize); sprintf(payloadStr, "%d", StreamConfig.packetSize);
err |= addAttributeString(&optionHead, "x-nv-video[0].packetSize", payloadStr); err |= addAttributeString(&optionHead, "x-nv-video[0].packetSize", payloadStr);
@@ -223,15 +222,16 @@ static PSDP_OPTION getAttributesList(char *urlSafeAddr) {
err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.enable", "0"); err |= addAttributeString(&optionHead, "x-nv-vqos[0].fec.enable", "0");
err |= addAttributeString(&optionHead, "x-nv-vqos[0].videoQualityScoreUpdateTime", "5000"); err |= addAttributeString(&optionHead, "x-nv-vqos[0].videoQualityScoreUpdateTime", "5000");
if (StreamConfig.streamingRemotely) { if (StreamConfig.streamingRemotely) {
err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "0"); err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "0");
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "0"); err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "0");
} else { }
else {
err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "5"); err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "5");
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4"); err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4");
} }
if (ServerMajorVersion == 3) { if (ServerMajorVersion == 3) {
err |= addGen3Options(&optionHead, urlSafeAddr); err |= addGen3Options(&optionHead, urlSafeAddr);
} }
@@ -247,32 +247,32 @@ static PSDP_OPTION getAttributesList(char *urlSafeAddr) {
return NULL; return NULL;
} }
/* Populate the SDP header with required information */ // Populate the SDP header with required information
static int fillSdpHeader(char* buffer, int rtspClientVersion, char *urlSafeAddr) { static int fillSdpHeader(char* buffer, int rtspClientVersion, char *urlSafeAddr) {
return sprintf(buffer, return sprintf(buffer,
"v=0\r\n" "v=0\r\n"
"o=android 0 %d IN %s %s\r\n" "o=android 0 %d IN %s %s\r\n"
"s=NVIDIA Streaming Client\r\n", "s=NVIDIA Streaming Client\r\n",
rtspClientVersion, rtspClientVersion,
RemoteAddr.ss_family == AF_INET ? "IPv4" : "IPv6", RemoteAddr.ss_family == AF_INET ? "IPv4" : "IPv6",
urlSafeAddr); urlSafeAddr);
} }
/* Populate the SDP tail with required information */ // Populate the SDP tail with required information
static int fillSdpTail(char* buffer) { 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); ServerMajorVersion < 4 ? 47996 : 47998);
} }
/* Get the SDP attributes for the stream config */ // Get the SDP attributes for the stream config
char* getSdpPayloadForStreamConfig(int rtspClientVersion, int *length) { char* getSdpPayloadForStreamConfig(int rtspClientVersion, int *length) {
PSDP_OPTION attributeList; PSDP_OPTION attributeList;
int offset; int offset;
char* payload; char* payload;
char urlSafeAddr[URLSAFESTRING_LEN]; char urlSafeAddr[URLSAFESTRING_LEN];
addrToUrlSafeString(&RemoteAddr, urlSafeAddr); addrToUrlSafeString(&RemoteAddr, urlSafeAddr);
attributeList = getAttributesList(urlSafeAddr); attributeList = getAttributesList(urlSafeAddr);
+36 -35
View File
@@ -28,7 +28,7 @@ typedef struct _BUFFER_DESC {
unsigned int length; unsigned int length;
} BUFFER_DESC, *PBUFFER_DESC; } BUFFER_DESC, *PBUFFER_DESC;
/* Init */ // Init
void initializeVideoDepacketizer(int pktSize) { void initializeVideoDepacketizer(int pktSize) {
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
LbqInitializeLinkedBlockingQueue(&decodeUnitQueue, 15); LbqInitializeLinkedBlockingQueue(&decodeUnitQueue, 15);
@@ -46,7 +46,7 @@ void initializeVideoDepacketizer(int pktSize) {
strictIdrFrameWait = !(VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION); strictIdrFrameWait = !(VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION);
} }
/* Free malloced memory in AvcFrameState*/ // Free malloced memory in AvcFrameState*/
static void cleanupAvcFrameState(void) { static void cleanupAvcFrameState(void) {
PLENTRY lastEntry; PLENTRY lastEntry;
@@ -59,7 +59,7 @@ static void cleanupAvcFrameState(void) {
nalChainDataLength = 0; nalChainDataLength = 0;
} }
/* Cleanup AVC frame state and set that we're waiting for an IDR Frame*/ // Cleanup AVC frame state and set that we're waiting for an IDR Frame*/
static void dropAvcFrameState(void) { static void dropAvcFrameState(void) {
// We'll need an IDR frame now if we're in strict mode // We'll need an IDR frame now if we're in strict mode
if (strictIdrFrameWait) { if (strictIdrFrameWait) {
@@ -68,36 +68,36 @@ static void dropAvcFrameState(void) {
// Count the number of consecutive frames dropped // Count the number of consecutive frames dropped
consecutiveFrameDrops++; consecutiveFrameDrops++;
// If we reach our limit, immediately request an IDR frame and reset // If we reach our limit, immediately request an IDR frame and reset
if (consecutiveFrameDrops == CONSECUTIVE_DROP_LIMIT) { if (consecutiveFrameDrops == CONSECUTIVE_DROP_LIMIT) {
Limelog("Reached consecutive drop limit\n"); Limelog("Reached consecutive drop limit\n");
// Restart the count // Restart the count
consecutiveFrameDrops = 0; consecutiveFrameDrops = 0;
// Request an IDR frame // Request an IDR frame
waitingForIdrFrame = 1; waitingForIdrFrame = 1;
requestIdrOnDemand(); requestIdrOnDemand();
} }
cleanupAvcFrameState(); cleanupAvcFrameState();
} }
/* Cleanup the list of decode units */ // Cleanup the list of decode units
static void freeDecodeUnitList(PLINKED_BLOCKING_QUEUE_ENTRY entry) { static void freeDecodeUnitList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
PLINKED_BLOCKING_QUEUE_ENTRY nextEntry; PLINKED_BLOCKING_QUEUE_ENTRY nextEntry;
while (entry != NULL) { while (entry != NULL) {
nextEntry = entry->flink; nextEntry = entry->flink;
freeQueuedDecodeUnit((PQUEUED_DECODE_UNIT) entry->data); freeQueuedDecodeUnit((PQUEUED_DECODE_UNIT)entry->data);
entry = nextEntry; entry = nextEntry;
} }
} }
/* Cleanup video depacketizer and free malloced memory */ // Cleanup video depacketizer and free malloced memory
void destroyVideoDepacketizer(void) { void destroyVideoDepacketizer(void) {
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
freeDecodeUnitList(LbqDestroyLinkedBlockingQueue(&decodeUnitQueue)); freeDecodeUnitList(LbqDestroyLinkedBlockingQueue(&decodeUnitQueue));
@@ -106,22 +106,22 @@ void destroyVideoDepacketizer(void) {
cleanupAvcFrameState(); cleanupAvcFrameState();
} }
/* Returns 1 if candidate is a frame start and 0 otherwise */ // Returns 1 if candidate is a frame start and 0 otherwise
static int isSeqFrameStart(PBUFFER_DESC candidate) { static int isSeqFrameStart(PBUFFER_DESC candidate) {
return (candidate->length == 4 && candidate->data[candidate->offset + candidate->length - 1] == 1); return (candidate->length == 4 && candidate->data[candidate->offset + candidate->length - 1] == 1);
} }
/* Returns 1 if candidate an AVC start and 0 otherwise */ // Returns 1 if candidate an AVC start and 0 otherwise
static int isSeqAvcStart(PBUFFER_DESC candidate) { static int isSeqAvcStart(PBUFFER_DESC candidate) {
return (candidate->data[candidate->offset + candidate->length - 1] == 1); return (candidate->data[candidate->offset + candidate->length - 1] == 1);
} }
/* Returns 1 if candidate is padding and 0 otherwise */ // Returns 1 if candidate is padding and 0 otherwise
static int isSeqPadding(PBUFFER_DESC candidate) { static int isSeqPadding(PBUFFER_DESC candidate) {
return (candidate->data[candidate->offset + candidate->length - 1] == 0); return (candidate->data[candidate->offset + candidate->length - 1] == 0);
} }
/* Returns 1 on success, 0 otherwise */ // Returns 1 on success, 0 otherwise
static int getSpecialSeq(PBUFFER_DESC current, PBUFFER_DESC candidate) { static int getSpecialSeq(PBUFFER_DESC current, PBUFFER_DESC candidate) {
if (current->length < 3) { if (current->length < 3) {
return 0; return 0;
@@ -158,9 +158,9 @@ static int getSpecialSeq(PBUFFER_DESC current, PBUFFER_DESC candidate) {
return 0; return 0;
} }
/* Get the first decode unit available */ // Get the first decode unit available
int getNextQueuedDecodeUnit(PQUEUED_DECODE_UNIT *qdu) { int getNextQueuedDecodeUnit(PQUEUED_DECODE_UNIT *qdu) {
int err = LbqWaitForQueueElement(&decodeUnitQueue, (void**) qdu); int err = LbqWaitForQueueElement(&decodeUnitQueue, (void**)qdu);
if (err == LBQ_SUCCESS) { if (err == LBQ_SUCCESS) {
return 1; return 1;
} }
@@ -169,7 +169,7 @@ int getNextQueuedDecodeUnit(PQUEUED_DECODE_UNIT *qdu) {
} }
} }
/* Cleanup a decode unit by freeing the buffer chain and the holder */ // Cleanup a decode unit by freeing the buffer chain and the holder
void freeQueuedDecodeUnit(PQUEUED_DECODE_UNIT qdu) { void freeQueuedDecodeUnit(PQUEUED_DECODE_UNIT qdu) {
PLENTRY lastEntry; PLENTRY lastEntry;
@@ -182,10 +182,10 @@ void freeQueuedDecodeUnit(PQUEUED_DECODE_UNIT qdu) {
free(qdu); free(qdu);
} }
/* Reassemble the frame with the given frame number */ // Reassemble the frame with the given frame number
static void reassembleAvcFrame(int frameNumber) { static void reassembleAvcFrame(int frameNumber) {
if (nalChainHead != NULL) { if (nalChainHead != NULL) {
PQUEUED_DECODE_UNIT qdu = (PQUEUED_DECODE_UNIT) malloc(sizeof(*qdu)); PQUEUED_DECODE_UNIT qdu = (PQUEUED_DECODE_UNIT)malloc(sizeof(*qdu));
if (qdu != NULL) { if (qdu != NULL) {
qdu->decodeUnit.bufferList = nalChainHead; qdu->decodeUnit.bufferList = nalChainHead;
qdu->decodeUnit.fullLength = nalChainDataLength; qdu->decodeUnit.fullLength = nalChainDataLength;
@@ -212,7 +212,8 @@ static void reassembleAvcFrame(int frameNumber) {
connectionSinkTooSlow(0, frameNumber); connectionSinkTooSlow(0, frameNumber);
return; return;
} }
} else { }
else {
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit); int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit);
freeQueuedDecodeUnit(qdu); freeQueuedDecodeUnit(qdu);
@@ -225,7 +226,7 @@ static void reassembleAvcFrame(int frameNumber) {
// Notify the control connection // Notify the control connection
connectionReceivedFrame(frameNumber); connectionReceivedFrame(frameNumber);
// Clear frame drops // Clear frame drops
consecutiveFrameDrops = 0; consecutiveFrameDrops = 0;
} }
@@ -233,11 +234,11 @@ static void reassembleAvcFrame(int frameNumber) {
} }
static void queueFragment(char *data, int offset, int length) { static void queueFragment(char *data, int offset, int length) {
PLENTRY entry = (PLENTRY) malloc(sizeof(*entry) + length); PLENTRY entry = (PLENTRY)malloc(sizeof(*entry) + length);
if (entry != NULL) { if (entry != NULL) {
entry->next = NULL; entry->next = NULL;
entry->length = length; entry->length = length;
entry->data = (char*) (entry + 1); entry->data = (char*)(entry + 1);
memcpy(entry->data, &data[offset], entry->length); memcpy(entry->data, &data[offset], entry->length);
@@ -258,7 +259,7 @@ static void queueFragment(char *data, int offset, int length) {
} }
} }
/* Process an RTP Payload */ // Process an RTP Payload
static void processRtpPayloadSlow(PNV_VIDEO_PACKET videoPacket, PBUFFER_DESC currentPos) { static void processRtpPayloadSlow(PNV_VIDEO_PACKET videoPacket, PBUFFER_DESC currentPos) {
BUFFER_DESC specialSeq; BUFFER_DESC specialSeq;
int decodingAvc = 0; int decodingAvc = 0;
@@ -323,22 +324,22 @@ static void processRtpPayloadSlow(PNV_VIDEO_PACKET videoPacket, PBUFFER_DESC cur
} }
} }
/* Return 1 if packet is the first one in the frame */ // Return 1 if packet is the first one in the frame
static int isFirstPacket(char flags) { static int isFirstPacket(char flags) {
// Clear the picture data flag // Clear the picture data flag
flags &= ~FLAG_CONTAINS_PIC_DATA; flags &= ~FLAG_CONTAINS_PIC_DATA;
// Check if it's just the start or both start and end of a frame // Check if it's just the start or both start and end of a frame
return (flags == (FLAG_SOF | FLAG_EOF) || return (flags == (FLAG_SOF | FLAG_EOF) ||
flags == FLAG_SOF); flags == FLAG_SOF);
} }
/* Adds a fragment directly to the queue */ // Adds a fragment directly to the queue
static void processRtpPayloadFast(BUFFER_DESC location) { static void processRtpPayloadFast(BUFFER_DESC location) {
queueFragment(location.data, location.offset, location.length); queueFragment(location.data, location.offset, location.length);
} }
/* Process an RTP Payload */ // Process an RTP Payload
void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) { void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
BUFFER_DESC currentPos, specialSeq; BUFFER_DESC currentPos, specialSeq;
int frameIndex; int frameIndex;
@@ -349,8 +350,8 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
// Mask the top 8 bits from the SPI // Mask the top 8 bits from the SPI
videoPacket->streamPacketIndex >>= 8; videoPacket->streamPacketIndex >>= 8;
videoPacket->streamPacketIndex &= 0xFFFFFF; videoPacket->streamPacketIndex &= 0xFFFFFF;
currentPos.data = (char*) (videoPacket + 1); currentPos.data = (char*)(videoPacket + 1);
currentPos.offset = 0; currentPos.offset = 0;
currentPos.length = length - sizeof(*videoPacket); currentPos.length = length - sizeof(*videoPacket);
@@ -360,7 +361,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
// Drop duplicates or re-ordered packets // Drop duplicates or re-ordered packets
streamPacketIndex = videoPacket->streamPacketIndex; streamPacketIndex = videoPacket->streamPacketIndex;
if (isBeforeSignedInt((short) streamPacketIndex, (short) (lastPacketInStream + 1), 0)) { if (isBeforeSignedInt((short)streamPacketIndex, (short)(lastPacketInStream + 1), 0)) {
return; return;
} }
@@ -426,7 +427,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
// we need to drop it if the stream packet index // we need to drop it if the stream packet index
// doesn't match // doesn't match
if (!firstPacket && decodingFrame) { if (!firstPacket && decodingFrame) {
if (streamPacketIndex != (int) (lastPacketInStream + 1)) { if (streamPacketIndex != (int)(lastPacketInStream + 1)) {
Limelog("Network dropped middle of a frame\n"); Limelog("Network dropped middle of a frame\n");
nextFrameNumber = frameIndex + 1; nextFrameNumber = frameIndex + 1;
@@ -440,7 +441,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
} }
// Notify the server of any packet losses // Notify the server of any packet losses
if (streamPacketIndex != (int) (lastPacketInStream + 1)) { if (streamPacketIndex != (int)(lastPacketInStream + 1)) {
// Packets were lost so report this to the server // Packets were lost so report this to the server
connectionLostPackets(lastPacketInStream, streamPacketIndex); connectionLostPackets(lastPacketInStream, streamPacketIndex);
} }
@@ -486,7 +487,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
} }
} }
/* Add an RTP Packet to the queue */ // Add an RTP Packet to the queue
void queueRtpPacket(PRTP_PACKET rtpPacket, int length) { void queueRtpPacket(PRTP_PACKET rtpPacket, int length) {
int dataOffset; int dataOffset;
@@ -496,4 +497,4 @@ void queueRtpPacket(PRTP_PACKET rtpPacket, int length) {
} }
processRtpPayload((PNV_VIDEO_PACKET)(((char*)rtpPacket) + dataOffset), length - dataOffset); processRtpPayload((PNV_VIDEO_PACKET)(((char*)rtpPacket) + dataOffset), length - dataOffset);
} }
+25 -25
View File
@@ -25,21 +25,21 @@ static PLT_THREAD decoderThread;
// the RTP queue will wait for missing/reordered packets. // the RTP queue will wait for missing/reordered packets.
#define RTP_QUEUE_DELAY 10 #define RTP_QUEUE_DELAY 10
/* Initialize the video stream */ // Initialize the video stream
void initializeVideoStream(void) { void initializeVideoStream(void) {
initializeVideoDepacketizer(StreamConfig.packetSize); initializeVideoDepacketizer(StreamConfig.packetSize);
RtpqInitializeQueue(&rtpQueue, RTPQ_DEFAULT_MAX_SIZE, RTP_QUEUE_DELAY); RtpqInitializeQueue(&rtpQueue, RTPQ_DEFAULT_MAX_SIZE, RTP_QUEUE_DELAY);
} }
/* Clean up the video stream */ // Clean up the video stream
void destroyVideoStream(void) { void destroyVideoStream(void) {
destroyVideoDepacketizer(); destroyVideoDepacketizer();
RtpqCleanupQueue(&rtpQueue); RtpqCleanupQueue(&rtpQueue);
} }
/* UDP Ping proc */ // UDP Ping proc
static void UdpPingThreadProc(void *context) { static void UdpPingThreadProc(void *context) {
char pingData [] = { 0x50, 0x49, 0x4E, 0x47 }; char pingData[] = { 0x50, 0x49, 0x4E, 0x47 };
struct sockaddr_in6 saddr; struct sockaddr_in6 saddr;
SOCK_RET err; SOCK_RET err;
@@ -58,7 +58,7 @@ static void UdpPingThreadProc(void *context) {
} }
} }
/* Receive thread proc */ // Receive thread proc
static void ReceiveThreadProc(void* context) { static void ReceiveThreadProc(void* context) {
int err; int err;
int bufferSize, receiveSize; int bufferSize, receiveSize;
@@ -71,9 +71,9 @@ static void ReceiveThreadProc(void* context) {
while (!PltIsThreadInterrupted(&receiveThread)) { while (!PltIsThreadInterrupted(&receiveThread)) {
PRTP_PACKET packet; PRTP_PACKET packet;
if (buffer == NULL) { if (buffer == NULL) {
buffer = (char*) malloc(bufferSize); buffer = (char*)malloc(bufferSize);
if (buffer == NULL) { if (buffer == NULL) {
Limelog("Video Receive: malloc() failed\n"); Limelog("Video Receive: malloc() failed\n");
ListenerCallbacks.connectionTerminated(-1); ListenerCallbacks.connectionTerminated(-1);
@@ -81,7 +81,7 @@ static void ReceiveThreadProc(void* context) {
} }
} }
err = (int) recv(rtpSocket, buffer, receiveSize, 0); err = (int)recv(rtpSocket, buffer, receiveSize, 0);
if (err <= 0) { if (err <= 0) {
Limelog("Video Receive: recv() failed: %d\n", (int)LastSocketError()); Limelog("Video Receive: recv() failed: %d\n", (int)LastSocketError());
ListenerCallbacks.connectionTerminated(LastSocketError()); ListenerCallbacks.connectionTerminated(LastSocketError());
@@ -89,21 +89,21 @@ static void ReceiveThreadProc(void* context) {
} }
memcpy(&buffer[receiveSize], &err, sizeof(int)); memcpy(&buffer[receiveSize], &err, sizeof(int));
// RTP sequence number must be in host order for the RTP queue // RTP sequence number must be in host order for the RTP queue
packet = (PRTP_PACKET) &buffer[0]; packet = (PRTP_PACKET)&buffer[0];
packet->sequenceNumber = htons(packet->sequenceNumber); packet->sequenceNumber = htons(packet->sequenceNumber);
queueStatus = RtpqAddPacket(&rtpQueue, packet, (PRTP_QUEUE_ENTRY) &buffer[receiveSize + sizeof(int)]); queueStatus = RtpqAddPacket(&rtpQueue, packet, (PRTP_QUEUE_ENTRY)&buffer[receiveSize + sizeof(int)]);
if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) { if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) {
// queueRtpPacket() copies the data it needs to we can reuse the buffer // queueRtpPacket() copies the data it needs to we can reuse the buffer
queueRtpPacket(packet, err); queueRtpPacket(packet, err);
} }
else if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) { else if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) {
// The packet queue now has packets ready // The packet queue now has packets ready
while ((buffer = (char*) RtpqGetQueuedPacket(&rtpQueue)) != NULL) { while ((buffer = (char*)RtpqGetQueuedPacket(&rtpQueue)) != NULL) {
memcpy(&err, &buffer[receiveSize], sizeof(int)); memcpy(&err, &buffer[receiveSize], sizeof(int));
queueRtpPacket((PRTP_PACKET) buffer, err); queueRtpPacket((PRTP_PACKET)buffer, err);
free(buffer); free(buffer);
} }
} }
@@ -118,7 +118,7 @@ static void ReceiveThreadProc(void* context) {
} }
} }
/* Decoder thread proc */ // Decoder thread proc
static void DecoderThreadProc(void* context) { static void DecoderThreadProc(void* context) {
PQUEUED_DECODE_UNIT qdu; PQUEUED_DECODE_UNIT qdu;
while (!PltIsThreadInterrupted(&decoderThread)) { while (!PltIsThreadInterrupted(&decoderThread)) {
@@ -129,7 +129,7 @@ static void DecoderThreadProc(void* context) {
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit); int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit);
freeQueuedDecodeUnit(qdu); freeQueuedDecodeUnit(qdu);
if (ret == DR_NEED_IDR) { if (ret == DR_NEED_IDR) {
Limelog("Requesting IDR frame on behalf of DR\n"); Limelog("Requesting IDR frame on behalf of DR\n");
requestIdrOnDemand(); requestIdrOnDemand();
@@ -137,18 +137,18 @@ static void DecoderThreadProc(void* context) {
} }
} }
/* Read the first frame of the video stream */ // Read the first frame of the video stream
int readFirstFrame(void) { int readFirstFrame(void) {
// All that matters is that we close this socket. // All that matters is that we close this socket.
// This starts the flow of video on Gen 3 servers. // This starts the flow of video on Gen 3 servers.
closesocket(firstFrameSocket); closesocket(firstFrameSocket);
firstFrameSocket = INVALID_SOCKET; firstFrameSocket = INVALID_SOCKET;
return 0; return 0;
} }
/* Terminate the video stream */ // Terminate the video stream
void stopVideoStream(void) { void stopVideoStream(void) {
PltInterruptThread(&udpPingThread); PltInterruptThread(&udpPingThread);
PltInterruptThread(&receiveThread); PltInterruptThread(&receiveThread);
@@ -180,7 +180,7 @@ void stopVideoStream(void) {
VideoCallbacks.cleanup(); VideoCallbacks.cleanup();
} }
/* Start the video stream */ // Start the video stream
int startVideoStream(void* rendererContext, int drFlags) { int startVideoStream(void* rendererContext, int drFlags) {
int err; int err;
@@ -188,7 +188,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
// decode units // decode units
VideoCallbacks.setup(StreamConfig.width, VideoCallbacks.setup(StreamConfig.width,
StreamConfig.height, StreamConfig.fps, rendererContext, drFlags); StreamConfig.height, StreamConfig.fps, rendererContext, drFlags);
rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER); rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER);
if (rtpSocket == INVALID_SOCKET) { if (rtpSocket == INVALID_SOCKET) {
return LastSocketError(); return LastSocketError();
@@ -205,7 +205,7 @@ int startVideoStream(void* rendererContext, int drFlags) {
return err; return err;
} }
} }
if (ServerMajorVersion == 3) { if (ServerMajorVersion == 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, FIRST_FRAME_PORT); firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen, FIRST_FRAME_PORT);
@@ -213,14 +213,14 @@ int startVideoStream(void* rendererContext, int drFlags) {
return LastSocketError(); return LastSocketError();
} }
} }
// Start pinging before reading the first frame so GFE knows where // Start pinging before reading the first frame so GFE knows where
// to send UDP data // to send UDP data
err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread); err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread);
if (err != 0) { if (err != 0) {
return err; return err;
} }
if (ServerMajorVersion == 3) { if (ServerMajorVersion == 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();
@@ -230,4 +230,4 @@ int startVideoStream(void* rendererContext, int drFlags) {
} }
return 0; return 0;
} }