//------------------------------------------------------------------------------ // File: OutputQ.h // // Desc: DirectShow base classes - defines the COutputQueue class, which // makes a queue of samples and sends them to an output pin. The // class will optionally send the samples to the pin directly. // // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ typedef CGenericList CSampleList; class COutputQueue : public CCritSec { public: // Constructor COutputQueue(IPin *pInputPin, // Pin to send stuff to __inout HRESULT *phr, // 'Return code' BOOL bAuto = TRUE, // Ask pin if blocks BOOL bQueue = TRUE, // Send through queue (ignored if // bAuto set) LONG lBatchSize = 1, // Batch BOOL bBatchExact = FALSE,// Batch exactly to BatchSize LONG lListSize = // Likely number in the list DEFAULTCACHE, DWORD dwPriority = // Priority of thread to create THREAD_PRIORITY_NORMAL, bool bFlushingOpt = false // flushing optimization ); ~COutputQueue(); // enter flush state - discard all data void BeginFlush(); // Begin flushing samples // re-enable receives (pass this downstream) void EndFlush(); // Complete flush of samples - downstream // pin guaranteed not to block at this stage void EOS(); // Call this on End of stream void SendAnyway(); // Send batched samples anyway (if bBatchExact set) void NewSegment( REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); HRESULT Receive(IMediaSample *pSample); // do something with these media samples HRESULT ReceiveMultiple ( __in_ecount(nSamples) IMediaSample **pSamples, long nSamples, __out long *nSamplesProcessed); void Reset(); // Reset m_hr ready for more data // See if its idle or not BOOL IsIdle(); // give the class an event to fire after everything removed from the queue void SetPopEvent(HANDLE hEvent); protected: static DWORD WINAPI InitialThreadProc(__in LPVOID pv); DWORD ThreadProc(); BOOL IsQueued() { return m_List != NULL; }; // The critical section MUST be held when this is called void QueueSample(IMediaSample *pSample); BOOL IsSpecialSample(IMediaSample *pSample) { return (DWORD_PTR)pSample > (DWORD_PTR)(LONG_PTR)(-16); }; // Remove and Release() batched and queued samples void FreeSamples(); // Notify the thread there is something to do void NotifyThread(); protected: // Queue 'messages' #define SEND_PACKET ((IMediaSample *)(LONG_PTR)(-2)) // Send batch #define EOS_PACKET ((IMediaSample *)(LONG_PTR)(-3)) // End of stream #define RESET_PACKET ((IMediaSample *)(LONG_PTR)(-4)) // Reset m_hr #define NEW_SEGMENT ((IMediaSample *)(LONG_PTR)(-5)) // send NewSegment // new segment packet is always followed by one of these struct NewSegmentPacket { REFERENCE_TIME tStart; REFERENCE_TIME tStop; double dRate; }; // Remember input stuff IPin * const m_pPin; IMemInputPin * m_pInputPin; BOOL const m_bBatchExact; LONG const m_lBatchSize; CSampleList * m_List; HANDLE m_hSem; CAMEvent m_evFlushComplete; HANDLE m_hThread; __field_ecount_opt(m_lBatchSize) IMediaSample ** m_ppSamples; __range(0, m_lBatchSize) LONG m_nBatched; // Wait optimization LONG m_lWaiting; // Flush synchronization BOOL m_bFlushing; // flushing optimization. some downstream filters have trouble // with the queue's flushing optimization. other rely on it BOOL m_bFlushed; bool m_bFlushingOpt; // Terminate now BOOL m_bTerminate; // Send anyway flag for batching BOOL m_bSendAnyway; // Deferred 'return code' HRESULT volatile m_hr; // an event that can be fired after every deliver HANDLE m_hEventPop; };