/* * Copyright 1993-2015 NVIDIA Corporation. All rights reserved. * * Please refer to the NVIDIA end user license agreement (EULA) associated * with this source code for terms and conditions that govern your use of * this software. Any use, reproduction, disclosure, or distribution of * this software and related documentation outside the terms of the EULA * is strictly prohibited. * */ #include "FrameQueue.h" #include #define ENABLE_DEBUG_OUT 0 #if ENABLE_DEBUG_OUT #include #define dbgprintf(x) printf x #else #define dbgprintf(x) #endif FrameQueue::FrameQueue(): nReadPosition_(0) , nFramesInQueue_(0) , bEndOfDecode_(0) { //#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) InitializeCriticalSection(&oCriticalSection_); //#endif memset(aDisplayQueue_, 0, cnMaximumSize * sizeof(CUVIDPARSERDISPINFO)); memset((void *)aIsFrameInUse_, 0, cnMaximumSize * sizeof(int)); } #include FrameQueue::~FrameQueue() { if ( nFramesInQueue_ > 0 ) { printf( "%d\n", nFramesInQueue_ ); } //#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) DeleteCriticalSection(&oCriticalSection_); //#endif } void FrameQueue::enter_CS(CRITICAL_SECTION *pCS) { //#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) EnterCriticalSection(pCS); //#endif } void FrameQueue::leave_CS(CRITICAL_SECTION *pCS) { //#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) LeaveCriticalSection(pCS); //#endif } /* void FrameQueue::set_event(HANDLE event) { #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) SetEvent(event); #endif } void FrameQueue::reset_event(HANDLE event) { #if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) ResetEvent(event); #endif } */ void FrameQueue::enqueue(const CUVIDPARSERDISPINFO *pPicParams) { // Mark the frame as 'in-use' so we don't re-use it for decoding until it is no longer needed // for display aIsFrameInUse_[pPicParams->picture_index] = true; // Wait until we have a free entry in the display queue (should never block if we have enough entries) do { bool bPlacedFrame = false; enter_CS(&oCriticalSection_); if (nFramesInQueue_ < (int)FrameQueue::cnMaximumSize) { int iWritePosition = (nReadPosition_ + nFramesInQueue_) % cnMaximumSize; aDisplayQueue_[iWritePosition] = *pPicParams; nFramesInQueue_++; bPlacedFrame = true; } leave_CS(&oCriticalSection_); if (bPlacedFrame) // Done break; Sleep(1); // Wait a bit } while (!bEndOfDecode_); } // if no valid picture can be return the pic-info's picture_index will // be -1. bool FrameQueue::dequeue(CUVIDPARSERDISPINFO *pDisplayInfo) { pDisplayInfo->picture_index = -1; bool bHaveNewFrame = false; enter_CS(&oCriticalSection_); if (nFramesInQueue_ > 0) { int iEntry = nReadPosition_; *pDisplayInfo = aDisplayQueue_[iEntry]; nReadPosition_ = (iEntry+1) % cnMaximumSize; nFramesInQueue_--; bHaveNewFrame = true; } leave_CS(&oCriticalSection_); return bHaveNewFrame; } void FrameQueue::releaseFrame(const CUVIDPARSERDISPINFO *pPicParams) { aIsFrameInUse_[pPicParams->picture_index] = false; } bool FrameQueue::isInUse(int nPictureIndex) const { assert(nPictureIndex >= 0); assert(nPictureIndex < (int)cnMaximumSize); return (0 != aIsFrameInUse_[nPictureIndex]); } bool FrameQueue::isDecodeFinished() const { return (nFramesInQueue_ == 0 && 0 != bEndOfDecode_); } void FrameQueue::endDecode() { bEndOfDecode_ = true; } // Spins until frame becomes available or decoding // gets canceled. // If the requested frame is available the method returns true. // If decoding was interupted before the requested frame becomes // available, the method returns false. bool FrameQueue::waitUntilFrameAvailable(int nPictureIndex) { while (isInUse(nPictureIndex)) { Sleep(1); // Decoder is getting too far ahead from display if (0 != bEndOfDecode_) { return false; } } return true; }