Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/Makefile.in | 1 + dlls/mf/quality.c | 311 ++++++++++++++++++++++++++++++++++++++++++++ dlls/mf/session.c | 283 ---------------------------------------- 3 files changed, 312 insertions(+), 283 deletions(-) create mode 100644 dlls/mf/quality.c
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in index 77d85ad041b..36727d4d4e3 100644 --- a/dlls/mf/Makefile.in +++ b/dlls/mf/Makefile.in @@ -10,6 +10,7 @@ C_SRCS = \ copier.c \ evr.c \ main.c \ + quality.c \ samplegrabber.c \ sar.c \ session.c \ diff --git a/dlls/mf/quality.c b/dlls/mf/quality.c new file mode 100644 index 00000000000..6c71a5a71c6 --- /dev/null +++ b/dlls/mf/quality.c @@ -0,0 +1,311 @@ +/* + * Copyright 2022 Nikolay Sivov for CodeWeavers + * + * 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 <stdarg.h> + +#define COBJMACROS + +#include "windef.h" +#include "mf_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); + +enum quality_manager_state +{ + QUALITY_MANAGER_READY = 0, + QUALITY_MANAGER_SHUT_DOWN, +}; + +struct quality_manager +{ + IMFQualityManager IMFQualityManager_iface; + IMFClockStateSink IMFClockStateSink_iface; + LONG refcount; + + IMFTopology *topology; + IMFPresentationClock *clock; + unsigned int state; + CRITICAL_SECTION cs; +}; + +static struct quality_manager *impl_from_IMFQualityManager(IMFQualityManager *iface) +{ + return CONTAINING_RECORD(iface, struct quality_manager, IMFQualityManager_iface); +} + +static struct quality_manager *impl_from_IMFClockStateSink(IMFClockStateSink *iface) +{ + return CONTAINING_RECORD(iface, struct quality_manager, IMFClockStateSink_iface); +} + +static HRESULT WINAPI standard_quality_manager_QueryInterface(IMFQualityManager *iface, REFIID riid, void **out) +{ + struct quality_manager *manager = impl_from_IMFQualityManager(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualIID(riid, &IID_IMFQualityManager) || + IsEqualIID(riid, &IID_IUnknown)) + { + *out = iface; + } + else if (IsEqualIID(riid, &IID_IMFClockStateSink)) + { + *out = &manager->IMFClockStateSink_iface; + } + else + { + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI standard_quality_manager_AddRef(IMFQualityManager *iface) +{ + struct quality_manager *manager = impl_from_IMFQualityManager(iface); + ULONG refcount = InterlockedIncrement(&manager->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI standard_quality_manager_Release(IMFQualityManager *iface) +{ + struct quality_manager *manager = impl_from_IMFQualityManager(iface); + ULONG refcount = InterlockedDecrement(&manager->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + if (manager->clock) + IMFPresentationClock_Release(manager->clock); + if (manager->topology) + IMFTopology_Release(manager->topology); + DeleteCriticalSection(&manager->cs); + free(manager); + } + + return refcount; +} + +static void standard_quality_manager_set_topology(struct quality_manager *manager, IMFTopology *topology) +{ + if (manager->topology) + IMFTopology_Release(manager->topology); + manager->topology = topology; + if (manager->topology) + IMFTopology_AddRef(manager->topology); +} + +static HRESULT WINAPI standard_quality_manager_NotifyTopology(IMFQualityManager *iface, IMFTopology *topology) +{ + struct quality_manager *manager = impl_from_IMFQualityManager(iface); + HRESULT hr = S_OK; + + TRACE("%p, %p.\n", iface, topology); + + EnterCriticalSection(&manager->cs); + if (manager->state == QUALITY_MANAGER_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else + { + standard_quality_manager_set_topology(manager, topology); + } + LeaveCriticalSection(&manager->cs); + + return hr; +} + +static void standard_quality_manager_release_clock(struct quality_manager *manager) +{ + if (manager->clock) + { + IMFPresentationClock_RemoveClockStateSink(manager->clock, &manager->IMFClockStateSink_iface); + IMFPresentationClock_Release(manager->clock); + } + manager->clock = NULL; +} + +static HRESULT WINAPI standard_quality_manager_NotifyPresentationClock(IMFQualityManager *iface, + IMFPresentationClock *clock) +{ + struct quality_manager *manager = impl_from_IMFQualityManager(iface); + HRESULT hr = S_OK; + + TRACE("%p, %p.\n", iface, clock); + + EnterCriticalSection(&manager->cs); + if (manager->state == QUALITY_MANAGER_SHUT_DOWN) + hr = MF_E_SHUTDOWN; + else if (!clock) + hr = E_POINTER; + else + { + standard_quality_manager_release_clock(manager); + manager->clock = clock; + IMFPresentationClock_AddRef(manager->clock); + if (FAILED(IMFPresentationClock_AddClockStateSink(manager->clock, &manager->IMFClockStateSink_iface))) + WARN("Failed to set state sink.\n"); + } + LeaveCriticalSection(&manager->cs); + + return hr; +} + +static HRESULT WINAPI standard_quality_manager_NotifyProcessInput(IMFQualityManager *iface, IMFTopologyNode *node, + LONG input_index, IMFSample *sample) +{ + TRACE("%p, %p, %d, %p stub.\n", iface, node, input_index, sample); + + return E_NOTIMPL; +} + +static HRESULT WINAPI standard_quality_manager_NotifyProcessOutput(IMFQualityManager *iface, IMFTopologyNode *node, + LONG output_index, IMFSample *sample) +{ + TRACE("%p, %p, %d, %p stub.\n", iface, node, output_index, sample); + + return E_NOTIMPL; +} + +static HRESULT WINAPI standard_quality_manager_NotifyQualityEvent(IMFQualityManager *iface, IUnknown *object, + IMFMediaEvent *event) +{ + FIXME("%p, %p, %p stub.\n", iface, object, event); + + return E_NOTIMPL; +} + +static HRESULT WINAPI standard_quality_manager_Shutdown(IMFQualityManager *iface) +{ + struct quality_manager *manager = impl_from_IMFQualityManager(iface); + + TRACE("%p.\n", iface); + + EnterCriticalSection(&manager->cs); + if (manager->state != QUALITY_MANAGER_SHUT_DOWN) + { + standard_quality_manager_release_clock(manager); + standard_quality_manager_set_topology(manager, NULL); + manager->state = QUALITY_MANAGER_SHUT_DOWN; + } + LeaveCriticalSection(&manager->cs); + + return S_OK; +} + +static const IMFQualityManagerVtbl standard_quality_manager_vtbl = +{ + standard_quality_manager_QueryInterface, + standard_quality_manager_AddRef, + standard_quality_manager_Release, + standard_quality_manager_NotifyTopology, + standard_quality_manager_NotifyPresentationClock, + standard_quality_manager_NotifyProcessInput, + standard_quality_manager_NotifyProcessOutput, + standard_quality_manager_NotifyQualityEvent, + standard_quality_manager_Shutdown, +}; + +static HRESULT WINAPI standard_quality_manager_sink_QueryInterface(IMFClockStateSink *iface, + REFIID riid, void **obj) +{ + struct quality_manager *manager = impl_from_IMFClockStateSink(iface); + return IMFQualityManager_QueryInterface(&manager->IMFQualityManager_iface, riid, obj); +} + +static ULONG WINAPI standard_quality_manager_sink_AddRef(IMFClockStateSink *iface) +{ + struct quality_manager *manager = impl_from_IMFClockStateSink(iface); + return IMFQualityManager_AddRef(&manager->IMFQualityManager_iface); +} + +static ULONG WINAPI standard_quality_manager_sink_Release(IMFClockStateSink *iface) +{ + struct quality_manager *manager = impl_from_IMFClockStateSink(iface); + return IMFQualityManager_Release(&manager->IMFQualityManager_iface); +} + +static HRESULT WINAPI standard_quality_manager_sink_OnClockStart(IMFClockStateSink *iface, + MFTIME systime, LONGLONG offset) +{ + return S_OK; +} + +static HRESULT WINAPI standard_quality_manager_sink_OnClockStop(IMFClockStateSink *iface, + MFTIME systime) +{ + return S_OK; +} + +static HRESULT WINAPI standard_quality_manager_sink_OnClockPause(IMFClockStateSink *iface, + MFTIME systime) +{ + return S_OK; +} + +static HRESULT WINAPI standard_quality_manager_sink_OnClockRestart(IMFClockStateSink *iface, + MFTIME systime) +{ + return S_OK; +} + +static HRESULT WINAPI standard_quality_manager_sink_OnClockSetRate(IMFClockStateSink *iface, + MFTIME systime, float rate) +{ + return S_OK; +} + +static const IMFClockStateSinkVtbl standard_quality_manager_sink_vtbl = +{ + standard_quality_manager_sink_QueryInterface, + standard_quality_manager_sink_AddRef, + standard_quality_manager_sink_Release, + standard_quality_manager_sink_OnClockStart, + standard_quality_manager_sink_OnClockStop, + standard_quality_manager_sink_OnClockPause, + standard_quality_manager_sink_OnClockRestart, + standard_quality_manager_sink_OnClockSetRate, +}; + +HRESULT WINAPI MFCreateStandardQualityManager(IMFQualityManager **manager) +{ + struct quality_manager *object; + + TRACE("%p.\n", manager); + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IMFQualityManager_iface.lpVtbl = &standard_quality_manager_vtbl; + object->IMFClockStateSink_iface.lpVtbl = &standard_quality_manager_sink_vtbl; + object->refcount = 1; + InitializeCriticalSection(&object->cs); + + *manager = &object->IMFQualityManager_iface; + + return S_OK; +} diff --git a/dlls/mf/session.c b/dlls/mf/session.c index c8ec1b5c33f..c365495ee48 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -254,24 +254,6 @@ struct media_session CRITICAL_SECTION cs; };
-enum quality_manager_state -{ - QUALITY_MANAGER_READY = 0, - QUALITY_MANAGER_SHUT_DOWN, -}; - -struct quality_manager -{ - IMFQualityManager IMFQualityManager_iface; - IMFClockStateSink IMFClockStateSink_iface; - LONG refcount; - - IMFTopology *topology; - IMFPresentationClock *clock; - unsigned int state; - CRITICAL_SECTION cs; -}; - static inline struct media_session *impl_from_IMFMediaSession(IMFMediaSession *iface) { return CONTAINING_RECORD(iface, struct media_session, IMFMediaSession_iface); @@ -317,16 +299,6 @@ static struct session_op *impl_op_from_IUnknown(IUnknown *iface) return CONTAINING_RECORD(iface, struct session_op, IUnknown_iface); }
-static struct quality_manager *impl_from_IMFQualityManager(IMFQualityManager *iface) -{ - return CONTAINING_RECORD(iface, struct quality_manager, IMFQualityManager_iface); -} - -static struct quality_manager *impl_from_qm_IMFClockStateSink(IMFClockStateSink *iface) -{ - return CONTAINING_RECORD(iface, struct quality_manager, IMFClockStateSink_iface); -} - static struct topo_node *impl_node_from_IMFVideoSampleAllocatorNotify(IMFVideoSampleAllocatorNotify *iface) { return CONTAINING_RECORD(iface, struct topo_node, u.sink.notify_cb); @@ -3856,258 +3828,3 @@ failed: IMFMediaSession_Release(&object->IMFMediaSession_iface); return hr; } - -static HRESULT WINAPI standard_quality_manager_QueryInterface(IMFQualityManager *iface, REFIID riid, void **out) -{ - struct quality_manager *manager = impl_from_IMFQualityManager(iface); - - TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out); - - if (IsEqualIID(riid, &IID_IMFQualityManager) || - IsEqualIID(riid, &IID_IUnknown)) - { - *out = iface; - } - else if (IsEqualIID(riid, &IID_IMFClockStateSink)) - { - *out = &manager->IMFClockStateSink_iface; - } - else - { - WARN("Unsupported %s.\n", debugstr_guid(riid)); - *out = NULL; - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)*out); - return S_OK; -} - -static ULONG WINAPI standard_quality_manager_AddRef(IMFQualityManager *iface) -{ - struct quality_manager *manager = impl_from_IMFQualityManager(iface); - ULONG refcount = InterlockedIncrement(&manager->refcount); - - TRACE("%p, refcount %u.\n", iface, refcount); - - return refcount; -} - -static ULONG WINAPI standard_quality_manager_Release(IMFQualityManager *iface) -{ - struct quality_manager *manager = impl_from_IMFQualityManager(iface); - ULONG refcount = InterlockedDecrement(&manager->refcount); - - TRACE("%p, refcount %u.\n", iface, refcount); - - if (!refcount) - { - if (manager->clock) - IMFPresentationClock_Release(manager->clock); - if (manager->topology) - IMFTopology_Release(manager->topology); - DeleteCriticalSection(&manager->cs); - free(manager); - } - - return refcount; -} - -static void standard_quality_manager_set_topology(struct quality_manager *manager, IMFTopology *topology) -{ - if (manager->topology) - IMFTopology_Release(manager->topology); - manager->topology = topology; - if (manager->topology) - IMFTopology_AddRef(manager->topology); -} - -static HRESULT WINAPI standard_quality_manager_NotifyTopology(IMFQualityManager *iface, IMFTopology *topology) -{ - struct quality_manager *manager = impl_from_IMFQualityManager(iface); - HRESULT hr = S_OK; - - TRACE("%p, %p.\n", iface, topology); - - EnterCriticalSection(&manager->cs); - if (manager->state == QUALITY_MANAGER_SHUT_DOWN) - hr = MF_E_SHUTDOWN; - else - { - standard_quality_manager_set_topology(manager, topology); - } - LeaveCriticalSection(&manager->cs); - - return hr; -} - -static void standard_quality_manager_release_clock(struct quality_manager *manager) -{ - if (manager->clock) - { - IMFPresentationClock_RemoveClockStateSink(manager->clock, &manager->IMFClockStateSink_iface); - IMFPresentationClock_Release(manager->clock); - } - manager->clock = NULL; -} - -static HRESULT WINAPI standard_quality_manager_NotifyPresentationClock(IMFQualityManager *iface, - IMFPresentationClock *clock) -{ - struct quality_manager *manager = impl_from_IMFQualityManager(iface); - HRESULT hr = S_OK; - - TRACE("%p, %p.\n", iface, clock); - - EnterCriticalSection(&manager->cs); - if (manager->state == QUALITY_MANAGER_SHUT_DOWN) - hr = MF_E_SHUTDOWN; - else if (!clock) - hr = E_POINTER; - else - { - standard_quality_manager_release_clock(manager); - manager->clock = clock; - IMFPresentationClock_AddRef(manager->clock); - if (FAILED(IMFPresentationClock_AddClockStateSink(manager->clock, &manager->IMFClockStateSink_iface))) - WARN("Failed to set state sink.\n"); - } - LeaveCriticalSection(&manager->cs); - - return hr; -} - -static HRESULT WINAPI standard_quality_manager_NotifyProcessInput(IMFQualityManager *iface, IMFTopologyNode *node, - LONG input_index, IMFSample *sample) -{ - TRACE("%p, %p, %d, %p stub.\n", iface, node, input_index, sample); - - return E_NOTIMPL; -} - -static HRESULT WINAPI standard_quality_manager_NotifyProcessOutput(IMFQualityManager *iface, IMFTopologyNode *node, - LONG output_index, IMFSample *sample) -{ - TRACE("%p, %p, %d, %p stub.\n", iface, node, output_index, sample); - - return E_NOTIMPL; -} - -static HRESULT WINAPI standard_quality_manager_NotifyQualityEvent(IMFQualityManager *iface, IUnknown *object, - IMFMediaEvent *event) -{ - FIXME("%p, %p, %p stub.\n", iface, object, event); - - return E_NOTIMPL; -} - -static HRESULT WINAPI standard_quality_manager_Shutdown(IMFQualityManager *iface) -{ - struct quality_manager *manager = impl_from_IMFQualityManager(iface); - - TRACE("%p.\n", iface); - - EnterCriticalSection(&manager->cs); - if (manager->state != QUALITY_MANAGER_SHUT_DOWN) - { - standard_quality_manager_release_clock(manager); - standard_quality_manager_set_topology(manager, NULL); - manager->state = QUALITY_MANAGER_SHUT_DOWN; - } - LeaveCriticalSection(&manager->cs); - - return S_OK; -} - -static const IMFQualityManagerVtbl standard_quality_manager_vtbl = -{ - standard_quality_manager_QueryInterface, - standard_quality_manager_AddRef, - standard_quality_manager_Release, - standard_quality_manager_NotifyTopology, - standard_quality_manager_NotifyPresentationClock, - standard_quality_manager_NotifyProcessInput, - standard_quality_manager_NotifyProcessOutput, - standard_quality_manager_NotifyQualityEvent, - standard_quality_manager_Shutdown, -}; - -static HRESULT WINAPI standard_quality_manager_sink_QueryInterface(IMFClockStateSink *iface, - REFIID riid, void **obj) -{ - struct quality_manager *manager = impl_from_qm_IMFClockStateSink(iface); - return IMFQualityManager_QueryInterface(&manager->IMFQualityManager_iface, riid, obj); -} - -static ULONG WINAPI standard_quality_manager_sink_AddRef(IMFClockStateSink *iface) -{ - struct quality_manager *manager = impl_from_qm_IMFClockStateSink(iface); - return IMFQualityManager_AddRef(&manager->IMFQualityManager_iface); -} - -static ULONG WINAPI standard_quality_manager_sink_Release(IMFClockStateSink *iface) -{ - struct quality_manager *manager = impl_from_qm_IMFClockStateSink(iface); - return IMFQualityManager_Release(&manager->IMFQualityManager_iface); -} - -static HRESULT WINAPI standard_quality_manager_sink_OnClockStart(IMFClockStateSink *iface, - MFTIME systime, LONGLONG offset) -{ - return S_OK; -} - -static HRESULT WINAPI standard_quality_manager_sink_OnClockStop(IMFClockStateSink *iface, - MFTIME systime) -{ - return S_OK; -} - -static HRESULT WINAPI standard_quality_manager_sink_OnClockPause(IMFClockStateSink *iface, - MFTIME systime) -{ - return S_OK; -} - -static HRESULT WINAPI standard_quality_manager_sink_OnClockRestart(IMFClockStateSink *iface, - MFTIME systime) -{ - return S_OK; -} - -static HRESULT WINAPI standard_quality_manager_sink_OnClockSetRate(IMFClockStateSink *iface, - MFTIME systime, float rate) -{ - return S_OK; -} - -static const IMFClockStateSinkVtbl standard_quality_manager_sink_vtbl = -{ - standard_quality_manager_sink_QueryInterface, - standard_quality_manager_sink_AddRef, - standard_quality_manager_sink_Release, - standard_quality_manager_sink_OnClockStart, - standard_quality_manager_sink_OnClockStop, - standard_quality_manager_sink_OnClockPause, - standard_quality_manager_sink_OnClockRestart, - standard_quality_manager_sink_OnClockSetRate, -}; - -HRESULT WINAPI MFCreateStandardQualityManager(IMFQualityManager **manager) -{ - struct quality_manager *object; - - TRACE("%p.\n", manager); - - if (!(object = calloc(1, sizeof(*object)))) - return E_OUTOFMEMORY; - - object->IMFQualityManager_iface.lpVtbl = &standard_quality_manager_vtbl; - object->IMFClockStateSink_iface.lpVtbl = &standard_quality_manager_sink_vtbl; - object->refcount = 1; - InitializeCriticalSection(&object->cs); - - *manager = &object->IMFQualityManager_iface; - - return S_OK; -}