qedit: Support COM aggregation for SampleGrabber.

This commit is contained in:
Michael Stefaniuc 2012-06-26 23:54:49 +02:00 committed by Alexandre Julliard
parent 703d0a33ce
commit 7367685021
3 changed files with 84 additions and 63 deletions

View File

@ -105,6 +105,9 @@ static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
*ppobj = NULL; *ppobj = NULL;
if (pOuter && !IsEqualGUID(&IID_IUnknown, riid))
return E_INVALIDARG;
hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk); hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
if (SUCCEEDED(hres)) { if (SUCCEEDED(hres)) {
hres = IUnknown_QueryInterface(punk, riid, ppobj); hres = IUnknown_QueryInterface(punk, riid, ppobj);

View File

@ -365,11 +365,13 @@ static inline SG_Pin *impl_from_IPin(IPin *iface)
/* Sample Grabber filter implementation */ /* Sample Grabber filter implementation */
typedef struct _SG_Impl { typedef struct _SG_Impl {
IUnknown IUnknown_inner;
IBaseFilter IBaseFilter_iface; IBaseFilter IBaseFilter_iface;
ISampleGrabber ISampleGrabber_iface; ISampleGrabber ISampleGrabber_iface;
IMemInputPin IMemInputPin_iface; IMemInputPin IMemInputPin_iface;
/* TODO: IMediaPosition, IMediaSeeking, IQualityControl */ /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
LONG refCount; IUnknown *outer_unk;
LONG ref;
CRITICAL_SECTION critSect; CRITICAL_SECTION critSect;
FILTER_INFO info; FILTER_INFO info;
FILTER_STATE state; FILTER_STATE state;
@ -392,7 +394,11 @@ enum {
OneShot_Past, OneShot_Past,
}; };
/* Get the SampleGrabber implementation This pointer from various interface pointers */ static inline SG_Impl *impl_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, SG_Impl, IUnknown_inner);
}
static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface) static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
{ {
return CONTAINING_RECORD(iface, SG_Impl, IBaseFilter_iface); return CONTAINING_RECORD(iface, SG_Impl, IBaseFilter_iface);
@ -431,62 +437,72 @@ static void SampleGrabber_cleanup(SG_Impl *This)
DeleteCriticalSection(&This->critSect); DeleteCriticalSection(&This->critSect);
} }
/* Common helper AddRef called from all interfaces */ /* SampleGrabber inner IUnknown */
static ULONG SampleGrabber_addref(SG_Impl *This) static HRESULT WINAPI SampleGrabber_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{ {
ULONG refCount = InterlockedIncrement(&This->refCount); SG_Impl *This = impl_from_IUnknown(iface);
TRACE("(%p) new ref = %u\n", This, refCount);
return refCount;
}
/* Common helper Release called from all interfaces */ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
static ULONG SampleGrabber_release(SG_Impl *This)
{
ULONG refCount = InterlockedDecrement(&This->refCount);
TRACE("(%p) new ref = %u\n", This, refCount);
if (refCount == 0)
{
SampleGrabber_cleanup(This);
CoTaskMemFree(This);
return 0;
}
return refCount;
}
/* Common helper QueryInterface called from all interfaces */ *ppv = NULL;
static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject) if (IsEqualIID(riid, &IID_IUnknown))
{ *ppv = &This->IUnknown_inner;
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); else if (IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IMediaFilter) ||
IsEqualIID(riid, &IID_IBaseFilter))
if (IsEqualIID(riid, &IID_IUnknown) || *ppv = &This->IBaseFilter_iface;
IsEqualIID(riid, &IID_IPersist) || else if (IsEqualIID(riid, &IID_ISampleGrabber))
IsEqualIID(riid, &IID_IMediaFilter) || *ppv = &This->ISampleGrabber_iface;
IsEqualIID(riid, &IID_IBaseFilter)) { else if (IsEqualIID(riid, &IID_IMemInputPin))
SampleGrabber_addref(This); *ppv = &This->IMemInputPin_iface;
*ppvObject = &This->IBaseFilter_iface;
return S_OK;
}
else if (IsEqualIID(riid, &IID_ISampleGrabber)) {
SampleGrabber_addref(This);
*ppvObject = &This->ISampleGrabber_iface;
return S_OK;
}
else if (IsEqualIID(riid, &IID_IMemInputPin)) {
SampleGrabber_addref(This);
*ppvObject = &This->IMemInputPin_iface;
return S_OK;
}
else if (IsEqualIID(riid, &IID_IMediaPosition)) else if (IsEqualIID(riid, &IID_IMediaPosition))
FIXME("IMediaPosition not implemented\n"); FIXME("IMediaPosition not implemented\n");
else if (IsEqualIID(riid, &IID_IMediaSeeking)) else if (IsEqualIID(riid, &IID_IMediaSeeking))
FIXME("IMediaSeeking not implemented\n"); FIXME("IMediaSeeking not implemented\n");
else if (IsEqualIID(riid, &IID_IQualityControl)) else if (IsEqualIID(riid, &IID_IQualityControl))
FIXME("IQualityControl not implemented\n"); FIXME("IQualityControl not implemented\n");
*ppvObject = NULL; else
WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject); WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppv);
return E_NOINTERFACE;
if (!*ppv)
return E_NOINTERFACE;
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
} }
static ULONG WINAPI SampleGrabber_AddRef(IUnknown *iface)
{
SG_Impl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) new ref = %u\n", This, ref);
return ref;
}
static ULONG WINAPI SampleGrabber_Release(IUnknown *iface)
{
SG_Impl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) new ref = %u\n", This, ref);
if (ref == 0)
{
SampleGrabber_cleanup(This);
CoTaskMemFree(This);
return 0;
}
return ref;
}
static const IUnknownVtbl samplegrabber_vtbl =
{
SampleGrabber_QueryInterface,
SampleGrabber_AddRef,
SampleGrabber_Release,
};
/* Helper that buffers data and/or calls installed sample callbacks */ /* Helper that buffers data and/or calls installed sample callbacks */
static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample) static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
{ {
@ -554,7 +570,7 @@ static HRESULT WINAPI
SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv) SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv)
{ {
SG_Impl *This = impl_from_IBaseFilter(iface); SG_Impl *This = impl_from_IBaseFilter(iface);
return SampleGrabber_query(This, riid, ppv); return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
} }
/* IUnknown */ /* IUnknown */
@ -562,7 +578,7 @@ static ULONG WINAPI
SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface) SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface)
{ {
SG_Impl *This = impl_from_IBaseFilter(iface); SG_Impl *This = impl_from_IBaseFilter(iface);
return SampleGrabber_addref(This); return IUnknown_AddRef(This->outer_unk);
} }
/* IUnknown */ /* IUnknown */
@ -570,7 +586,7 @@ static ULONG WINAPI
SampleGrabber_IBaseFilter_Release(IBaseFilter *iface) SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
{ {
SG_Impl *This = impl_from_IBaseFilter(iface); SG_Impl *This = impl_from_IBaseFilter(iface);
return SampleGrabber_release(This); return IUnknown_Release(This->outer_unk);
} }
/* IPersist */ /* IPersist */
@ -743,7 +759,7 @@ static HRESULT WINAPI
SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppv) SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppv)
{ {
SG_Impl *This = impl_from_ISampleGrabber(iface); SG_Impl *This = impl_from_ISampleGrabber(iface);
return SampleGrabber_query(This, riid, ppv); return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
} }
/* IUnknown */ /* IUnknown */
@ -751,7 +767,7 @@ static ULONG WINAPI
SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface) SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface)
{ {
SG_Impl *This = impl_from_ISampleGrabber(iface); SG_Impl *This = impl_from_ISampleGrabber(iface);
return SampleGrabber_addref(This); return IUnknown_AddRef(This->outer_unk);
} }
/* IUnknown */ /* IUnknown */
@ -759,7 +775,7 @@ static ULONG WINAPI
SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface) SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface)
{ {
SG_Impl *This = impl_from_ISampleGrabber(iface); SG_Impl *This = impl_from_ISampleGrabber(iface);
return SampleGrabber_release(This); return IUnknown_Release(This->outer_unk);
} }
/* ISampleGrabber */ /* ISampleGrabber */
@ -893,7 +909,7 @@ static HRESULT WINAPI
SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppv) SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppv)
{ {
SG_Impl *This = impl_from_IMemInputPin(iface); SG_Impl *This = impl_from_IMemInputPin(iface);
return SampleGrabber_query(This, riid, ppv); return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
} }
/* IUnknown */ /* IUnknown */
@ -901,7 +917,7 @@ static ULONG WINAPI
SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface) SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface)
{ {
SG_Impl *This = impl_from_IMemInputPin(iface); SG_Impl *This = impl_from_IMemInputPin(iface);
return SampleGrabber_addref(This); return IUnknown_AddRef(This->outer_unk);
} }
/* IUnknown */ /* IUnknown */
@ -909,7 +925,7 @@ static ULONG WINAPI
SampleGrabber_IMemInputPin_Release(IMemInputPin *iface) SampleGrabber_IMemInputPin_Release(IMemInputPin *iface)
{ {
SG_Impl *This = impl_from_IMemInputPin(iface); SG_Impl *This = impl_from_IMemInputPin(iface);
return SampleGrabber_release(This); return IUnknown_Release(This->outer_unk);
} }
/* IMemInputPin */ /* IMemInputPin */
@ -1454,9 +1470,6 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
TRACE("(%p,%p)\n", ppv, pUnkOuter); TRACE("(%p,%p)\n", ppv, pUnkOuter);
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
obj = CoTaskMemAlloc(sizeof(SG_Impl)); obj = CoTaskMemAlloc(sizeof(SG_Impl));
if (NULL == obj) { if (NULL == obj) {
*ppv = NULL; *ppv = NULL;
@ -1464,7 +1477,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
} }
ZeroMemory(obj, sizeof(SG_Impl)); ZeroMemory(obj, sizeof(SG_Impl));
obj->refCount = 1; obj->ref = 1;
obj->IUnknown_inner.lpVtbl = &samplegrabber_vtbl;
obj->IBaseFilter_iface.lpVtbl = &IBaseFilter_VTable; obj->IBaseFilter_iface.lpVtbl = &IBaseFilter_VTable;
obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable; obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable; obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
@ -1494,7 +1508,12 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
obj->oneShot = OneShot_None; obj->oneShot = OneShot_None;
obj->bufferLen = -1; obj->bufferLen = -1;
obj->bufferData = NULL; obj->bufferData = NULL;
*ppv = obj;
if (pUnkOuter)
obj->outer_unk = pUnkOuter;
else
obj->outer_unk = &obj->IUnknown_inner;
*ppv = &obj->IUnknown_inner;
return S_OK; return S_OK;
} }

View File

@ -346,8 +346,7 @@ static void test_samplegrabber(void)
/* COM aggregation */ /* COM aggregation */
hr = CoCreateInstance(&CLSID_SampleGrabber, &unk_obj.IUnknown_iface, CLSCTX_INPROC_SERVER, hr = CoCreateInstance(&CLSID_SampleGrabber, &unk_obj.IUnknown_iface, CLSCTX_INPROC_SERVER,
&IID_IUnknown, (void**)&unk_obj.inner_unk); &IID_IUnknown, (void**)&unk_obj.inner_unk);
todo_wine ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr); ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
if (hr != S_OK) return;
hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_ISampleGrabber, (void**)&sg); hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_ISampleGrabber, (void**)&sg);
ok(hr == S_OK, "QueryInterface for IID_ISampleGrabber failed: %08x\n", hr); ok(hr == S_OK, "QueryInterface for IID_ISampleGrabber failed: %08x\n", hr);