From 0ee1609cc41d082329932e4c66eeb3379135f77e Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 30 Aug 2014 17:07:08 -0700 Subject: [PATCH] Properly flush the DU queue when we hit the limit. Fixes extreme lag that occurs after streaming for a bit. --- limelight-common/AudioStream.c | 19 ++++++++++++------- limelight-common/LinkedBlockingQueue.c | 19 +++++++++++++++++++ limelight-common/LinkedBlockingQueue.h | 3 ++- limelight-common/VideoDepacketizer.c | 24 ++++++++++++++++-------- 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/limelight-common/AudioStream.c b/limelight-common/AudioStream.c index 9d87976..f1b3ec4 100644 --- a/limelight-common/AudioStream.c +++ b/limelight-common/AudioStream.c @@ -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"); diff --git a/limelight-common/LinkedBlockingQueue.c b/limelight-common/LinkedBlockingQueue.c index 8804665..9856fae 100644 --- a/limelight-common/LinkedBlockingQueue.c +++ b/limelight-common/LinkedBlockingQueue.c @@ -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; diff --git a/limelight-common/LinkedBlockingQueue.h b/limelight-common/LinkedBlockingQueue.h index 1f03efe..033aec2 100644 --- a/limelight-common/LinkedBlockingQueue.h +++ b/limelight-common/LinkedBlockingQueue.h @@ -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); \ No newline at end of file +PLINKED_BLOCKING_QUEUE_ENTRY LbqDestroyLinkedBlockingQueue(PLINKED_BLOCKING_QUEUE queueHead); +PLINKED_BLOCKING_QUEUE_ENTRY LbqFlushQueueItems(PLINKED_BLOCKING_QUEUE queueHead); \ No newline at end of file diff --git a/limelight-common/VideoDepacketizer.c b/limelight-common/VideoDepacketizer.c index e4bac33..2f891c3 100644 --- a/limelight-common/VideoDepacketizer.c +++ b/limelight-common/VideoDepacketizer.c @@ -59,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(); } @@ -139,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; }