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 if (This
->seekthru_unk
)
231 IUnknown_Release(This
->seekthru_unk
);
233 This
->filter
.csFilter
.DebugInfo
->Spare
[0] = 0;
234 DeleteCriticalSection(&This
->filter
.csFilter
);
236 TRACE("Destroying Null Renderer\n");
244 static const IUnknownVtbl IInner_VTable
=
246 NullRendererInner_QueryInterface
,
247 NullRendererInner_AddRef
,
248 NullRendererInner_Release
251 static HRESULT WINAPI
NullRenderer_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
253 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
255 if (This
->bAggregatable
)
256 This
->bUnkOuterValid
= TRUE
;
260 if (This
->bAggregatable
)
261 return IUnknown_QueryInterface(This
->pUnkOuter
, riid
, ppv
);
263 if (IsEqualIID(riid
, &IID_IUnknown
))
267 IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
268 hr
= IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
269 IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
270 This
->bAggregatable
= TRUE
;
275 return E_NOINTERFACE
;
278 return IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
281 static ULONG WINAPI
NullRenderer_AddRef(IBaseFilter
* iface
)
283 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
285 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
286 return IUnknown_AddRef(This
->pUnkOuter
);
287 return IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
290 static ULONG WINAPI
NullRenderer_Release(IBaseFilter
* iface
)
292 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
294 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
295 return IUnknown_Release(This
->pUnkOuter
);
296 return IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
299 /** IMediaFilter methods **/
301 static HRESULT WINAPI
NullRenderer_Stop(IBaseFilter
* iface
)
303 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
305 TRACE("(%p/%p)->()\n", This
, iface
);
307 EnterCriticalSection(&This
->filter
.csFilter
);
309 This
->filter
.state
= State_Stopped
;
310 RendererPosPassThru_ResetMediaTime(This
->seekthru_unk
);
312 LeaveCriticalSection(&This
->filter
.csFilter
);
317 static HRESULT WINAPI
NullRenderer_Pause(IBaseFilter
* iface
)
319 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
321 TRACE("(%p/%p)->()\n", This
, iface
);
323 EnterCriticalSection(&This
->filter
.csFilter
);
325 if (This
->filter
.state
== State_Stopped
)
326 This
->pInputPin
->end_of_stream
= 0;
327 This
->filter
.state
= State_Paused
;
329 LeaveCriticalSection(&This
->filter
.csFilter
);
334 static HRESULT WINAPI
NullRenderer_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
337 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
339 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
341 EnterCriticalSection(&This
->filter
.csFilter
);
342 This
->filter
.rtStreamStart
= tStart
;
343 if (This
->filter
.state
== State_Running
)
345 if (This
->pInputPin
->pin
.pConnectedTo
)
347 This
->pInputPin
->end_of_stream
= 0;
349 else if (This
->filter
.filterInfo
.pGraph
)
351 IMediaEventSink
*pEventSink
;
352 hr
= IFilterGraph_QueryInterface(This
->filter
.filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
355 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, (LONG_PTR
)This
);
356 IMediaEventSink_Release(pEventSink
);
361 This
->filter
.state
= State_Running
;
363 LeaveCriticalSection(&This
->filter
.csFilter
);
368 /** IBaseFilter implementation **/
370 static HRESULT WINAPI
NullRenderer_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
372 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
374 TRACE("(%p/%p)->(%s,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
379 if (!lstrcmpiW(Id
,wcsInputPinName
) || !lstrcmpiW(Id
,wcsAltInputPinName
))
381 *ppPin
= (IPin
*)This
->pInputPin
;
386 return VFW_E_NOT_FOUND
;
389 static const IBaseFilterVtbl NullRenderer_Vtbl
=
391 NullRenderer_QueryInterface
,
393 NullRenderer_Release
,
394 BaseFilterImpl_GetClassID
,
398 BaseFilterImpl_GetState
,
399 BaseFilterImpl_SetSyncSource
,
400 BaseFilterImpl_GetSyncSource
,
401 BaseFilterImpl_EnumPins
,
402 NullRenderer_FindPin
,
403 BaseFilterImpl_QueryFilterInfo
,
404 BaseFilterImpl_JoinFilterGraph
,
405 BaseFilterImpl_QueryVendorInfo
408 static HRESULT WINAPI
NullRenderer_InputPin_EndOfStream(IPin
* iface
)
410 BaseInputPin
* This
= (BaseInputPin
*)iface
;
411 IMediaEventSink
* pEventSink
;
412 NullRendererImpl
*pNull
;
416 TRACE("(%p/%p)->()\n", This
, iface
);
418 BaseInputPinImpl_EndOfStream(iface
);
419 pNull
= (NullRendererImpl
*)This
->pin
.pinInfo
.pFilter
;
420 graph
= pNull
->filter
.filterInfo
.pGraph
;
423 hr
= IFilterGraph_QueryInterface(pNull
->filter
.filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
426 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, (LONG_PTR
)pNull
);
427 IMediaEventSink_Release(pEventSink
);
430 RendererPosPassThru_EOS(pNull
->seekthru_unk
);
435 static HRESULT WINAPI
NullRenderer_InputPin_EndFlush(IPin
* iface
)
437 BaseInputPin
* This
= (BaseInputPin
*)iface
;
438 NullRendererImpl
*pNull
;
441 TRACE("(%p/%p)->()\n", This
, iface
);
443 hr
= BaseInputPinImpl_EndOfStream(iface
);
444 pNull
= (NullRendererImpl
*)This
->pin
.pinInfo
.pFilter
;
445 RendererPosPassThru_ResetMediaTime(pNull
->seekthru_unk
);
449 static const IPinVtbl NullRenderer_InputPin_Vtbl
=
451 BaseInputPinImpl_QueryInterface
,
453 BaseInputPinImpl_Release
,
454 BaseInputPinImpl_Connect
,
455 BaseInputPinImpl_ReceiveConnection
,
456 BasePinImpl_Disconnect
,
457 BasePinImpl_ConnectedTo
,
458 BasePinImpl_ConnectionMediaType
,
459 BasePinImpl_QueryPinInfo
,
460 BasePinImpl_QueryDirection
,
462 BaseInputPinImpl_QueryAccept
,
463 BasePinImpl_EnumMediaTypes
,
464 BasePinImpl_QueryInternalConnections
,
465 NullRenderer_InputPin_EndOfStream
,
466 BaseInputPinImpl_BeginFlush
,
467 NullRenderer_InputPin_EndFlush
,
468 BaseInputPinImpl_NewSegment
471 static NullRendererImpl
*from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
) {
472 return (NullRendererImpl
*)((char*)iface
- offsetof(NullRendererImpl
, IAMFilterMiscFlags_vtbl
));
475 static HRESULT WINAPI
AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
, void **ppv
) {
476 NullRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
477 return IUnknown_QueryInterface((IUnknown
*)This
, riid
, ppv
);
480 static ULONG WINAPI
AMFilterMiscFlags_AddRef(IAMFilterMiscFlags
*iface
) {
481 NullRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
482 return IUnknown_AddRef((IUnknown
*)This
);
485 static ULONG WINAPI
AMFilterMiscFlags_Release(IAMFilterMiscFlags
*iface
) {
486 NullRendererImpl
*This
= from_IAMFilterMiscFlags(iface
);
487 return IUnknown_Release((IUnknown
*)This
);
490 static ULONG WINAPI
AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags
*iface
) {
491 return AM_FILTER_MISC_FLAGS_IS_RENDERER
;
494 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl
= {
495 AMFilterMiscFlags_QueryInterface
,
496 AMFilterMiscFlags_AddRef
,
497 AMFilterMiscFlags_Release
,
498 AMFilterMiscFlags_GetMiscFlags