//------------------------------------------------------------------------------
// File: AMFilter.cpp
//
// Desc: DirectShow base classes - implements class hierarchy for streams
// architecture.
//
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
//=====================================================================
//=====================================================================
// The following classes are declared in this header:
//
//
// CBaseMediaFilter Basic IMediaFilter support (abstract class)
// CBaseFilter Support for IBaseFilter (incl. IMediaFilter)
// CEnumPins Enumerate input and output pins
// CEnumMediaTypes Enumerate the preferred pin formats
// CBasePin Abstract base class for IPin interface
// CBaseOutputPin Adds data provider member functions
// CBaseInputPin Implements IMemInputPin interface
// CMediaSample Basic transport unit for IMemInputPin
// CBaseAllocator General list guff for most allocators
// CMemAllocator Implements memory buffer allocation
//
//=====================================================================
//=====================================================================
#include <streams.h>
#include <strsafe.h>
#ifdef DXMPERF
#include "dxmperf.h"
#endif // DXMPERF
//=====================================================================
// Helpers
//=====================================================================
STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator)
{
return CoCreateInstance(CLSID_MemoryAllocator,
0,
CLSCTX_INPROC_SERVER,
IID_IMemAllocator,
(void **)ppAllocator);
}
// Put this one here rather than in ctlutil.cpp to avoid linking
// anything brought in by ctlutil.cpp
STDAPI CreatePosPassThru(
__in_opt LPUNKNOWN pAgg,
BOOL bRenderer,
IPin *pPin,
__deref_out IUnknown **ppPassThru
)
{
*ppPassThru = NULL;
IUnknown *pUnkSeek;
HRESULT hr = CoCreateInstance(CLSID_SeekingPassThru,
pAgg,
CLSCTX_INPROC_SERVER,
IID_IUnknown,
(void **)&pUnkSeek
);
if (FAILED(hr)) {
return hr;
}
ISeekingPassThru *pPassThru;
hr = pUnkSeek->QueryInterface(IID_ISeekingPassThru, (void**)&pPassThru);
if (FAILED(hr)) {
pUnkSeek->Release();
return hr;
}
hr = pPassThru->Init(bRenderer, pPin);
pPassThru->Release();
if (FAILED(hr)) {
pUnkSeek->Release();
return hr;
}
*ppPassThru = pUnkSeek;
return S_OK;
}
#define CONNECT_TRACE_LEVEL 3
//=====================================================================
//=====================================================================
// Implements CBaseMediaFilter
//=====================================================================
//=====================================================================
/* Constructor */
CBaseMediaFilter::CBaseMediaFilter(__in_opt LPCTSTR pName,
__inout_opt LPUNKNOWN pUnk,
__in CCritSec *pLock,
REFCLSID clsid) :
CUnknown(pName, pUnk),
m_pLock(pLock),
m_clsid(clsid),
m_State(State_Stopped),
m_pClock(NULL)
{
}
/* Destructor */
CBaseMediaFilter::~CBaseMediaFilter()
{
// must be stopped, but can't call Stop here since
// our critsec has been destroyed.
/* Release any clock we were using */
if (m_pClock) {
m_pClock->Release();
m_pClock = NULL;
}
}
/* Override this to say what interfaces we support and where */
STDMETHODIMP
CBaseMediaFilter::NonDelegatingQueryInterface(
REFIID riid,
__deref_out void ** ppv)
{
if (riid == IID_IMediaFilter) {
return GetInterface((IMediaFilter *) this, ppv);
} else if (riid == IID_IPersist) {
return GetInterface((IPersist *) this, ppv);
} else {
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
}
/* Return the filter's clsid */
STDMETHODIMP
CBaseMediaFilter::GetClassID(__out CLSID *pClsID)
{
CheckPointer(pClsID,E_POINTER);
ValidateReadWritePtr(pClsID,sizeof(CLSID));
*pClsID = m_clsid;
return NOERROR;
}
/* Override this if your state changes are not done synchronously */
STDMETHODIMP
CBaseMediaFilter::GetState(DWORD dwMSecs, __out FILTER_STATE *State)
{
UNREFERENCED_PARAMETER(dwMSecs);
CheckPointer(State,E_POINTER);
ValidateReadWritePtr(State,sizeof(FILTER_STATE));
*State = m_State;
return S_OK;
}
/* Set the clock we will use for synchronisation */
STDMETHODIMP
CBaseMediaFilter::SetSyncSource(__inout_opt IReferenceClock *pClock)
{
CAutoLock cObjectLock(m_pLock);
// Ensure the new one does not go away - even if the same as the old
if (pClock) {
pClock->AddRef();
}
// if we have a clock, release it
if (m_pClock) {
m_pClock->Release();
}
// Set the new reference clock (might be NULL)
// Should we query it to ensure it is a clock? Consider for a debug build.
m_pClock = pClock;
return NOERROR;
}
/* Return the clock we are using for synchronisation */
STDMETHODIMP
CBaseMediaFilter::GetSyncSource(__deref_out_opt IReferenceClock **pClock)
{
CheckPointer(pClock,E_POINTER);
ValidateReadWritePtr(pClock,sizeof(IReferenceClock *));
CAutoLock cObjectLock(m_pLock);
if (m_pClock) {
// returning an interface... addref it...
m_pClock->AddRef();
}
*pClock = (IReferenceClock*)m_pClock;
return NOERROR;
}
/* Put the filter into a stopped state */
STDMETHODIMP
CBaseMediaFilter::Stop()
{
CAutoLock cObjectLock(m_pLock);
m_State = State_Stopped;
return S_OK;
}
/* Put the filter into a paused state */
STDMETHODIMP
CBaseMediaFilter::Pause()
{
CAutoLock cObjectLock(m_pLock);
m_State = State_Paused;
return S_OK;
}
// Put the filter into a running state.
// The time parameter is the offset to be added to the samples'
// stream time to get the reference time at which they should be presented.
//
// you can either add these two and compare it against the reference clock,
// or you can call CBaseMediaFilter::StreamTime and compare that against
// the sample timestamp.
STDMETHODIMP
CBaseMediaFilter::Run(REFERENCE_TIME tStart)
{
CAutoLock cObjectLock(m_pLock);
// remember the stream time offset
m_tStart = tStart;
if (m_State == State_Stopped){
HRESULT hr = Pause();
if (FAILED(hr)) {
return hr;
}
}
m_State = State_Running;
return S_OK;
}
//
// return the current stream time - samples with start timestamps of this
// time or before should be rendered by now
HRESULT
CBaseMediaFilter::StreamTime(CRefTime& rtStream)
{
// Caller must lock for synchronization
// We can't grab the filter lock because we want to be able to call
// this from worker threads without deadlocking
if (m_pClock == NULL) {
return VFW_E_NO_CLOCK;
}
// get the current reference time
HRESULT hr = m_pClock->GetTime((REFERENCE_TIME*)&rtStream);
if (FAILED(hr)) {
return hr;
}
// subtract the stream offset to get stream time
rtStream -= m_tStart;
return S_OK;
}
//====================================================================
评论4
最新资源