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