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:
Diego Waxemberg 2014-08-31 13:07:56 -04:00
commit 62825197ae
10 changed files with 162 additions and 27 deletions

View File

@ -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");

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
}