TRANSIP.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.
//
//--------------------------------------------------------------------------;

//
// base class from which you can derive a simple Transform-In-Place filter.
// The difference between this and Transfrm.h is that Transfrm copies the data.
//
// It assumes the filter has one input and one output stream, and has no
// interest in memory management, interface negotiation or anything else.
//
// Derive your class from this, and supply Transform and the media type/format
// negotiation functions. Implement that class, compile and link and
// you're done.


#ifndef __TRANSIP__
#define __TRANSIP__

// ======================================================================
// This is the com object that represents a simple transform filter. It
// supports IBaseFilter, IMediaFilter and two pins through nested interfaces
// ======================================================================

class CTransInPlaceFilter;

// Several of the pin functions call filter functions to do the work,
// so you can often use the pin classes unaltered, just overriding the
// functions in CTransInPlaceFilter. If that's not enough and you want
// to derive your own pin class, override GetPin in the filter to supply
// your own pin classes to the filter.

// ==================================================
// Implements the input pin
// ==================================================

class CTransInPlaceInputPin : public CTransformInputPin
{

protected:
CTransInPlaceFilter *m_pTIPFilter; // our filter
BOOL m_bReadOnly; // incoming stream is read only

public:

CTransInPlaceInputPin(
TCHAR *pObjectName,
CTransInPlaceFilter *pFilter,
HRESULT *phr,
LPCWSTR pName);

// --- IMemInputPin -----

// Provide an enumerator for media types by getting one from downstream
STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum );

// Say whether media type is acceptable.
HRESULT CheckMediaType(const CMediaType* pmt);

// Return our upstream allocator
STDMETHODIMP GetAllocator(IMemAllocator ** ppAllocator);

// get told which allocator the upstream output pin is actually
// going to use.
STDMETHODIMP NotifyAllocator(IMemAllocator * pAllocator,
BOOL bReadOnly);

// Allow the filter to see what allocator we have
// N.B. This does NOT AddRef
IMemAllocator * PeekAllocator()
{ return m_pAllocator; }

// Pass this on downstream if it ever gets called.
STDMETHODIMP
CTransInPlaceInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);

inline const BOOL ReadOnly() { return m_bReadOnly; }


}; // CTransInPlaceInputPin

// ==================================================
// Implements the output pin
// ==================================================

class CTransInPlaceOutputPin : public CTransformOutputPin
{

protected:
// m_pFilter points to our CBaseFilter
CTransInPlaceFilter *m_pTIPFilter;

public:

CTransInPlaceOutputPin(
TCHAR *pObjectName,
CTransInPlaceFilter *pFilter,
HRESULT *phr,
LPCWSTR pName);


// --- CBaseOutputPin ------------

// negotiate the allocator and its buffer size/count
// Insists on using our own allocator. (Actually the one upstream of us).
virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc);

// Provide a media type enumerator. Get it from upstream.
STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum );

// Say whether media type is acceptable.
HRESULT CheckMediaType(const CMediaType* pmt);

// This is like NotifyAllocator - only output pins do not normally have those
// This is only called internally by our own input pin to propagate
// allocator decisions downstream. ReadOnly allocators are not propagated
// but we check the properties and propagate those.
HRESULT ReceiveAllocator(IMemAllocator * pAllocator, BOOL bReadONly);

IMemInputPin * ConnectedIMemInputPin()
{ return m_pInputPin; }

// Allow the filter to see what allocator we have
// N.B. This does NOT AddRef
IMemAllocator * PeekAllocator()
{ return m_pAllocator; }
}; // CTransInPlaceOutputPin


class AM_NOVTABLE CTransInPlaceFilter : public CTransformFilter
{

public:

// map getpin/getpincount for base enum of pins to owner
// override this to return more specialised pin objects

virtual CBasePin *GetPin(int n);

public:

CTransInPlaceFilter(TCHAR *, LPUNKNOWN, REFCLSID clsid, HRESULT *);

// The following are defined to avoid undefined pure virtuals.
// Even if they are never called, they will give linkage warnings/errors

// We override EnumMediaTypes to bypass the transform class enumerator
// which would otherwise call this.
HRESULT GetMediaType(int iPosition, CMediaType *pMediaType)
{ DbgBreak("CTransInPlaceFilter::GetMediaType should never be called");
return E_UNEXPECTED;
}

// This is called when we actually have to provide out own allocator.
HRESULT DecideBufferSize(IMemAllocator*, ALLOCATOR_PROPERTIES *);

// The functions which call this in CTransform are overridden in this
// class to call CheckInputType with the assumption that the type
// does not change. In Debug builds some calls will be made and
// we just ensure that they do not assert.
HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
{
return S_OK;
};


// =================================================================
// ----- You may want to override this -----------------------------
// =================================================================

HRESULT CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin);

// chance to customize the transform process
virtual HRESULT Receive(IMediaSample *pSample);

// =================================================================
// ----- You MUST override these -----------------------------------
// =================================================================

virtual HRESULT Transform(IMediaSample *pSample) PURE;

// this goes in the factory template table to create new instances
// static CCOMObject * CreateInstance(LPUNKNOWN, HRESULT *);


#ifdef PERF
// Override to register performance measurement with a less generic string
// You should do this to avoid confusion with other filters
virtual void RegisterPerfId()
{m_idTransInPlace = MSR_REGISTER(TEXT("TransInPlace"));}
#endif // PERF


// implementation details

protected:

IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource);

int m_idTransInPlace; // performance measuring id

// these hold our input and output pins

friend class CTransInPlaceInputPin;
friend class CTransInPlaceOutputPin;

CTransInPlaceInputPin *InputPin()
{
return (CTransInPlaceInputPin *)m_pInput;
};
CTransInPlaceOutputPin *OutputPin()
{
return (CTransInPlaceOutputPin *)m_pOutput;
};
}; // CTransInPlaceFilter

#endif /* __TRANSIP__ */