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
;
70 static const IMemInputPinVtbl MemInputPin_Vtbl
=
72 MemInputPin_QueryInterface
,
75 MemInputPin_GetAllocator
,
76 MemInputPin_NotifyAllocator
,
77 MemInputPin_GetAllocatorRequirements
,
79 MemInputPin_ReceiveMultiple
,
80 MemInputPin_ReceiveCanBlock
83 static HRESULT
NullRenderer_InputPin_Construct(const PIN_INFO
* pPinInfo
, SAMPLEPROC pSampleProc
, LPVOID pUserData
, QUERYACCEPTPROC pQueryAccept
, LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
89 if (pPinInfo
->dir
!= PINDIR_INPUT
)
91 ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo
->dir
);
95 pPinImpl
= CoTaskMemAlloc(sizeof(*pPinImpl
));
100 if (SUCCEEDED(InputPin_Init(pPinInfo
, pSampleProc
, pUserData
, pQueryAccept
, pCritSec
, pPinImpl
)))
102 pPinImpl
->pin
.lpVtbl
= &NullRenderer_InputPin_Vtbl
;
103 pPinImpl
->lpVtblMemInput
= &MemInputPin_Vtbl
;
105 *ppPin
= (IPin
*)(&pPinImpl
->pin
.lpVtbl
);
109 CoTaskMemFree(pPinImpl
);
115 static HRESULT
NullRenderer_Sample(LPVOID iface
, IMediaSample
* pSample
)
117 LPBYTE pbSrcStream
= NULL
;
118 long cbSrcStream
= 0;
119 REFERENCE_TIME tStart
, tStop
;
122 TRACE("%p %p\n", iface
, pSample
);
124 hr
= IMediaSample_GetPointer(pSample
, &pbSrcStream
);
127 ERR("Cannot get pointer to sample data (%x)\n", hr
);
131 hr
= IMediaSample_GetTime(pSample
, &tStart
, &tStop
);
133 ERR("Cannot get sample time (%x)\n", hr
);
135 cbSrcStream
= IMediaSample_GetActualDataLength(pSample
);
137 TRACE("val %p %ld\n", pbSrcStream
, cbSrcStream
);
142 static HRESULT
NullRenderer_QueryAccept(LPVOID iface
, const AM_MEDIA_TYPE
* pmt
)
144 TRACE("Not a stub!\n");
148 HRESULT
NullRenderer_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
)
152 NullRendererImpl
* pNullRenderer
;
154 TRACE("(%p, %p)\n", pUnkOuter
, ppv
);
158 pNullRenderer
= CoTaskMemAlloc(sizeof(NullRendererImpl
));
159 pNullRenderer
->pUnkOuter
= pUnkOuter
;
160 pNullRenderer
->bUnkOuterValid
= FALSE
;
161 pNullRenderer
->bAggregatable
= FALSE
;
162 pNullRenderer
->IInner_vtbl
= &IInner_VTable
;
164 pNullRenderer
->lpVtbl
= &NullRenderer_Vtbl
;
165 pNullRenderer
->refCount
= 1;
166 InitializeCriticalSection(&pNullRenderer
->csFilter
);
167 pNullRenderer
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": NullRendererImpl.csFilter");
168 pNullRenderer
->state
= State_Stopped
;
169 pNullRenderer
->pClock
= NULL
;
170 ZeroMemory(&pNullRenderer
->filterInfo
, sizeof(FILTER_INFO
));
172 pNullRenderer
->ppPins
= CoTaskMemAlloc(1 * sizeof(IPin
*));
174 /* construct input pin */
175 piInput
.dir
= PINDIR_INPUT
;
176 piInput
.pFilter
= (IBaseFilter
*)pNullRenderer
;
177 lstrcpynW(piInput
.achName
, wcsInputPinName
, sizeof(piInput
.achName
) / sizeof(piInput
.achName
[0]));
179 hr
= NullRenderer_InputPin_Construct(&piInput
, NullRenderer_Sample
, (LPVOID
)pNullRenderer
, NullRenderer_QueryAccept
, &pNullRenderer
->csFilter
, (IPin
**)&pNullRenderer
->pInputPin
);
183 pNullRenderer
->ppPins
[0] = (IPin
*)pNullRenderer
->pInputPin
;
184 *ppv
= (LPVOID
)pNullRenderer
;
188 CoTaskMemFree(pNullRenderer
->ppPins
);
189 pNullRenderer
->csFilter
.DebugInfo
->Spare
[0] = 0;
190 DeleteCriticalSection(&pNullRenderer
->csFilter
);
191 CoTaskMemFree(pNullRenderer
);
197 static HRESULT WINAPI
NullRendererInner_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
199 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
200 TRACE("(%p/%p)->(%s, %p)\n", This
, iface
, qzdebugstr_guid(riid
), ppv
);
202 if (This
->bAggregatable
)
203 This
->bUnkOuterValid
= TRUE
;
207 if (IsEqualIID(riid
, &IID_IUnknown
))
208 *ppv
= (LPVOID
)&(This
->IInner_vtbl
);
209 else if (IsEqualIID(riid
, &IID_IPersist
))
211 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
213 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
218 IUnknown_AddRef((IUnknown
*)(*ppv
));
222 if (!IsEqualIID(riid
, &IID_IPin
))
223 FIXME("No interface for %s!\n", qzdebugstr_guid(riid
));
225 return E_NOINTERFACE
;
228 static ULONG WINAPI
NullRendererInner_AddRef(IUnknown
* iface
)
230 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
231 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
233 TRACE("(%p/%p)->() AddRef from %d\n", This
, iface
, refCount
- 1);
238 static ULONG WINAPI
NullRendererInner_Release(IUnknown
* iface
)
240 ICOM_THIS_MULTI(NullRendererImpl
, IInner_vtbl
, iface
);
241 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
243 TRACE("(%p/%p)->() Release from %d\n", This
, iface
, refCount
+ 1);
250 IReferenceClock_Release(This
->pClock
);
252 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[0], &pConnectedTo
)))
254 IPin_Disconnect(pConnectedTo
);
255 IPin_Release(pConnectedTo
);
257 IPin_Disconnect(This
->ppPins
[0]);
258 IPin_Release(This
->ppPins
[0]);
260 CoTaskMemFree(This
->ppPins
);
263 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
264 DeleteCriticalSection(&This
->csFilter
);
266 TRACE("Destroying Null Renderer\n");
274 static const IUnknownVtbl IInner_VTable
=
276 NullRendererInner_QueryInterface
,
277 NullRendererInner_AddRef
,
278 NullRendererInner_Release
281 static HRESULT WINAPI
NullRenderer_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
283 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
285 if (This
->bAggregatable
)
286 This
->bUnkOuterValid
= TRUE
;
290 if (This
->bAggregatable
)
291 return IUnknown_QueryInterface(This
->pUnkOuter
, riid
, ppv
);
293 if (IsEqualIID(riid
, &IID_IUnknown
))
297 IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
298 hr
= IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
299 IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
300 This
->bAggregatable
= TRUE
;
305 return E_NOINTERFACE
;
308 return IUnknown_QueryInterface((IUnknown
*)&(This
->IInner_vtbl
), riid
, ppv
);
311 static ULONG WINAPI
NullRenderer_AddRef(IBaseFilter
* iface
)
313 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
315 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
316 return IUnknown_AddRef(This
->pUnkOuter
);
317 return IUnknown_AddRef((IUnknown
*)&(This
->IInner_vtbl
));
320 static ULONG WINAPI
NullRenderer_Release(IBaseFilter
* iface
)
322 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
324 if (This
->pUnkOuter
&& This
->bUnkOuterValid
)
325 return IUnknown_Release(This
->pUnkOuter
);
326 return IUnknown_Release((IUnknown
*)&(This
->IInner_vtbl
));
329 /** IPersist methods **/
331 static HRESULT WINAPI
NullRenderer_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
333 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
335 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClsid
);
337 *pClsid
= CLSID_NullRenderer
;
342 /** IMediaFilter methods **/
344 static HRESULT WINAPI
NullRenderer_Stop(IBaseFilter
* iface
)
346 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
348 TRACE("(%p/%p)->()\n", This
, iface
);
350 EnterCriticalSection(&This
->csFilter
);
352 This
->state
= State_Stopped
;
354 LeaveCriticalSection(&This
->csFilter
);
359 static HRESULT WINAPI
NullRenderer_Pause(IBaseFilter
* iface
)
361 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
363 TRACE("(%p/%p)->()\n", This
, iface
);
365 EnterCriticalSection(&This
->csFilter
);
367 This
->state
= State_Paused
;
369 LeaveCriticalSection(&This
->csFilter
);
374 static HRESULT WINAPI
NullRenderer_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
376 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
378 TRACE("(%p/%p)->(%s)\n", This
, iface
, wine_dbgstr_longlong(tStart
));
380 EnterCriticalSection(&This
->csFilter
);
382 This
->rtStreamStart
= tStart
;
383 This
->state
= State_Running
;
385 LeaveCriticalSection(&This
->csFilter
);
390 static HRESULT WINAPI
NullRenderer_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
392 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
394 TRACE("(%p/%p)->(%d, %p)\n", This
, iface
, dwMilliSecsTimeout
, pState
);
396 EnterCriticalSection(&This
->csFilter
);
398 *pState
= This
->state
;
400 LeaveCriticalSection(&This
->csFilter
);
405 static HRESULT WINAPI
NullRenderer_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
407 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
409 TRACE("(%p/%p)->(%p)\n", This
, iface
, pClock
);
411 EnterCriticalSection(&This
->csFilter
);
414 IReferenceClock_Release(This
->pClock
);
415 This
->pClock
= pClock
;
417 IReferenceClock_AddRef(This
->pClock
);
419 LeaveCriticalSection(&This
->csFilter
);
424 static HRESULT WINAPI
NullRenderer_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
426 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
428 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppClock
);
430 EnterCriticalSection(&This
->csFilter
);
432 *ppClock
= This
->pClock
;
433 IReferenceClock_AddRef(This
->pClock
);
435 LeaveCriticalSection(&This
->csFilter
);
440 /** IBaseFilter implementation **/
442 static HRESULT WINAPI
NullRenderer_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
445 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
447 TRACE("(%p/%p)->(%p)\n", This
, iface
, ppEnum
);
449 epd
.cPins
= 1; /* input pin */
450 epd
.ppPins
= This
->ppPins
;
451 return IEnumPinsImpl_Construct(&epd
, ppEnum
);
454 static HRESULT WINAPI
NullRenderer_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
456 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
458 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, debugstr_w(Id
), ppPin
);
460 FIXME("NullRenderer::FindPin(...)\n");
462 /* FIXME: critical section */
467 static HRESULT WINAPI
NullRenderer_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
469 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
471 TRACE("(%p/%p)->(%p)\n", This
, iface
, pInfo
);
473 strcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
474 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
477 IFilterGraph_AddRef(pInfo
->pGraph
);
482 static HRESULT WINAPI
NullRenderer_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
484 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
486 TRACE("(%p/%p)->(%p, %s)\n", This
, iface
, pGraph
, debugstr_w(pName
));
488 EnterCriticalSection(&This
->csFilter
);
491 strcpyW(This
->filterInfo
.achName
, pName
);
493 *This
->filterInfo
.achName
= '\0';
494 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
496 LeaveCriticalSection(&This
->csFilter
);
501 static HRESULT WINAPI
NullRenderer_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
503 NullRendererImpl
*This
= (NullRendererImpl
*)iface
;
504 TRACE("(%p/%p)->(%p)\n", This
, iface
, pVendorInfo
);
508 static const IBaseFilterVtbl NullRenderer_Vtbl
=
510 NullRenderer_QueryInterface
,
512 NullRenderer_Release
,
513 NullRenderer_GetClassID
,
517 NullRenderer_GetState
,
518 NullRenderer_SetSyncSource
,
519 NullRenderer_GetSyncSource
,
520 NullRenderer_EnumPins
,
521 NullRenderer_FindPin
,
522 NullRenderer_QueryFilterInfo
,
523 NullRenderer_JoinFilterGraph
,
524 NullRenderer_QueryVendorInfo
527 static HRESULT WINAPI
NullRenderer_InputPin_EndOfStream(IPin
* iface
)
529 InputPin
* This
= (InputPin
*)iface
;
530 IMediaEventSink
* pEventSink
;
533 TRACE("(%p/%p)->()\n", This
, iface
);
535 hr
= IFilterGraph_QueryInterface(((NullRendererImpl
*)This
->pin
.pinInfo
.pFilter
)->filterInfo
.pGraph
, &IID_IMediaEventSink
, (LPVOID
*)&pEventSink
);
538 hr
= IMediaEventSink_Notify(pEventSink
, EC_COMPLETE
, S_OK
, 0);
539 IMediaEventSink_Release(pEventSink
);
545 static const IPinVtbl NullRenderer_InputPin_Vtbl
=
547 InputPin_QueryInterface
,
551 InputPin_ReceiveConnection
,
553 IPinImpl_ConnectedTo
,
554 IPinImpl_ConnectionMediaType
,
555 IPinImpl_QueryPinInfo
,
556 IPinImpl_QueryDirection
,
558 IPinImpl_QueryAccept
,
559 IPinImpl_EnumMediaTypes
,
560 IPinImpl_QueryInternalConnections
,
561 NullRenderer_InputPin_EndOfStream
,