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};
47 static const IBaseFilterVtbl NullRenderer_Vtbl
;
48 static const IUnknownVtbl IInner_VTable
;
49 static const IPinVtbl NullRenderer_InputPin_Vtbl
;
51 typedef struct NullRendererImpl
53 const IBaseFilterVtbl
* lpVtbl
;
54 const IUnknownVtbl
* IInner_vtbl
;
57 CRITICAL_SECTION csFilter
;
59 REFERENCE_TIME rtStreamStart
;
60 IReferenceClock
* pClock
;
61 FILTER_INFO filterInfo
;
68 MediaSeekingImpl mediaSeeking
;
71 static const IMemInputPinVtbl MemInputPin_Vtbl
=
73 MemInputPin_QueryInterface
,
76 MemInputPin_GetAllocator
,
77 MemInputPin_NotifyAllocator
,
78 MemInputPin_GetAllocatorRequirements
,
80 MemInputPin_ReceiveMultiple
,
81 MemInputPin_ReceiveCanBlock
84 static HRESULT
NullRenderer_Sample(LPVOID iface
, IMediaSample
* pSample
)
86 LPBYTE pbSrcStream
= NULL
;
88 REFERENCE_TIME tStart
, tStop
;
91 TRACE("%p %p\n", iface
, pSample
);
93 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
96 ERR("Cannot get pointer to sample data (%x)\n", hr
);
100 hr
= IMediaSample_GetTime(pSample
, &tStart
, &tStop
);
102 ERR("Cannot get sample time (%x)\n", hr
);
104 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
106 TRACE("val %p %ld\n", pbSrcStream
, cbSrcStream
);
111 static HRESULT
NullRenderer_QueryAccept(LPVOID iface
, const AM_MEDIA_TYPE
* pmt
)
113 TRACE("Not a stub!\n");
117 static inline NullRendererImpl
*impl_from_IMediaSeeking( IMediaSeeking
*iface
)
119 return (NullRendererImpl
*)((char*)iface
- FIELD_OFFSET(NullRendererImpl
, mediaSeeking
.lpVtbl
));
122 static HRESULT WINAPI
NullRendererImpl_Seeking_QueryInterface(IMediaSeeking
* iface
, REFIID riid
, LPVOID
* ppv
)
124 NullRendererImpl
*This
= impl_from_IMediaSeeking(iface
);
126 return IUnknown_QueryInterface((IUnknown
*)This
, riid
, ppv
);
129 static ULONG WINAPI
NullRendererImpl_Seeking_AddRef(IMediaSeeking
* iface
)
131 NullRendererImpl
*This
= impl_from_IMediaSeeking(iface
);
133 return IUnknown_AddRef((IUnknown
*)This
);
136 static ULONG WINAPI
NullRendererImpl_Seeking_Release(IMediaSeeking
* iface
)
138 NullRendererImpl
*This
= impl_from_IMediaSeeking(iface
);
140 return IUnknown_Release((IUnknown
*)This
);
143 static const IMediaSeekingVtbl TransformFilter_Seeking_Vtbl
=
145 NullRendererImpl_Seeking_QueryInterface
,
146 NullRendererImpl_Seeking_AddRef
,
147 NullRendererImpl_Seeking_Release
,
148 MediaSeekingImpl_GetCapabilities
,
149 MediaSeekingImpl_CheckCapabilities
,
150 MediaSeekingImpl_IsFormatSupported
,
151 MediaSeekingImpl_QueryPreferredFormat
,
152 MediaSeekingImpl_GetTimeFormat
,
153 MediaSeekingImpl_IsUsingTimeFormat
,
154 MediaSeekingImpl_SetTimeFormat
,
155 MediaSeekingImpl_GetDuration
,
156 MediaSeekingImpl_GetStopPosition
,
157 MediaSeekingImpl_GetCurrentPosition
,
158 MediaSeekingImpl_ConvertTimeFormat
,
159 MediaSeekingImpl_SetPositions
,
160 MediaSeekingImpl_GetPositions
,
161 MediaSeekingImpl_GetAvailable
,
162 MediaSeekingImpl_SetRate
,
163 MediaSeekingImpl_GetRate
,
164 MediaSeekingImpl_GetPreroll
167 static HRESULT
NullRendererImpl_Change(IBaseFilter
*iface
)
169 TRACE("(%p)\n", iface
);
173 HRESULT
NullRenderer_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
177 NullRendererImpl
* pNullRenderer
;
179 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
183 pNullRenderer
= CoTaskMemAlloc(sizeof(NullRendererImpl
));
184 pNullRenderer
->pUnkOuter
= pUnkOuter
;
185 pNullRenderer
->bUnkOuterValid
= FALSE
;
186 pNullRenderer
->bAggregatable
= FALSE
;
187 pNullRenderer
->IInner_vtbl
= &IInner_VTable
;
189 pNullRenderer
->lpVtbl
= &NullRenderer_Vtbl
;
190 pNullRenderer
->refCount
= 1;
191 InitializeCriticalSection(&pNullRenderer
->csFilter
);
192 pNullRenderer
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": NullRendererImpl.csFilter");
193 pNullRenderer
->state
= State_Stopped
;
194 pNullRenderer
->pClock
= NULL
;
195 ZeroMemory(&pNullRenderer
->filterInfo
, sizeof(FILTER_INFO
));
197 pNullRenderer
->ppPins
= CoTaskMemAlloc(1 * sizeof(IPin
*));
199 /* construct input pin */
200 piInput
.dir
= PINDIR_INPUT
;
201 piInput
.pFilter
= (IBaseFilter
*)pNullRenderer
;
202 lstrcpynW(piInput
.achName
, wcsInputPinName
, sizeof(piInput
.achName
) / sizeof(piInput
.achName
[0]));
204 hr
= InputPin_Construct(&NullRenderer_InputPin_Vtbl
, &piInput
, NullRenderer_Sample
, (LPVOID
)pNullRenderer
, NullRenderer_QueryAccept
, NULL
, &pNullRenderer
->csFilter
, (IPin
**)&pNullRenderer
->pInputPin
);
208 pNullRenderer
->ppPins
[0] = (IPin
*)pNullRenderer
->pInputPin
;
209 MediaSeekingImpl_Init((IBaseFilter
*)pNullRenderer
, NullRendererImpl_Change
, NullRendererImpl_Change
, NullRendererImpl_Change
, &pNullRenderer
->mediaSeeking
, &pNullRenderer
->csFilter
);
210 pNullRenderer
->mediaSeeking
.lpVtbl
= &TransformFilter_Seeking_Vtbl
;
212 *ppv
= (LPVOID
)pNullRenderer
;
216 CoTaskMemFree(pNullRenderer
->ppPins
);
217 pNullRenderer
->csFilter
.DebugInfo
->Spare
[0] = 0;
218 DeleteCriticalSection(&pNullRenderer
->csFilter
);
219 CoTaskMemFree(pNullRenderer
);
225 static HRESULT WINAPI
NullRendererInner_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
227 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
228 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
230 if (This
->bAggregatable
)
231 This
->bUnkOuterValid
= TRUE
;
235 if (IsEqualIID(riid
, &IID_IUnknown
))
236 *ppv
= (LPVOID
)&(This
->IInner_vtbl
);
237 else if (IsEqualIID(riid
, &IID_IPersist
))
239 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
241 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
243 else if (IsEqualIID(riid
, &IID_IMediaSeeking
))
244 *ppv
= &This
->mediaSeeking
;
248 IUnknown_AddRef((IUnknown
*)(*ppv
));
252 if (!IsEqualIID(riid
, &IID_IPin
))
253 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
255 return E_NOINTERFACE
;
258 static ULONG WINAPI
NullRendererInner_AddRef(IUnknown
* iface
)
260 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
261 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
263 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, refCount
- 1);
268 static ULONG WINAPI
NullRendererInner_Release(IUnknown
* iface
)
270 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
271 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
273 TRACE("(%p/%p)->() Release from %d\n", This
, iface
, refCount
+ 1);
280 IReferenceClock_Release(This
->pClock
);
282 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[0], &pConnectedTo
)))
284 IPin_Disconnect(pConnectedTo
);
285 IPin_Release(pConnectedTo
);
287 IPin_Disconnect(This
->ppPins
[0]);
288 IPin_Release(This
->ppPins
[0]);
290 CoTaskMemFree(This
->ppPins
);
293 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
294 DeleteCriticalSection(&This
->csFilter
);
296 TRACE("Destroying Null Renderer\n");
304 static const IUnknownVtbl IInner_VTable
=
306 NullRendererInner_QueryInterface
,
307 NullRendererInner_AddRef
,
308 NullRendererInner_Release
311 static HRESULT WINAPI
NullRenderer_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
313 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
315 if (This
->bAggregatable
)
316 This
->bUnkOuterValid
= TRUE
;
320 if (This
->bAggregatable
)
321 return IUnknown_QueryInterface(This
->pUnkOuter
, riid
, ppv
);
323 if (IsEqualIID(riid
, &IID_IUnknown
))
327 IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
328 hr
= IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
329 IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
330 This
->bAggregatable
= TRUE
;
335 return E_NOINTERFACE
;
338 return IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
341 static ULONG WINAPI
NullRenderer_AddRef(IBaseFilter
* iface
)
343 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
345 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
346 return IUnknown_AddRef(This
->pUnkOuter
);
347 return IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
350 static ULONG WINAPI
NullRenderer_Release(IBaseFilter
* iface
)
352 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
354 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
355 return IUnknown_Release(This
->pUnkOuter
);
356 return IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
359 /** IPersist methods **/
361 static HRESULT WINAPI
NullRenderer_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
363 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
365 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClsid
);
367 *pClsid
= CLSID_NullRenderer
;
372 /** IMediaFilter methods **/
374 static HRESULT WINAPI
NullRenderer_Stop(IBaseFilter
* iface
)
376 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
378 TRACE("(%p/%p)->()\n", This
, iface
);
380 EnterCriticalSection(&This
->csFilter
);
382 This
->state
= State_Stopped
;
384 LeaveCriticalSection(&This
->csFilter
);
389 static HRESULT WINAPI
NullRenderer_Pause(IBaseFilter
* iface
)
391 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
393 TRACE("(%p/%p)->()\n", This
, iface
);
395 EnterCriticalSection(&This
->csFilter
);
397 This
->state
= State_Paused
;
399 LeaveCriticalSection(&This
->csFilter
);
404 static HRESULT WINAPI
NullRenderer_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
406 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
408 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
410 EnterCriticalSection(&This
->csFilter
);
412 This
->rtStreamStart
= tStart
;
413 This
->state
= State_Running
;
415 LeaveCriticalSection(&This
->csFilter
);
420 static HRESULT WINAPI
NullRenderer_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
422 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
424 TRACE("(%p/%p)->(%d, %p)\n", This
, iface
, dwMilliSecsTimeout
, pState
);
426 EnterCriticalSection(&This
->csFilter
);
428 *pState
= This
->state
;
430 LeaveCriticalSection(&This
->csFilter
);
435 static HRESULT WINAPI
NullRenderer_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
437 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
439 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClock
);
441 EnterCriticalSection(&This
->csFilter
);
444 IReferenceClock_Release(This
->pClock
);
445 This
->pClock
= pClock
;
447 IReferenceClock_AddRef(This
->pClock
);
449 LeaveCriticalSection(&This
->csFilter
);
454 static HRESULT WINAPI
NullRenderer_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
456 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
458 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppClock
);
460 EnterCriticalSection(&This
->csFilter
);
462 *ppClock
= This
->pClock
;
463 IReferenceClock_AddRef(This
->pClock
);
465 LeaveCriticalSection(&This
->csFilter
);
470 /** IBaseFilter implementation **/
472 static HRESULT WINAPI
NullRenderer_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
475 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
477 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppEnum
);
479 epd
.cPins
= 1; /* input pin */
480 epd
.ppPins
= This
->ppPins
;
481 return IEnumPinsImpl_Construct(&epd
, ppEnum
);
484 static HRESULT WINAPI
NullRenderer_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
486 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
488 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
490 FIXME("NullRenderer::FindPin(...)\n");
492 /* FIXME: critical section */
497 static HRESULT WINAPI
NullRenderer_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
499 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
501 TRACE("(%p/%p)->(%p)\n", This
, iface
, pInfo
);
503 strcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
504 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
507 IFilterGraph_AddRef(pInfo
->pGraph
);
512 static HRESULT WINAPI
NullRenderer_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
514 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
516 TRACE("(%p/%p)->(%p, %s)\n", This
, iface
, pGraph
, debugstr_w(pName
));
518 EnterCriticalSection(&This
->csFilter
);
521 strcpyW(This
->filterInfo
.achName
, pName
);
523 *This
->filterInfo
.achName
= '\0';
524 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
526 LeaveCriticalSection(&This
->csFilter
);
531 static HRESULT WINAPI
NullRenderer_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
533 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
534 TRACE("(%p/%p)->(%p)\n", This
, iface
, pVendorInfo
);
538 static const IBaseFilterVtbl NullRenderer_Vtbl
=
540 NullRenderer_QueryInterface
,
542 NullRenderer_Release
,
543 NullRenderer_GetClassID
,
547 NullRenderer_GetState
,
548 NullRenderer_SetSyncSource
,
549 NullRenderer_GetSyncSource
,
550 NullRenderer_EnumPins
,
551 NullRenderer_FindPin
,
552 NullRenderer_QueryFilterInfo
,
553 NullRenderer_JoinFilterGraph
,
554 NullRenderer_QueryVendorInfo
557 static HRESULT WINAPI
NullRenderer_InputPin_EndOfStream(IPin
* iface
)
559 InputPin
* This
= (InputPin
*)iface
;
560 IMediaEventSink
* pEventSink
;
563 TRACE("(%p/%p)->()\n", This
, iface
);
565 InputPin_EndOfStream(iface
);
566 hr
= IFilterGraph_QueryInterface(((NullRendererImpl
*)This
->pin
.pinInfo
.pFilter
)->filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
569 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, 0);
570 IMediaEventSink_Release(pEventSink
);
576 static const IPinVtbl NullRenderer_InputPin_Vtbl
=
578 InputPin_QueryInterface
,
582 InputPin_ReceiveConnection
,
584 IPinImpl_ConnectedTo
,
585 IPinImpl_ConnectionMediaType
,
586 IPinImpl_QueryPinInfo
,
587 IPinImpl_QueryDirection
,
589 IPinImpl_QueryAccept
,
590 IPinImpl_EnumMediaTypes
,
591 IPinImpl_QueryInternalConnections
,
592 NullRenderer_InputPin_EndOfStream
,