mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2026-06-17 06:11:03 +00:00
Major code cleanup: comment style & run CodeMaid
This commit is contained in:
@@ -133,8 +133,8 @@ static int queuePacketToLbq(PQUEUED_AUDIO_PACKET *packet) {
|
|||||||
static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
|
static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
|
||||||
PRTP_PACKET rtp;
|
PRTP_PACKET rtp;
|
||||||
|
|
||||||
rtp = (PRTP_PACKET) &packet->data[0];
|
rtp = (PRTP_PACKET)&packet->data[0];
|
||||||
if (lastSeq != 0 && (unsigned short) (lastSeq + 1) != rtp->sequenceNumber) {
|
if (lastSeq != 0 && (unsigned short)(lastSeq + 1) != rtp->sequenceNumber) {
|
||||||
Limelog("Received OOS audio data (expected %d, but got %d)\n", lastSeq + 1, rtp->sequenceNumber);
|
Limelog("Received OOS audio data (expected %d, but got %d)\n", lastSeq + 1, rtp->sequenceNumber);
|
||||||
|
|
||||||
AudioCallbacks.decodeAndPlaySample(NULL, 0);
|
AudioCallbacks.decodeAndPlaySample(NULL, 0);
|
||||||
@@ -142,7 +142,7 @@ static void decodeInputData(PQUEUED_AUDIO_PACKET packet) {
|
|||||||
|
|
||||||
lastSeq = rtp->sequenceNumber;
|
lastSeq = rtp->sequenceNumber;
|
||||||
|
|
||||||
AudioCallbacks.decodeAndPlaySample((char *) (rtp + 1), packet->size - sizeof(*rtp));
|
AudioCallbacks.decodeAndPlaySample((char *)(rtp + 1), packet->size - sizeof(*rtp));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReceiveThreadProc(void* context) {
|
static void ReceiveThreadProc(void* context) {
|
||||||
@@ -154,7 +154,7 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
|
|
||||||
while (!PltIsThreadInterrupted(&receiveThread)) {
|
while (!PltIsThreadInterrupted(&receiveThread)) {
|
||||||
if (packet == NULL) {
|
if (packet == NULL) {
|
||||||
packet = (PQUEUED_AUDIO_PACKET) malloc(sizeof(*packet));
|
packet = (PQUEUED_AUDIO_PACKET)malloc(sizeof(*packet));
|
||||||
if (packet == NULL) {
|
if (packet == NULL) {
|
||||||
Limelog("Audio Receive: malloc() failed\n");
|
Limelog("Audio Receive: malloc() failed\n");
|
||||||
ListenerCallbacks.connectionTerminated(-1);
|
ListenerCallbacks.connectionTerminated(-1);
|
||||||
@@ -162,7 +162,7 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
packet->size = (int) recv(rtpSocket, &packet->data[0], MAX_PACKET_SIZE, 0);
|
packet->size = (int)recv(rtpSocket, &packet->data[0], MAX_PACKET_SIZE, 0);
|
||||||
if (packet->size <= 0) {
|
if (packet->size <= 0) {
|
||||||
Limelog("Audio Receive: recv() failed: %d\n", (int)LastSocketError());
|
Limelog("Audio Receive: recv() failed: %d\n", (int)LastSocketError());
|
||||||
free(packet);
|
free(packet);
|
||||||
@@ -175,7 +175,7 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtp = (PRTP_PACKET) &packet->data[0];
|
rtp = (PRTP_PACKET)&packet->data[0];
|
||||||
if (rtp->packetType != 97) {
|
if (rtp->packetType != 97) {
|
||||||
// Not audio
|
// Not audio
|
||||||
continue;
|
continue;
|
||||||
@@ -184,14 +184,15 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
// RTP sequence number must be in host order for the RTP queue
|
// RTP sequence number must be in host order for the RTP queue
|
||||||
rtp->sequenceNumber = htons(rtp->sequenceNumber);
|
rtp->sequenceNumber = htons(rtp->sequenceNumber);
|
||||||
|
|
||||||
queueStatus = RtpqAddPacket(&rtpReorderQueue, (PRTP_PACKET) packet, &packet->q.rentry);
|
queueStatus = RtpqAddPacket(&rtpReorderQueue, (PRTP_PACKET)packet, &packet->q.rentry);
|
||||||
if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) {
|
if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) {
|
||||||
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
if (!queuePacketToLbq(&packet)) {
|
if (!queuePacketToLbq(&packet)) {
|
||||||
// An exit signal was received
|
// An exit signal was received
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
decodeInputData(packet);
|
decodeInputData(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,13 +204,14 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
|
|
||||||
if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) {
|
if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) {
|
||||||
// If packets are ready, pull them and send them to the decoder
|
// If packets are ready, pull them and send them to the decoder
|
||||||
while ((packet = (PQUEUED_AUDIO_PACKET) RtpqGetQueuedPacket(&rtpReorderQueue)) != NULL) {
|
while ((packet = (PQUEUED_AUDIO_PACKET)RtpqGetQueuedPacket(&rtpReorderQueue)) != NULL) {
|
||||||
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
if (!queuePacketToLbq(&packet)) {
|
if (!queuePacketToLbq(&packet)) {
|
||||||
// An exit signal was received
|
// An exit signal was received
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
decodeInputData(packet);
|
decodeInputData(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +225,7 @@ static void DecoderThreadProc(void* context) {
|
|||||||
PQUEUED_AUDIO_PACKET packet;
|
PQUEUED_AUDIO_PACKET packet;
|
||||||
|
|
||||||
while (!PltIsThreadInterrupted(&decoderThread)) {
|
while (!PltIsThreadInterrupted(&decoderThread)) {
|
||||||
err = LbqWaitForQueueElement(&packetQueue, (void**) &packet);
|
err = LbqWaitForQueueElement(&packetQueue, (void**)&packet);
|
||||||
if (err != LBQ_SUCCESS) {
|
if (err != LBQ_SUCCESS) {
|
||||||
// An exit signal was received
|
// An exit signal was received
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
|
|||||||
DECODER_RENDERER_CALLBACKS VideoCallbacks;
|
DECODER_RENDERER_CALLBACKS VideoCallbacks;
|
||||||
AUDIO_RENDERER_CALLBACKS AudioCallbacks;
|
AUDIO_RENDERER_CALLBACKS AudioCallbacks;
|
||||||
|
|
||||||
/* Connection stages */
|
// Connection stages
|
||||||
static const char* stageNames[STAGE_MAX] = {
|
static const char* stageNames[STAGE_MAX] = {
|
||||||
"none",
|
"none",
|
||||||
"platform initialization",
|
"platform initialization",
|
||||||
@@ -32,12 +32,12 @@ static const char* stageNames[STAGE_MAX] = {
|
|||||||
"input stream establishment"
|
"input stream establishment"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Get the name of the current stage based on its number */
|
// Get the name of the current stage based on its number
|
||||||
const char* LiGetStageName(int stage) {
|
const char* LiGetStageName(int stage) {
|
||||||
return stageNames[stage];
|
return stageNames[stage];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop the connection by undoing the step at the current stage and those before it */
|
// Stop the connection by undoing the step at the current stage and those before it
|
||||||
void LiStopConnection(void) {
|
void LiStopConnection(void) {
|
||||||
// Disable termination callbacks now
|
// Disable termination callbacks now
|
||||||
alreadyTerminated = 1;
|
alreadyTerminated = 1;
|
||||||
@@ -171,7 +171,7 @@ static int resolveHostName(const char *host)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Starts the connection to the streaming machine */
|
// Starts the connection to the streaming machine
|
||||||
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
||||||
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks,
|
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks,
|
||||||
void* renderContext, int drFlags, int _serverMajorVersion) {
|
void* renderContext, int drFlags, int _serverMajorVersion) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "ByteBuffer.h"
|
#include "ByteBuffer.h"
|
||||||
|
|
||||||
/* NV control stream packet header */
|
// NV control stream packet header
|
||||||
typedef struct _NVCTL_PACKET_HEADER {
|
typedef struct _NVCTL_PACKET_HEADER {
|
||||||
unsigned short type;
|
unsigned short type;
|
||||||
unsigned short payloadLength;
|
unsigned short payloadLength;
|
||||||
@@ -47,11 +47,11 @@ static const short packetTypesGen4[] = {
|
|||||||
0x0611, // Frame Stats (unused)
|
0x0611, // Frame Stats (unused)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char startAGen3[] = {0};
|
static const char startAGen3[] = { 0 };
|
||||||
static const int startBGen3[] = {0, 0, 0, 0xa};
|
static const int startBGen3[] = { 0, 0, 0, 0xa };
|
||||||
|
|
||||||
static const char requestIdrFrameGen4[] = {0, 0};
|
static const char requestIdrFrameGen4[] = { 0, 0 };
|
||||||
static const char startBGen4[] = {0};
|
static const char startBGen4[] = { 0 };
|
||||||
|
|
||||||
static const short payloadLengthsGen3[] = {
|
static const short payloadLengthsGen3[] = {
|
||||||
sizeof(startAGen3), // Start A
|
sizeof(startAGen3), // Start A
|
||||||
@@ -83,7 +83,7 @@ static char **preconstructedPayloads;
|
|||||||
|
|
||||||
#define LOSS_REPORT_INTERVAL_MS 50
|
#define LOSS_REPORT_INTERVAL_MS 50
|
||||||
|
|
||||||
/* Initializes the control stream */
|
// Initializes the control stream
|
||||||
int initializeControlStream(void) {
|
int initializeControlStream(void) {
|
||||||
PltCreateEvent(&invalidateRefFramesEvent);
|
PltCreateEvent(&invalidateRefFramesEvent);
|
||||||
LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20);
|
LbqInitializeLinkedBlockingQueue(&invalidReferenceFrameTuples, 20);
|
||||||
@@ -116,19 +116,18 @@ void freeFrameInvalidationList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleans up control stream */
|
// Cleans up control stream
|
||||||
void destroyControlStream(void) {
|
void destroyControlStream(void) {
|
||||||
PltCloseEvent(&invalidateRefFramesEvent);
|
PltCloseEvent(&invalidateRefFramesEvent);
|
||||||
freeFrameInvalidationList(LbqDestroyLinkedBlockingQueue(&invalidReferenceFrameTuples));
|
freeFrameInvalidationList(LbqDestroyLinkedBlockingQueue(&invalidReferenceFrameTuples));
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNextFrameInvalidationTuple(PQUEUED_FRAME_INVALIDATION_TUPLE *qfit) {
|
int getNextFrameInvalidationTuple(PQUEUED_FRAME_INVALIDATION_TUPLE *qfit) {
|
||||||
int err = LbqPollQueueElement(&invalidReferenceFrameTuples, (void**) qfit);
|
int err = LbqPollQueueElement(&invalidReferenceFrameTuples, (void**)qfit);
|
||||||
return (err == LBQ_SUCCESS);
|
return (err == LBQ_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void queueFrameInvalidationTuple(int startFrame, int endFrame) {
|
void queueFrameInvalidationTuple(int startFrame, int endFrame) {
|
||||||
|
|
||||||
if (VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION) {
|
if (VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION) {
|
||||||
PQUEUED_FRAME_INVALIDATION_TUPLE qfit;
|
PQUEUED_FRAME_INVALIDATION_TUPLE qfit;
|
||||||
qfit = malloc(sizeof(*qfit));
|
qfit = malloc(sizeof(*qfit));
|
||||||
@@ -152,51 +151,51 @@ void queueFrameInvalidationTuple(int startFrame, int endFrame) {
|
|||||||
PltSetEvent(&invalidateRefFramesEvent);
|
PltSetEvent(&invalidateRefFramesEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Request an IDR frame on demand by the decoder */
|
// Request an IDR frame on demand by the decoder
|
||||||
void requestIdrOnDemand(void) {
|
void requestIdrOnDemand(void) {
|
||||||
idrFrameRequired = 1;
|
idrFrameRequired = 1;
|
||||||
PltSetEvent(&invalidateRefFramesEvent);
|
PltSetEvent(&invalidateRefFramesEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invalidate reference frames if the decoder is too slow */
|
// Invalidate reference frames if the decoder is too slow
|
||||||
void connectionSinkTooSlow(int startFrame, int endFrame) {
|
void connectionSinkTooSlow(int startFrame, int endFrame) {
|
||||||
queueFrameInvalidationTuple(startFrame, endFrame);
|
queueFrameInvalidationTuple(startFrame, endFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invalidate reference frames lost by the network */
|
// Invalidate reference frames lost by the network
|
||||||
void connectionDetectedFrameLoss(int startFrame, int endFrame) {
|
void connectionDetectedFrameLoss(int startFrame, int endFrame) {
|
||||||
queueFrameInvalidationTuple(startFrame, endFrame);
|
queueFrameInvalidationTuple(startFrame, endFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When we receive a frame, update the number of our current frame */
|
// When we receive a frame, update the number of our current frame
|
||||||
void connectionReceivedFrame(int frameIndex) {
|
void connectionReceivedFrame(int frameIndex) {
|
||||||
currentFrame = frameIndex;
|
currentFrame = frameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When we lose packets, update our packet loss count */
|
// When we lose packets, update our packet loss count
|
||||||
void connectionLostPackets(int lastReceivedPacket, int nextReceivedPacket) {
|
void connectionLostPackets(int lastReceivedPacket, int nextReceivedPacket) {
|
||||||
lossCountSinceLastReport += (nextReceivedPacket - lastReceivedPacket) - 1;
|
lossCountSinceLastReport += (nextReceivedPacket - lastReceivedPacket) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads an NV control stream packet */
|
// Reads an NV control stream packet
|
||||||
static PNVCTL_PACKET_HEADER readNvctlPacket(void) {
|
static PNVCTL_PACKET_HEADER readNvctlPacket(void) {
|
||||||
NVCTL_PACKET_HEADER staticHeader;
|
NVCTL_PACKET_HEADER staticHeader;
|
||||||
PNVCTL_PACKET_HEADER fullPacket;
|
PNVCTL_PACKET_HEADER fullPacket;
|
||||||
SOCK_RET err;
|
SOCK_RET err;
|
||||||
|
|
||||||
err = recv(ctlSock, (char*) &staticHeader, sizeof(staticHeader), 0);
|
err = recv(ctlSock, (char*)&staticHeader, sizeof(staticHeader), 0);
|
||||||
if (err != sizeof(staticHeader)) {
|
if (err != sizeof(staticHeader)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullPacket = (PNVCTL_PACKET_HEADER) malloc(staticHeader.payloadLength + sizeof(staticHeader));
|
fullPacket = (PNVCTL_PACKET_HEADER)malloc(staticHeader.payloadLength + sizeof(staticHeader));
|
||||||
if (fullPacket == NULL) {
|
if (fullPacket == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(fullPacket, &staticHeader, sizeof(staticHeader));
|
memcpy(fullPacket, &staticHeader, sizeof(staticHeader));
|
||||||
if (staticHeader.payloadLength != 0) {
|
if (staticHeader.payloadLength != 0) {
|
||||||
err = recv(ctlSock, (char*) (fullPacket + 1), staticHeader.payloadLength, 0);
|
err = recv(ctlSock, (char*)(fullPacket + 1), staticHeader.payloadLength, 0);
|
||||||
if (err != staticHeader.payloadLength) {
|
if (err != staticHeader.payloadLength) {
|
||||||
free(fullPacket);
|
free(fullPacket);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -219,7 +218,7 @@ static int sendMessageAndForget(short ptype, short paylen, const void* payload)
|
|||||||
packet->payloadLength = paylen;
|
packet->payloadLength = paylen;
|
||||||
memcpy(&packet[1], payload, paylen);
|
memcpy(&packet[1], payload, paylen);
|
||||||
|
|
||||||
err = send(ctlSock, (char*) packet, sizeof(*packet) + paylen, 0);
|
err = send(ctlSock, (char*)packet, sizeof(*packet) + paylen, 0);
|
||||||
free(packet);
|
free(packet);
|
||||||
|
|
||||||
if (err != sizeof(*packet) + paylen) {
|
if (err != sizeof(*packet) + paylen) {
|
||||||
@@ -302,7 +301,7 @@ static void requestIdrFrame(void) {
|
|||||||
// Send the reference frame invalidation request and read the response
|
// Send the reference frame invalidation request and read the response
|
||||||
if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES],
|
if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES],
|
||||||
payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) {
|
payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) {
|
||||||
Limelog("Request IDR Frame: Transaction failed: %d\n", (int) LastSocketError());
|
Limelog("Request IDR Frame: Transaction failed: %d\n", (int)LastSocketError());
|
||||||
ListenerCallbacks.connectionTerminated(LastSocketError());
|
ListenerCallbacks.connectionTerminated(LastSocketError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -311,7 +310,7 @@ static void requestIdrFrame(void) {
|
|||||||
// Send IDR frame request and read the response
|
// Send IDR frame request and read the response
|
||||||
if (!sendMessageAndDiscardReply(packetTypes[IDX_REQUEST_IDR_FRAME],
|
if (!sendMessageAndDiscardReply(packetTypes[IDX_REQUEST_IDR_FRAME],
|
||||||
payloadLengths[IDX_REQUEST_IDR_FRAME], preconstructedPayloads[IDX_REQUEST_IDR_FRAME])) {
|
payloadLengths[IDX_REQUEST_IDR_FRAME], preconstructedPayloads[IDX_REQUEST_IDR_FRAME])) {
|
||||||
Limelog("Request IDR Frame: Transaction failed: %d\n", (int) LastSocketError());
|
Limelog("Request IDR Frame: Transaction failed: %d\n", (int)LastSocketError());
|
||||||
ListenerCallbacks.connectionTerminated(LastSocketError());
|
ListenerCallbacks.connectionTerminated(LastSocketError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -346,7 +345,7 @@ static void requestInvalidateReferenceFrames(void) {
|
|||||||
// Send the reference frame invalidation request and read the response
|
// Send the reference frame invalidation request and read the response
|
||||||
if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES],
|
if (!sendMessageAndDiscardReply(packetTypes[IDX_INVALIDATE_REF_FRAMES],
|
||||||
payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) {
|
payloadLengths[IDX_INVALIDATE_REF_FRAMES], payload)) {
|
||||||
Limelog("Request Invaldiate Reference Frames: Transaction failed: %d\n", (int) LastSocketError());
|
Limelog("Request Invaldiate Reference Frames: Transaction failed: %d\n", (int)LastSocketError());
|
||||||
ListenerCallbacks.connectionTerminated(LastSocketError());
|
ListenerCallbacks.connectionTerminated(LastSocketError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -371,14 +370,15 @@ static void invalidateRefFramesFunc(void* context) {
|
|||||||
// Send an IDR frame request
|
// Send an IDR frame request
|
||||||
idrFrameRequired = 0;
|
idrFrameRequired = 0;
|
||||||
requestIdrFrame();
|
requestIdrFrame();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Otherwise invalidate reference frames
|
// Otherwise invalidate reference frames
|
||||||
requestInvalidateReferenceFrames();
|
requestInvalidateReferenceFrames();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stops the control stream */
|
// Stops the control stream
|
||||||
int stopControlStream(void) {
|
int stopControlStream(void) {
|
||||||
PltInterruptThread(&lossStatsThread);
|
PltInterruptThread(&lossStatsThread);
|
||||||
PltInterruptThread(&invalidateRefFramesThread);
|
PltInterruptThread(&invalidateRefFramesThread);
|
||||||
@@ -397,7 +397,7 @@ int stopControlStream(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Starts the control stream */
|
// Starts the control stream
|
||||||
int startControlStream(void) {
|
int startControlStream(void) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@@ -410,16 +410,16 @@ int startControlStream(void) {
|
|||||||
|
|
||||||
// Send START A
|
// Send START A
|
||||||
if (!sendMessageAndDiscardReply(packetTypes[IDX_START_A],
|
if (!sendMessageAndDiscardReply(packetTypes[IDX_START_A],
|
||||||
payloadLengths[IDX_START_A],
|
payloadLengths[IDX_START_A],
|
||||||
preconstructedPayloads[IDX_START_A])) {
|
preconstructedPayloads[IDX_START_A])) {
|
||||||
Limelog("Start A failed: %d\n", (int)LastSocketError());
|
Limelog("Start A failed: %d\n", (int)LastSocketError());
|
||||||
return LastSocketFail();
|
return LastSocketFail();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send START B
|
// Send START B
|
||||||
if (!sendMessageAndDiscardReply(packetTypes[IDX_START_B],
|
if (!sendMessageAndDiscardReply(packetTypes[IDX_START_B],
|
||||||
payloadLengths[IDX_START_B],
|
payloadLengths[IDX_START_B],
|
||||||
preconstructedPayloads[IDX_START_B])) {
|
preconstructedPayloads[IDX_START_B])) {
|
||||||
Limelog("Start B failed: %d\n", (int)LastSocketError());
|
Limelog("Start B failed: %d\n", (int)LastSocketError());
|
||||||
return LastSocketFail();
|
return LastSocketFail();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ static OAES_CTX* oaesContext;
|
|||||||
|
|
||||||
#define MAX_INPUT_PACKET_SIZE 128
|
#define MAX_INPUT_PACKET_SIZE 128
|
||||||
|
|
||||||
/* Contains input stream packets */
|
// Contains input stream packets
|
||||||
typedef struct _PACKET_HOLDER {
|
typedef struct _PACKET_HOLDER {
|
||||||
int packetLength;
|
int packetLength;
|
||||||
union {
|
union {
|
||||||
@@ -30,9 +30,9 @@ typedef struct _PACKET_HOLDER {
|
|||||||
LINKED_BLOCKING_QUEUE_ENTRY entry;
|
LINKED_BLOCKING_QUEUE_ENTRY entry;
|
||||||
} PACKET_HOLDER, *PPACKET_HOLDER;
|
} PACKET_HOLDER, *PPACKET_HOLDER;
|
||||||
|
|
||||||
/* Initializes the input stream */
|
// Initializes the input stream
|
||||||
int initializeInputStream(char* aesKeyData, int aesKeyDataLength,
|
int initializeInputStream(char* aesKeyData, int aesKeyDataLength,
|
||||||
char* aesIv, int aesIvLength) {
|
char* aesIv, int aesIvLength) {
|
||||||
if (aesIvLength != OAES_BLOCK_SIZE)
|
if (aesIvLength != OAES_BLOCK_SIZE)
|
||||||
{
|
{
|
||||||
Limelog("AES IV is incorrect length. Should be %d\n", aesIvLength);
|
Limelog("AES IV is incorrect length. Should be %d\n", aesIvLength);
|
||||||
@@ -64,7 +64,7 @@ int initializeInputStream(char* aesKeyData, int aesKeyDataLength,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroys and cleans up the input stream */
|
// Destroys and cleans up the input stream
|
||||||
void destroyInputStream(void) {
|
void destroyInputStream(void) {
|
||||||
PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry;
|
PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry;
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ static int checkDirs(short currentVal, short newVal, int* dir) {
|
|||||||
|
|
||||||
#define OAES_DATA_OFFSET 32
|
#define OAES_DATA_OFFSET 32
|
||||||
|
|
||||||
/* Input thread proc */
|
// Input thread proc
|
||||||
static void inputSendThreadProc(void* context) {
|
static void inputSendThreadProc(void* context) {
|
||||||
SOCK_RET err;
|
SOCK_RET err;
|
||||||
PPACKET_HOLDER holder;
|
PPACKET_HOLDER holder;
|
||||||
@@ -130,7 +130,7 @@ static void inputSendThreadProc(void* context) {
|
|||||||
while (!PltIsThreadInterrupted(&inputSendThread)) {
|
while (!PltIsThreadInterrupted(&inputSendThread)) {
|
||||||
int encryptedLengthPrefix;
|
int encryptedLengthPrefix;
|
||||||
|
|
||||||
err = LbqWaitForQueueElement(&packetQueue, (void**) &holder);
|
err = LbqWaitForQueueElement(&packetQueue, (void**)&holder);
|
||||||
if (err != LBQ_SUCCESS) {
|
if (err != LBQ_SUCCESS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -238,8 +238,8 @@ static void inputSendThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encryptedSize = sizeof(encryptedBuffer);
|
encryptedSize = sizeof(encryptedBuffer);
|
||||||
err = oaes_encrypt(oaesContext, (const unsigned char*) &holder->packet, holder->packetLength,
|
err = oaes_encrypt(oaesContext, (const unsigned char*)&holder->packet, holder->packetLength,
|
||||||
(unsigned char*) encryptedBuffer, &encryptedSize);
|
(unsigned char*)encryptedBuffer, &encryptedSize);
|
||||||
free(holder);
|
free(holder);
|
||||||
if (err != OAES_RET_SUCCESS) {
|
if (err != OAES_RET_SUCCESS) {
|
||||||
Limelog("Input: Encryption failed: %d\n", (int)err);
|
Limelog("Input: Encryption failed: %d\n", (int)err);
|
||||||
@@ -253,12 +253,12 @@ static void inputSendThreadProc(void* context) {
|
|||||||
// Overwrite the last 4 bytes before the encrypted data with the length so
|
// Overwrite the last 4 bytes before the encrypted data with the length so
|
||||||
// we can send the message all at once. GFE can choke if it gets the header
|
// we can send the message all at once. GFE can choke if it gets the header
|
||||||
// before the rest of the message.
|
// before the rest of the message.
|
||||||
encryptedLengthPrefix = htonl((unsigned long) encryptedSize);
|
encryptedLengthPrefix = htonl((unsigned long)encryptedSize);
|
||||||
memcpy(&encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)],
|
memcpy(&encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)],
|
||||||
&encryptedLengthPrefix, sizeof(encryptedLengthPrefix));
|
&encryptedLengthPrefix, sizeof(encryptedLengthPrefix));
|
||||||
|
|
||||||
// Send the encrypted payload
|
// Send the encrypted payload
|
||||||
err = send(inputSock, (const char*) &encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)],
|
err = send(inputSock, (const char*)&encryptedBuffer[OAES_DATA_OFFSET - sizeof(encryptedLengthPrefix)],
|
||||||
(int)(encryptedSize + sizeof(encryptedLengthPrefix)), 0);
|
(int)(encryptedSize + sizeof(encryptedLengthPrefix)), 0);
|
||||||
if (err <= 0) {
|
if (err <= 0) {
|
||||||
Limelog("Input: send() failed: %d\n", (int)LastSocketError());
|
Limelog("Input: send() failed: %d\n", (int)LastSocketError());
|
||||||
@@ -268,7 +268,7 @@ static void inputSendThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Begin the input stream */
|
// Begin the input stream
|
||||||
int startInputStream(void) {
|
int startInputStream(void) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ int startInputStream(void) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stops the input stream */
|
// Stops the input stream
|
||||||
int stopInputStream(void) {
|
int stopInputStream(void) {
|
||||||
PltInterruptThread(&inputSendThread);
|
PltInterruptThread(&inputSendThread);
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ int stopInputStream(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a mouse move event to the streaming machine */
|
// Send a mouse move event to the streaming machine
|
||||||
int LiSendMouseMoveEvent(short deltaX, short deltaY) {
|
int LiSendMouseMoveEvent(short deltaX, short deltaY) {
|
||||||
PPACKET_HOLDER holder;
|
PPACKET_HOLDER holder;
|
||||||
int err;
|
int err;
|
||||||
@@ -330,7 +330,7 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a mouse button event to the streaming machine */
|
// Send a mouse button event to the streaming machine
|
||||||
int LiSendMouseButtonEvent(char action, int button) {
|
int LiSendMouseButtonEvent(char action, int button) {
|
||||||
PPACKET_HOLDER holder;
|
PPACKET_HOLDER holder;
|
||||||
int err;
|
int err;
|
||||||
@@ -357,7 +357,7 @@ int LiSendMouseButtonEvent(char action, int button) {
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a key press event to the streaming machine */
|
// Send a key press event to the streaming machine
|
||||||
int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
|
int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
|
||||||
PPACKET_HOLDER holder;
|
PPACKET_HOLDER holder;
|
||||||
int err;
|
int err;
|
||||||
@@ -388,7 +388,7 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int sendControllerEventInternal(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
static int sendControllerEventInternal(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
||||||
short leftStickX, short leftStickY, short rightStickX, short rightStickY)
|
short leftStickX, short leftStickY, short rightStickX, short rightStickY)
|
||||||
{
|
{
|
||||||
PPACKET_HOLDER holder;
|
PPACKET_HOLDER holder;
|
||||||
int err;
|
int err;
|
||||||
@@ -447,23 +447,23 @@ static int sendControllerEventInternal(short controllerNumber, short buttonFlags
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a controller event to the streaming machine */
|
// Send a controller event to the streaming machine
|
||||||
int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
||||||
short leftStickX, short leftStickY, short rightStickX, short rightStickY)
|
short leftStickX, short leftStickY, short rightStickX, short rightStickY)
|
||||||
{
|
{
|
||||||
return sendControllerEventInternal(0, buttonFlags, leftTrigger, rightTrigger,
|
return sendControllerEventInternal(0, buttonFlags, leftTrigger, rightTrigger,
|
||||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a controller event to the streaming machine */
|
// Send a controller event to the streaming machine
|
||||||
int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
||||||
short leftStickX, short leftStickY, short rightStickX, short rightStickY)
|
short leftStickX, short leftStickY, short rightStickX, short rightStickY)
|
||||||
{
|
{
|
||||||
return sendControllerEventInternal(controllerNumber, buttonFlags, leftTrigger, rightTrigger,
|
return sendControllerEventInternal(controllerNumber, buttonFlags, leftTrigger, rightTrigger,
|
||||||
leftStickX, leftStickY, rightStickX, rightStickY);
|
leftStickX, leftStickY, rightStickX, rightStickY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a scroll event to the streaming machine */
|
// Send a scroll event to the streaming machine
|
||||||
int LiSendScrollEvent(signed char scrollClicks) {
|
int LiSendScrollEvent(signed char scrollClicks) {
|
||||||
PPACKET_HOLDER holder;
|
PPACKET_HOLDER holder;
|
||||||
int err;
|
int err;
|
||||||
|
|||||||
+153
-153
@@ -8,62 +8,62 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable this definition during debugging to enable assertions
|
// Enable this definition during debugging to enable assertions
|
||||||
//#define LC_DEBUG
|
//#define LC_DEBUG
|
||||||
|
|
||||||
typedef struct _STREAM_CONFIGURATION {
|
typedef struct _STREAM_CONFIGURATION {
|
||||||
// Dimensions in pixels of the desired video stream
|
// Dimensions in pixels of the desired video stream
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
// FPS of the desired video stream
|
// FPS of the desired video stream
|
||||||
int fps;
|
int fps;
|
||||||
|
|
||||||
// Bitrate of the desired video stream (audio adds another ~1 Mbps)
|
// Bitrate of the desired video stream (audio adds another ~1 Mbps)
|
||||||
int bitrate;
|
int bitrate;
|
||||||
|
|
||||||
// Max video packet size in bytes (use 1024 if unsure)
|
// Max video packet size in bytes (use 1024 if unsure)
|
||||||
int packetSize;
|
int packetSize;
|
||||||
|
|
||||||
// Set to non-zero value to enable remote (over the Internet)
|
// Set to non-zero value to enable remote (over the Internet)
|
||||||
// streaming optimizations. If unsure, set to 0.
|
// streaming optimizations. If unsure, set to 0.
|
||||||
int streamingRemotely;
|
int streamingRemotely;
|
||||||
|
|
||||||
// Specifies the channel configuration of the audio stream.
|
// Specifies the channel configuration of the audio stream.
|
||||||
// See AUDIO_CONFIGURATION_XXX constants below.
|
// See AUDIO_CONFIGURATION_XXX constants below.
|
||||||
int audioConfiguration;
|
int audioConfiguration;
|
||||||
|
|
||||||
// AES encryption data for the remote input stream. This must be
|
// AES encryption data for the remote input stream. This must be
|
||||||
// the same as what was passed as rikey and rikeyid
|
// the same as what was passed as rikey and rikeyid
|
||||||
// in /launch and /resume requests.
|
// in /launch and /resume requests.
|
||||||
char remoteInputAesKey[16];
|
char remoteInputAesKey[16];
|
||||||
char remoteInputAesIv[16];
|
char remoteInputAesIv[16];
|
||||||
} STREAM_CONFIGURATION, *PSTREAM_CONFIGURATION;
|
} STREAM_CONFIGURATION, *PSTREAM_CONFIGURATION;
|
||||||
|
|
||||||
// Use this function to zero the stream configuration when allocated on the stack or heap
|
// Use this function to zero the stream configuration when allocated on the stack or heap
|
||||||
void LiInitializeStreamConfiguration(PSTREAM_CONFIGURATION streamConfig);
|
void LiInitializeStreamConfiguration(PSTREAM_CONFIGURATION streamConfig);
|
||||||
|
|
||||||
typedef struct _LENTRY {
|
typedef struct _LENTRY {
|
||||||
// Pointer to the next entry or NULL if this is the last entry
|
// Pointer to the next entry or NULL if this is the last entry
|
||||||
struct _LENTRY *next;
|
struct _LENTRY *next;
|
||||||
|
|
||||||
// Pointer to data (never NULL)
|
// Pointer to data (never NULL)
|
||||||
char* data;
|
char* data;
|
||||||
|
|
||||||
// Size of data in bytes (never <= 0)
|
// Size of data in bytes (never <= 0)
|
||||||
int length;
|
int length;
|
||||||
} LENTRY, *PLENTRY;
|
} LENTRY, *PLENTRY;
|
||||||
|
|
||||||
// A decode unit describes a buffer chain of H264 data from multiple packets
|
// A decode unit describes a buffer chain of H264 data from multiple packets
|
||||||
typedef struct _DECODE_UNIT {
|
typedef struct _DECODE_UNIT {
|
||||||
// Length of the entire buffer chain in bytes
|
// Length of the entire buffer chain in bytes
|
||||||
int fullLength;
|
int fullLength;
|
||||||
|
|
||||||
// Head of the buffer chain (never NULL)
|
// Head of the buffer chain (never NULL)
|
||||||
PLENTRY bufferList;
|
PLENTRY bufferList;
|
||||||
} DECODE_UNIT, *PDECODE_UNIT;
|
} DECODE_UNIT, *PDECODE_UNIT;
|
||||||
|
|
||||||
// Specifies that the audio stream should be encoded in stereo (default)
|
// Specifies that the audio stream should be encoded in stereo (default)
|
||||||
#define AUDIO_CONFIGURATION_STEREO 0
|
#define AUDIO_CONFIGURATION_STEREO 0
|
||||||
|
|
||||||
// Specifies that the audio stream should be in 5.1 surround sound if the PC is able
|
// Specifies that the audio stream should be in 5.1 surround sound if the PC is able
|
||||||
@@ -85,73 +85,73 @@ typedef struct _DECODE_UNIT {
|
|||||||
#define CAPABILITY_SLICES_PER_FRAME(x) (((unsigned char)(x)) << 24)
|
#define CAPABILITY_SLICES_PER_FRAME(x) (((unsigned char)(x)) << 24)
|
||||||
|
|
||||||
// This callback is invoked to provide details about the video stream and allow configuration of the decoder
|
// This callback is invoked to provide details about the video stream and allow configuration of the decoder
|
||||||
typedef void(*DecoderRendererSetup)(int width, int height, int redrawRate, void* context, int drFlags);
|
typedef void(*DecoderRendererSetup)(int width, int height, int redrawRate, void* context, int drFlags);
|
||||||
|
|
||||||
// This callback performs the teardown of the video decoder
|
// This callback performs the teardown of the video decoder
|
||||||
typedef void(*DecoderRendererCleanup)(void);
|
typedef void(*DecoderRendererCleanup)(void);
|
||||||
|
|
||||||
// This callback provides Annex B formatted H264 elementary stream data to the
|
// This callback provides Annex B formatted H264 elementary stream data to the
|
||||||
// decoder. If the decoder is unable to process the submitted data for some reason,
|
// decoder. If the decoder is unable to process the submitted data for some reason,
|
||||||
// it must return DR_NEED_IDR to generate a keyframe.
|
// it must return DR_NEED_IDR to generate a keyframe.
|
||||||
#define DR_OK 0
|
#define DR_OK 0
|
||||||
#define DR_NEED_IDR -1
|
#define DR_NEED_IDR -1
|
||||||
typedef int(*DecoderRendererSubmitDecodeUnit)(PDECODE_UNIT decodeUnit);
|
typedef int(*DecoderRendererSubmitDecodeUnit)(PDECODE_UNIT decodeUnit);
|
||||||
|
|
||||||
typedef struct _DECODER_RENDERER_CALLBACKS {
|
typedef struct _DECODER_RENDERER_CALLBACKS {
|
||||||
DecoderRendererSetup setup;
|
DecoderRendererSetup setup;
|
||||||
DecoderRendererCleanup cleanup;
|
DecoderRendererCleanup cleanup;
|
||||||
DecoderRendererSubmitDecodeUnit submitDecodeUnit;
|
DecoderRendererSubmitDecodeUnit submitDecodeUnit;
|
||||||
int capabilities;
|
int capabilities;
|
||||||
} DECODER_RENDERER_CALLBACKS, *PDECODER_RENDERER_CALLBACKS;
|
} DECODER_RENDERER_CALLBACKS, *PDECODER_RENDERER_CALLBACKS;
|
||||||
|
|
||||||
// Use this function to zero the video callbacks when allocated on the stack or heap
|
// Use this function to zero the video callbacks when allocated on the stack or heap
|
||||||
void LiInitializeVideoCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks);
|
void LiInitializeVideoCallbacks(PDECODER_RENDERER_CALLBACKS drCallbacks);
|
||||||
|
|
||||||
// This structure provides the Opus multistream decoder parameters required to successfully
|
// This structure provides the Opus multistream decoder parameters required to successfully
|
||||||
// decode the audio stream being sent from the computer. See opus_multistream_decoder_init docs
|
// decode the audio stream being sent from the computer. See opus_multistream_decoder_init docs
|
||||||
// for details about these fields.
|
// for details about these fields.
|
||||||
//
|
//
|
||||||
// The supplied mapping array is indexed according to the following output channel order:
|
// The supplied mapping array is indexed according to the following output channel order:
|
||||||
// 0 - Front Left
|
// 0 - Front Left
|
||||||
// 1 - Front Right
|
// 1 - Front Right
|
||||||
// 2 - Center
|
// 2 - Center
|
||||||
// 3 - LFE
|
// 3 - LFE
|
||||||
// 4 - Surround Left
|
// 4 - Surround Left
|
||||||
// 5 - Surround Right
|
// 5 - Surround Right
|
||||||
//
|
//
|
||||||
// If the mapping order does not match the channel order of the audio renderer, you may swap
|
// If the mapping order does not match the channel order of the audio renderer, you may swap
|
||||||
// the values in the mismatched indices until the mapping array matches the desired channel order.
|
// the values in the mismatched indices until the mapping array matches the desired channel order.
|
||||||
typedef struct _OPUS_MULTISTREAM_CONFIGURATION {
|
typedef struct _OPUS_MULTISTREAM_CONFIGURATION {
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
int channelCount;
|
int channelCount;
|
||||||
int streams;
|
int streams;
|
||||||
int coupledStreams;
|
int coupledStreams;
|
||||||
const unsigned char mapping[6];
|
const unsigned char mapping[6];
|
||||||
} OPUS_MULTISTREAM_CONFIGURATION, *POPUS_MULTISTREAM_CONFIGURATION;
|
} OPUS_MULTISTREAM_CONFIGURATION, *POPUS_MULTISTREAM_CONFIGURATION;
|
||||||
|
|
||||||
// This callback initializes the audio renderer. The audio configuration parameter
|
// This callback initializes the audio renderer. The audio configuration parameter
|
||||||
// provides the negotiated audio configuration. This may differ from the one
|
// provides the negotiated audio configuration. This may differ from the one
|
||||||
// specified in the stream configuration.
|
// specified in the stream configuration.
|
||||||
typedef void(*AudioRendererInit)(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig);
|
typedef void(*AudioRendererInit)(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig);
|
||||||
|
|
||||||
// This callback performs the final teardown of the audio decoder
|
// This callback performs the final teardown of the audio decoder
|
||||||
typedef void(*AudioRendererCleanup)(void);
|
typedef void(*AudioRendererCleanup)(void);
|
||||||
|
|
||||||
// This callback provides Opus audio data to be decoded and played. sampleLength is in bytes.
|
// This callback provides Opus audio data to be decoded and played. sampleLength is in bytes.
|
||||||
typedef void(*AudioRendererDecodeAndPlaySample)(char* sampleData, int sampleLength);
|
typedef void(*AudioRendererDecodeAndPlaySample)(char* sampleData, int sampleLength);
|
||||||
|
|
||||||
typedef struct _AUDIO_RENDERER_CALLBACKS {
|
typedef struct _AUDIO_RENDERER_CALLBACKS {
|
||||||
AudioRendererInit init;
|
AudioRendererInit init;
|
||||||
AudioRendererCleanup cleanup;
|
AudioRendererCleanup cleanup;
|
||||||
AudioRendererDecodeAndPlaySample decodeAndPlaySample;
|
AudioRendererDecodeAndPlaySample decodeAndPlaySample;
|
||||||
int capabilities;
|
int capabilities;
|
||||||
} AUDIO_RENDERER_CALLBACKS, *PAUDIO_RENDERER_CALLBACKS;
|
} AUDIO_RENDERER_CALLBACKS, *PAUDIO_RENDERER_CALLBACKS;
|
||||||
|
|
||||||
// Use this function to zero the audio callbacks when allocated on the stack or heap
|
// Use this function to zero the audio callbacks when allocated on the stack or heap
|
||||||
void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks);
|
void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks);
|
||||||
|
|
||||||
// Subject to change in future releases
|
// Subject to change in future releases
|
||||||
// Use LiGetStageName() for stable stage names
|
// Use LiGetStageName() for stable stage names
|
||||||
#define STAGE_NONE 0
|
#define STAGE_NONE 0
|
||||||
#define STAGE_PLATFORM_INIT 1
|
#define STAGE_PLATFORM_INIT 1
|
||||||
#define STAGE_NAME_RESOLUTION 2
|
#define STAGE_NAME_RESOLUTION 2
|
||||||
@@ -167,78 +167,78 @@ void LiInitializeAudioCallbacks(PAUDIO_RENDERER_CALLBACKS arCallbacks);
|
|||||||
#define STAGE_MAX 12
|
#define STAGE_MAX 12
|
||||||
|
|
||||||
// This callback is invoked to indicate that a stage of initialization is about to begin
|
// This callback is invoked to indicate that a stage of initialization is about to begin
|
||||||
typedef void(*ConnListenerStageStarting)(int stage);
|
typedef void(*ConnListenerStageStarting)(int stage);
|
||||||
|
|
||||||
// This callback is invoked to indicate that a stage of initialization has completed
|
// This callback is invoked to indicate that a stage of initialization has completed
|
||||||
typedef void(*ConnListenerStageComplete)(int stage);
|
typedef void(*ConnListenerStageComplete)(int stage);
|
||||||
|
|
||||||
// This callback is invoked to indicate that a stage of initialization has failed
|
// This callback is invoked to indicate that a stage of initialization has failed
|
||||||
typedef void(*ConnListenerStageFailed)(int stage, long errorCode);
|
typedef void(*ConnListenerStageFailed)(int stage, long errorCode);
|
||||||
|
|
||||||
// This callback is invoked after initialization has finished
|
// This callback is invoked after initialization has finished
|
||||||
typedef void(*ConnListenerConnectionStarted)(void);
|
typedef void(*ConnListenerConnectionStarted)(void);
|
||||||
|
|
||||||
// This callback is invoked when a connection failure occurs. It will not
|
// This callback is invoked when a connection failure occurs. It will not
|
||||||
// occur as a result of a call to LiStopConnection()
|
// occur as a result of a call to LiStopConnection()
|
||||||
typedef void(*ConnListenerConnectionTerminated)(long errorCode);
|
typedef void(*ConnListenerConnectionTerminated)(long errorCode);
|
||||||
|
|
||||||
// This callback is invoked to display a dialog-type message to the user
|
// This callback is invoked to display a dialog-type message to the user
|
||||||
typedef void(*ConnListenerDisplayMessage)(char* message);
|
typedef void(*ConnListenerDisplayMessage)(char* message);
|
||||||
|
|
||||||
// This callback is invoked to display a transient message for the user
|
// This callback is invoked to display a transient message for the user
|
||||||
// while streaming
|
// while streaming
|
||||||
typedef void(*ConnListenerDisplayTransientMessage)(char* message);
|
typedef void(*ConnListenerDisplayTransientMessage)(char* message);
|
||||||
|
|
||||||
typedef struct _CONNECTION_LISTENER_CALLBACKS {
|
typedef struct _CONNECTION_LISTENER_CALLBACKS {
|
||||||
ConnListenerStageStarting stageStarting;
|
ConnListenerStageStarting stageStarting;
|
||||||
ConnListenerStageComplete stageComplete;
|
ConnListenerStageComplete stageComplete;
|
||||||
ConnListenerStageFailed stageFailed;
|
ConnListenerStageFailed stageFailed;
|
||||||
ConnListenerConnectionStarted connectionStarted;
|
ConnListenerConnectionStarted connectionStarted;
|
||||||
ConnListenerConnectionTerminated connectionTerminated;
|
ConnListenerConnectionTerminated connectionTerminated;
|
||||||
ConnListenerDisplayMessage displayMessage;
|
ConnListenerDisplayMessage displayMessage;
|
||||||
ConnListenerDisplayTransientMessage displayTransientMessage;
|
ConnListenerDisplayTransientMessage displayTransientMessage;
|
||||||
} CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS;
|
} CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS;
|
||||||
|
|
||||||
// Use this function to zero the connection callbacks when allocated on the stack or heap
|
// Use this function to zero the connection callbacks when allocated on the stack or heap
|
||||||
void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks);
|
void LiInitializeConnectionCallbacks(PCONNECTION_LISTENER_CALLBACKS clCallbacks);
|
||||||
|
|
||||||
// This function begins streaming.
|
// This function begins streaming.
|
||||||
//
|
//
|
||||||
// Callbacks are all optional. Pass NULL for individual callbacks within each struct or pass NULL for the entire struct
|
// Callbacks are all optional. Pass NULL for individual callbacks within each struct or pass NULL for the entire struct
|
||||||
// to use the defaults for all callbacks.
|
// to use the defaults for all callbacks.
|
||||||
//
|
//
|
||||||
// _serverMajorVersion is the major version number of the 'appversion' tag in the /serverinfo request
|
// _serverMajorVersion is the major version number of the 'appversion' tag in the /serverinfo request
|
||||||
//
|
//
|
||||||
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
||||||
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags, int _serverMajorVersion);
|
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags, int _serverMajorVersion);
|
||||||
|
|
||||||
// This function stops streaming.
|
// This function stops streaming.
|
||||||
void LiStopConnection(void);
|
void LiStopConnection(void);
|
||||||
|
|
||||||
// Use to get a user-visible string to display initialization progress
|
// Use to get a user-visible string to display initialization progress
|
||||||
// from the integer passed to the ConnListenerStageXXX callbacks
|
// from the integer passed to the ConnListenerStageXXX callbacks
|
||||||
const char* LiGetStageName(int stage);
|
const char* LiGetStageName(int stage);
|
||||||
|
|
||||||
// This function queues a mouse move event to be sent to the remote server.
|
// This function queues a mouse move event to be sent to the remote server.
|
||||||
int LiSendMouseMoveEvent(short deltaX, short deltaY);
|
int LiSendMouseMoveEvent(short deltaX, short deltaY);
|
||||||
|
|
||||||
// This function queues a mouse button event to be sent to the remote server.
|
// This function queues a mouse button event to be sent to the remote server.
|
||||||
#define BUTTON_ACTION_PRESS 0x07
|
#define BUTTON_ACTION_PRESS 0x07
|
||||||
#define BUTTON_ACTION_RELEASE 0x08
|
#define BUTTON_ACTION_RELEASE 0x08
|
||||||
#define BUTTON_LEFT 0x01
|
#define BUTTON_LEFT 0x01
|
||||||
#define BUTTON_MIDDLE 0x02
|
#define BUTTON_MIDDLE 0x02
|
||||||
#define BUTTON_RIGHT 0x03
|
#define BUTTON_RIGHT 0x03
|
||||||
int LiSendMouseButtonEvent(char action, int button);
|
int LiSendMouseButtonEvent(char action, int button);
|
||||||
|
|
||||||
// This function queues a keyboard event to be sent to the remote server.
|
// This function queues a keyboard event to be sent to the remote server.
|
||||||
#define KEY_ACTION_DOWN 0x03
|
#define KEY_ACTION_DOWN 0x03
|
||||||
#define KEY_ACTION_UP 0x04
|
#define KEY_ACTION_UP 0x04
|
||||||
#define MODIFIER_SHIFT 0x01
|
#define MODIFIER_SHIFT 0x01
|
||||||
#define MODIFIER_CTRL 0x02
|
#define MODIFIER_CTRL 0x02
|
||||||
#define MODIFIER_ALT 0x04
|
#define MODIFIER_ALT 0x04
|
||||||
int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers);
|
int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers);
|
||||||
|
|
||||||
// Button flags
|
// Button flags
|
||||||
#define A_FLAG 0x1000
|
#define A_FLAG 0x1000
|
||||||
#define B_FLAG 0x2000
|
#define B_FLAG 0x2000
|
||||||
#define X_FLAG 0x4000
|
#define X_FLAG 0x4000
|
||||||
@@ -257,18 +257,18 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers);
|
|||||||
|
|
||||||
// This function queues a controller event to be sent to the remote server. It will
|
// This function queues a controller event to be sent to the remote server. It will
|
||||||
// be seen by the computer as the first controller.
|
// be seen by the computer as the first controller.
|
||||||
int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
int LiSendControllerEvent(short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
||||||
short leftStickX, short leftStickY, short rightStickX, short rightStickY);
|
short leftStickX, short leftStickY, short rightStickX, short rightStickY);
|
||||||
|
|
||||||
// This function queues a controller event to be sent to the remote server. The controllerNumber
|
// This function queues a controller event to be sent to the remote server. The controllerNumber
|
||||||
// parameter is a zero-based index of which controller this event corresponds to. The largest legal
|
// parameter is a zero-based index of which controller this event corresponds to. The largest legal
|
||||||
// controller number is 3 (for a total of 4 controllers, the Xinput maximum). On generation 3 servers (GFE 2.1.x),
|
// controller number is 3 (for a total of 4 controllers, the Xinput maximum). On generation 3 servers (GFE 2.1.x),
|
||||||
// these will be sent as controller 0 regardless of the controllerNumber parameter.
|
// these will be sent as controller 0 regardless of the controllerNumber parameter.
|
||||||
int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
int LiSendMultiControllerEvent(short controllerNumber, short buttonFlags, unsigned char leftTrigger, unsigned char rightTrigger,
|
||||||
short leftStickX, short leftStickY, short rightStickX, short rightStickY);
|
short leftStickX, short leftStickY, short rightStickX, short rightStickY);
|
||||||
|
|
||||||
// This function queues a vertical scroll event to the remote server.
|
// This function queues a vertical scroll event to the remote server.
|
||||||
int LiSendScrollEvent(signed char scrollClicks);
|
int LiSendScrollEvent(signed char scrollClicks);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "LinkedBlockingQueue.h"
|
#include "LinkedBlockingQueue.h"
|
||||||
|
|
||||||
/* Destroy the linked blocking queue and associated mutex and event */
|
// Destroy the linked blocking queue and associated mutex and event
|
||||||
PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead) {
|
PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead) {
|
||||||
PltDeleteMutex(&queueHead->mutex);
|
PltDeleteMutex(&queueHead->mutex);
|
||||||
PltCloseEvent(&queueHead->containsDataEvent);
|
PltCloseEvent(&queueHead->containsDataEvent);
|
||||||
@@ -8,7 +8,7 @@ PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEU
|
|||||||
return queueHead->head;
|
return queueHead->head;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush the queue */
|
// Flush the queue
|
||||||
PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead) {
|
PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead) {
|
||||||
PLINKED_BLOCKING_QUEUE_ENTRY head;
|
PLINKED_BLOCKING_QUEUE_ENTRY head;
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead
|
|||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Linked blocking queue init */
|
// Linked blocking queue init
|
||||||
int LbqInitializeLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead, int sizeBound) {
|
int LbqInitializeLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead, int sizeBound) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,6 @@ int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
|
|||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-13
@@ -39,21 +39,21 @@ void LimelogWindows(char* Format, ...);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LC_WINDOWS)
|
#if defined(LC_WINDOWS)
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
#ifdef LC_DEBUG
|
#ifdef LC_DEBUG
|
||||||
#define LC_ASSERT(x) __analysis_assume(x); \
|
#define LC_ASSERT(x) __analysis_assume(x); \
|
||||||
_ASSERTE(x)
|
_ASSERTE(x)
|
||||||
#else
|
|
||||||
#define LC_ASSERT(x)
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
#ifndef LC_DEBUG
|
#define LC_ASSERT(x)
|
||||||
#ifndef NDEBUG
|
#endif
|
||||||
#define NDEBUG
|
#else
|
||||||
#endif
|
#ifndef LC_DEBUG
|
||||||
#endif
|
#ifndef NDEBUG
|
||||||
#include <assert.h>
|
#define NDEBUG
|
||||||
#define LC_ASSERT(x) assert(x)
|
#endif
|
||||||
|
#endif
|
||||||
|
#include <assert.h>
|
||||||
|
#define LC_ASSERT(x) assert(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int initializePlatform(void);
|
int initializePlatform(void);
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
|
|||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.ss_family = addrfamily;
|
addr.ss_family = addrfamily;
|
||||||
if (bind(s, (struct sockaddr*) &addr,
|
if (bind(s, (struct sockaddr*) &addr,
|
||||||
addrfamily == AF_INET ?
|
addrfamily == AF_INET ?
|
||||||
sizeof(struct sockaddr_in) :
|
sizeof(struct sockaddr_in) :
|
||||||
sizeof(struct sockaddr_in6)) == SOCKET_ERROR) {
|
sizeof(struct sockaddr_in6)) == SOCKET_ERROR) {
|
||||||
err = LastSocketError();
|
err = LastSocketError();
|
||||||
Limelog("bind() failed: %d\n", err);
|
Limelog("bind() failed: %d\n", err);
|
||||||
closesocket(s);
|
closesocket(s);
|
||||||
@@ -53,10 +53,10 @@ SOCKET bindUdpSocket(int addrfamily, int bufferSize) {
|
|||||||
#ifdef LC_DARWIN
|
#ifdef LC_DARWIN
|
||||||
// Disable SIGPIPE on iOS
|
// Disable SIGPIPE on iOS
|
||||||
val = 1;
|
val = 1;
|
||||||
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char* )&val, sizeof(val));
|
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*) &bufferSize, sizeof(bufferSize));
|
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize, sizeof(bufferSize));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ SOCKET connectTcpSocket(struct sockaddr_storage *dstaddr, SOCKADDR_LEN addrlen,
|
|||||||
#ifdef LC_DARWIN
|
#ifdef LC_DARWIN
|
||||||
// Disable SIGPIPE on iOS
|
// Disable SIGPIPE on iOS
|
||||||
val = 1;
|
val = 1;
|
||||||
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char* )&val, sizeof(val));
|
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&val, sizeof(val));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memcpy(&addr, dstaddr, sizeof(addr));
|
memcpy(&addr, dstaddr, sizeof(addr));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "Limelight.h"
|
#include "Limelight.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
typedef void (*ThreadEntry)(void *context);
|
typedef void(*ThreadEntry)(void *context);
|
||||||
|
|
||||||
struct thread_context {
|
struct thread_context {
|
||||||
ThreadEntry entry;
|
ThreadEntry entry;
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ static int requestDescribe(PRTSP_MESSAGE response, int* error) {
|
|||||||
ret = initializeRtspRequest(&request, "DESCRIBE", rtspTargetUrl);
|
ret = initializeRtspRequest(&request, "DESCRIBE", rtspTargetUrl);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (addOption(&request, "Accept",
|
if (addOption(&request, "Accept",
|
||||||
"application/sdp") &&
|
"application/sdp") &&
|
||||||
addOption(&request, "If-Modified-Since",
|
addOption(&request, "If-Modified-Since",
|
||||||
"Thu, 01 Jan 1970 00:00:00 GMT")) {
|
"Thu, 01 Jan 1970 00:00:00 GMT")) {
|
||||||
ret = transactRtspMessage(&request, response, error);
|
ret = transactRtspMessage(&request, response, error);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
// Check if String s begins with the given prefix
|
// Check if String s begins with the given prefix
|
||||||
static int startsWith(const char* s, const char* prefix) {
|
static int startsWith(const char* s, const char* prefix) {
|
||||||
|
|
||||||
if (strncmp(s, prefix, strlen(prefix)) == 0) {
|
if (strncmp(s, prefix, strlen(prefix)) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -140,7 +139,6 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
|
|||||||
{
|
{
|
||||||
token = strtok(NULL, typeFlag == TOKEN_OPTION ? optDelim : end);
|
token = strtok(NULL, typeFlag == TOKEN_OPTION ? optDelim : end);
|
||||||
if (token != NULL) {
|
if (token != NULL) {
|
||||||
|
|
||||||
if (typeFlag == TOKEN_OPTION) {
|
if (typeFlag == TOKEN_OPTION) {
|
||||||
opt = token;
|
opt = token;
|
||||||
}
|
}
|
||||||
@@ -160,12 +158,11 @@ int parseRtspMessage(PRTSP_MESSAGE msg, char* rtspMessage, int length) {
|
|||||||
insertOption(&options, newOpt);
|
insertOption(&options, newOpt);
|
||||||
|
|
||||||
// Check if we're at the end of the message portion marked by \r\n\r\n
|
// Check if we're at the end of the message portion marked by \r\n\r\n
|
||||||
//endCheck points to the remainder of messageBuffer after the token
|
// endCheck points to the remainder of messageBuffer after the token
|
||||||
endCheck = &token[0] + strlen(token) + 1;
|
endCheck = &token[0] + strlen(token) + 1;
|
||||||
|
|
||||||
// See if we've hit the end of the message. The first \r is missing because it's been tokenized
|
// See if we've hit the end of the message. The first \r is missing because it's been tokenized
|
||||||
if (startsWith(endCheck, "\n\r\n")) {
|
if (startsWith(endCheck, "\n\r\n")) {
|
||||||
|
|
||||||
// We've encountered the end of the message - mark it thus
|
// We've encountered the end of the message - mark it thus
|
||||||
messageEnded = 1;
|
messageEnded = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
#define CHANNEL_MASK_51_SURROUND 0xFC
|
#define CHANNEL_MASK_51_SURROUND 0xFC
|
||||||
|
|
||||||
typedef struct _SDP_OPTION {
|
typedef struct _SDP_OPTION {
|
||||||
char name[MAX_OPTION_NAME_LEN+1];
|
char name[MAX_OPTION_NAME_LEN + 1];
|
||||||
void* payload;
|
void* payload;
|
||||||
int payloadLen;
|
int payloadLen;
|
||||||
struct _SDP_OPTION *next;
|
struct _SDP_OPTION *next;
|
||||||
} SDP_OPTION, *PSDP_OPTION;
|
} SDP_OPTION, *PSDP_OPTION;
|
||||||
|
|
||||||
/* Cleanup the attribute list */
|
// Cleanup the attribute list
|
||||||
static void freeAttributeList(PSDP_OPTION head) {
|
static void freeAttributeList(PSDP_OPTION head) {
|
||||||
PSDP_OPTION next;
|
PSDP_OPTION next;
|
||||||
while (head != NULL) {
|
while (head != NULL) {
|
||||||
@@ -28,7 +28,7 @@ static void freeAttributeList(PSDP_OPTION head) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the size of the attribute list */
|
// Get the size of the attribute list
|
||||||
static int getSerializedAttributeListSize(PSDP_OPTION head) {
|
static int getSerializedAttributeListSize(PSDP_OPTION head) {
|
||||||
PSDP_OPTION currentEntry = head;
|
PSDP_OPTION currentEntry = head;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
@@ -44,7 +44,7 @@ static int getSerializedAttributeListSize(PSDP_OPTION head) {
|
|||||||
return (int)size;
|
return (int)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Populate the serialized attribute list into a string */
|
// Populate the serialized attribute list into a string
|
||||||
static int fillSerializedAttributeList(char* buffer, PSDP_OPTION head) {
|
static int fillSerializedAttributeList(char* buffer, PSDP_OPTION head) {
|
||||||
PSDP_OPTION currentEntry = head;
|
PSDP_OPTION currentEntry = head;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
@@ -59,7 +59,7 @@ static int fillSerializedAttributeList(char* buffer, PSDP_OPTION head) {
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an attribute */
|
// Add an attribute
|
||||||
static int addAttributeBinary(PSDP_OPTION *head, char* name, const void* payload, int payloadLen) {
|
static int addAttributeBinary(PSDP_OPTION *head, char* name, const void* payload, int payloadLen) {
|
||||||
PSDP_OPTION option, currentOption;
|
PSDP_OPTION option, currentOption;
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ static int addAttributeBinary(PSDP_OPTION *head, char* name, const void* payload
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an attribute string */
|
// Add an attribute string
|
||||||
static int addAttributeString(PSDP_OPTION *head, char* name, const char* payload) {
|
static int addAttributeString(PSDP_OPTION *head, char* name, const char* payload) {
|
||||||
// We purposefully omit the null terminating character
|
// We purposefully omit the null terminating character
|
||||||
return addAttributeBinary(head, name, payload, (int)strlen(payload));
|
return addAttributeBinary(head, name, payload, (int)strlen(payload));
|
||||||
@@ -102,29 +102,28 @@ static int addGen3Options(PSDP_OPTION *head, char* addrStr) {
|
|||||||
|
|
||||||
payloadInt = htonl(0x42774141);
|
payloadInt = htonl(0x42774141);
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-general.featureFlags", &payloadInt, sizeof(payloadInt));
|
"x-nv-general.featureFlags", &payloadInt, sizeof(payloadInt));
|
||||||
|
|
||||||
|
|
||||||
payloadInt = htonl(0x41514141);
|
payloadInt = htonl(0x41514141);
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[0].transferProtocol", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[0].transferProtocol", &payloadInt, sizeof(payloadInt));
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[1].transferProtocol", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[1].transferProtocol", &payloadInt, sizeof(payloadInt));
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[2].transferProtocol", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[2].transferProtocol", &payloadInt, sizeof(payloadInt));
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[3].transferProtocol", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[3].transferProtocol", &payloadInt, sizeof(payloadInt));
|
||||||
|
|
||||||
payloadInt = htonl(0x42414141);
|
payloadInt = htonl(0x42414141);
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[0].rateControlMode", &payloadInt, sizeof(payloadInt));
|
||||||
payloadInt = htonl(0x42514141);
|
payloadInt = htonl(0x42514141);
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[1].rateControlMode", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[1].rateControlMode", &payloadInt, sizeof(payloadInt));
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[2].rateControlMode", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[2].rateControlMode", &payloadInt, sizeof(payloadInt));
|
||||||
err |= addAttributeBinary(head,
|
err |= addAttributeBinary(head,
|
||||||
"x-nv-video[3].rateControlMode", &payloadInt, sizeof(payloadInt));
|
"x-nv-video[3].rateControlMode", &payloadInt, sizeof(payloadInt));
|
||||||
|
|
||||||
err |= addAttributeString(head, "x-nv-vqos[0].bw.flags", "14083");
|
err |= addAttributeString(head, "x-nv-vqos[0].bw.flags", "14083");
|
||||||
|
|
||||||
@@ -149,7 +148,7 @@ static int addGen4Options(PSDP_OPTION *head, char* addrStr) {
|
|||||||
err |= addAttributeString(head, "x-nv-video[0].rateControlMode", "4");
|
err |= addAttributeString(head, "x-nv-video[0].rateControlMode", "4");
|
||||||
|
|
||||||
// Use slicing for increased performance on some decoders
|
// Use slicing for increased performance on some decoders
|
||||||
slicesPerFrame = (unsigned char) (VideoCallbacks.capabilities >> 24);
|
slicesPerFrame = (unsigned char)(VideoCallbacks.capabilities >> 24);
|
||||||
if (slicesPerFrame == 0) {
|
if (slicesPerFrame == 0) {
|
||||||
// If not using slicing, we request 1 slice per frame
|
// If not using slicing, we request 1 slice per frame
|
||||||
slicesPerFrame = 1;
|
slicesPerFrame = 1;
|
||||||
@@ -227,7 +226,8 @@ static PSDP_OPTION getAttributesList(char *urlSafeAddr) {
|
|||||||
if (StreamConfig.streamingRemotely) {
|
if (StreamConfig.streamingRemotely) {
|
||||||
err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "0");
|
err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "0");
|
||||||
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "0");
|
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "0");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "5");
|
err |= addAttributeString(&optionHead, "x-nv-vqos[0].qosTrafficType", "5");
|
||||||
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4");
|
err |= addAttributeString(&optionHead, "x-nv-aqos.qosTrafficType", "4");
|
||||||
}
|
}
|
||||||
@@ -247,26 +247,26 @@ static PSDP_OPTION getAttributesList(char *urlSafeAddr) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Populate the SDP header with required information */
|
// Populate the SDP header with required information
|
||||||
static int fillSdpHeader(char* buffer, int rtspClientVersion, char *urlSafeAddr) {
|
static int fillSdpHeader(char* buffer, int rtspClientVersion, char *urlSafeAddr) {
|
||||||
return sprintf(buffer,
|
return sprintf(buffer,
|
||||||
"v=0\r\n"
|
"v=0\r\n"
|
||||||
"o=android 0 %d IN %s %s\r\n"
|
"o=android 0 %d IN %s %s\r\n"
|
||||||
"s=NVIDIA Streaming Client\r\n",
|
"s=NVIDIA Streaming Client\r\n",
|
||||||
rtspClientVersion,
|
rtspClientVersion,
|
||||||
RemoteAddr.ss_family == AF_INET ? "IPv4" : "IPv6",
|
RemoteAddr.ss_family == AF_INET ? "IPv4" : "IPv6",
|
||||||
urlSafeAddr);
|
urlSafeAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Populate the SDP tail with required information */
|
// Populate the SDP tail with required information
|
||||||
static int fillSdpTail(char* buffer) {
|
static int fillSdpTail(char* buffer) {
|
||||||
return sprintf(buffer,
|
return sprintf(buffer,
|
||||||
"t=0 0\r\n"
|
"t=0 0\r\n"
|
||||||
"m=video %d \r\n",
|
"m=video %d \r\n",
|
||||||
ServerMajorVersion < 4 ? 47996 : 47998);
|
ServerMajorVersion < 4 ? 47996 : 47998);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the SDP attributes for the stream config */
|
// Get the SDP attributes for the stream config
|
||||||
char* getSdpPayloadForStreamConfig(int rtspClientVersion, int *length) {
|
char* getSdpPayloadForStreamConfig(int rtspClientVersion, int *length) {
|
||||||
PSDP_OPTION attributeList;
|
PSDP_OPTION attributeList;
|
||||||
int offset;
|
int offset;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ typedef struct _BUFFER_DESC {
|
|||||||
unsigned int length;
|
unsigned int length;
|
||||||
} BUFFER_DESC, *PBUFFER_DESC;
|
} BUFFER_DESC, *PBUFFER_DESC;
|
||||||
|
|
||||||
/* Init */
|
// Init
|
||||||
void initializeVideoDepacketizer(int pktSize) {
|
void initializeVideoDepacketizer(int pktSize) {
|
||||||
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
LbqInitializeLinkedBlockingQueue(&decodeUnitQueue, 15);
|
LbqInitializeLinkedBlockingQueue(&decodeUnitQueue, 15);
|
||||||
@@ -46,7 +46,7 @@ void initializeVideoDepacketizer(int pktSize) {
|
|||||||
strictIdrFrameWait = !(VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION);
|
strictIdrFrameWait = !(VideoCallbacks.capabilities & CAPABILITY_REFERENCE_FRAME_INVALIDATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free malloced memory in AvcFrameState*/
|
// Free malloced memory in AvcFrameState*/
|
||||||
static void cleanupAvcFrameState(void) {
|
static void cleanupAvcFrameState(void) {
|
||||||
PLENTRY lastEntry;
|
PLENTRY lastEntry;
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ static void cleanupAvcFrameState(void) {
|
|||||||
nalChainDataLength = 0;
|
nalChainDataLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup AVC frame state and set that we're waiting for an IDR Frame*/
|
// Cleanup AVC frame state and set that we're waiting for an IDR Frame*/
|
||||||
static void dropAvcFrameState(void) {
|
static void dropAvcFrameState(void) {
|
||||||
// We'll need an IDR frame now if we're in strict mode
|
// We'll need an IDR frame now if we're in strict mode
|
||||||
if (strictIdrFrameWait) {
|
if (strictIdrFrameWait) {
|
||||||
@@ -84,20 +84,20 @@ static void dropAvcFrameState(void) {
|
|||||||
cleanupAvcFrameState();
|
cleanupAvcFrameState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup the list of decode units */
|
// Cleanup the list of decode units
|
||||||
static void freeDecodeUnitList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
|
static void freeDecodeUnitList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
|
||||||
PLINKED_BLOCKING_QUEUE_ENTRY nextEntry;
|
PLINKED_BLOCKING_QUEUE_ENTRY nextEntry;
|
||||||
|
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
nextEntry = entry->flink;
|
nextEntry = entry->flink;
|
||||||
|
|
||||||
freeQueuedDecodeUnit((PQUEUED_DECODE_UNIT) entry->data);
|
freeQueuedDecodeUnit((PQUEUED_DECODE_UNIT)entry->data);
|
||||||
|
|
||||||
entry = nextEntry;
|
entry = nextEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup video depacketizer and free malloced memory */
|
// Cleanup video depacketizer and free malloced memory
|
||||||
void destroyVideoDepacketizer(void) {
|
void destroyVideoDepacketizer(void) {
|
||||||
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
|
||||||
freeDecodeUnitList(LbqDestroyLinkedBlockingQueue(&decodeUnitQueue));
|
freeDecodeUnitList(LbqDestroyLinkedBlockingQueue(&decodeUnitQueue));
|
||||||
@@ -106,22 +106,22 @@ void destroyVideoDepacketizer(void) {
|
|||||||
cleanupAvcFrameState();
|
cleanupAvcFrameState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if candidate is a frame start and 0 otherwise */
|
// Returns 1 if candidate is a frame start and 0 otherwise
|
||||||
static int isSeqFrameStart(PBUFFER_DESC candidate) {
|
static int isSeqFrameStart(PBUFFER_DESC candidate) {
|
||||||
return (candidate->length == 4 && candidate->data[candidate->offset + candidate->length - 1] == 1);
|
return (candidate->length == 4 && candidate->data[candidate->offset + candidate->length - 1] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if candidate an AVC start and 0 otherwise */
|
// Returns 1 if candidate an AVC start and 0 otherwise
|
||||||
static int isSeqAvcStart(PBUFFER_DESC candidate) {
|
static int isSeqAvcStart(PBUFFER_DESC candidate) {
|
||||||
return (candidate->data[candidate->offset + candidate->length - 1] == 1);
|
return (candidate->data[candidate->offset + candidate->length - 1] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if candidate is padding and 0 otherwise */
|
// Returns 1 if candidate is padding and 0 otherwise
|
||||||
static int isSeqPadding(PBUFFER_DESC candidate) {
|
static int isSeqPadding(PBUFFER_DESC candidate) {
|
||||||
return (candidate->data[candidate->offset + candidate->length - 1] == 0);
|
return (candidate->data[candidate->offset + candidate->length - 1] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 on success, 0 otherwise */
|
// Returns 1 on success, 0 otherwise
|
||||||
static int getSpecialSeq(PBUFFER_DESC current, PBUFFER_DESC candidate) {
|
static int getSpecialSeq(PBUFFER_DESC current, PBUFFER_DESC candidate) {
|
||||||
if (current->length < 3) {
|
if (current->length < 3) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -158,9 +158,9 @@ static int getSpecialSeq(PBUFFER_DESC current, PBUFFER_DESC candidate) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the first decode unit available */
|
// Get the first decode unit available
|
||||||
int getNextQueuedDecodeUnit(PQUEUED_DECODE_UNIT *qdu) {
|
int getNextQueuedDecodeUnit(PQUEUED_DECODE_UNIT *qdu) {
|
||||||
int err = LbqWaitForQueueElement(&decodeUnitQueue, (void**) qdu);
|
int err = LbqWaitForQueueElement(&decodeUnitQueue, (void**)qdu);
|
||||||
if (err == LBQ_SUCCESS) {
|
if (err == LBQ_SUCCESS) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ int getNextQueuedDecodeUnit(PQUEUED_DECODE_UNIT *qdu) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup a decode unit by freeing the buffer chain and the holder */
|
// Cleanup a decode unit by freeing the buffer chain and the holder
|
||||||
void freeQueuedDecodeUnit(PQUEUED_DECODE_UNIT qdu) {
|
void freeQueuedDecodeUnit(PQUEUED_DECODE_UNIT qdu) {
|
||||||
PLENTRY lastEntry;
|
PLENTRY lastEntry;
|
||||||
|
|
||||||
@@ -182,10 +182,10 @@ void freeQueuedDecodeUnit(PQUEUED_DECODE_UNIT qdu) {
|
|||||||
free(qdu);
|
free(qdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reassemble the frame with the given frame number */
|
// Reassemble the frame with the given frame number
|
||||||
static void reassembleAvcFrame(int frameNumber) {
|
static void reassembleAvcFrame(int frameNumber) {
|
||||||
if (nalChainHead != NULL) {
|
if (nalChainHead != NULL) {
|
||||||
PQUEUED_DECODE_UNIT qdu = (PQUEUED_DECODE_UNIT) malloc(sizeof(*qdu));
|
PQUEUED_DECODE_UNIT qdu = (PQUEUED_DECODE_UNIT)malloc(sizeof(*qdu));
|
||||||
if (qdu != NULL) {
|
if (qdu != NULL) {
|
||||||
qdu->decodeUnit.bufferList = nalChainHead;
|
qdu->decodeUnit.bufferList = nalChainHead;
|
||||||
qdu->decodeUnit.fullLength = nalChainDataLength;
|
qdu->decodeUnit.fullLength = nalChainDataLength;
|
||||||
@@ -212,7 +212,8 @@ static void reassembleAvcFrame(int frameNumber) {
|
|||||||
connectionSinkTooSlow(0, frameNumber);
|
connectionSinkTooSlow(0, frameNumber);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit);
|
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit);
|
||||||
|
|
||||||
freeQueuedDecodeUnit(qdu);
|
freeQueuedDecodeUnit(qdu);
|
||||||
@@ -233,11 +234,11 @@ static void reassembleAvcFrame(int frameNumber) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void queueFragment(char *data, int offset, int length) {
|
static void queueFragment(char *data, int offset, int length) {
|
||||||
PLENTRY entry = (PLENTRY) malloc(sizeof(*entry) + length);
|
PLENTRY entry = (PLENTRY)malloc(sizeof(*entry) + length);
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
entry->next = NULL;
|
entry->next = NULL;
|
||||||
entry->length = length;
|
entry->length = length;
|
||||||
entry->data = (char*) (entry + 1);
|
entry->data = (char*)(entry + 1);
|
||||||
|
|
||||||
memcpy(entry->data, &data[offset], entry->length);
|
memcpy(entry->data, &data[offset], entry->length);
|
||||||
|
|
||||||
@@ -258,7 +259,7 @@ static void queueFragment(char *data, int offset, int length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process an RTP Payload */
|
// Process an RTP Payload
|
||||||
static void processRtpPayloadSlow(PNV_VIDEO_PACKET videoPacket, PBUFFER_DESC currentPos) {
|
static void processRtpPayloadSlow(PNV_VIDEO_PACKET videoPacket, PBUFFER_DESC currentPos) {
|
||||||
BUFFER_DESC specialSeq;
|
BUFFER_DESC specialSeq;
|
||||||
int decodingAvc = 0;
|
int decodingAvc = 0;
|
||||||
@@ -323,7 +324,7 @@ static void processRtpPayloadSlow(PNV_VIDEO_PACKET videoPacket, PBUFFER_DESC cur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if packet is the first one in the frame */
|
// Return 1 if packet is the first one in the frame
|
||||||
static int isFirstPacket(char flags) {
|
static int isFirstPacket(char flags) {
|
||||||
// Clear the picture data flag
|
// Clear the picture data flag
|
||||||
flags &= ~FLAG_CONTAINS_PIC_DATA;
|
flags &= ~FLAG_CONTAINS_PIC_DATA;
|
||||||
@@ -333,12 +334,12 @@ static int isFirstPacket(char flags) {
|
|||||||
flags == FLAG_SOF);
|
flags == FLAG_SOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adds a fragment directly to the queue */
|
// Adds a fragment directly to the queue
|
||||||
static void processRtpPayloadFast(BUFFER_DESC location) {
|
static void processRtpPayloadFast(BUFFER_DESC location) {
|
||||||
queueFragment(location.data, location.offset, location.length);
|
queueFragment(location.data, location.offset, location.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process an RTP Payload */
|
// Process an RTP Payload
|
||||||
void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
||||||
BUFFER_DESC currentPos, specialSeq;
|
BUFFER_DESC currentPos, specialSeq;
|
||||||
int frameIndex;
|
int frameIndex;
|
||||||
@@ -350,7 +351,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
|||||||
videoPacket->streamPacketIndex >>= 8;
|
videoPacket->streamPacketIndex >>= 8;
|
||||||
videoPacket->streamPacketIndex &= 0xFFFFFF;
|
videoPacket->streamPacketIndex &= 0xFFFFFF;
|
||||||
|
|
||||||
currentPos.data = (char*) (videoPacket + 1);
|
currentPos.data = (char*)(videoPacket + 1);
|
||||||
currentPos.offset = 0;
|
currentPos.offset = 0;
|
||||||
currentPos.length = length - sizeof(*videoPacket);
|
currentPos.length = length - sizeof(*videoPacket);
|
||||||
|
|
||||||
@@ -360,7 +361,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
|||||||
|
|
||||||
// Drop duplicates or re-ordered packets
|
// Drop duplicates or re-ordered packets
|
||||||
streamPacketIndex = videoPacket->streamPacketIndex;
|
streamPacketIndex = videoPacket->streamPacketIndex;
|
||||||
if (isBeforeSignedInt((short) streamPacketIndex, (short) (lastPacketInStream + 1), 0)) {
|
if (isBeforeSignedInt((short)streamPacketIndex, (short)(lastPacketInStream + 1), 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,7 +427,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
|||||||
// we need to drop it if the stream packet index
|
// we need to drop it if the stream packet index
|
||||||
// doesn't match
|
// doesn't match
|
||||||
if (!firstPacket && decodingFrame) {
|
if (!firstPacket && decodingFrame) {
|
||||||
if (streamPacketIndex != (int) (lastPacketInStream + 1)) {
|
if (streamPacketIndex != (int)(lastPacketInStream + 1)) {
|
||||||
Limelog("Network dropped middle of a frame\n");
|
Limelog("Network dropped middle of a frame\n");
|
||||||
nextFrameNumber = frameIndex + 1;
|
nextFrameNumber = frameIndex + 1;
|
||||||
|
|
||||||
@@ -440,7 +441,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notify the server of any packet losses
|
// Notify the server of any packet losses
|
||||||
if (streamPacketIndex != (int) (lastPacketInStream + 1)) {
|
if (streamPacketIndex != (int)(lastPacketInStream + 1)) {
|
||||||
// Packets were lost so report this to the server
|
// Packets were lost so report this to the server
|
||||||
connectionLostPackets(lastPacketInStream, streamPacketIndex);
|
connectionLostPackets(lastPacketInStream, streamPacketIndex);
|
||||||
}
|
}
|
||||||
@@ -486,7 +487,7 @@ void processRtpPayload(PNV_VIDEO_PACKET videoPacket, int length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an RTP Packet to the queue */
|
// Add an RTP Packet to the queue
|
||||||
void queueRtpPacket(PRTP_PACKET rtpPacket, int length) {
|
void queueRtpPacket(PRTP_PACKET rtpPacket, int length) {
|
||||||
int dataOffset;
|
int dataOffset;
|
||||||
|
|
||||||
|
|||||||
@@ -25,21 +25,21 @@ static PLT_THREAD decoderThread;
|
|||||||
// the RTP queue will wait for missing/reordered packets.
|
// the RTP queue will wait for missing/reordered packets.
|
||||||
#define RTP_QUEUE_DELAY 10
|
#define RTP_QUEUE_DELAY 10
|
||||||
|
|
||||||
/* Initialize the video stream */
|
// Initialize the video stream
|
||||||
void initializeVideoStream(void) {
|
void initializeVideoStream(void) {
|
||||||
initializeVideoDepacketizer(StreamConfig.packetSize);
|
initializeVideoDepacketizer(StreamConfig.packetSize);
|
||||||
RtpqInitializeQueue(&rtpQueue, RTPQ_DEFAULT_MAX_SIZE, RTP_QUEUE_DELAY);
|
RtpqInitializeQueue(&rtpQueue, RTPQ_DEFAULT_MAX_SIZE, RTP_QUEUE_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean up the video stream */
|
// Clean up the video stream
|
||||||
void destroyVideoStream(void) {
|
void destroyVideoStream(void) {
|
||||||
destroyVideoDepacketizer();
|
destroyVideoDepacketizer();
|
||||||
RtpqCleanupQueue(&rtpQueue);
|
RtpqCleanupQueue(&rtpQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UDP Ping proc */
|
// UDP Ping proc
|
||||||
static void UdpPingThreadProc(void *context) {
|
static void UdpPingThreadProc(void *context) {
|
||||||
char pingData [] = { 0x50, 0x49, 0x4E, 0x47 };
|
char pingData[] = { 0x50, 0x49, 0x4E, 0x47 };
|
||||||
struct sockaddr_in6 saddr;
|
struct sockaddr_in6 saddr;
|
||||||
SOCK_RET err;
|
SOCK_RET err;
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ static void UdpPingThreadProc(void *context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive thread proc */
|
// Receive thread proc
|
||||||
static void ReceiveThreadProc(void* context) {
|
static void ReceiveThreadProc(void* context) {
|
||||||
int err;
|
int err;
|
||||||
int bufferSize, receiveSize;
|
int bufferSize, receiveSize;
|
||||||
@@ -73,7 +73,7 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
PRTP_PACKET packet;
|
PRTP_PACKET packet;
|
||||||
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
buffer = (char*) malloc(bufferSize);
|
buffer = (char*)malloc(bufferSize);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
Limelog("Video Receive: malloc() failed\n");
|
Limelog("Video Receive: malloc() failed\n");
|
||||||
ListenerCallbacks.connectionTerminated(-1);
|
ListenerCallbacks.connectionTerminated(-1);
|
||||||
@@ -81,7 +81,7 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = (int) recv(rtpSocket, buffer, receiveSize, 0);
|
err = (int)recv(rtpSocket, buffer, receiveSize, 0);
|
||||||
if (err <= 0) {
|
if (err <= 0) {
|
||||||
Limelog("Video Receive: recv() failed: %d\n", (int)LastSocketError());
|
Limelog("Video Receive: recv() failed: %d\n", (int)LastSocketError());
|
||||||
ListenerCallbacks.connectionTerminated(LastSocketError());
|
ListenerCallbacks.connectionTerminated(LastSocketError());
|
||||||
@@ -91,19 +91,19 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
memcpy(&buffer[receiveSize], &err, sizeof(int));
|
memcpy(&buffer[receiveSize], &err, sizeof(int));
|
||||||
|
|
||||||
// RTP sequence number must be in host order for the RTP queue
|
// RTP sequence number must be in host order for the RTP queue
|
||||||
packet = (PRTP_PACKET) &buffer[0];
|
packet = (PRTP_PACKET)&buffer[0];
|
||||||
packet->sequenceNumber = htons(packet->sequenceNumber);
|
packet->sequenceNumber = htons(packet->sequenceNumber);
|
||||||
|
|
||||||
queueStatus = RtpqAddPacket(&rtpQueue, packet, (PRTP_QUEUE_ENTRY) &buffer[receiveSize + sizeof(int)]);
|
queueStatus = RtpqAddPacket(&rtpQueue, packet, (PRTP_QUEUE_ENTRY)&buffer[receiveSize + sizeof(int)]);
|
||||||
if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) {
|
if (queueStatus == RTPQ_RET_HANDLE_IMMEDIATELY) {
|
||||||
// queueRtpPacket() copies the data it needs to we can reuse the buffer
|
// queueRtpPacket() copies the data it needs to we can reuse the buffer
|
||||||
queueRtpPacket(packet, err);
|
queueRtpPacket(packet, err);
|
||||||
}
|
}
|
||||||
else if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) {
|
else if (queueStatus == RTPQ_RET_QUEUED_PACKETS_READY) {
|
||||||
// The packet queue now has packets ready
|
// The packet queue now has packets ready
|
||||||
while ((buffer = (char*) RtpqGetQueuedPacket(&rtpQueue)) != NULL) {
|
while ((buffer = (char*)RtpqGetQueuedPacket(&rtpQueue)) != NULL) {
|
||||||
memcpy(&err, &buffer[receiveSize], sizeof(int));
|
memcpy(&err, &buffer[receiveSize], sizeof(int));
|
||||||
queueRtpPacket((PRTP_PACKET) buffer, err);
|
queueRtpPacket((PRTP_PACKET)buffer, err);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ static void ReceiveThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decoder thread proc */
|
// Decoder thread proc
|
||||||
static void DecoderThreadProc(void* context) {
|
static void DecoderThreadProc(void* context) {
|
||||||
PQUEUED_DECODE_UNIT qdu;
|
PQUEUED_DECODE_UNIT qdu;
|
||||||
while (!PltIsThreadInterrupted(&decoderThread)) {
|
while (!PltIsThreadInterrupted(&decoderThread)) {
|
||||||
@@ -137,7 +137,7 @@ static void DecoderThreadProc(void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the first frame of the video stream */
|
// Read the first frame of the video stream
|
||||||
int readFirstFrame(void) {
|
int readFirstFrame(void) {
|
||||||
// All that matters is that we close this socket.
|
// All that matters is that we close this socket.
|
||||||
// This starts the flow of video on Gen 3 servers.
|
// This starts the flow of video on Gen 3 servers.
|
||||||
@@ -148,7 +148,7 @@ int readFirstFrame(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Terminate the video stream */
|
// Terminate the video stream
|
||||||
void stopVideoStream(void) {
|
void stopVideoStream(void) {
|
||||||
PltInterruptThread(&udpPingThread);
|
PltInterruptThread(&udpPingThread);
|
||||||
PltInterruptThread(&receiveThread);
|
PltInterruptThread(&receiveThread);
|
||||||
@@ -180,7 +180,7 @@ void stopVideoStream(void) {
|
|||||||
VideoCallbacks.cleanup();
|
VideoCallbacks.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the video stream */
|
// Start the video stream
|
||||||
int startVideoStream(void* rendererContext, int drFlags) {
|
int startVideoStream(void* rendererContext, int drFlags) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user