Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

333 lines
10 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: mxfilter.h
//
//--------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
//
// File: mxfilter.h
//
// Description: Defines the mixer filter & pin classes
//
///////////////////////////////////////////////////////////////////////////////
#include <mixflter.h> // for the CLSID
// If more than X packets are delivered with the time interval of a packet
// the overflow will be disgarded
const DWORD MAX_QUEUE_STORAGE = 8;
//
// These should not change anyway.
//
enum { OUTPUT_PIN, INPUT_PIN0 };
const TCHAR MIXER_KEY[] =
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DxmRTP\\MIXER");
const TCHAR JITTERBUFFER[] = TEXT("JitterBuffer");
const TCHAR MIXBUFFER[] = TEXT("MixDelay");
const DWORD MAX_QUEUES = 32;
const DWORD MAX_TIMEDELTA = 180; // 180ms
const DWORD DEFAULT_JITTERBUFFERTIME = 60; // 60ms of jitter buffer.
const DWORD DEFAULT_MIXDELAYTIME = 40; // 40ms of mix delay.
class CMixer;
class CMixerInputPin;
class CMixerOutputPin;
#ifndef CBufferQueue_DEFINED
#include "queue.h"
#endif // #ifndef CBufferQueue_DEFINED
///////////////////////////////////////////////////////////////////////////////
//***************************************************************************//
//***************************************************************************//
///////////////////////////////////////////////////////////////////////////////
class CMixerOutputPin : public CBaseOutputPin
{
CMixer *m_pMixer;
public:
CMixerOutputPin(
TCHAR *pObjName,
CMixer *pMixer,
HRESULT *phr,
LPCWSTR pPinName
);
//
// Connection helpers
//
virtual HRESULT DecideBufferSize(IMemAllocator * pAlloc,
ALLOCATOR_PROPERTIES * ppropInputRequest);
virtual HRESULT CheckMediaType(const CMediaType *pmt);
virtual HRESULT DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc);
virtual HRESULT CompleteConnect(IPin *pReceivePin);
IMemInputPin *GetIMemInputPin() { return m_pInputPin; }
//
// Media Type related functions
//
HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
CMediaType &CurrentMediaType();
};
///////////////////////////////////////////////////////////////////////////////
//***************************************************************************//
//***************************************************************************//
///////////////////////////////////////////////////////////////////////////////
class CMixerInputPin : public CBaseInputPin
{
CMixer *m_pMixer; // Main filter object
ULONG m_cOurRef; // Local ref count
int m_iPinNumber; // Number of this pin
// queues created for the input pins
CBufferQueue *m_pQueue;
public:
//
// Construction
//
CMixerInputPin(
TCHAR * pObjName,
CMixer * pMixer,
HRESULT * phr,
LPCWSTR pPinName,
int iPin,
CBufferQueue *pQueue
);
//
// Methods dealing with media type
//
HRESULT CheckMediaType(const CMediaType *pmt);
CMediaType &CurrentMediaType();
// Connection stuff
virtual HRESULT CompleteConnect(IPin *pReceivePin);
virtual HRESULT STDMETHODCALLTYPE Disconnect();
//
// Methods dealing with the allocator
//
IMemAllocator *GetAllocator() { return m_pAllocator; }
#if 0
STDMETHODIMP GetAllocator(IMemAllocator **ppAllocator);
STDMETHODIMP NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
#endif
STDMETHODIMP AllocatorProperties(ALLOCATOR_PROPERTIES * pprop);
STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
// Handles the next block of data from the stream
STDMETHODIMP Receive(IMediaSample *pSample);
// Override since the life time of pins and filters are not the same
STDMETHODIMP_(ULONG) NonDelegatingAddRef();
STDMETHODIMP_(ULONG) NonDelegatingRelease();
// We deal with these because we queue.
STDMETHODIMP EndOfStream();
STDMETHODIMP BeginFlush();
STDMETHODIMP EndFlush();
HRESULT Inactive();
HRESULT Active();
};
///////////////////////////////////////////////////////////////////////////////
//***************************************************************************//
//***************************************************************************//
///////////////////////////////////////////////////////////////////////////////
class CMixer : public CCritSec, public CBaseFilter
{
typedef CGenericList <CMixerInputPin> CInputPinList;
INT m_cInputPins; // Current Input pin count
CInputPinList m_listInputPins; // List of the Input pins
INT m_iNextInputPinNumber; // Increases monotonically.
CMixerOutputPin *m_pMixerOutput; // Common Output Pin
DWORD m_dwInputBytesPerMS;
WORD m_wInputBitsPerSample;
WORD m_wOutputBitsPerSample;
WORD m_wInputFormatTag; // Input format tag
WORD m_wPAD;
#if USE_LOCK
// Critical section for the queues.
CCritSec m_cQueues;
#endif
// queues created for the input pins
CBufferQueue * m_queues[MAX_QUEUES];
// the size of the jitter buffer, in time and in bytes.
long m_lJitterBufferTime;
long m_lTotalDelayTime;
long m_lTotalDelayBufferSize;
// time reserved for mixing delay
long m_lMixDelayTime;
// the size of the sample measued in ms.
long m_lSampleTime;
// the dword value of the system clock of the last sample.
DWORD m_dwLastTime;
// the dword value of the start time of a spurt.
DWORD m_dwSpurtStartTime;
// the dword value of the difference between the wall clock and the
// the samples played.
long m_lTimeDelta;
public:
CMixer(TCHAR *pName,LPUNKNOWN pUnk,HRESULT *hr);
~CMixer();
//
// Function needed for the class factory
//
static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
//
// External Utilities
//
FILTER_STATE GetState() { return m_State; }
//
// Exeternal methods for pin management
//
CBasePin *GetPin(int n);
int GetPinCount() { return 1 + m_cInputPins; }
int GetInputPinCount() { return m_cInputPins; }
int GetConnectedPinCount() { return m_cInputPins - GetFreePinCount(); }
int GetFreePinCount();
BOOL SpawnNewInput();
void DeleteInputPin(CMixerInputPin *pPin, CBufferQueue *pQueue);
CMixerInputPin *GetInput0() { return (CMixerInputPin*)GetPin(INPUT_PIN0); }
CMixerInputPin *GetInput(int n) { return (CMixerInputPin*)GetPin(INPUT_PIN0+n); }
CMixerOutputPin *GetOutput() { return m_pMixerOutput; }
//
// Self Registration
//
LPAMOVIESETUP_FILTER GetSetupData();
//
// Media Type Methods
//
HRESULT CheckMediaType(const CMediaType *pmt);
HRESULT CheckOutputMediaType(const CMediaType* pMediaType);
CMediaType &CurrentMediaType();
BOOL MediaTypeKnown();
HRESULT CopyMTParams(const CMediaType *pmt);
//
// Allocator methods
//
HRESULT GetAgregateAllocatorProperties(ALLOCATOR_PROPERTIES * pprop);
HRESULT CompleteConnect();
HRESULT DecideBufferSize(IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pprop);
HRESULT DisconnectInput();
// Streaming methods.
STDMETHOD (Run)(REFERENCE_TIME tStart);
// Public data
public:
//
// Keep from rereconnecting the output
//
BOOL m_fReconnect;
// called from the input pins.
void FlushQueue(CBufferQueue *pQueue);
HRESULT Receive(CBufferQueue *pQueue, IMediaSample * pSample);
// The following manage the list of input pins
protected:
void InitInputPinsList();
CMixerInputPin *GetInputPinNFromList(int n);
HRESULT MixOneSample(
IMediaSample *pMixedSample,
IMediaSample ** ppSample,
long lCount
);
HRESULT FillSilentBuffer(IMediaSample *, DWORD); // Fill a buffer with silence
void FlushAllQueues();
BOOL ResetQueuesIfNecessary();
HRESULT PrePlay();
HRESULT SendSample();
};
///////////////////////////////////////////////////////////////////////////////
//***************************************************************************//
//*************************** Inline Function Section ***********************//
//***************************************************************************//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// GetFreePinCount
//
///////////////////////////////////////////////////////////////////////////////
inline int CMixer::GetFreePinCount()
{
int n = 0;
POSITION pos = m_listInputPins.GetHeadPosition();
while(pos)
{
CBaseInputPin *pInputPin = (CBaseInputPin *)m_listInputPins.GetNext(pos);
if (!pInputPin->IsConnected())
n++;
}
return n;
}
///////////////////////////////////////////////////////////////////////////////
inline BOOL CMixer::MediaTypeKnown()
{
return GetPin(INPUT_PIN0)->IsConnected();
}
///////////////////////////////////////////////////////////////////////////////
//***************************************************************************//
//***************************************************************************//
///////////////////////////////////////////////////////////////////////////////
inline HRESULT CMixerInputPin::CheckMediaType(const CMediaType *pmt)
{
return m_pMixer->CheckMediaType(pmt);
}
///////////////////////////////////////////////////////////////////////////////
inline CMediaType &CMixerInputPin::CurrentMediaType()
{
return m_mt;
}
///////////////////////////////////////////////////////////////////////////////
inline CMediaType &CMixerOutputPin::CurrentMediaType()
{
return m_mt;
}