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