OUTPUTQ.H

//==========================================================================; 
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;

//
// outputq.h
//
// Defines the COutputQueue class
//
// Makes a queue of samples and sends them
// to an output pin
//
// The class will optionally send the samples to the pin directly
//
//

typedef CGenericList<IMediaSample> CSampleList;

class COutputQueue : public CCritSec
{
public:
// Constructor
COutputQueue(IPin *pInputPin, // Pin to send stuff to
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
);
~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 (
IMediaSample **pSamples,
long nSamples,
long *nSamplesProcessed);

void Reset(); // Reset m_hr ready for more data

// See if its idle or not
BOOL IsIdle();

protected:
static DWORD WINAPI InitialThreadProc(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)pSample > 0xFFFFFFF0;
};

// 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 *)0xFFFFFFFE) // Send batch
#define EOS_PACKET ((IMediaSample *)0xFFFFFFFD) // End of stream
#define RESET_PACKET ((IMediaSample *)0xFFFFFFFC) // Reset m_hr
#define NEW_SEGMENT ((IMediaSample *)0xFFFFFFFB) // 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;
IMediaSample ** m_ppSamples;
LONG m_nBatched;

// Wait optimization
LONG m_lWaiting;
// Flush synchronization
BOOL m_bFlushing;
BOOL m_bFlushed;

// Terminate now
BOOL m_bTerminate;

// Send anyway flag for batching
BOOL m_bSendAnyway;

// Deferred 'return code'
BOOL volatile m_hr;
};