xref: /reactos/sdk/lib/3rdparty/strmbase/filter.c (revision 10517de5)
1 /*
2  * Generic Implementation of IBaseFilter Interface
3  *
4  * Copyright 2010 Aric Stewart, CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #define COBJMACROS
22 
23 #include "dshow.h"
24 #include "wine/debug.h"
25 #include "wine/unicode.h"
26 #include "wine/strmbase.h"
27 #include "uuids.h"
28 #include <assert.h>
29 
30 WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
31 
impl_from_IBaseFilter(IBaseFilter * iface)32 static inline BaseFilter *impl_from_IBaseFilter(IBaseFilter *iface)
33 {
34     return CONTAINING_RECORD(iface, BaseFilter, IBaseFilter_iface);
35 }
36 
BaseFilterImpl_QueryInterface(IBaseFilter * iface,REFIID riid,LPVOID * ppv)37 HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
38 {
39     TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
40 
41     *ppv = NULL;
42 
43     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPersist) ||
44         IsEqualIID(riid, &IID_IMediaFilter) || IsEqualIID(riid, &IID_IBaseFilter))
45     {
46         *ppv = iface;
47         IBaseFilter_AddRef(iface);
48         return S_OK;
49     }
50 
51     return E_NOINTERFACE;
52 }
53 
BaseFilterImpl_AddRef(IBaseFilter * iface)54 ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter * iface)
55 {
56     BaseFilter *This = impl_from_IBaseFilter(iface);
57     ULONG refCount = InterlockedIncrement(&This->refCount);
58 
59     TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
60 
61     return refCount;
62 }
63 
BaseFilterImpl_Release(IBaseFilter * iface)64 ULONG WINAPI BaseFilterImpl_Release(IBaseFilter * iface)
65 {
66     BaseFilter *This = impl_from_IBaseFilter(iface);
67     ULONG refCount = InterlockedDecrement(&This->refCount);
68 
69     TRACE("(%p)->() Release from %d\n", This, refCount + 1);
70 
71     if (!refCount)
72         BaseFilter_Destroy(This);
73 
74     return refCount;
75 }
76 
BaseFilterImpl_GetClassID(IBaseFilter * iface,CLSID * pClsid)77 HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid)
78 {
79     BaseFilter *This = impl_from_IBaseFilter(iface);
80     TRACE("(%p)->(%p)\n", This, pClsid);
81 
82     *pClsid = This->clsid;
83 
84     return S_OK;
85 }
86 
BaseFilterImpl_GetState(IBaseFilter * iface,DWORD dwMilliSecsTimeout,FILTER_STATE * pState)87 HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState )
88 {
89     BaseFilter *This = impl_from_IBaseFilter(iface);
90     TRACE("(%p)->(%d, %p)\n", This, dwMilliSecsTimeout, pState);
91 
92     EnterCriticalSection(&This->csFilter);
93     {
94         *pState = This->state;
95     }
96     LeaveCriticalSection(&This->csFilter);
97 
98     return S_OK;
99 }
100 
BaseFilterImpl_SetSyncSource(IBaseFilter * iface,IReferenceClock * pClock)101 HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
102 {
103     BaseFilter *This = impl_from_IBaseFilter(iface);
104     TRACE("(%p)->(%p)\n", This, pClock);
105 
106     EnterCriticalSection(&This->csFilter);
107     {
108         if (This->pClock)
109             IReferenceClock_Release(This->pClock);
110         This->pClock = pClock;
111         if (This->pClock)
112             IReferenceClock_AddRef(This->pClock);
113     }
114     LeaveCriticalSection(&This->csFilter);
115 
116     return S_OK;
117 }
118 
BaseFilterImpl_GetSyncSource(IBaseFilter * iface,IReferenceClock ** ppClock)119 HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
120 {
121     BaseFilter *This = impl_from_IBaseFilter(iface);
122     TRACE("(%p)->(%p)\n", This, ppClock);
123 
124     EnterCriticalSection(&This->csFilter);
125     {
126         *ppClock = This->pClock;
127         if (This->pClock)
128             IReferenceClock_AddRef(This->pClock);
129     }
130     LeaveCriticalSection(&This->csFilter);
131 
132     return S_OK;
133 }
134 
BaseFilterImpl_EnumPins(IBaseFilter * iface,IEnumPins ** ppEnum)135 HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
136 {
137     BaseFilter *This = impl_from_IBaseFilter(iface);
138 
139     TRACE("(%p)->(%p)\n", iface, ppEnum);
140 
141     return EnumPins_Construct(This, This->pFuncsTable->pfnGetPin, This->pFuncsTable->pfnGetPinCount, BaseFilterImpl_GetPinVersion, ppEnum);
142 }
143 
144 
BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface,FILTER_INFO * pInfo)145 HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
146 {
147     BaseFilter *This = impl_from_IBaseFilter(iface);
148     TRACE("(%p)->(%p)\n", This, pInfo);
149 
150     strcpyW(pInfo->achName, This->filterInfo.achName);
151     pInfo->pGraph = This->filterInfo.pGraph;
152 
153     if (pInfo->pGraph)
154         IFilterGraph_AddRef(pInfo->pGraph);
155 
156     return S_OK;
157 }
158 
BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface,IFilterGraph * pGraph,LPCWSTR pName)159 HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName )
160 {
161     BaseFilter *This = impl_from_IBaseFilter(iface);
162 
163     TRACE("(%p)->(%p, %s)\n", This, pGraph, debugstr_w(pName));
164 
165     EnterCriticalSection(&This->csFilter);
166     {
167         if (pName)
168             strcpyW(This->filterInfo.achName, pName);
169         else
170             *This->filterInfo.achName = '\0';
171         This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
172     }
173     LeaveCriticalSection(&This->csFilter);
174 
175     return S_OK;
176 }
177 
BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface,LPWSTR * pVendorInfo)178 HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
179 {
180     TRACE("(%p)->(%p)\n", iface, pVendorInfo);
181     return E_NOTIMPL;
182 }
183 
BaseFilterImpl_GetPinVersion(BaseFilter * This)184 LONG WINAPI BaseFilterImpl_GetPinVersion(BaseFilter * This)
185 {
186     TRACE("(%p)\n", This);
187     return This->pinVersion;
188 }
189 
BaseFilterImpl_IncrementPinVersion(BaseFilter * This)190 VOID WINAPI BaseFilterImpl_IncrementPinVersion(BaseFilter * This)
191 {
192     InterlockedIncrement(&This->pinVersion);
193     TRACE("(%p) -> New pinVersion %i\n", This,This->pinVersion);
194 }
195 
BaseFilter_Init(BaseFilter * This,const IBaseFilterVtbl * Vtbl,const CLSID * pClsid,DWORD_PTR DebugInfo,const BaseFilterFuncTable * pBaseFuncsTable)196 HRESULT WINAPI BaseFilter_Init(BaseFilter * This, const IBaseFilterVtbl *Vtbl, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseFilterFuncTable* pBaseFuncsTable)
197 {
198     This->IBaseFilter_iface.lpVtbl = Vtbl;
199     This->refCount = 1;
200     InitializeCriticalSection(&This->csFilter);
201     This->state = State_Stopped;
202     This->rtStreamStart = 0;
203     This->pClock = NULL;
204     ZeroMemory(&This->filterInfo, sizeof(FILTER_INFO));
205     This->clsid = *pClsid;
206     This->csFilter.DebugInfo->Spare[0] = DebugInfo;
207     This->pinVersion = 1;
208 
209     This->pFuncsTable = pBaseFuncsTable;
210 
211     return S_OK;
212 }
213 
BaseFilter_Destroy(BaseFilter * This)214 HRESULT WINAPI BaseFilter_Destroy(BaseFilter * This)
215 {
216     if (This->pClock)
217         IReferenceClock_Release(This->pClock);
218 
219     This->IBaseFilter_iface.lpVtbl = NULL;
220     This->csFilter.DebugInfo->Spare[0] = 0;
221     DeleteCriticalSection(&This->csFilter);
222 
223     return S_OK;
224 }
225