Add capability to combine video receive and decode thread

This commit is contained in:
Iwan Timmer 2015-07-24 10:38:37 +02:00
parent c829d9c742
commit 812f356868
3 changed files with 45 additions and 21 deletions

View File

@ -71,6 +71,7 @@ typedef struct _DECODER_RENDERER_CALLBACKS {
DecoderRendererSetup setup;
DecoderRendererCleanup cleanup;
DecoderRendererSubmitDecodeUnit submitDecodeUnit;
int capabilities;
} DECODER_RENDERER_CALLBACKS, *PDECODER_RENDERER_CALLBACKS;
// This callback initializes the audio renderer

View File

@ -29,7 +29,9 @@ typedef struct _BUFFER_DESC {
/* Init */
void initializeVideoDepacketizer(int pktSize) {
LbqInitializeLinkedBlockingQueue(&decodeUnitQueue, 15);
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
LbqInitializeLinkedBlockingQueue(&decodeUnitQueue, 15);
}
nominalPacketDataLength = pktSize - sizeof(NV_VIDEO_PACKET);
nextFrameNumber = 1;
@ -91,7 +93,9 @@ static void freeDecodeUnitList(PLINKED_BLOCKING_QUEUE_ENTRY entry) {
/* Cleanup video depacketizer and free malloced memory */
void destroyVideoDepacketizer(void) {
freeDecodeUnitList(LbqDestroyLinkedBlockingQueue(&decodeUnitQueue));
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
freeDecodeUnitList(LbqDestroyLinkedBlockingQueue(&decodeUnitQueue));
}
cleanupAvcFrameState();
}
@ -183,23 +187,34 @@ static void reassembleAvcFrame(int frameNumber) {
nalChainHead = NULL;
nalChainDataLength = 0;
if (LbqOfferQueueItem(&decodeUnitQueue, qdu, &qdu->entry) == LBQ_BOUND_EXCEEDED) {
Limelog("Video decode unit queue overflow\n");
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
if (LbqOfferQueueItem(&decodeUnitQueue, qdu, &qdu->entry) == LBQ_BOUND_EXCEEDED) {
Limelog("Video decode unit queue overflow\n");
// Clear frame state and wait for an IDR
nalChainHead = qdu->decodeUnit.bufferList;
nalChainDataLength = qdu->decodeUnit.fullLength;
dropAvcFrameState();
// Clear frame state and wait for an IDR
nalChainHead = qdu->decodeUnit.bufferList;
nalChainDataLength = qdu->decodeUnit.fullLength;
dropAvcFrameState();
// Free the DU
free(qdu);
// Free the DU
free(qdu);
// Flush the decode unit queue
freeDecodeUnitList(LbqFlushQueueItems(&decodeUnitQueue));
// Flush the decode unit queue
freeDecodeUnitList(LbqFlushQueueItems(&decodeUnitQueue));
// FIXME: Get proper lower bound
connectionSinkTooSlow(0, frameNumber);
return;
// FIXME: Get proper lower bound
connectionSinkTooSlow(0, frameNumber);
return;
}
} else {
int ret = VideoCallbacks.submitDecodeUnit(&qdu->decodeUnit);
freeQueuedDecodeUnit(qdu);
if (ret == DR_NEED_IDR) {
Limelog("Request IDR frame on behalf of DR\n");
requestIdrOnDemand();
}
}
// Notify the control connection

View File

@ -150,7 +150,9 @@ int readFirstFrame(void) {
void stopVideoStream(void) {
PltInterruptThread(&udpPingThread);
PltInterruptThread(&receiveThread);
PltInterruptThread(&decoderThread);
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
PltInterruptThread(&decoderThread);
}
if (firstFrameSocket != INVALID_SOCKET) {
closesocket(firstFrameSocket);
@ -163,11 +165,15 @@ void stopVideoStream(void) {
PltJoinThread(&udpPingThread);
PltJoinThread(&receiveThread);
PltJoinThread(&decoderThread);
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
PltJoinThread(&decoderThread);
}
PltCloseThread(&udpPingThread);
PltCloseThread(&receiveThread);
PltCloseThread(&decoderThread);
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
PltCloseThread(&decoderThread);
}
VideoCallbacks.cleanup();
}
@ -191,9 +197,11 @@ int startVideoStream(void* rendererContext, int drFlags) {
return err;
}
err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread);
if (err != 0) {
return err;
if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) {
err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread);
if (err != 0) {
return err;
}
}
if (ServerMajorVersion == 3) {