/////////////////////////////////////////////////////////////// // // CCompressorJobQueueImpl::RemoveUnwantedResults // // Check result queue items for match with ignore list items. // * Must be called from inside a locked section * // /////////////////////////////////////////////////////////////// void CCompressorJobQueueImpl::RemoveUnwantedResults ( void ) { if ( m_IgnoreResultList.empty () ) return; again: for ( std::list < CCompressJobData* >::iterator iter = shared.m_ResultQueue.begin () ; iter != shared.m_ResultQueue.end () ; ) { CCompressJobData* pJobData = *iter; if ( MapContains ( m_IgnoreResultList, pJobData ) ) { // Found result to ignore, remove from result and ignore lists, add to finished list iter = shared.m_ResultQueue.erase ( iter ); MapRemove ( m_IgnoreResultList, pJobData ); pJobData->stage = EJobStage::FINISHED; MapInsert ( m_FinishedList, pJobData ); // Do callback incase any cleanup is needed if ( pJobData->HasCallback () ) { shared.m_Mutex.Unlock (); pJobData->ProcessCallback (); shared.m_Mutex.Lock (); goto again; } } else ++iter; } }
//////////////////////////////////////////////////////////////// // // CScreenGrabber::ProcessScreenShotQueue // // Process queued requests // //////////////////////////////////////////////////////////////// void CScreenGrabber::ProcessScreenShotQueue ( void ) { // Check if busy if ( m_pCompressJobData ) { // Previous job complete? if ( !m_pCompressorJobQueue->PollCommand ( m_pCompressJobData, 0 ) ) return; // Compression done if ( m_pCompressJobData->HasCallback () ) m_pCompressJobData->ProcessCallback (); m_pCompressJobData = NULL; } // Anything new? if ( m_ScreenShotQueue.empty () ) return; // Limit queue size while( m_ScreenShotQueue.size() >= 20 ) { SScreenShotQueueItem item = m_ScreenShotQueue.front (); m_ScreenShotQueue.pop_front (); item.pfnScreenShotCallback( NULL, 0, "Too many queued screenshots" ); } // Get new args SScreenShotQueueItem item = m_ScreenShotQueue.front (); uint uiSizeX = item.uiSizeX; uint uiSizeY = item.uiSizeY; uint uiQuality = item.uiQuality; uint uiTimeSpentInQueue = GetTickCount32 () - item.uiTimeQueued; PFN_SCREENSHOT_CALLBACK pfnScreenShotCallback = item.pfnScreenShotCallback; m_ScreenShotQueue.pop_front (); CBuffer buffer; SString strError; if ( GetBackBufferPixels ( uiSizeX, uiSizeY, buffer, strError ) ) { // Start compression m_pCompressJobData = m_pCompressorJobQueue->AddCommand ( uiSizeX, uiSizeY, uiQuality, uiTimeSpentInQueue, pfnScreenShotCallback, buffer ); } else { // Pass on error pfnScreenShotCallback( NULL, 0, strError ); } }
/////////////////////////////////////////////////////////////// // // CCompressorJobQueueImpl::AddCommand // // AddCommand to queue // Can't fail // /////////////////////////////////////////////////////////////// CCompressJobData* CCompressorJobQueueImpl::AddCommand ( uint uiSizeX, uint uiSizeY, uint uiQuality, uint uiTimeSpentInQueue, PFN_SCREENSHOT_CALLBACK pfnScreenShotCallback, const CBuffer& buffer ) { // Create command CCompressJobData* pJobData = new CCompressJobData (); pJobData->command.uiSizeX = uiSizeX; pJobData->command.uiSizeY = uiSizeY; pJobData->command.uiQuality = uiQuality; pJobData->command.buffer = buffer; pJobData->SetCallback ( pfnScreenShotCallback, uiTimeSpentInQueue ); // Add to queue shared.m_Mutex.Lock (); pJobData->stage = EJobStage::COMMAND_QUEUE; shared.m_CommandQueue.push_back ( pJobData ); shared.m_Mutex.Signal (); shared.m_Mutex.Unlock (); return pJobData; }
/////////////////////////////////////////////////////////////// // // CCompressorJobQueueImpl::DoPulse // // Check if any callback functions are due // /////////////////////////////////////////////////////////////// void CCompressorJobQueueImpl::DoPulse ( void ) { shared.m_Mutex.Lock (); again: // Delete finished for ( std::set < CCompressJobData* >::iterator iter = m_FinishedList.begin () ; iter != m_FinishedList.end () ; ) { CCompressJobData* pJobData = *iter; m_FinishedList.erase ( iter++ ); // Check not refed assert ( !ListContains ( shared.m_CommandQueue, pJobData ) ); assert ( !ListContains ( shared.m_ResultQueue, pJobData ) ); assert ( !MapContains ( m_IgnoreResultList, pJobData ) ); assert ( !MapContains ( m_FinishedList, pJobData ) ); assert ( !pJobData->HasCallback () ); SAFE_DELETE( pJobData ); } // Remove ignored RemoveUnwantedResults (); // Do pending callbacks for ( std::list < CCompressJobData* >::iterator iter = shared.m_ResultQueue.begin () ; iter != shared.m_ResultQueue.end () ; ++iter ) { CCompressJobData* pJobData = *iter; if ( pJobData->HasCallback () ) { shared.m_Mutex.Unlock (); pJobData->ProcessCallback (); shared.m_Mutex.Lock (); // Redo from the top to ensure everything is consistent goto again; } } shared.m_Mutex.Unlock (); }