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
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26 #include "quartz_private.h"
27 #include "control_private.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;
51 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl;
53 typedef struct NullRendererImpl
56 const IUnknownVtbl * IInner_vtbl;
57 const IAMFilterMiscFlagsVtbl *IAMFilterMiscFlags_vtbl;
58 IUnknown *seekthru_unk;
60 BaseInputPin *pInputPin;
66 static HRESULT WINAPI NullRenderer_Receive(BaseInputPin *pin, IMediaSample * pSample)
68 NullRendererImpl *This = ((NullRendererImpl*)pin->pin.pinInfo.pFilter);
70 REFERENCE_TIME start, stop;
72 TRACE("%p %p\n", pin, pSample);
74 if (SUCCEEDED(IMediaSample_GetMediaTime(pSample, &start, &stop)))
75 MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, start);
76 EnterCriticalSection(&This->filter.csFilter);
77 if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
79 LeaveCriticalSection(&This->filter.csFilter);
84 static HRESULT WINAPI NullRenderer_CheckMediaType(BasePin *iface, const AM_MEDIA_TYPE * pmt)
86 TRACE("Not a stub!\n");
90 static IPin* WINAPI NullRenderer_GetPin(BaseFilter *iface, int pos)
92 NullRendererImpl *This = (NullRendererImpl *)iface;
94 if (pos >= 1 || pos < 0)
97 IPin_AddRef((IPin *)This->pInputPin);
98 return (IPin *)This->pInputPin;
101 static LONG WINAPI NullRenderer_GetPinCount(BaseFilter *iface)
106 static const BaseFilterFuncTable BaseFuncTable = {
108 NullRenderer_GetPinCount
111 static const BasePinFuncTable input_BaseFuncTable = {
112 NullRenderer_CheckMediaType,
114 BasePinImpl_GetMediaTypeVersion,
115 BasePinImpl_GetMediaType
118 static const BaseInputPinFuncTable input_BaseInputFuncTable = {
123 HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
127 NullRendererImpl * pNullRenderer;
129 TRACE("(%p, %p)\n", pUnkOuter, ppv);
133 pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl));
134 pNullRenderer->pUnkOuter = pUnkOuter;
135 pNullRenderer->bUnkOuterValid = FALSE;
136 pNullRenderer->bAggregatable = FALSE;
137 pNullRenderer->IInner_vtbl = &IInner_VTable;
138 pNullRenderer->IAMFilterMiscFlags_vtbl = &IAMFilterMiscFlags_Vtbl;
140 BaseFilter_Init(&pNullRenderer->filter, &NullRenderer_Vtbl, &CLSID_NullRenderer, (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"), &BaseFuncTable);
142 /* construct input pin */
143 piInput.dir = PINDIR_INPUT;
144 piInput.pFilter = (IBaseFilter *)pNullRenderer;
145 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
147 hr = BaseInputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, &input_BaseFuncTable, &input_BaseInputFuncTable, &pNullRenderer->filter.csFilter, NULL, (IPin **)&pNullRenderer->pInputPin);
151 ISeekingPassThru *passthru;
152 hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter ? pUnkOuter : (IUnknown*)&pNullRenderer->IInner_vtbl, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pNullRenderer->seekthru_unk);
154 IUnknown_Release((IUnknown*)pNullRenderer);
157 IUnknown_QueryInterface(pNullRenderer->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru);
158 ISeekingPassThru_Init(passthru, TRUE, (IPin*)pNullRenderer->pInputPin);
159 ISeekingPassThru_Release(passthru);
160 *ppv = pNullRenderer;
164 BaseFilterImpl_Release((IBaseFilter*)pNullRenderer);
165 CoTaskMemFree(pNullRenderer);
171 static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
173 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
174 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
176 if (This->bAggregatable)
177 This->bUnkOuterValid = TRUE;
181 if (IsEqualIID(riid, &IID_IUnknown))
182 *ppv = &This->IInner_vtbl;
183 else if (IsEqualIID(riid, &IID_IPersist))
185 else if (IsEqualIID(riid, &IID_IMediaFilter))
187 else if (IsEqualIID(riid, &IID_IBaseFilter))
189 else if (IsEqualIID(riid, &IID_IMediaSeeking))
190 return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
191 else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
192 *ppv = &This->IAMFilterMiscFlags_vtbl;
196 IUnknown_AddRef((IUnknown *)(*ppv));
200 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
201 FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
203 return E_NOINTERFACE;
206 static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface)
208 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
209 ULONG refCount = InterlockedIncrement(&This->filter.refCount);
211 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
216 static ULONG WINAPI NullRendererInner_Release(IUnknown * iface)
218 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
219 ULONG refCount = InterlockedDecrement(&This->filter.refCount);
221 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
227 if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
229 IPin_Disconnect(pConnectedTo);
230 IPin_Release(pConnectedTo);
232 IPin_Disconnect((IPin *)This->pInputPin);
233 IPin_Release((IPin *)This->pInputPin);
235 This->filter.lpVtbl = NULL;
236 if (This->seekthru_unk)
237 IUnknown_Release(This->seekthru_unk);
239 This->filter.csFilter.DebugInfo->Spare[0] = 0;
240 DeleteCriticalSection(&This->filter.csFilter);
242 TRACE("Destroying Null Renderer\n");
250 static const IUnknownVtbl IInner_VTable =
252 NullRendererInner_QueryInterface,
253 NullRendererInner_AddRef,
254 NullRendererInner_Release
257 static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
259 NullRendererImpl *This = (NullRendererImpl *)iface;
261 if (This->bAggregatable)
262 This->bUnkOuterValid = TRUE;
266 if (This->bAggregatable)
267 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
269 if (IsEqualIID(riid, &IID_IUnknown))
273 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
274 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
275 IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
276 This->bAggregatable = TRUE;
281 return E_NOINTERFACE;
284 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
287 static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface)
289 NullRendererImpl *This = (NullRendererImpl *)iface;
291 if (This->pUnkOuter && This->bUnkOuterValid)
292 return IUnknown_AddRef(This->pUnkOuter);
293 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
296 static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface)
298 NullRendererImpl *This = (NullRendererImpl *)iface;
300 if (This->pUnkOuter && This->bUnkOuterValid)
301 return IUnknown_Release(This->pUnkOuter);
302 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
305 /** IMediaFilter methods **/
307 static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface)
309 NullRendererImpl *This = (NullRendererImpl *)iface;
311 TRACE("(%p/%p)->()\n", This, iface);
313 EnterCriticalSection(&This->filter.csFilter);
315 This->filter.state = State_Stopped;
316 MediaSeekingPassThru_ResetMediaTime(This->seekthru_unk);
318 LeaveCriticalSection(&This->filter.csFilter);
323 static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface)
325 NullRendererImpl *This = (NullRendererImpl *)iface;
327 TRACE("(%p/%p)->()\n", This, iface);
329 EnterCriticalSection(&This->filter.csFilter);
331 if (This->filter.state == State_Stopped)
332 This->pInputPin->end_of_stream = 0;
333 This->filter.state = State_Paused;
335 LeaveCriticalSection(&This->filter.csFilter);
340 static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
343 NullRendererImpl *This = (NullRendererImpl *)iface;
345 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
347 EnterCriticalSection(&This->filter.csFilter);
348 This->filter.rtStreamStart = tStart;
349 if (This->filter.state == State_Running)
351 if (This->pInputPin->pin.pConnectedTo)
353 This->pInputPin->end_of_stream = 0;
355 else if (This->filter.filterInfo.pGraph)
357 IMediaEventSink *pEventSink;
358 hr = IFilterGraph_QueryInterface(This->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
361 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)This);
362 IMediaEventSink_Release(pEventSink);
367 This->filter.state = State_Running;
369 LeaveCriticalSection(&This->filter.csFilter);
374 /** IBaseFilter implementation **/
376 static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
378 NullRendererImpl *This = (NullRendererImpl *)iface;
380 TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
385 if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName))
387 *ppPin = (IPin *)This->pInputPin;
392 return VFW_E_NOT_FOUND;
395 static const IBaseFilterVtbl NullRenderer_Vtbl =
397 NullRenderer_QueryInterface,
399 NullRenderer_Release,
400 BaseFilterImpl_GetClassID,
404 BaseFilterImpl_GetState,
405 BaseFilterImpl_SetSyncSource,
406 BaseFilterImpl_GetSyncSource,
407 BaseFilterImpl_EnumPins,
408 NullRenderer_FindPin,
409 BaseFilterImpl_QueryFilterInfo,
410 BaseFilterImpl_JoinFilterGraph,
411 BaseFilterImpl_QueryVendorInfo
414 static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
416 BaseInputPin* This = (BaseInputPin*)iface;
417 IMediaEventSink* pEventSink;
418 NullRendererImpl *pNull;
422 TRACE("(%p/%p)->()\n", This, iface);
424 BaseInputPinImpl_EndOfStream(iface);
425 pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
426 graph = pNull->filter.filterInfo.pGraph;
429 hr = IFilterGraph_QueryInterface(pNull->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
432 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)pNull);
433 IMediaEventSink_Release(pEventSink);
436 MediaSeekingPassThru_EOS(pNull->seekthru_unk);
441 static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface)
443 BaseInputPin* This = (BaseInputPin*)iface;
444 NullRendererImpl *pNull;
447 TRACE("(%p/%p)->()\n", This, iface);
449 hr = BaseInputPinImpl_EndOfStream(iface);
450 pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
451 MediaSeekingPassThru_ResetMediaTime(pNull->seekthru_unk);
455 static const IPinVtbl NullRenderer_InputPin_Vtbl =
457 BaseInputPinImpl_QueryInterface,
459 BaseInputPinImpl_Release,
460 BaseInputPinImpl_Connect,
461 BaseInputPinImpl_ReceiveConnection,
462 BasePinImpl_Disconnect,
463 BasePinImpl_ConnectedTo,
464 BasePinImpl_ConnectionMediaType,
465 BasePinImpl_QueryPinInfo,
466 BasePinImpl_QueryDirection,
468 BaseInputPinImpl_QueryAccept,
469 BasePinImpl_EnumMediaTypes,
470 BasePinImpl_QueryInternalConnections,
471 NullRenderer_InputPin_EndOfStream,
472 BaseInputPinImpl_BeginFlush,
473 NullRenderer_InputPin_EndFlush,
474 BaseInputPinImpl_NewSegment
477 static NullRendererImpl *from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) {
478 return (NullRendererImpl*)((char*)iface - offsetof(NullRendererImpl, IAMFilterMiscFlags_vtbl));
481 static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
482 NullRendererImpl *This = from_IAMFilterMiscFlags(iface);
483 return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
486 static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
487 NullRendererImpl *This = from_IAMFilterMiscFlags(iface);
488 return IUnknown_AddRef((IUnknown*)This);
491 static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
492 NullRendererImpl *This = from_IAMFilterMiscFlags(iface);
493 return IUnknown_Release((IUnknown*)This);
496 static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
497 return AM_FILTER_MISC_FLAGS_IS_RENDERER;
500 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
501 AMFilterMiscFlags_QueryInterface,
502 AMFilterMiscFlags_AddRef,
503 AMFilterMiscFlags_Release,
504 AMFilterMiscFlags_GetMiscFlags