strmbase: Implement BaseFilter in strmbase.
[wine/multimedia.git] / dlls / quartz / nullrenderer.c
blobc8559c5d80b247dc842802286331da8c12eade99
1 /*
2 * Null Renderer (Promiscuous, not rendering anything at all!)
4 * Copyright 2004 Christian Costa
5 * Copyright 2008 Maarten Lankhorst
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26 #include "quartz_private.h"
27 #include "control_private.h"
28 #include "pin.h"
30 #include "uuids.h"
31 #include "vfwmsgs.h"
32 #include "amvideo.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "dshow.h"
36 #include "evcode.h"
37 #include "strmif.h"
38 #include "ddraw.h"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
46 static const WCHAR wcsAltInputPinName[] = {'I','n',0};
48 static const IBaseFilterVtbl NullRenderer_Vtbl;
49 static const IUnknownVtbl IInner_VTable;
50 static const IPinVtbl NullRenderer_InputPin_Vtbl;
52 typedef struct NullRendererImpl
54 BaseFilter filter;
55 const IUnknownVtbl * IInner_vtbl;
56 IUnknown *seekthru_unk;
58 BaseInputPin *pInputPin;
59 IUnknown * pUnkOuter;
60 BOOL bUnkOuterValid;
61 BOOL bAggregatable;
62 } NullRendererImpl;
64 static HRESULT WINAPI NullRenderer_Receive(IPin *iface, IMediaSample * pSample)
66 BaseInputPin *pin = (BaseInputPin*)iface;
67 NullRendererImpl *This = ((NullRendererImpl*)pin->pin.pinInfo.pFilter);
68 HRESULT hr = S_OK;
69 REFERENCE_TIME start, stop;
71 TRACE("%p %p\n", iface, pSample);
73 if (SUCCEEDED(IMediaSample_GetTime(pSample, &start, &stop)))
74 MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, start);
75 EnterCriticalSection(&This->filter.csFilter);
76 if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
77 hr = S_FALSE;
78 LeaveCriticalSection(&This->filter.csFilter);
80 return hr;
83 static HRESULT WINAPI NullRenderer_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
85 TRACE("Not a stub!\n");
86 return S_OK;
89 HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
91 HRESULT hr;
92 PIN_INFO piInput;
93 NullRendererImpl * pNullRenderer;
95 TRACE("(%p, %p)\n", pUnkOuter, ppv);
97 *ppv = NULL;
99 pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl));
100 pNullRenderer->pUnkOuter = pUnkOuter;
101 pNullRenderer->bUnkOuterValid = FALSE;
102 pNullRenderer->bAggregatable = FALSE;
103 pNullRenderer->IInner_vtbl = &IInner_VTable;
105 BaseFilter_Init(&pNullRenderer->filter, &NullRenderer_Vtbl, &CLSID_NullRenderer, (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"));
107 /* construct input pin */
108 piInput.dir = PINDIR_INPUT;
109 piInput.pFilter = (IBaseFilter *)pNullRenderer;
110 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
112 hr = BaseInputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_CheckMediaType, NullRenderer_Receive, &pNullRenderer->filter.csFilter, NULL, (IPin **)&pNullRenderer->pInputPin);
114 if (SUCCEEDED(hr))
116 ISeekingPassThru *passthru;
117 hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter ? pUnkOuter : (IUnknown*)&pNullRenderer->IInner_vtbl, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pNullRenderer->seekthru_unk);
118 if (FAILED(hr)) {
119 IUnknown_Release((IUnknown*)pNullRenderer);
120 return hr;
122 IUnknown_QueryInterface(pNullRenderer->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
123 ISeekingPassThru_Init(passthru, TRUE, (IPin*)pNullRenderer->pInputPin);
124 ISeekingPassThru_Release(passthru);
125 *ppv = pNullRenderer;
127 else
129 BaseFilterImpl_Release((IBaseFilter*)pNullRenderer);
130 CoTaskMemFree(pNullRenderer);
133 return hr;
136 static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
138 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
139 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
141 if (This->bAggregatable)
142 This->bUnkOuterValid = TRUE;
144 *ppv = NULL;
146 if (IsEqualIID(riid, &IID_IUnknown))
147 *ppv = &This->IInner_vtbl;
148 else if (IsEqualIID(riid, &IID_IPersist))
149 *ppv = This;
150 else if (IsEqualIID(riid, &IID_IMediaFilter))
151 *ppv = This;
152 else if (IsEqualIID(riid, &IID_IBaseFilter))
153 *ppv = This;
154 else if (IsEqualIID(riid, &IID_IMediaSeeking))
155 return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
157 if (*ppv)
159 IUnknown_AddRef((IUnknown *)(*ppv));
160 return S_OK;
163 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
164 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
166 return E_NOINTERFACE;
169 static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface)
171 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
172 ULONG refCount = InterlockedIncrement(&This->filter.refCount);
174 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
176 return refCount;
179 static ULONG WINAPI NullRendererInner_Release(IUnknown * iface)
181 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
182 ULONG refCount = InterlockedDecrement(&This->filter.refCount);
184 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
186 if (!refCount)
188 IPin *pConnectedTo;
190 if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
192 IPin_Disconnect(pConnectedTo);
193 IPin_Release(pConnectedTo);
195 IPin_Disconnect((IPin *)This->pInputPin);
196 IPin_Release((IPin *)This->pInputPin);
198 This->filter.lpVtbl = NULL;
199 if (This->seekthru_unk)
200 IUnknown_Release(This->seekthru_unk);
202 This->filter.csFilter.DebugInfo->Spare[0] = 0;
203 DeleteCriticalSection(&This->filter.csFilter);
205 TRACE("Destroying Null Renderer\n");
206 CoTaskMemFree(This);
207 return 0;
209 else
210 return refCount;
213 static const IUnknownVtbl IInner_VTable =
215 NullRendererInner_QueryInterface,
216 NullRendererInner_AddRef,
217 NullRendererInner_Release
220 static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
222 NullRendererImpl *This = (NullRendererImpl *)iface;
224 if (This->bAggregatable)
225 This->bUnkOuterValid = TRUE;
227 if (This->pUnkOuter)
229 if (This->bAggregatable)
230 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
232 if (IsEqualIID(riid, &IID_IUnknown))
234 HRESULT hr;
236 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
237 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
238 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
239 This->bAggregatable = TRUE;
240 return hr;
243 *ppv = NULL;
244 return E_NOINTERFACE;
247 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
250 static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface)
252 NullRendererImpl *This = (NullRendererImpl *)iface;
254 if (This->pUnkOuter && This->bUnkOuterValid)
255 return IUnknown_AddRef(This->pUnkOuter);
256 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
259 static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface)
261 NullRendererImpl *This = (NullRendererImpl *)iface;
263 if (This->pUnkOuter && This->bUnkOuterValid)
264 return IUnknown_Release(This->pUnkOuter);
265 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
268 /** IMediaFilter methods **/
270 static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface)
272 NullRendererImpl *This = (NullRendererImpl *)iface;
274 TRACE("(%p/%p)->()\n", This, iface);
276 EnterCriticalSection(&This->filter.csFilter);
278 This->filter.state = State_Stopped;
279 MediaSeekingPassThru_ResetMediaTime(This->seekthru_unk);
281 LeaveCriticalSection(&This->filter.csFilter);
283 return S_OK;
286 static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface)
288 NullRendererImpl *This = (NullRendererImpl *)iface;
290 TRACE("(%p/%p)->()\n", This, iface);
292 EnterCriticalSection(&This->filter.csFilter);
294 if (This->filter.state == State_Stopped)
295 This->pInputPin->end_of_stream = 0;
296 This->filter.state = State_Paused;
298 LeaveCriticalSection(&This->filter.csFilter);
300 return S_OK;
303 static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
305 NullRendererImpl *This = (NullRendererImpl *)iface;
307 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
309 EnterCriticalSection(&This->filter.csFilter);
311 This->filter.rtStreamStart = tStart;
312 This->filter.state = State_Running;
313 This->pInputPin->end_of_stream = 0;
315 LeaveCriticalSection(&This->filter.csFilter);
317 return S_OK;
320 /** IBaseFilter implementation **/
322 static IPin* WINAPI NullRenderer_GetPin(IBaseFilter *iface, int pos)
324 NullRendererImpl *This = (NullRendererImpl *)iface;
326 if (pos >= 1 || pos < 0)
327 return NULL;
329 IPin_AddRef((IPin *)This->pInputPin);
330 return (IPin *)This->pInputPin;
333 static LONG WINAPI NullRenderer_GetPinCount(IBaseFilter *iface)
335 return 1;
338 static LONG WINAPI NullRenderer_GetPinVersion(IBaseFilter *iface)
340 /* Our pins are static, not changing so setting static tick count is ok */
341 return 0;
344 static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
346 NullRendererImpl *This = (NullRendererImpl *)iface;
348 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
350 return EnumPins_Construct(iface, NullRenderer_GetPin, NullRenderer_GetPinCount, NullRenderer_GetPinVersion, ppEnum);
353 static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
355 NullRendererImpl *This = (NullRendererImpl *)iface;
357 TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
359 if (!Id || !ppPin)
360 return E_POINTER;
362 if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName))
364 *ppPin = (IPin *)This->pInputPin;
365 IPin_AddRef(*ppPin);
366 return S_OK;
368 *ppPin = NULL;
369 return VFW_E_NOT_FOUND;
372 static const IBaseFilterVtbl NullRenderer_Vtbl =
374 NullRenderer_QueryInterface,
375 NullRenderer_AddRef,
376 NullRenderer_Release,
377 BaseFilterImpl_GetClassID,
378 NullRenderer_Stop,
379 NullRenderer_Pause,
380 NullRenderer_Run,
381 BaseFilterImpl_GetState,
382 BaseFilterImpl_SetSyncSource,
383 BaseFilterImpl_GetSyncSource,
384 NullRenderer_EnumPins,
385 NullRenderer_FindPin,
386 BaseFilterImpl_QueryFilterInfo,
387 BaseFilterImpl_JoinFilterGraph,
388 BaseFilterImpl_QueryVendorInfo
391 static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
393 BaseInputPin* This = (BaseInputPin*)iface;
394 IMediaEventSink* pEventSink;
395 NullRendererImpl *pNull;
396 IFilterGraph *graph;
397 HRESULT hr = S_OK;
399 TRACE("(%p/%p)->()\n", This, iface);
401 BaseInputPinImpl_EndOfStream(iface);
402 pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
403 graph = pNull->filter.filterInfo.pGraph;
404 if (graph)
406 hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
407 if (SUCCEEDED(hr))
409 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
410 IMediaEventSink_Release(pEventSink);
413 MediaSeekingPassThru_EOS(pNull->seekthru_unk);
415 return hr;
418 static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface)
420 BaseInputPin* This = (BaseInputPin*)iface;
421 NullRendererImpl *pNull;
422 HRESULT hr = S_OK;
424 TRACE("(%p/%p)->()\n", This, iface);
426 hr = BaseInputPinImpl_EndOfStream(iface);
427 pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
428 MediaSeekingPassThru_ResetMediaTime(pNull->seekthru_unk);
429 return hr;
432 static const IPinVtbl NullRenderer_InputPin_Vtbl =
434 BaseInputPinImpl_QueryInterface,
435 BasePinImpl_AddRef,
436 BaseInputPinImpl_Release,
437 BaseInputPinImpl_Connect,
438 BaseInputPinImpl_ReceiveConnection,
439 BasePinImpl_Disconnect,
440 BasePinImpl_ConnectedTo,
441 BasePinImpl_ConnectionMediaType,
442 BasePinImpl_QueryPinInfo,
443 BasePinImpl_QueryDirection,
444 BasePinImpl_QueryId,
445 BaseInputPinImpl_QueryAccept,
446 BasePinImpl_EnumMediaTypes,
447 BasePinImpl_QueryInternalConnections,
448 NullRenderer_InputPin_EndOfStream,
449 BaseInputPinImpl_BeginFlush,
450 NullRenderer_InputPin_EndFlush,
451 BaseInputPinImpl_NewSegment