//------------------------------------------------------------------------------ | |
// 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<IMediaSample> 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; | |
}; | |