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"
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
44 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
45 static const WCHAR wcsAltInputPinName
[] = {'I','n',0};
47 static const IBaseFilterVtbl NullRenderer_Vtbl
;
48 static const IUnknownVtbl IInner_VTable
;
49 static const IPinVtbl NullRenderer_InputPin_Vtbl
;
50 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl
;
52 typedef struct NullRendererImpl
55 const IUnknownVtbl
* IInner_vtbl
;
56 const IAMFilterMiscFlagsVtbl
*IAMFilterMiscFlags_vtbl
;
57 IUnknown
*seekthru_unk
;
59 BaseInputPin
*pInputPin
;
65 static HRESULT WINAPI
NullRenderer_Receive(BaseInputPin
*pin
, IMediaSample
* pSample
)
67 NullRendererImpl
*This
= ((NullRendererImpl
*)pin
->pin
.pinInfo
.pFilter
);
69 REFERENCE_TIME start
, stop
;
71 TRACE("%p %p\n", pin
, pSample
);
73 if (SUCCEEDED(IMediaSample_GetMediaTime(pSample
, &start
, &stop
)))
74 RendererPosPassThru_RegisterMediaTime(This
->seekthru_unk
, start
);
75 EnterCriticalSection(&This
->filter
.csFilter
);
76 if (This
->pInputPin
->flushing
|| This
->pInputPin
->end_of_stream
)
78 LeaveCriticalSection(&This
->filter
.csFilter
);
83 static HRESULT WINAPI
NullRenderer_CheckMediaType(BasePin
*iface
, const AM_MEDIA_TYPE
* pmt
)
85 TRACE("Not a stub!\n");
89 static IPin
* WINAPI
NullRenderer_GetPin(BaseFilter
*iface
, int pos
)
91 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
93 if (pos
>= 1 || pos
< 0)
96 IPin_AddRef((IPin
*)This
->pInputPin
);
97 return (IPin
*)This
->pInputPin
;
100 static LONG WINAPI
NullRenderer_GetPinCount(BaseFilter
*iface
)
105 static const BaseFilterFuncTable BaseFuncTable
= {
107 NullRenderer_GetPinCount
110 static const BasePinFuncTable input_BaseFuncTable
= {
111 NullRenderer_CheckMediaType
,
113 BasePinImpl_GetMediaTypeVersion
,
114 BasePinImpl_GetMediaType
117 static const BaseInputPinFuncTable input_BaseInputFuncTable
= {
122 HRESULT
NullRenderer_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
126 NullRendererImpl
* pNullRenderer
;
128 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
132 pNullRenderer
= CoTaskMemAlloc(sizeof(NullRendererImpl
));
133 pNullRenderer
->pUnkOuter
= pUnkOuter
;
134 pNullRenderer
->bUnkOuterValid
= FALSE
;
135 pNullRenderer
->bAggregatable
= FALSE
;
136 pNullRenderer
->IInner_vtbl
= &IInner_VTable
;
137 pNullRenderer
->IAMFilterMiscFlags_vtbl
= &IAMFilterMiscFlags_Vtbl
;
139 BaseFilter_Init(&pNullRenderer
->filter
, &NullRenderer_Vtbl
, &CLSID_NullRenderer
, (DWORD_PTR
)(__FILE__
": NullRendererImpl.csFilter"), &BaseFuncTable
);
141 /* construct input pin */
142 piInput
.dir
= PINDIR_INPUT
;
143 piInput
.pFilter
= (IBaseFilter
*)pNullRenderer
;
144 lstrcpynW(piInput
.achName
, wcsInputPinName
, sizeof(piInput
.achName
) / sizeof(piInput
.achName
[0]));
146 hr
= BaseInputPin_Construct(&NullRenderer_InputPin_Vtbl
, &piInput
, &input_BaseFuncTable
, &input_BaseInputFuncTable
, &pNullRenderer
->filter
.csFilter
, NULL
, (IPin
**)&pNullRenderer
->pInputPin
);
150 hr
= CreatePosPassThru(pUnkOuter
? pUnkOuter
: (IUnknown
*)&pNullRenderer
->IInner_vtbl
, TRUE
, (IPin
*)pNullRenderer
->pInputPin
, &pNullRenderer
->seekthru_unk
);
152 IUnknown_Release((IUnknown
*)pNullRenderer
);
155 *ppv
= pNullRenderer
;
159 BaseFilterImpl_Release((IBaseFilter
*)pNullRenderer
);
160 CoTaskMemFree(pNullRenderer
);
166 static HRESULT WINAPI
NullRendererInner_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
168 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
169 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
171 if (This
->bAggregatable
)
172 This
->bUnkOuterValid
= TRUE
;
176 if (IsEqualIID(riid
, &IID_IUnknown
))
177 *ppv
= &This
->IInner_vtbl
;
178 else if (IsEqualIID(riid
, &IID_IPersist
))
180 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
182 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
184 else if (IsEqualIID(riid
, &IID_IMediaSeeking
))
185 return IUnknown_QueryInterface(This
->seekthru_unk
, riid
, ppv
);
186 else if (IsEqualIID(riid
, &IID_IAMFilterMiscFlags
))
187 *ppv
= &This
->IAMFilterMiscFlags_vtbl
;
191 IUnknown_AddRef((IUnknown
*)(*ppv
));
195 if (!IsEqualIID(riid
, &IID_IPin
) && !IsEqualIID(riid
, &IID_IVideoWindow
))
196 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
198 return E_NOINTERFACE
;
201 static ULONG WINAPI
NullRendererInner_AddRef(IUnknown
* iface
)
203 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
204 ULONG refCount
= InterlockedIncrement(&This
->filter
.refCount
);
206 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, refCount
- 1);
211 static ULONG WINAPI
NullRendererInner_Release(IUnknown
* iface
)
213 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
214 ULONG refCount
= InterlockedDecrement(&This
->filter
.refCount
);
216 TRACE("(%p/%p)->() Release from %d\n", This
, iface
, refCount
+ 1);
222 if (SUCCEEDED(IPin_ConnectedTo((IPin
*)This
->pInputPin
, &pConnectedTo
)))
224 IPin_Disconnect(pConnectedTo
);
225 IPin_Release(pConnectedTo
);
227 IPin_Disconnect((IPin
*)This
->pInputPin
);
228 IPin_Release((IPin
*)This
->pInputPin
);
230 This
->filter
.lpVtbl
= NULL
;
231 if (This
->seekthru_unk
)
232 IUnknown_Release(This
->seekthru_unk
);
234 This
->filter
.csFilter
.DebugInfo
->Spare
[0] = 0;
235 DeleteCriticalSection(&This
->filter
.csFilter
);
237 TRACE("Destroying Null Renderer\n");
245 static const IUnknownVtbl IInner_VTable
=
247 NullRendererInner_QueryInterface
,
248 NullRendererInner_AddRef
,
249 NullRendererInner_Release
252 static HRESULT WINAPI
NullRenderer_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
254 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
256 if (This
->bAggregatable
)
257 This
->bUnkOuterValid
= TRUE
;
261 if (This
->bAggregatable
)
262 return IUnknown_QueryInterface(This
->pUnkOuter
, riid
, ppv
);
264 if (IsEqualIID(riid
, &IID_IUnknown
))
268 IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
269 hr
= IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
270 IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
271 This
->bAggregatable
= TRUE
;
276 return E_NOINTERFACE
;
279 return IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
282 static ULONG WINAPI
NullRenderer_AddRef(IBaseFilter
* iface
)
284 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
286 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
287 return IUnknown_AddRef(This
->pUnkOuter
);
288 return IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
291 static ULONG WINAPI
NullRenderer_Release(IBaseFilter
* iface
)
293 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
295 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
296 return IUnknown_Release(This
->pUnkOuter
);
297 return IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
300 /** IMediaFilter methods **/
302 static HRESULT WINAPI
NullRenderer_Stop(IBaseFilter
* iface
)
304 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
306 TRACE("(%p/%p)->()\n", This
, iface
);
308 EnterCriticalSection(&This
->filter
.csFilter
);
310 This
->filter
.state
= State_Stopped
;
311 RendererPosPassThru_ResetMediaTime(This
->seekthru_unk
);
313 LeaveCriticalSection(&This
->filter
.csFilter
);
318 static HRESULT WINAPI
NullRenderer_Pause(IBaseFilter
* iface
)
320 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
322 TRACE("(%p/%p)->()\n", This
, iface
);
324 EnterCriticalSection(&This
->filter
.csFilter
);
326 if (This
->filter
.state
== State_Stopped
)
327 This
->pInputPin
->end_of_stream
= 0;
328 This
->filter
.state
= State_Paused
;
330 LeaveCriticalSection(&This
->filter
.csFilter
);
335 static HRESULT WINAPI
NullRenderer_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
338 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
340 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
342 EnterCriticalSection(&This
->filter
.csFilter
);
343 This
->filter
.rtStreamStart
= tStart
;
344 if (This
->filter
.state
== State_Running
)
346 if (This
->pInputPin
->pin
.pConnectedTo
)
348 This
->pInputPin
->end_of_stream
= 0;
350 else if (This
->filter
.filterInfo
.pGraph
)
352 IMediaEventSink
*pEventSink
;
353 hr
= IFilterGraph_QueryInterface(This
->filter
.filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
356 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, (LONG_PTR
)This
);
357 IMediaEventSink_Release(pEventSink
);
362 This
->filter
.state
= State_Running
;
364 LeaveCriticalSection(&This
->filter
.csFilter
);
369 /** IBaseFilter implementation **/
371 static HRESULT WINAPI
NullRenderer_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
373 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
375 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
380 if (!lstrcmpiW(Id
,wcsInputPinName
) || !lstrcmpiW(Id
,wcsAltInputPinName
))
382 *ppPin
= (IPin
*)This
->pInputPin
;
387 return VFW_E_NOT_FOUND
;
390 static const IBaseFilterVtbl NullRenderer_Vtbl
=
392 NullRenderer_QueryInterface
,
394 NullRenderer_Release
,
395 BaseFilterImpl_GetClassID
,
399 BaseFilterImpl_GetState
,
400 BaseFilterImpl_SetSyncSource
,
401 BaseFilterImpl_GetSyncSource
,
402 BaseFilterImpl_EnumPins
,
403 NullRenderer_FindPin
,
404 BaseFilterImpl_QueryFilterInfo
,
405 BaseFilterImpl_JoinFilterGraph
,
406 BaseFilterImpl_QueryVendorInfo
409 static HRESULT WINAPI
NullRenderer_InputPin_EndOfStream(IPin
* iface
)
411 BaseInputPin
* This
= (BaseInputPin
*)iface
;
412 IMediaEventSink
* pEventSink
;
413 NullRendererImpl
*pNull
;
417 TRACE("(%p/%p)->()\n", This
, iface
);
419 BaseInputPinImpl_EndOfStream(iface
);
420 pNull
= (NullRendererImpl
*)This
->pin
.pinInfo
.pFilter
;
421 graph
= pNull
->filter
.filterInfo
.pGraph
;
424 hr
= IFilterGraph_QueryInterface(pNull
->filter
.filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
427 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, (LONG_PTR
)pNull
);
428 IMediaEventSink_Release(pEventSink
);
431 RendererPosPassThru_EOS(pNull
->seekthru_unk
);
436 static HRESULT WINAPI
NullRenderer_InputPin_EndFlush(IPin
* iface
)
438 BaseInputPin
* This
= (BaseInputPin
*)iface
;
439 NullRendererImpl
*pNull
;
442 TRACE("(%p/%p)->()\n", This
, iface
);
444 hr
= BaseInputPinImpl_EndOfStream(iface
);
445 pNull
= (NullRendererImpl
*)This
->pin
.pinInfo
.pFilter
;
446 RendererPosPassThru_ResetMediaTime(pNull
->seekthru_unk
);
450 static const IPinVtbl NullRenderer_InputPin_Vtbl
=
452 BaseInputPinImpl_QueryInterface
,
454 BaseInputPinImpl_Release
,
455 BaseInputPinImpl_Connect
,
456 BaseInputPinImpl_ReceiveConnection
,
457 BasePinImpl_Disconnect
,
458 BasePinImpl_ConnectedTo
,
459 BasePinImpl_ConnectionMediaType
,
460 BasePinImpl_QueryPinInfo
,
461 BasePinImpl_QueryDirection
,
463 BaseInputPinImpl_QueryAccept
,
464 BasePinImpl_EnumMediaTypes
,
465 BasePinImpl_QueryInternalConnections
,
466 NullRenderer_InputPin_EndOfStream
,
467 BaseInputPinImpl_BeginFlush
,
468 NullRenderer_InputPin_EndFlush
,
469 BaseInputPinImpl_NewSegment
472 static NullRendererImpl
*from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
) {
473 return (NullRendererImpl
*)((char*)iface
- offsetof(NullRendererImpl
, IAMFilterMiscFlags_vtbl
));
476 static HRESULT WINAPI
AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
, void **ppv
) {
477 NullRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
478 return IUnknown_QueryInterface((IUnknown
*)This
, riid
, ppv
);
481 static ULONG WINAPI
AMFilterMiscFlags_AddRef(IAMFilterMiscFlags
*iface
) {
482 NullRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
483 return IUnknown_AddRef((IUnknown
*)This
);
486 static ULONG WINAPI
AMFilterMiscFlags_Release(IAMFilterMiscFlags
*iface
) {
487 NullRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
488 return IUnknown_Release((IUnknown
*)This
);
491 static ULONG WINAPI
AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags
*iface
) {
492 return AM_FILTER_MISC_FLAGS_IS_RENDERER
;
495 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl
= {
496 AMFilterMiscFlags_QueryInterface
,
497 AMFilterMiscFlags_AddRef
,
498 AMFilterMiscFlags_Release
,
499 AMFilterMiscFlags_GetMiscFlags