Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennullrenderer.c
Go to the documentation of this file.
00001 /* 00002 * Null Renderer (Promiscuous, not rendering anything at all!) 00003 * 00004 * Copyright 2004 Christian Costa 00005 * Copyright 2008 Maarten Lankhorst 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "config.h" 00023 00024 #define NONAMELESSSTRUCT 00025 #define NONAMELESSUNION 00026 #include "quartz_private.h" 00027 #include "control_private.h" 00028 #include "pin.h" 00029 00030 #include "uuids.h" 00031 #include "vfwmsgs.h" 00032 #include "amvideo.h" 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "dshow.h" 00036 #include "evcode.h" 00037 #include "strmif.h" 00038 #include "ddraw.h" 00039 00040 #include "wine/unicode.h" 00041 #include "wine/debug.h" 00042 00043 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 00044 00045 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; 00046 static const WCHAR wcsAltInputPinName[] = {'I','n',0}; 00047 00048 static const IBaseFilterVtbl NullRenderer_Vtbl; 00049 static const IUnknownVtbl IInner_VTable; 00050 static const IPinVtbl NullRenderer_InputPin_Vtbl; 00051 00052 typedef struct NullRendererImpl 00053 { 00054 const IBaseFilterVtbl * lpVtbl; 00055 const IUnknownVtbl * IInner_vtbl; 00056 00057 LONG refCount; 00058 CRITICAL_SECTION csFilter; 00059 FILTER_STATE state; 00060 REFERENCE_TIME rtStreamStart; 00061 IReferenceClock * pClock; 00062 FILTER_INFO filterInfo; 00063 00064 InputPin *pInputPin; 00065 IUnknown * pUnkOuter; 00066 BOOL bUnkOuterValid; 00067 BOOL bAggregatable; 00068 MediaSeekingImpl mediaSeeking; 00069 } NullRendererImpl; 00070 00071 static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample) 00072 { 00073 NullRendererImpl *This = iface; 00074 HRESULT hr = S_OK; 00075 00076 TRACE("%p %p\n", iface, pSample); 00077 00078 EnterCriticalSection(&This->csFilter); 00079 if (This->pInputPin->flushing || This->pInputPin->end_of_stream) 00080 hr = S_FALSE; 00081 LeaveCriticalSection(&This->csFilter); 00082 00083 return hr; 00084 } 00085 00086 static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) 00087 { 00088 TRACE("Not a stub!\n"); 00089 return S_OK; 00090 } 00091 00092 static inline NullRendererImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) 00093 { 00094 return (NullRendererImpl *)((char*)iface - FIELD_OFFSET(NullRendererImpl, mediaSeeking.lpVtbl)); 00095 } 00096 00097 static HRESULT WINAPI NullRendererImpl_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) 00098 { 00099 NullRendererImpl *This = impl_from_IMediaSeeking(iface); 00100 00101 return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); 00102 } 00103 00104 static ULONG WINAPI NullRendererImpl_Seeking_AddRef(IMediaSeeking * iface) 00105 { 00106 NullRendererImpl *This = impl_from_IMediaSeeking(iface); 00107 00108 return IUnknown_AddRef((IUnknown *)This); 00109 } 00110 00111 static ULONG WINAPI NullRendererImpl_Seeking_Release(IMediaSeeking * iface) 00112 { 00113 NullRendererImpl *This = impl_from_IMediaSeeking(iface); 00114 00115 return IUnknown_Release((IUnknown *)This); 00116 } 00117 00118 static const IMediaSeekingVtbl TransformFilter_Seeking_Vtbl = 00119 { 00120 NullRendererImpl_Seeking_QueryInterface, 00121 NullRendererImpl_Seeking_AddRef, 00122 NullRendererImpl_Seeking_Release, 00123 MediaSeekingImpl_GetCapabilities, 00124 MediaSeekingImpl_CheckCapabilities, 00125 MediaSeekingImpl_IsFormatSupported, 00126 MediaSeekingImpl_QueryPreferredFormat, 00127 MediaSeekingImpl_GetTimeFormat, 00128 MediaSeekingImpl_IsUsingTimeFormat, 00129 MediaSeekingImpl_SetTimeFormat, 00130 MediaSeekingImpl_GetDuration, 00131 MediaSeekingImpl_GetStopPosition, 00132 MediaSeekingImpl_GetCurrentPosition, 00133 MediaSeekingImpl_ConvertTimeFormat, 00134 MediaSeekingImpl_SetPositions, 00135 MediaSeekingImpl_GetPositions, 00136 MediaSeekingImpl_GetAvailable, 00137 MediaSeekingImpl_SetRate, 00138 MediaSeekingImpl_GetRate, 00139 MediaSeekingImpl_GetPreroll 00140 }; 00141 00142 static HRESULT NullRendererImpl_Change(IBaseFilter *iface) 00143 { 00144 TRACE("(%p)\n", iface); 00145 return S_OK; 00146 } 00147 00148 HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) 00149 { 00150 HRESULT hr; 00151 PIN_INFO piInput; 00152 NullRendererImpl * pNullRenderer; 00153 00154 TRACE("(%p, %p)\n", pUnkOuter, ppv); 00155 00156 *ppv = NULL; 00157 00158 pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl)); 00159 pNullRenderer->pUnkOuter = pUnkOuter; 00160 pNullRenderer->bUnkOuterValid = FALSE; 00161 pNullRenderer->bAggregatable = FALSE; 00162 pNullRenderer->IInner_vtbl = &IInner_VTable; 00163 00164 pNullRenderer->lpVtbl = &NullRenderer_Vtbl; 00165 pNullRenderer->refCount = 1; 00166 InitializeCriticalSection(&pNullRenderer->csFilter); 00167 pNullRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"); 00168 pNullRenderer->state = State_Stopped; 00169 pNullRenderer->pClock = NULL; 00170 ZeroMemory(&pNullRenderer->filterInfo, sizeof(FILTER_INFO)); 00171 00172 /* construct input pin */ 00173 piInput.dir = PINDIR_INPUT; 00174 piInput.pFilter = (IBaseFilter *)pNullRenderer; 00175 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); 00176 00177 hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin); 00178 00179 if (SUCCEEDED(hr)) 00180 { 00181 MediaSeekingImpl_Init((IBaseFilter*)pNullRenderer, NullRendererImpl_Change, NullRendererImpl_Change, NullRendererImpl_Change, &pNullRenderer->mediaSeeking, &pNullRenderer->csFilter); 00182 pNullRenderer->mediaSeeking.lpVtbl = &TransformFilter_Seeking_Vtbl; 00183 00184 *ppv = pNullRenderer; 00185 } 00186 else 00187 { 00188 pNullRenderer->csFilter.DebugInfo->Spare[0] = 0; 00189 DeleteCriticalSection(&pNullRenderer->csFilter); 00190 CoTaskMemFree(pNullRenderer); 00191 } 00192 00193 return hr; 00194 } 00195 00196 static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) 00197 { 00198 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); 00199 TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); 00200 00201 if (This->bAggregatable) 00202 This->bUnkOuterValid = TRUE; 00203 00204 *ppv = NULL; 00205 00206 if (IsEqualIID(riid, &IID_IUnknown)) 00207 *ppv = &This->IInner_vtbl; 00208 else if (IsEqualIID(riid, &IID_IPersist)) 00209 *ppv = This; 00210 else if (IsEqualIID(riid, &IID_IMediaFilter)) 00211 *ppv = This; 00212 else if (IsEqualIID(riid, &IID_IBaseFilter)) 00213 *ppv = This; 00214 else if (IsEqualIID(riid, &IID_IMediaSeeking)) 00215 *ppv = &This->mediaSeeking; 00216 00217 if (*ppv) 00218 { 00219 IUnknown_AddRef((IUnknown *)(*ppv)); 00220 return S_OK; 00221 } 00222 00223 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow)) 00224 FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); 00225 00226 return E_NOINTERFACE; 00227 } 00228 00229 static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface) 00230 { 00231 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); 00232 ULONG refCount = InterlockedIncrement(&This->refCount); 00233 00234 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); 00235 00236 return refCount; 00237 } 00238 00239 static ULONG WINAPI NullRendererInner_Release(IUnknown * iface) 00240 { 00241 ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); 00242 ULONG refCount = InterlockedDecrement(&This->refCount); 00243 00244 TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); 00245 00246 if (!refCount) 00247 { 00248 IPin *pConnectedTo; 00249 00250 if (This->pClock) 00251 IReferenceClock_Release(This->pClock); 00252 00253 if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo))) 00254 { 00255 IPin_Disconnect(pConnectedTo); 00256 IPin_Release(pConnectedTo); 00257 } 00258 IPin_Disconnect((IPin *)This->pInputPin); 00259 IPin_Release((IPin *)This->pInputPin); 00260 00261 This->lpVtbl = NULL; 00262 00263 This->csFilter.DebugInfo->Spare[0] = 0; 00264 DeleteCriticalSection(&This->csFilter); 00265 00266 TRACE("Destroying Null Renderer\n"); 00267 CoTaskMemFree(This); 00268 return 0; 00269 } 00270 else 00271 return refCount; 00272 } 00273 00274 static const IUnknownVtbl IInner_VTable = 00275 { 00276 NullRendererInner_QueryInterface, 00277 NullRendererInner_AddRef, 00278 NullRendererInner_Release 00279 }; 00280 00281 static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) 00282 { 00283 NullRendererImpl *This = (NullRendererImpl *)iface; 00284 00285 if (This->bAggregatable) 00286 This->bUnkOuterValid = TRUE; 00287 00288 if (This->pUnkOuter) 00289 { 00290 if (This->bAggregatable) 00291 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); 00292 00293 if (IsEqualIID(riid, &IID_IUnknown)) 00294 { 00295 HRESULT hr; 00296 00297 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); 00298 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); 00299 IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); 00300 This->bAggregatable = TRUE; 00301 return hr; 00302 } 00303 00304 *ppv = NULL; 00305 return E_NOINTERFACE; 00306 } 00307 00308 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); 00309 } 00310 00311 static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface) 00312 { 00313 NullRendererImpl *This = (NullRendererImpl *)iface; 00314 00315 if (This->pUnkOuter && This->bUnkOuterValid) 00316 return IUnknown_AddRef(This->pUnkOuter); 00317 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); 00318 } 00319 00320 static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface) 00321 { 00322 NullRendererImpl *This = (NullRendererImpl *)iface; 00323 00324 if (This->pUnkOuter && This->bUnkOuterValid) 00325 return IUnknown_Release(This->pUnkOuter); 00326 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); 00327 } 00328 00331 static HRESULT WINAPI NullRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid) 00332 { 00333 NullRendererImpl *This = (NullRendererImpl *)iface; 00334 00335 TRACE("(%p/%p)->(%p)\n", This, iface, pClsid); 00336 00337 *pClsid = CLSID_NullRenderer; 00338 00339 return S_OK; 00340 } 00341 00344 static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface) 00345 { 00346 NullRendererImpl *This = (NullRendererImpl *)iface; 00347 00348 TRACE("(%p/%p)->()\n", This, iface); 00349 00350 EnterCriticalSection(&This->csFilter); 00351 { 00352 This->state = State_Stopped; 00353 } 00354 LeaveCriticalSection(&This->csFilter); 00355 00356 return S_OK; 00357 } 00358 00359 static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface) 00360 { 00361 NullRendererImpl *This = (NullRendererImpl *)iface; 00362 00363 TRACE("(%p/%p)->()\n", This, iface); 00364 00365 EnterCriticalSection(&This->csFilter); 00366 { 00367 if (This->state == State_Stopped) 00368 This->pInputPin->end_of_stream = 0; 00369 This->state = State_Paused; 00370 } 00371 LeaveCriticalSection(&This->csFilter); 00372 00373 return S_OK; 00374 } 00375 00376 static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart) 00377 { 00378 NullRendererImpl *This = (NullRendererImpl *)iface; 00379 00380 TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); 00381 00382 EnterCriticalSection(&This->csFilter); 00383 { 00384 This->rtStreamStart = tStart; 00385 This->state = State_Running; 00386 This->pInputPin->end_of_stream = 0; 00387 } 00388 LeaveCriticalSection(&This->csFilter); 00389 00390 return S_OK; 00391 } 00392 00393 static HRESULT WINAPI NullRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) 00394 { 00395 NullRendererImpl *This = (NullRendererImpl *)iface; 00396 00397 TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); 00398 00399 EnterCriticalSection(&This->csFilter); 00400 { 00401 *pState = This->state; 00402 } 00403 LeaveCriticalSection(&This->csFilter); 00404 00405 return S_OK; 00406 } 00407 00408 static HRESULT WINAPI NullRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) 00409 { 00410 NullRendererImpl *This = (NullRendererImpl *)iface; 00411 00412 TRACE("(%p/%p)->(%p)\n", This, iface, pClock); 00413 00414 EnterCriticalSection(&This->csFilter); 00415 { 00416 if (This->pClock) 00417 IReferenceClock_Release(This->pClock); 00418 This->pClock = pClock; 00419 if (This->pClock) 00420 IReferenceClock_AddRef(This->pClock); 00421 } 00422 LeaveCriticalSection(&This->csFilter); 00423 00424 return S_OK; 00425 } 00426 00427 static HRESULT WINAPI NullRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) 00428 { 00429 NullRendererImpl *This = (NullRendererImpl *)iface; 00430 00431 TRACE("(%p/%p)->(%p)\n", This, iface, ppClock); 00432 00433 EnterCriticalSection(&This->csFilter); 00434 { 00435 *ppClock = This->pClock; 00436 if (This->pClock) 00437 IReferenceClock_AddRef(This->pClock); 00438 } 00439 LeaveCriticalSection(&This->csFilter); 00440 00441 return S_OK; 00442 } 00443 00446 static HRESULT NullRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) 00447 { 00448 NullRendererImpl *This = (NullRendererImpl *)iface; 00449 00450 /* Our pins are static, not changing so setting static tick count is ok */ 00451 *lastsynctick = 0; 00452 00453 if (pos >= 1) 00454 return S_FALSE; 00455 00456 *pin = (IPin *)This->pInputPin; 00457 IPin_AddRef(*pin); 00458 return S_OK; 00459 } 00460 00461 static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) 00462 { 00463 NullRendererImpl *This = (NullRendererImpl *)iface; 00464 00465 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); 00466 00467 return IEnumPinsImpl_Construct(ppEnum, NullRenderer_GetPin, iface); 00468 } 00469 00470 static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) 00471 { 00472 NullRendererImpl *This = (NullRendererImpl *)iface; 00473 00474 TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin); 00475 00476 if (!Id || !ppPin) 00477 return E_POINTER; 00478 00479 if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName)) 00480 { 00481 *ppPin = (IPin *)This->pInputPin; 00482 IPin_AddRef(*ppPin); 00483 return S_OK; 00484 } 00485 *ppPin = NULL; 00486 return VFW_E_NOT_FOUND; 00487 } 00488 00489 static HRESULT WINAPI NullRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) 00490 { 00491 NullRendererImpl *This = (NullRendererImpl *)iface; 00492 00493 TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); 00494 00495 strcpyW(pInfo->achName, This->filterInfo.achName); 00496 pInfo->pGraph = This->filterInfo.pGraph; 00497 00498 if (pInfo->pGraph) 00499 IFilterGraph_AddRef(pInfo->pGraph); 00500 00501 return S_OK; 00502 } 00503 00504 static HRESULT WINAPI NullRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) 00505 { 00506 NullRendererImpl *This = (NullRendererImpl *)iface; 00507 00508 TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); 00509 00510 EnterCriticalSection(&This->csFilter); 00511 { 00512 if (pName) 00513 strcpyW(This->filterInfo.achName, pName); 00514 else 00515 *This->filterInfo.achName = '\0'; 00516 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ 00517 } 00518 LeaveCriticalSection(&This->csFilter); 00519 00520 return S_OK; 00521 } 00522 00523 static HRESULT WINAPI NullRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) 00524 { 00525 NullRendererImpl *This = (NullRendererImpl *)iface; 00526 TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo); 00527 return E_NOTIMPL; 00528 } 00529 00530 static const IBaseFilterVtbl NullRenderer_Vtbl = 00531 { 00532 NullRenderer_QueryInterface, 00533 NullRenderer_AddRef, 00534 NullRenderer_Release, 00535 NullRenderer_GetClassID, 00536 NullRenderer_Stop, 00537 NullRenderer_Pause, 00538 NullRenderer_Run, 00539 NullRenderer_GetState, 00540 NullRenderer_SetSyncSource, 00541 NullRenderer_GetSyncSource, 00542 NullRenderer_EnumPins, 00543 NullRenderer_FindPin, 00544 NullRenderer_QueryFilterInfo, 00545 NullRenderer_JoinFilterGraph, 00546 NullRenderer_QueryVendorInfo 00547 }; 00548 00549 static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) 00550 { 00551 InputPin* This = (InputPin*)iface; 00552 IMediaEventSink* pEventSink; 00553 IFilterGraph *graph; 00554 HRESULT hr = S_OK; 00555 00556 TRACE("(%p/%p)->()\n", This, iface); 00557 00558 InputPin_EndOfStream(iface); 00559 graph = ((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph; 00560 if (graph) 00561 { 00562 hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); 00563 if (SUCCEEDED(hr)) 00564 { 00565 hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); 00566 IMediaEventSink_Release(pEventSink); 00567 } 00568 } 00569 00570 return hr; 00571 } 00572 00573 static const IPinVtbl NullRenderer_InputPin_Vtbl = 00574 { 00575 InputPin_QueryInterface, 00576 IPinImpl_AddRef, 00577 InputPin_Release, 00578 InputPin_Connect, 00579 InputPin_ReceiveConnection, 00580 IPinImpl_Disconnect, 00581 IPinImpl_ConnectedTo, 00582 IPinImpl_ConnectionMediaType, 00583 IPinImpl_QueryPinInfo, 00584 IPinImpl_QueryDirection, 00585 IPinImpl_QueryId, 00586 IPinImpl_QueryAccept, 00587 IPinImpl_EnumMediaTypes, 00588 IPinImpl_QueryInternalConnections, 00589 NullRenderer_InputPin_EndOfStream, 00590 InputPin_BeginFlush, 00591 InputPin_EndFlush, 00592 InputPin_NewSegment 00593 }; Generated on Sun May 27 2012 04:21:57 for ReactOS by
1.7.6.1
|