- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# StreamSwitcher.h

    00001 // Copyright 2003 Gabest.
    00002 // http://www.gabest.org
    00003 //
    00004 // This program is free software; you can redistribute it and/or modify
    00005 // it under the terms of the GNU General Public License as published by
    00006 // the Free Software Foundation; either version 2 of the License, or
    00007 // (at your option) any later version.
    00008 //
    00009 // This program is distributed in the hope that it will be useful,
    00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00012 // GNU General Public License for more details.
    00013 //
    00014 // You should have received a copy of the GNU General Public License
    00015 // along with this program; if not, write to the Free Software
    00016 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
    00017 // http://www.gnu.org/copyleft/gpl.html
    00018
    00019 #pragma once
    00020
    00021 #include <afxtempl.h>
    00022 #include <atlbase.h>
    00023 #include <atlcoll.h>
    00024
    00025 #define PauseGraph \
    00026         CComQIPtr<IMediaControl> _pMC(m_pGraph); \
    00027         OAFilterState _fs = -1; \
    00028         if(_pMC) _pMC->GetState(1000, &_fs); \
    00029         if(_fs == State_Running) \
    00030                 _pMC->Pause(); \
    00031  \
    00032         HRESULT _hr = E_FAIL; \
    00033         CComQIPtr<IMediaSeeking> _pMS((IUnknown*)(INonDelegatingUnknown*)m_pGraph); \
    00034         LONGLONG _rtNow = 0; \
    00035         if(_pMS) _hr = _pMS->GetCurrentPosition(&_rtNow); \
    00036
    00037 #define ResumeGraph \
    00038         if(SUCCEEDED(_hr) && _pMS) \
    00039                 _hr = _pMS->SetPositions(&_rtNow, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); \
    00040  \
    00041         if(_fs == State_Running && _pMS) \
    00042                 _pMC->Run(); \
    00043
    00044 class CStreamSwitcherFilter;
    00045
    00046 class CStreamSwitcherPassThru : public IMediaSeeking, public CMediaPosition
    00047 {
    00048 protected:
    00049         CStreamSwitcherFilter* m_pFilter;
    00050
    00051 public:
    00052     CStreamSwitcherPassThru(LPUNKNOWN, HRESULT* phr, CStreamSwitcherFilter* pFilter);
    00053
    00054         DECLARE_IUNKNOWN
    00055     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
    00056
    00057     // IMediaSeeking methods
    00058     STDMETHODIMP GetCapabilities(DWORD* pCapabilities);
    00059     STDMETHODIMP CheckCapabilities(DWORD* pCapabilities);
    00060     STDMETHODIMP SetTimeFormat(const GUID* pFormat);
    00061     STDMETHODIMP GetTimeFormat(GUID* pFormat);
    00062     STDMETHODIMP IsUsingTimeFormat(const GUID* pFormat);
    00063     STDMETHODIMP IsFormatSupported(const GUID* pFormat);
    00064     STDMETHODIMP QueryPreferredFormat(GUID* pFormat);
    00065     STDMETHODIMP ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat);
    00066     STDMETHODIMP SetPositions(LONGLONG* pCurrent, DWORD CurrentFlags, LONGLONG* pStop, DWORD StopFlags);
    00067     STDMETHODIMP GetPositions(LONGLONG* pCurrent, LONGLONG* pStop);
    00068     STDMETHODIMP GetCurrentPosition(LONGLONG* pCurrent);
    00069     STDMETHODIMP GetStopPosition(LONGLONG* pStop);
    00070     STDMETHODIMP SetRate(double dRate);
    00071     STDMETHODIMP GetRate(double* pdRate);
    00072     STDMETHODIMP GetDuration(LONGLONG* pDuration);
    00073     STDMETHODIMP GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest);
    00074     STDMETHODIMP GetPreroll(LONGLONG* pllPreroll);
    00075
    00076     // IMediaPosition properties
    00077     STDMETHODIMP get_Duration(REFTIME* plength);
    00078     STDMETHODIMP put_CurrentPosition(REFTIME llTime);
    00079     STDMETHODIMP get_StopTime(REFTIME* pllTime);
    00080     STDMETHODIMP put_StopTime(REFTIME llTime);
    00081     STDMETHODIMP get_PrerollTime(REFTIME* pllTime);
    00082     STDMETHODIMP put_PrerollTime(REFTIME llTime);
    00083     STDMETHODIMP get_Rate(double* pdRate);
    00084     STDMETHODIMP put_Rate(double dRate);
    00085     STDMETHODIMP get_CurrentPosition(REFTIME* pllTime);
    00086     STDMETHODIMP CanSeekForward(LONG* pCanSeekForward);
    00087     STDMETHODIMP CanSeekBackward(LONG* pCanSeekBackward);
    00088 };
    00089
    00090 class CStreamSwitcherInputPin;
    00091
    00092 class CStreamSwitcherAllocator : public CMemAllocator
    00093 {
    00094 protected:
    00095     CStreamSwitcherInputPin* m_pPin;
    00096
    00097     CMediaType m_mt;
    00098         bool m_fMediaTypeChanged;
    00099
    00100 public:
    00101         CStreamSwitcherAllocator(CStreamSwitcherInputPin* pPin, HRESULT* phr);
    00102 #ifdef DEBUG
    00103         ~CStreamSwitcherAllocator();
    00104 #endif
    00105
    00106         STDMETHODIMP_(ULONG) NonDelegatingAddRef();
    00107         STDMETHODIMP_(ULONG) NonDelegatingRelease();
    00108
    00109         STDMETHODIMP GetBuffer(
    00110                 IMediaSample** ppBuffer,
    00111                 REFERENCE_TIME* pStartTime, REFERENCE_TIME* pEndTime,
    00112                 DWORD dwFlags);
    00113
    00114         void NotifyMediaType(const CMediaType& mt);
    00115 };
    00116
    00117 [uuid("DA395FA3-4A3E-4D85-805E-0BEFF53D4BCD")]
    00118 interface IStreamSwitcherInputPin : public IUnknown
    00119 {
    00120         STDMETHOD_(bool, IsActive)() = 0;
    00121 };
    00122
    00123 class CStreamSwitcherInputPin : public CBaseInputPin, public IPinConnection, public IStreamSwitcherInputPin
    00124 {
    00125         friend class CStreamSwitcherAllocator;
    00126
    00127         CStreamSwitcherAllocator m_Allocator;
    00128
    00129         BOOL m_bSampleSkipped;
    00130         BOOL m_bQualityChanged;
    00131         BOOL m_bUsingOwnAllocator;
    00132
    00133         CAMEvent m_evBlock;
    00134         bool m_fCanBlock;
    00135         HRESULT Active();
    00136         HRESULT Inactive();
    00137
    00138         HRESULT QueryAcceptDownstream(const AM_MEDIA_TYPE* pmt);
    00139
    00140         HRESULT InitializeOutputSample(IMediaSample* pInSample, IMediaSample** ppOutSample);
    00141
    00142         HANDLE m_hNotifyEvent;
    00143
    00144 public:
    00145     CStreamSwitcherInputPin(CStreamSwitcherFilter* pFilter, HRESULT* phr, LPCWSTR pName);
    00146
    00147         DECLARE_IUNKNOWN
    00148     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
    00149
    00150     CMediaType& CurrentMediaType() {return m_mt;}
    00151         IMemAllocator* CurrentAllocator() {return m_pAllocator;}
    00152
    00153         bool IsUsingOwnAllocator() {return m_bUsingOwnAllocator == TRUE;}
    00154
    00155         void Block(bool fBlock);
    00156
    00157         CCritSec m_csReceive;
    00158
    00159         // pure virtual
    00160         HRESULT CheckMediaType(const CMediaType* pmt);
    00161
    00162         // virtual
    00163         HRESULT CheckConnect(IPin* pPin);
    00164         HRESULT CompleteConnect(IPin* pReceivePin);
    00165
    00166         // IPin
    00167         STDMETHODIMP QueryAccept(const AM_MEDIA_TYPE* pmt);
    00168         STDMETHODIMP ReceiveConnection(IPin* pConnector, const AM_MEDIA_TYPE* pmt);
    00169         STDMETHODIMP GetAllocator(IMemAllocator** ppAllocator);
    00170         STDMETHODIMP NotifyAllocator(IMemAllocator* pAllocator, BOOL bReadOnly);
    00171         STDMETHODIMP BeginFlush();
    00172     STDMETHODIMP EndFlush();
    00173         STDMETHODIMP EndOfStream();
    00174
    00175         // IMemInputPin
    00176     STDMETHODIMP Receive(IMediaSample* pSample);
    00177         STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
    00178
    00179         // IPinConnection
    00180         STDMETHODIMP DynamicQueryAccept(const AM_MEDIA_TYPE* pmt);
    00181         STDMETHODIMP NotifyEndOfStream(HANDLE hNotifyEvent);
    00182         STDMETHODIMP IsEndPin();
    00183         STDMETHODIMP DynamicDisconnect();
    00184
    00185         // IStreamSwitcherInputPin
    00186         STDMETHODIMP_(bool) IsActive();
    00187 };
    00188
    00189 class CStreamSwitcherOutputPin : public CBaseOutputPin, public IStreamBuilder
    00190 {
    00191         CComPtr<IUnknown> m_pStreamSwitcherPassThru;
    00192         CComPtr<IPinConnection> m_pPinConnection;
    00193
    00194         HRESULT QueryAcceptUpstream(const AM_MEDIA_TYPE* pmt);
    00195
    00196 public:
    00197     CStreamSwitcherOutputPin(CStreamSwitcherFilter* pFilter, HRESULT* phr);
    00198
    00199         DECLARE_IUNKNOWN
    00200     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
    00201
    00202     CMediaType& CurrentMediaType() {return m_mt;}
    00203         IMemAllocator* CurrentAllocator() {return m_pAllocator;}
    00204         IPinConnection* CurrentPinConnection() {return m_pPinConnection;}
    00205
    00206         // pure virtual
    00207         HRESULT DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties);
    00208
    00209         // virtual
    00210         HRESULT CheckConnect(IPin* pPin);
    00211         HRESULT BreakConnect();
    00212         HRESULT CompleteConnect(IPin* pReceivePin);
    00213
    00214         HRESULT CheckMediaType(const CMediaType* pmt);
    00215         HRESULT GetMediaType(int iPosition, CMediaType* pmt);
    00216
    00217         // IPin
    00218         STDMETHODIMP QueryAccept(const AM_MEDIA_TYPE* pmt);
    00219
    00220         // IQualityControl
    00221         STDMETHODIMP Notify(IBaseFilter* pSender, Quality q);
    00222
    00223         // IStreamBuilder
    00224         STDMETHODIMP Render(IPin* ppinOut, IGraphBuilder* pGraph);
    00225         STDMETHODIMP Backout(IPin* ppinOut, IGraphBuilder* pGraph);
    00226 };
    00227
    00228 class CStreamSwitcherFilter : public CBaseFilter, public IAMStreamSelect
    00229 {
    00230         friend class CStreamSwitcherInputPin;
    00231         friend class CStreamSwitcherOutputPin;
    00232         friend class CStreamSwitcherPassThru;
    00233
    00234         CList<CStreamSwitcherInputPin*> m_pInputs;
    00235         CStreamSwitcherInputPin* m_pInput;
    00236         CStreamSwitcherOutputPin* m_pOutput;
    00237
    00238         CCritSec m_csState, m_csPins;
    00239
    00240         HRESULT CompleteConnect(PIN_DIRECTION dir, CBasePin* pPin, IPin* pReceivePin);
    00241
    00242 protected:
    00243         void SelectInput(CStreamSwitcherInputPin* pInput);
    00244
    00245 public:
    00246         CStreamSwitcherFilter(LPUNKNOWN lpunk, HRESULT* phr, const CLSID& clsid);
    00247         virtual ~CStreamSwitcherFilter();
    00248
    00249         DECLARE_IUNKNOWN
    00250     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
    00251
    00252         int GetPinCount();
    00253         CBasePin* GetPin(int n);
    00254
    00255         int GetConnectedInputPinCount();
    00256         CStreamSwitcherInputPin* GetConnectedInputPin(int n);
    00257         CStreamSwitcherInputPin* GetInputPin();
    00258         CStreamSwitcherOutputPin* GetOutputPin();
    00259
    00260         bool m_fResetOutputMediaType;
    00261         void ResetOutputMediaType() {m_fResetOutputMediaType = true;}
    00262
    00263         // override these
    00264         virtual HRESULT CheckMediaType(const CMediaType* pmt) = 0;
    00265         virtual HRESULT Transform(IMediaSample* pIn, IMediaSample* pOut);
    00266         virtual CMediaType CreateNewOutputMediaType(CMediaType mt, long& cbBuffer);
    00267         virtual void OnNewOutputMediaType(const CMediaType& mtIn, const CMediaType& mtOut) {}
    00268
    00269         // IAMStreamSelect
    00270     STDMETHODIMP Count(DWORD* pcStreams);
    00271     STDMETHODIMP Info(long lIndex, AM_MEDIA_TYPE** ppmt, DWORD* pdwFlags, LCID* plcid, DWORD* pdwGroup, WCHAR** ppszName, IUnknown** ppObject, IUnknown** ppUnk);
    00272     STDMETHODIMP Enable(long lIndex, DWORD dwFlags);
    00273 };
    00274