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 

Generated on Tue Dec 13 14:47:26 2005 for guliverkli by  doxygen 1.4.5