From 7b92a11b9cdb9208ecab95c452a3833a22d854c5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 12 Mar 2008 10:12:18 -0700 Subject: [PATCH] quartz: Implement a dummy null renderer for directshow --- dlls/quartz/Makefile.in | 1 + dlls/quartz/main.c | 1 + dlls/quartz/nullrenderer.c | 564 ++++++++++++++++++++++++++++++++++++++++++ dlls/quartz/quartz_private.h | 1 + dlls/quartz/regsvr.c | 18 ++ include/uuids.h | 1 + 6 files changed, 586 insertions(+), 0 deletions(-) create mode 100644 dlls/quartz/nullrenderer.c diff --git a/dlls/quartz/Makefile.in b/dlls/quartz/Makefile.in index e183f20..207ea1e 100644 --- a/dlls/quartz/Makefile.in +++ b/dlls/quartz/Makefile.in @@ -24,6 +24,7 @@ C_SRCS = \ main.c \ memallocator.c \ mpegsplit.c \ + nullrenderer.c \ parser.c \ pin.c \ regsvr.c \ diff --git a/dlls/quartz/main.c b/dlls/quartz/main.c index 73c5062..fa08d73 100644 --- a/dlls/quartz/main.c +++ b/dlls/quartz/main.c @@ -69,6 +69,7 @@ static const struct object_creation_info object_creation[] = { &CLSID_AviSplitter, AVISplitter_create }, { &CLSID_MPEG1Splitter, MPEGSplitter_create }, { &CLSID_VideoRenderer, VideoRenderer_create }, + { &CLSID_NullRenderer, NullRenderer_create }, { &CLSID_VideoRendererDefault, VideoRendererDefault_create }, { &CLSID_DSoundRender, DSoundRender_create }, { &CLSID_AVIDec, AVIDec_create }, diff --git a/dlls/quartz/nullrenderer.c b/dlls/quartz/nullrenderer.c new file mode 100644 index 0000000..3695f10 --- /dev/null +++ b/dlls/quartz/nullrenderer.c @@ -0,0 +1,564 @@ +/* + * Null Renderer (Promiscuous, not rendering anything at all!) + * + * Copyright 2004 Christian Costa + * Copyright 2008 Maarten Lankhorst + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#define NONAMELESSSTRUCT +#define NONAMELESSUNION +#include "quartz_private.h" +#include "control_private.h" +#include "pin.h" + +#include "uuids.h" +#include "vfwmsgs.h" +#include "amvideo.h" +#include "windef.h" +#include "winbase.h" +#include "dshow.h" +#include "evcode.h" +#include "strmif.h" +#include "ddraw.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(quartz); + +static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; + +static const IBaseFilterVtbl NullRenderer_Vtbl; +static const IUnknownVtbl IInner_VTable; +static const IPinVtbl NullRenderer_InputPin_Vtbl; + +typedef struct NullRendererImpl +{ + const IBaseFilterVtbl * lpVtbl; + const IUnknownVtbl * IInner_vtbl; + + LONG refCount; + CRITICAL_SECTION csFilter; + FILTER_STATE state; + REFERENCE_TIME rtStreamStart; + IReferenceClock * pClock; + FILTER_INFO filterInfo; + + InputPin * pInputPin; + IPin ** ppPins; + IUnknown * pUnkOuter; + BOOL bUnkOuterValid; + BOOL bAggregatable; +} NullRendererImpl; + +static const IMemInputPinVtbl MemInputPin_Vtbl = +{ + MemInputPin_QueryInterface, + MemInputPin_AddRef, + MemInputPin_Release, + MemInputPin_GetAllocator, + MemInputPin_NotifyAllocator, + MemInputPin_GetAllocatorRequirements, + MemInputPin_Receive, + MemInputPin_ReceiveMultiple, + MemInputPin_ReceiveCanBlock +}; + +static HRESULT NullRenderer_InputPin_Construct(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin) +{ + InputPin * pPinImpl; + + *ppPin = NULL; + + if (pPinInfo->dir != PINDIR_INPUT) + { + ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir); + return E_INVALIDARG; + } + + pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl)); + + if (!pPinImpl) + return E_OUTOFMEMORY; + + if (SUCCEEDED(InputPin_Init(pPinInfo, pSampleProc, pUserData, pQueryAccept, pCritSec, pPinImpl))) + { + pPinImpl->pin.lpVtbl = &NullRenderer_InputPin_Vtbl; + pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl; + + *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl); + return S_OK; + } + + CoTaskMemFree(pPinImpl); + return E_FAIL; +} + + + +static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample) +{ + LPBYTE pbSrcStream = NULL; + long cbSrcStream = 0; + REFERENCE_TIME tStart, tStop; + HRESULT hr; + + TRACE("%p %p\n", iface, pSample); + + hr = IMediaSample_GetPointer(pSample, &pbSrcStream); + if (FAILED(hr)) + { + ERR("Cannot get pointer to sample data (%x)\n", hr); + return hr; + } + + hr = IMediaSample_GetTime(pSample, &tStart, &tStop); + if (FAILED(hr)) + ERR("Cannot get sample time (%x)\n", hr); + + cbSrcStream = IMediaSample_GetActualDataLength(pSample); + + TRACE("val %p %ld\n", pbSrcStream, cbSrcStream); + + return S_OK; +} + +static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +{ + TRACE("Not a stub!\n"); + return S_OK; +} + +HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) +{ + HRESULT hr; + PIN_INFO piInput; + NullRendererImpl * pNullRenderer; + + TRACE("(%p, %p)\n", pUnkOuter, ppv); + + *ppv = NULL; + + pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl)); + pNullRenderer->pUnkOuter = pUnkOuter; + pNullRenderer->bUnkOuterValid = FALSE; + pNullRenderer->bAggregatable = FALSE; + pNullRenderer->IInner_vtbl = &IInner_VTable; + + pNullRenderer->lpVtbl = &NullRenderer_Vtbl; + pNullRenderer->refCount = 1; + InitializeCriticalSection(&pNullRenderer->csFilter); + pNullRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"); + pNullRenderer->state = State_Stopped; + pNullRenderer->pClock = NULL; + ZeroMemory(&pNullRenderer->filterInfo, sizeof(FILTER_INFO)); + + pNullRenderer->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *)); + + /* construct input pin */ + piInput.dir = PINDIR_INPUT; + piInput.pFilter = (IBaseFilter *)pNullRenderer; + lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); + + hr = NullRenderer_InputPin_Construct(&piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, &pNullRenderer->csFilter, (IPin **)&pNullRenderer->pInputPin); + + if (SUCCEEDED(hr)) + { + pNullRenderer->ppPins[0] = (IPin *)pNullRenderer->pInputPin; + *ppv = (LPVOID)pNullRenderer; + } + else + { + CoTaskMemFree(pNullRenderer->ppPins); + pNullRenderer->csFilter.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&pNullRenderer->csFilter); + CoTaskMemFree(pNullRenderer); + } + + return hr; +} + +static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) +{ + ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); + TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); + + if (This->bAggregatable) + This->bUnkOuterValid = TRUE; + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = (LPVOID)&(This->IInner_vtbl); + else if (IsEqualIID(riid, &IID_IPersist)) + *ppv = (LPVOID)This; + else if (IsEqualIID(riid, &IID_IMediaFilter)) + *ppv = (LPVOID)This; + else if (IsEqualIID(riid, &IID_IBaseFilter)) + *ppv = (LPVOID)This; + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); + + return E_NOINTERFACE; +} + +static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface) +{ + ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); + ULONG refCount = InterlockedIncrement(&This->refCount); + + TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); + + return refCount; +} + +static ULONG WINAPI NullRendererInner_Release(IUnknown * iface) +{ + ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); + ULONG refCount = InterlockedDecrement(&This->refCount); + + TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); + + if (!refCount) + { + IPin *pConnectedTo; + + if (This->pClock) + IReferenceClock_Release(This->pClock); + + if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo))) + { + IPin_Disconnect(pConnectedTo); + IPin_Release(pConnectedTo); + } + IPin_Disconnect(This->ppPins[0]); + IPin_Release(This->ppPins[0]); + + CoTaskMemFree(This->ppPins); + This->lpVtbl = NULL; + + This->csFilter.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->csFilter); + + TRACE("Destroying Null Renderer\n"); + CoTaskMemFree(This); + return 0; + } + else + return refCount; +} + +static const IUnknownVtbl IInner_VTable = +{ + NullRendererInner_QueryInterface, + NullRendererInner_AddRef, + NullRendererInner_Release +}; + +static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + if (This->bAggregatable) + This->bUnkOuterValid = TRUE; + + if (This->pUnkOuter) + { + if (This->bAggregatable) + return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); + + if (IsEqualIID(riid, &IID_IUnknown)) + { + HRESULT hr; + + IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); + hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); + IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); + This->bAggregatable = TRUE; + return hr; + } + + *ppv = NULL; + return E_NOINTERFACE; + } + + return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); +} + +static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + if (This->pUnkOuter && This->bUnkOuterValid) + return IUnknown_AddRef(This->pUnkOuter); + return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); +} + +static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + if (This->pUnkOuter && This->bUnkOuterValid) + return IUnknown_Release(This->pUnkOuter); + return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); +} + +/** IPersist methods **/ + +static HRESULT WINAPI NullRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%p)\n", This, iface, pClsid); + + *pClsid = CLSID_NullRenderer; + + return S_OK; +} + +/** IMediaFilter methods **/ + +static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(&This->csFilter); + { + This->state = State_Stopped; + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(&This->csFilter); + { + This->state = State_Paused; + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); + + EnterCriticalSection(&This->csFilter); + { + This->rtStreamStart = tStart; + This->state = State_Running; + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +static HRESULT WINAPI NullRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); + + EnterCriticalSection(&This->csFilter); + { + *pState = This->state; + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +static HRESULT WINAPI NullRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%p)\n", This, iface, pClock); + + EnterCriticalSection(&This->csFilter); + { + if (This->pClock) + IReferenceClock_Release(This->pClock); + This->pClock = pClock; + if (This->pClock) + IReferenceClock_AddRef(This->pClock); + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +static HRESULT WINAPI NullRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%p)\n", This, iface, ppClock); + + EnterCriticalSection(&This->csFilter); + { + *ppClock = This->pClock; + IReferenceClock_AddRef(This->pClock); + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +/** IBaseFilter implementation **/ + +static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) +{ + ENUMPINDETAILS epd; + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); + + epd.cPins = 1; /* input pin */ + epd.ppPins = This->ppPins; + return IEnumPinsImpl_Construct(&epd, ppEnum); +} + +static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin); + + FIXME("NullRenderer::FindPin(...)\n"); + + /* FIXME: critical section */ + + return E_NOTIMPL; +} + +static HRESULT WINAPI NullRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); + + strcpyW(pInfo->achName, This->filterInfo.achName); + pInfo->pGraph = This->filterInfo.pGraph; + + if (pInfo->pGraph) + IFilterGraph_AddRef(pInfo->pGraph); + + return S_OK; +} + +static HRESULT WINAPI NullRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + + TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); + + EnterCriticalSection(&This->csFilter); + { + if (pName) + strcpyW(This->filterInfo.achName, pName); + else + *This->filterInfo.achName = '\0'; + This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +static HRESULT WINAPI NullRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) +{ + NullRendererImpl *This = (NullRendererImpl *)iface; + TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo); + return E_NOTIMPL; +} + +static const IBaseFilterVtbl NullRenderer_Vtbl = +{ + NullRenderer_QueryInterface, + NullRenderer_AddRef, + NullRenderer_Release, + NullRenderer_GetClassID, + NullRenderer_Stop, + NullRenderer_Pause, + NullRenderer_Run, + NullRenderer_GetState, + NullRenderer_SetSyncSource, + NullRenderer_GetSyncSource, + NullRenderer_EnumPins, + NullRenderer_FindPin, + NullRenderer_QueryFilterInfo, + NullRenderer_JoinFilterGraph, + NullRenderer_QueryVendorInfo +}; + +static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) +{ + InputPin* This = (InputPin*)iface; + IMediaEventSink* pEventSink; + HRESULT hr; + + TRACE("(%p/%p)->()\n", This, iface); + + hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); + if (SUCCEEDED(hr)) + { + hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); + IMediaEventSink_Release(pEventSink); + } + + return hr; +} + +static const IPinVtbl NullRenderer_InputPin_Vtbl = +{ + InputPin_QueryInterface, + IPinImpl_AddRef, + InputPin_Release, + InputPin_Connect, + InputPin_ReceiveConnection, + IPinImpl_Disconnect, + IPinImpl_ConnectedTo, + IPinImpl_ConnectionMediaType, + IPinImpl_QueryPinInfo, + IPinImpl_QueryDirection, + IPinImpl_QueryId, + IPinImpl_QueryAccept, + IPinImpl_EnumMediaTypes, + IPinImpl_QueryInternalConnections, + NullRenderer_InputPin_EndOfStream, + InputPin_BeginFlush, + InputPin_EndFlush, + InputPin_NewSegment +}; diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h index ebb6a02..f730876 100644 --- a/dlls/quartz/quartz_private.h +++ b/dlls/quartz/quartz_private.h @@ -52,6 +52,7 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv); +HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv); diff --git a/dlls/quartz/regsvr.c b/dlls/quartz/regsvr.c index 98fd0bc..b4a304e 100644 --- a/dlls/quartz/regsvr.c +++ b/dlls/quartz/regsvr.c @@ -855,6 +855,12 @@ static struct regsvr_coclass const coclass_list[] = { "quartz.dll", "Both" }, + { &CLSID_NullRenderer, + "Null Renderer", + NULL, + "quartz.dll", + "Both" + }, { &CLSID_VideoRenderer, "Video Renderer", NULL, @@ -1069,6 +1075,18 @@ static struct regsvr_filter const filter_list[] = { { 0xFFFFFFFF }, } }, + { &CLSID_NullRenderer, + &CLSID_LegacyAmFilterCategory, + {'N','u','l','l',' ','R','e','n','d','e','r','e','r',0}, + 0x200000, + { { REG_PINFLAG_B_RENDERER, + { { &MEDIATYPE_NULL, &GUID_NULL }, + { NULL } + }, + }, + { 0xFFFFFFFF }, + } + }, { &CLSID_VideoRenderer, &CLSID_LegacyAmFilterCategory, {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0}, diff --git a/include/uuids.h b/include/uuids.h index b767fcc..9f57dd7 100644 --- a/include/uuids.h +++ b/include/uuids.h @@ -134,6 +134,7 @@ OUR_GUID_ENTRY(CLSID_WAVEParser, 0xd51bd5a1, 0x7548, 0x11cf, OUR_GUID_ENTRY(CLSID_QTDec, 0xfdfe9681, 0x74a3, 0x11d0, 0xaf, 0xa7, 0x00, 0xaa, 0x00, 0xb6, 0x7a, 0x42) OUR_GUID_ENTRY(CLSID_AVIDoc, 0xd3588ab0, 0x0781, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70) OUR_GUID_ENTRY(CLSID_AVIDocWriter, 0xd3588ab1, 0x0781, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70) +OUR_GUID_ENTRY(CLSID_NullRenderer, 0xc1f400a4, 0x3f08, 0x11d3, 0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37) OUR_GUID_ENTRY(CLSID_VideoRenderer, 0x70e102b0, 0x5556, 0x11ce, 0x97, 0xc0, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a) OUR_GUID_ENTRY(CLSID_VideoRendererDefault, 0x6bc1cffa, 0x8fc1, 0x4261, 0xac, 0x22, 0xcf, 0xb4, 0xcc, 0x38, 0xdb, 0x50) OUR_GUID_ENTRY(CLSID_Colour, 0x1643e180, 0x90f5, 0x11ce, 0x97, 0xd5, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a) -- 1.5.4.1