mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-17 17:05:50 +00:00
Merge branch 'master' of github.com:limelight-stream/limelight-common-c
* 'master' of github.com:limelight-stream/limelight-common-c: Properly flush the DU queue when we hit the limit. Fixes extreme lag that occurs after streaming for a bit. Handle reuse of limelight-common for another stream Fix debugging on Windows 8.1 Fix controller and keyboard packets Prevent queuing input packets before the queue is initialized Implement LiSendControllerEvent
This commit is contained in:
commit
62825197ae
@ -28,13 +28,8 @@ void initializeAudioStream(IP_ADDRESS host, PAUDIO_RENDERER_CALLBACKS arCallback
|
||||
LbqInitializeLinkedBlockingQueue(&packetQueue, 30);
|
||||
}
|
||||
|
||||
/* Tear down the audio stream once we're done with it */
|
||||
void destroyAudioStream(void) {
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry;
|
||||
|
||||
callbacks.release();
|
||||
|
||||
entry = LbqDestroyLinkedBlockingQueue(&packetQueue);
|
||||
static void freePacketList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY nextEntry;
|
||||
|
||||
while (entry != NULL) {
|
||||
nextEntry = entry->flink;
|
||||
@ -44,6 +39,15 @@ void destroyAudioStream(void) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Tear down the audio stream once we're done with it */
|
||||
void destroyAudioStream(void) {
|
||||
callbacks.release();
|
||||
|
||||
freePacketList(LbqDestroyLinkedBlockingQueue(&packetQueue));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void UdpPingThreadProc(void *context) {
|
||||
/* Ping in ASCII */
|
||||
char pingData[] = { 0x50, 0x49, 0x4E, 0x47 };
|
||||
@ -112,6 +116,7 @@ static void ReceiveThreadProc(void* context) {
|
||||
|
||||
if (err == LBQ_BOUND_EXCEEDED) {
|
||||
Limelog("Audio packet queue overflow\n");
|
||||
freePacketList(LbqFlushQueueItems(&packetQueue));
|
||||
}
|
||||
else if (err == LBQ_INTERRUPTED) {
|
||||
Limelog("Receive thread terminating #2\n");
|
||||
|
@ -32,4 +32,24 @@ typedef struct _NV_MOUSE_BUTTON_PACKET {
|
||||
int button;
|
||||
} NV_MOUSE_BUTTON_PACKET, *PNV_MOUSE_BUTTON_PACKET;
|
||||
|
||||
#define PACKET_TYPE_CONTROLLER 0x18
|
||||
#define HEADER_A 0x0000000A
|
||||
#define HEADER_B 0x1400
|
||||
#define TAIL_A 0x0000009C
|
||||
#define TAIL_B 0x0055
|
||||
typedef struct _NV_CONTROLLER_PACKET {
|
||||
NV_INPUT_HEADER header;
|
||||
int headerA;
|
||||
short headerB;
|
||||
short buttonFlags;
|
||||
char leftTrigger;
|
||||
char rightTrigger;
|
||||
short leftStickX;
|
||||
short leftStickY;
|
||||
short rightStickX;
|
||||
short rightStickY;
|
||||
int tailA;
|
||||
short tailB;
|
||||
} NV_CONTROLLER_PACKET, *PNV_CONTROLLER_PACKET;
|
||||
|
||||
#pragma pack(pop)
|
@ -10,6 +10,7 @@
|
||||
static IP_ADDRESS host;
|
||||
static SOCKET inputSock = INVALID_SOCKET;
|
||||
static PCONNECTION_LISTENER_CALLBACKS listenerCallbacks;
|
||||
static int initialized;
|
||||
|
||||
static LINKED_BLOCKING_QUEUE packetQueue;
|
||||
static PLT_THREAD inputSendThread;
|
||||
@ -23,6 +24,7 @@ typedef struct _PACKET_HOLDER {
|
||||
NV_KEYBOARD_PACKET keyboard;
|
||||
NV_MOUSE_MOVE_PACKET mouseMove;
|
||||
NV_MOUSE_BUTTON_PACKET mouseButton;
|
||||
NV_CONTROLLER_PACKET controller;
|
||||
} packet;
|
||||
} PACKET_HOLDER, *PPACKET_HOLDER;
|
||||
|
||||
@ -58,6 +60,7 @@ int initializeInputStream(IP_ADDRESS addr, PCONNECTION_LISTENER_CALLBACKS clCall
|
||||
|
||||
LbqInitializeLinkedBlockingQueue(&packetQueue, 30);
|
||||
|
||||
initialized = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -67,6 +70,7 @@ void destroyInputStream(void) {
|
||||
if (oaesContext != NULL)
|
||||
{
|
||||
oaes_free(oaesContext);
|
||||
oaesContext = NULL;
|
||||
}
|
||||
|
||||
entry = LbqDestroyLinkedBlockingQueue(&packetQueue);
|
||||
@ -77,6 +81,8 @@ void destroyInputStream(void) {
|
||||
free(entry);
|
||||
entry = nextEntry;
|
||||
}
|
||||
|
||||
initialized = 0;
|
||||
}
|
||||
|
||||
static void inputSendThreadProc(void* context) {
|
||||
@ -163,6 +169,10 @@ int LiSendMouseMoveEvent(short deltaX, short deltaY) {
|
||||
PPACKET_HOLDER holder;
|
||||
int err;
|
||||
|
||||
if (!initialized) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
holder = malloc(sizeof(*holder));
|
||||
if (holder == NULL) {
|
||||
return -1;
|
||||
@ -186,6 +196,10 @@ int LiSendMouseButtonEvent(char action, int button) {
|
||||
PPACKET_HOLDER holder;
|
||||
int err;
|
||||
|
||||
if (!initialized) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
holder = malloc(sizeof(*holder));
|
||||
if (holder == NULL) {
|
||||
return -1;
|
||||
@ -208,6 +222,10 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
|
||||
PPACKET_HOLDER holder;
|
||||
int err;
|
||||
|
||||
if (!initialized) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
holder = malloc(sizeof(*holder));
|
||||
if (holder == NULL) {
|
||||
return -1;
|
||||
@ -217,7 +235,7 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
|
||||
holder->packet.keyboard.header.packetType = htonl(PACKET_TYPE_KEYBOARD);
|
||||
holder->packet.keyboard.keyAction = keyAction;
|
||||
holder->packet.keyboard.zero1 = 0;
|
||||
holder->packet.keyboard.keyCode = htons(keyCode);
|
||||
holder->packet.keyboard.keyCode = keyCode;
|
||||
holder->packet.keyboard.modifiers = modifiers;
|
||||
holder->packet.keyboard.zero2 = 0;
|
||||
|
||||
@ -229,3 +247,38 @@ int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers) {
|
||||
return err;
|
||||
}
|
||||
|
||||
int LiSendControllerEvent(short buttonFlags, char leftTrigger, char rightTrigger,
|
||||
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;
|
||||
}
|
||||
|
||||
holder->packetLength = sizeof(NV_CONTROLLER_PACKET);
|
||||
holder->packet.controller.header.packetType = htonl(PACKET_TYPE_CONTROLLER);
|
||||
holder->packet.controller.headerA = HEADER_A;
|
||||
holder->packet.controller.headerB = HEADER_B;
|
||||
holder->packet.controller.buttonFlags = buttonFlags;
|
||||
holder->packet.controller.leftTrigger = leftTrigger;
|
||||
holder->packet.controller.rightTrigger = rightTrigger;
|
||||
holder->packet.controller.leftStickX = leftStickX;
|
||||
holder->packet.controller.leftStickY = leftStickY;
|
||||
holder->packet.controller.rightStickX = rightStickX;
|
||||
holder->packet.controller.rightStickY = rightStickY;
|
||||
holder->packet.controller.tailA = TAIL_A;
|
||||
holder->packet.controller.tailB = TAIL_B;
|
||||
err = LbqOfferQueueItem(&packetQueue, holder);
|
||||
if (err != LBQ_SUCCESS) {
|
||||
free(holder);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -111,6 +111,24 @@ int LiSendMouseButtonEvent(char action, int button);
|
||||
#define MODIFIER_ALT 0x04
|
||||
int LiSendKeyboardEvent(short keyCode, char keyAction, char modifiers);
|
||||
|
||||
#define A_FLAG 0x1000
|
||||
#define B_FLAG 0x2000
|
||||
#define X_FLAG 0x4000
|
||||
#define Y_FLAG 0x8000
|
||||
#define UP_FLAG 0x0001
|
||||
#define DOWN_FLAG 0x0002
|
||||
#define LEFT_FLAG 0x0004
|
||||
#define RIGHT_FLAG 0x0008
|
||||
#define LB_FLAG 0x0100
|
||||
#define RB_FLAG 0x0200
|
||||
#define PLAY_FLAG 0x0010
|
||||
#define BACK_FLAG 0x0020
|
||||
#define LS_CLK_FLAG 0x0040
|
||||
#define RS_CLK_FLAG 0x0080
|
||||
#define SPECIAL_FLAG 0x0400
|
||||
int LiSendControllerEvent(short buttonFlags, char leftTrigger, char rightTrigger,
|
||||
short leftStickX, short leftStickY, short rightStickX, short rightStickY);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -7,6 +7,25 @@ PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEU
|
||||
return queueHead->head;
|
||||
}
|
||||
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead) {
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY head;
|
||||
|
||||
PltLockMutex(&queueHead->mutex);
|
||||
|
||||
// Save the old head
|
||||
head = queueHead->head;
|
||||
|
||||
// Reinitialize the queue to empty
|
||||
queueHead->head = NULL;
|
||||
queueHead->tail = NULL;
|
||||
queueHead->currentSize = 0;
|
||||
PltClearEvent(&queueHead->containsDataEvent);
|
||||
|
||||
PltUnlockMutex(&queueHead->mutex);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
int LbqInitializeLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead, int sizeBound) {
|
||||
int err;
|
||||
|
||||
|
@ -26,4 +26,5 @@ typedef struct _LINKED_BLOCKING_QUEUE {
|
||||
int LbqInitializeLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead, int sizeBound);
|
||||
int LbqOfferQueueItem(PLINKED_BLOCKING_QUEUE queueHead, void* data);
|
||||
int LbqWaitForQueueElement(PLINKED_BLOCKING_QUEUE queueHead, void** data);
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead);
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead);
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead);
|
@ -24,11 +24,11 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef LC_WINDOWS_PHONE
|
||||
#if defined(LC_WINDOWS_PHONE) || defined(LC_WINDOWS)
|
||||
extern WCHAR DbgBuf[512];
|
||||
#define Limelog(s, ...) \
|
||||
swprintf(DbgBuf, sizeof(DbgBuf) / sizeof(WCHAR), L ## s, ##__VA_ARGS__); \
|
||||
OutputDebugString(DbgBuf)
|
||||
OutputDebugStringW(DbgBuf)
|
||||
#else
|
||||
#define Limelog printf
|
||||
#endif
|
||||
|
@ -6,7 +6,7 @@ struct thread_context {
|
||||
void* context;
|
||||
};
|
||||
|
||||
#if defined(LC_WINDOWS_PHONE)
|
||||
#if defined(LC_WINDOWS_PHONE) || defined(LC_WINDOWS)
|
||||
WCHAR DbgBuf[512];
|
||||
#endif
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
|
||||
static SOCKET sock = INVALID_SOCKET;
|
||||
static IP_ADDRESS remoteAddr;
|
||||
static int currentSeqNumber = 1;
|
||||
static int currentSeqNumber;
|
||||
static char rtspTargetUrl[256];
|
||||
static char sessionIdString[16];
|
||||
static int hasSessionId = 0;
|
||||
static int hasSessionId;
|
||||
static char responseBuffer[RTSP_MAX_RESP_SIZE];
|
||||
|
||||
/* GFE 2.1.1 */
|
||||
@ -281,6 +281,8 @@ int performRtspHandshake(IP_ADDRESS addr, PSTREAM_CONFIGURATION streamConfigPtr)
|
||||
remoteAddr = addr;
|
||||
memcpy(&inaddr, &addr, sizeof(addr));
|
||||
sprintf(rtspTargetUrl, "rtsp://%s", inet_ntoa(inaddr));
|
||||
currentSeqNumber = 1;
|
||||
hasSessionId = 0;
|
||||
|
||||
{
|
||||
RTSP_MESSAGE response;
|
||||
|
@ -6,14 +6,14 @@
|
||||
static PLENTRY nalChainHead;
|
||||
static int nalChainDataLength;
|
||||
|
||||
static int nextFrameNumber = 1;
|
||||
static int nextFrameNumber;
|
||||
static int nextPacketNumber;
|
||||
static int startFrameNumber = 1;
|
||||
static int startFrameNumber;
|
||||
static int waitingForNextSuccessfulFrame;
|
||||
static int waitingForIdrFrame = 1;
|
||||
static int waitingForIdrFrame;
|
||||
static int gotNextFrameStart;
|
||||
static int lastPacketInStream = 0;
|
||||
static int decodingFrame = 0;
|
||||
static int lastPacketInStream;
|
||||
static int decodingFrame;
|
||||
|
||||
static LINKED_BLOCKING_QUEUE decodeUnitQueue;
|
||||
static unsigned int nominalPacketDataLength;
|
||||
@ -30,6 +30,15 @@ typedef struct _BUFFER_DESC {
|
||||
void initializeVideoDepacketizer(int pktSize) {
|
||||
LbqInitializeLinkedBlockingQueue(&decodeUnitQueue, 15);
|
||||
nominalPacketDataLength = pktSize - sizeof(NV_VIDEO_PACKET);
|
||||
|
||||
nextFrameNumber = 1;
|
||||
nextPacketNumber = 0;
|
||||
startFrameNumber = 1;
|
||||
waitingForNextSuccessfulFrame = 0;
|
||||
waitingForIdrFrame = 1;
|
||||
gotNextFrameStart = 0;
|
||||
lastPacketInStream = 0;
|
||||
decodingFrame = 0;
|
||||
}
|
||||
|
||||
/* Free malloced memory in AvcFrameState*/
|
||||
@ -50,16 +59,20 @@ static void dropAvcFrameState(void) {
|
||||
cleanupAvcFrameState();
|
||||
}
|
||||
|
||||
/* Cleanup video depacketizer and free malloced memory */
|
||||
void destroyVideoDepacketizer(void) {
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry;
|
||||
|
||||
entry = LbqDestroyLinkedBlockingQueue(&decodeUnitQueue);
|
||||
static void freeDecodeUnitList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
|
||||
PLINKED_BLOCKING_QUEUE_ENTRY nextEntry;
|
||||
|
||||
while (entry != NULL) {
|
||||
nextEntry = entry->flink;
|
||||
free(entry->data);
|
||||
free(entry);
|
||||
entry = nextEntry;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup video depacketizer and free malloced memory */
|
||||
void destroyVideoDepacketizer(void) {
|
||||
freeDecodeUnitList(LbqDestroyLinkedBlockingQueue(&decodeUnitQueue));
|
||||
|
||||
cleanupAvcFrameState();
|
||||
}
|
||||
@ -130,15 +143,19 @@ static void reassembleAvcFrame(int frameNumber) {
|
||||
if (LbqOfferQueueItem(&decodeUnitQueue, du) == LBQ_BOUND_EXCEEDED) {
|
||||
Limelog("Decode unit queue overflow\n");
|
||||
|
||||
// Clear frame state and wait for an IDR
|
||||
nalChainHead = du->bufferList;
|
||||
nalChainDataLength = du->fullLength;
|
||||
dropAvcFrameState();
|
||||
|
||||
// Free the DU
|
||||
free(du);
|
||||
|
||||
// Flush the decode unit queue
|
||||
freeDecodeUnitList(LbqFlushQueueItems(&decodeUnitQueue));
|
||||
|
||||
// FIXME: Get proper lower bound
|
||||
connectionSinkTooSlow(0, frameNumber);
|
||||
|
||||
// Clear frame state and wait for an IDR
|
||||
dropAvcFrameState();
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user