#ifndef _CSimpleFilter_h_
#define _CSimpleFilter_h_

#include <streams.h>

#define SAFE_DELETE(p) { if(p!=NULL) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p!=NULL) { (p)->Release(); (p)=NULL; } }

#define ONE_SECOND 10000000
#define INFINITE_SECOND 0x7fffffffffffffff



static const GUID IID_IDecodeInterface =
{ 0x51296c64, 0x6a98, 0x462c, { 0x81, 0x14, 0x22, 0x59, 0xc0, 0x56, 0xc9, 0x6c } };

__interface
IDecodeInterface : public IUnknown
{
public:
   HRESULT GetOutFormat(void *);
   HRESULT SetOutFormat(void *);
};

class CSimpleTransform : public CTransformFilter
{
protected:
   CCritSec m_Lock;

public:
   DECLARE_IUNKNOWN

   
   CSimpleTransform(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID, HRESULT *);
   ~CSimpleTransform();

   
   virtual HRESULT OnConnectInPin(const CMediaType *) PURE;
   virtual HRESULT OnConnectOutPin(const CMediaType *, int, CMediaType *, int *) PURE;

   
   virtual HRESULT OnReceive(IMediaSample *);
   virtual HRESULT OnTransform(IMediaSample *, IMediaSample *);
   virtual STDMETHODIMP OnQueryInterface(REFIID riid, void ** ppv);
   virtual HRESULT OnStart(void);
   virtual HRESULT OnStop(bool);
   virtual HRESULT OnSeek(void);

   
   HRESULT CheckInputType(const CMediaType *);
   HRESULT CheckTransform(const CMediaType *, const CMediaType *);
   HRESULT DecideBufferSize(IMemAllocator *, ALLOCATOR_PROPERTIES *);
   HRESULT GetMediaType(int, CMediaType *);

   
   HRESULT Receive(IMediaSample *);
   HRESULT BreakConnect(PIN_DIRECTION dir);
   STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
   virtual HRESULT StartStreaming();
   virtual HRESULT StopStreaming();
   virtual HRESULT EndOfStream(void);
   HRESULT BeginFlush();

private:

   
   CMediaType m_mtOut;
   int m_nOutBufferSize;
};


class CSimpleInPlace : public CTransInPlaceFilter
{
public:
   DECLARE_IUNKNOWN

   
   CSimpleInPlace(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID, HRESULT *, bool);
   ~CSimpleInPlace();

   
   virtual HRESULT OnConnectInPin(const CMediaType *) PURE;
   virtual HRESULT OnTransform(IMediaSample *) PURE;

   
   virtual STDMETHODIMP OnQueryInterface(REFIID riid, void ** ppv);
   virtual HRESULT OnStart(void);
   virtual HRESULT OnStop(bool);
   virtual HRESULT OnSeek(void);

   
   HRESULT CheckInputType(const CMediaType *pmtIn)
   {
      CAutoLock lck(&m_Lock);
      return OnConnectInPin(pmtIn);
   }

   HRESULT Transform(IMediaSample *pInSample)
   {
      CAutoLock lck(&m_Lock);
      return OnTransform(pInSample);
   }

   
   STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);

   HRESULT StartStreaming()
   {
      return OnStart();
   }

   HRESULT StopStreaming()
   {
      CAutoLock lck(&m_Lock);
      return OnStop(false);
   }

   HRESULT EndOfStream(void)
   {
      CAutoLock lck(&m_Lock);
      return OnStop(true);
   }

private:

   
   CCritSec m_Lock;
   CPosPassThru *m_pPosition;
};


class CSimpleWriterInputPin : public CRenderedInputPin
{
   friend class CSimpleWriter;

public:

   
   CSimpleWriterInputPin(CSimpleWriter *, LPUNKNOWN,CCritSec *, CCritSec *, HRESULT *);
   ~CSimpleWriterInputPin();

   
   virtual HRESULT CheckMediaType(const CMediaType *);

   
   STDMETHODIMP Receive(IMediaSample *);
   STDMETHODIMP EndOfStream(void);
   STDMETHODIMP ReceiveCanBlock() { return S_FALSE;}
   STDMETHODIMP BeginFlush();
   HRESULT BreakConnect();

   STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
   {
      return S_OK;
   }

private:

   
   CSimpleWriter * const m_pFilter;
   CCritSec *m_pLock;
};

class CSimpleWriter : public CBaseFilter , public  IFileSinkFilter
{
   friend class CSimpleWriterInputPin;

protected:
   CSimpleWriterInputPin *m_pInput;
   WCHAR m_awInputFileName[MAX_PATH];

   HANDLE m_hFile;
   CCritSec m_Lock;

public:
   DECLARE_IUNKNOWN

   
   CSimpleWriter::CSimpleWriter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID, HRESULT *);
   ~CSimpleWriter();

   
   virtual HRESULT OnConnectInPin(const CMediaType *) PURE;

   
   virtual HRESULT OnReceive(HANDLE, IMediaSample *);
   virtual STDMETHODIMP OnQueryInterface(REFIID riid, void ** ppv);
   virtual HRESULT OnStart(HANDLE);
   virtual HRESULT OnStop(HANDLE, bool);
   virtual HRESULT OnSeek(HANDLE);

   
   virtual CBasePin *GetPin(int n);
   virtual int GetPinCount();

   
   STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);
   STDMETHODIMP Stop();

   
   STDMETHODIMP SetFileName(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt);
   STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName, AM_MEDIA_TYPE *pmt);

private:

   
   CCritSec m_ReceiveLock;
   CPosPassThru *m_pPosition;

   bool m_bFirstReceive;
};


class CSimplePushSourceOutputPin : public CSourceStream
{
   friend class CSimplePushSource;

public:

   
   CSimplePushSourceOutputPin(CSimplePushSource *, CCritSec *, HRESULT *);
   ~CSimplePushSourceOutputPin();

   
   HRESULT DecideBufferSize(IMemAllocator *, ALLOCATOR_PROPERTIES *);
   HRESULT FillBuffer(IMediaSample *);
 
   
   HRESULT GetMediaType(CMediaType *);
   HRESULT CheckMediaType(const CMediaType *);
   HRESULT OnThreadCreate(void);
   HRESULT OnThreadDestroy(void);

private:  

   
   int m_nOutBufferSize;
   CCritSec *m_pMyLock;
};

class CSimplePushSource : public CSource, public IMediaSeeking
{
   friend class CSimplePushSourceOutputPin;

public:
   DECLARE_IUNKNOWN

   
   CSimplePushSource(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID, HRESULT *);
   ~CSimplePushSource();

   
   virtual HRESULT OnConnectOutPin(CMediaType *, int *, REFERENCE_TIME *) PURE;
   virtual HRESULT FillBuffer(IMediaSample *) PURE;

   
   virtual STDMETHODIMP OnQueryInterface(REFIID riid, void ** ppv);
   virtual HRESULT OnStart(void);
   virtual HRESULT OnStop(void);
   virtual HRESULT OnSeek(LONGLONG, LONGLONG);

   
   STDMETHODIMP NonDelegatingQueryInterface(REFIID, void **);

   
   HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *);
   HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *);
   HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *);
   HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *);
   HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *);
   HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *);
   HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *);
   HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *);
   HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *);
   HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *);
   HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *, const GUID *, LONGLONG, const GUID *);
   HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *, DWORD, LONGLONG *, DWORD);
   HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *, LONGLONG *);
   HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *, LONGLONG *);
   HRESULT STDMETHODCALLTYPE SetRate(double);
   HRESULT STDMETHODCALLTYPE GetRate(double *);
   HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *);

private:

   
   CCritSec m_MyLock;
   WCHAR m_awInputFileName[MAX_PATH];
   CSimplePushSourceOutputPin *m_pOutPin;
   REFERENCE_TIME m_rtStopTime, m_rtTotalTime;
   REFERENCE_TIME m_rtStart, m_rtEnd;
};


#endif _CSimpleFilter_h_
