00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
00160 HRESULT CheckMediaType(const CMediaType* pmt);
00161
00162
00163 HRESULT CheckConnect(IPin* pPin);
00164 HRESULT CompleteConnect(IPin* pReceivePin);
00165
00166
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
00176 STDMETHODIMP Receive(IMediaSample* pSample);
00177 STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
00178
00179
00180 STDMETHODIMP DynamicQueryAccept(const AM_MEDIA_TYPE* pmt);
00181 STDMETHODIMP NotifyEndOfStream(HANDLE hNotifyEvent);
00182 STDMETHODIMP IsEndPin();
00183 STDMETHODIMP DynamicDisconnect();
00184
00185
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
00207 HRESULT DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties);
00208
00209
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
00218 STDMETHODIMP QueryAccept(const AM_MEDIA_TYPE* pmt);
00219
00220
00221 STDMETHODIMP Notify(IBaseFilter* pSender, Quality q);
00222
00223
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
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
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