From d5d6cfbf63c7ad00403be0b74f01876458fcaaa8 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Thu, 12 Mar 2020 21:34:08 -0500 Subject: [PATCH] strmbase: Separate the seeking passthrough object from its implementation. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/strmbase/pospass.c | 275 +++++++++++++++++++++------------------- 1 file changed, 147 insertions(+), 128 deletions(-) diff --git a/dlls/strmbase/pospass.c b/dlls/strmbase/pospass.c index 6920b378650..c5be17ec62b 100644 --- a/dlls/strmbase/pospass.c +++ b/dlls/strmbase/pospass.c @@ -24,16 +24,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(strmbase); -static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl; -static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl; - typedef struct PassThruImpl { - IUnknown IUnknown_inner; ISeekingPassThru ISeekingPassThru_iface; IMediaSeeking IMediaSeeking_iface; IMediaPosition IMediaPosition_iface; - LONG ref; IUnknown * outer_unk; IPin * pin; BOOL renderer; @@ -42,11 +37,6 @@ typedef struct PassThruImpl { REFERENCE_TIME time_earliest; } PassThruImpl; -static inline PassThruImpl *impl_from_IUnknown_inner(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, PassThruImpl, IUnknown_inner); -} - static inline PassThruImpl *impl_from_ISeekingPassThru(ISeekingPassThru *iface) { return CONTAINING_RECORD(iface, PassThruImpl, ISeekingPassThru_iface); @@ -62,66 +52,6 @@ static inline PassThruImpl *impl_from_IMediaPosition(IMediaPosition *iface) return CONTAINING_RECORD(iface, PassThruImpl, IMediaPosition_iface); } -static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface, - REFIID riid, - LPVOID *ppvObj) { - PassThruImpl *This = impl_from_IUnknown_inner(iface); - TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj); - - if (IsEqualGUID(&IID_IUnknown, riid)) - { - *ppvObj = &(This->IUnknown_inner); - TRACE(" returning IUnknown interface (%p)\n", *ppvObj); - } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) { - *ppvObj = &(This->ISeekingPassThru_iface); - TRACE(" returning ISeekingPassThru interface (%p)\n", *ppvObj); - } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) { - *ppvObj = &(This->IMediaSeeking_iface); - TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj); - } else if (IsEqualGUID(&IID_IMediaPosition, riid)) { - *ppvObj = &(This->IMediaPosition_iface); - TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj); - } else { - *ppvObj = NULL; - FIXME("unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)(*ppvObj)); - return S_OK; -} - -static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) { - PassThruImpl *This = impl_from_IUnknown_inner(iface); - ULONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(): new ref = %d\n", This, ref); - - return ref; -} - -static ULONG WINAPI SeekInner_Release(IUnknown * iface) { - PassThruImpl *This = impl_from_IUnknown_inner(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(): new ref = %d\n", This, ref); - - if (ref == 0) - { - This->time_cs.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->time_cs); - CoTaskMemFree(This); - } - return ref; -} - -static const IUnknownVtbl IInner_VTable = -{ - SeekInner_QueryInterface, - SeekInner_AddRef, - SeekInner_Release -}; - static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID iid, void **out) { PassThruImpl *passthrough = impl_from_ISeekingPassThru(iface); @@ -182,29 +112,6 @@ HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin return hr; } -HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru) -{ - PassThruImpl *fimpl; - - TRACE("(%p,%p)\n", pUnkOuter, ppPassThru); - - *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl)); - if (!fimpl) - return E_OUTOFMEMORY; - - fimpl->outer_unk = pUnkOuter ? pUnkOuter : &fimpl->IUnknown_inner; - fimpl->IUnknown_inner.lpVtbl = &IInner_VTable; - fimpl->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl; - fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl; - fimpl->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl; - fimpl->ref = 1; - fimpl->pin = NULL; - fimpl->timevalid = FALSE; - InitializeCriticalSection(&fimpl->time_cs); - fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs"); - return S_OK; -} - static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out) { PassThruImpl *passthrough = impl_from_IMediaSeeking(iface); @@ -523,41 +430,6 @@ static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LON return hr; } -HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start) -{ - PassThruImpl *This = impl_from_IUnknown_inner(iface); - EnterCriticalSection(&This->time_cs); - This->time_earliest = start; - This->timevalid = TRUE; - LeaveCriticalSection(&This->time_cs); - return S_OK; -} - -HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface) -{ - PassThruImpl *This = impl_from_IUnknown_inner(iface); - EnterCriticalSection(&This->time_cs); - This->timevalid = FALSE; - LeaveCriticalSection(&This->time_cs); - return S_OK; -} - -HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface) -{ - PassThruImpl *This = impl_from_IUnknown_inner(iface); - REFERENCE_TIME time; - HRESULT hr; - hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time); - EnterCriticalSection(&This->time_cs); - if (SUCCEEDED(hr)) { - This->timevalid = TRUE; - This->time_earliest = time; - } else - This->timevalid = FALSE; - LeaveCriticalSection(&This->time_cs); - return hr; -} - static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl = { MediaSeekingPassThru_QueryInterface, @@ -870,3 +742,150 @@ static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl = MediaPositionPassThru_CanSeekForward, MediaPositionPassThru_CanSeekBackward }; + +void strmbase_passthrough_init(PassThruImpl *passthrough, IUnknown *outer) +{ + memset(passthrough, 0, sizeof(*passthrough)); + + passthrough->outer_unk = outer; + passthrough->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl; + passthrough->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl; + passthrough->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl; + InitializeCriticalSection(&passthrough->time_cs); + passthrough->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs" ); +} + +void strmbase_passthrough_cleanup(PassThruImpl *passthrough) +{ + passthrough->time_cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&passthrough->time_cs); +} + +struct seeking_passthrough +{ + PassThruImpl passthrough; + + IUnknown IUnknown_inner; + IUnknown *outer_unk; + LONG refcount; +}; + +static struct seeking_passthrough *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct seeking_passthrough, IUnknown_inner); +} + +static HRESULT WINAPI seeking_passthrough_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + struct seeking_passthrough *passthrough = impl_from_IUnknown(iface); + + TRACE("passthrough %p, iid %s, out %p.\n", passthrough, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown)) + *out = iface; + else if (IsEqualGUID(iid, &IID_IMediaPosition)) + *out = &passthrough->passthrough.IMediaPosition_iface; + else if (IsEqualGUID(iid, &IID_IMediaSeeking)) + *out = &passthrough->passthrough.IMediaSeeking_iface; + else if (IsEqualGUID(iid, &IID_ISeekingPassThru)) + *out = &passthrough->passthrough.ISeekingPassThru_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI seeking_passthrough_AddRef(IUnknown *iface) +{ + struct seeking_passthrough *passthrough = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&passthrough->refcount); + + TRACE("%p increasing refcount to %u.\n", passthrough, refcount); + return refcount; +} + +static ULONG WINAPI seeking_passthrough_Release(IUnknown *iface) +{ + struct seeking_passthrough *passthrough = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&passthrough->refcount); + + TRACE("%p decreasing refcount to %u.\n", passthrough, refcount); + if (!refcount) + { + strmbase_passthrough_cleanup(&passthrough->passthrough); + heap_free(passthrough); + } + return refcount; +} + +static const IUnknownVtbl seeking_passthrough_vtbl = +{ + seeking_passthrough_QueryInterface, + seeking_passthrough_AddRef, + seeking_passthrough_Release, +}; + +HRESULT WINAPI PosPassThru_Construct(IUnknown *outer, void **out) +{ + struct seeking_passthrough *object; + + TRACE("outer %p, out %p.\n", outer, out); + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IUnknown_inner.lpVtbl = &seeking_passthrough_vtbl; + object->outer_unk = outer ? outer : &object->IUnknown_inner; + object->refcount = 1; + + strmbase_passthrough_init(&object->passthrough, object->outer_unk); + + TRACE("Created seeking passthrough %p.\n", object); + *out = &object->IUnknown_inner; + return S_OK; +} + +HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start) +{ + struct seeking_passthrough *passthrough = impl_from_IUnknown(iface); + + EnterCriticalSection(&passthrough->passthrough.time_cs); + passthrough->passthrough.time_earliest = start; + passthrough->passthrough.timevalid = TRUE; + LeaveCriticalSection(&passthrough->passthrough.time_cs); + return S_OK; +} + +HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface) +{ + struct seeking_passthrough *passthrough = impl_from_IUnknown(iface); + + EnterCriticalSection(&passthrough->passthrough.time_cs); + passthrough->passthrough.timevalid = FALSE; + LeaveCriticalSection(&passthrough->passthrough.time_cs); + return S_OK; +} + +HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface) +{ + struct seeking_passthrough *passthrough = impl_from_IUnknown(iface); + REFERENCE_TIME time; + HRESULT hr; + + hr = IMediaSeeking_GetStopPosition(&passthrough->passthrough.IMediaSeeking_iface, &time); + EnterCriticalSection(&passthrough->passthrough.time_cs); + if (SUCCEEDED(hr)) + { + passthrough->passthrough.timevalid = TRUE; + passthrough->passthrough.time_earliest = time; + } + else + passthrough->passthrough.timevalid = FALSE; + LeaveCriticalSection(&passthrough->passthrough.time_cs); + return hr; +}