Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 131 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 9 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 67c60663b33..a3311bc10f1 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -19,6 +19,7 @@ #define COBJMACROS
#include "mfplat_private.h" +#include "rtworkq.h"
#include "wine/debug.h"
@@ -71,6 +72,10 @@ struct sample DWORD prop_flags; LONGLONG duration; LONGLONG timestamp; + + /* Tracked sample functionality. */ + IRtwqAsyncResult *tracked_result; + LONG tracked_refcount; };
static inline struct memory_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface) @@ -752,22 +757,53 @@ static ULONG WINAPI sample_AddRef(IMFSample *iface) return refcount; }
+static void release_sample_object(struct sample *sample) +{ + size_t i; + + for (i = 0; i < sample->buffer_count; ++i) + IMFMediaBuffer_Release(sample->buffers[i]); + clear_attributes_object(&sample->attributes); + heap_free(sample->buffers); + heap_free(sample); +} + static ULONG WINAPI sample_Release(IMFSample *iface) { struct sample *sample = impl_from_IMFSample(iface); ULONG refcount = InterlockedDecrement(&sample->attributes.ref); - size_t i;
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount) + release_sample_object(sample); + + return refcount; +} + +static ULONG WINAPI sample_tracked_Release(IMFSample *iface) +{ + struct sample *sample = impl_from_IMFSample(iface); + ULONG refcount; + HRESULT hr; + + EnterCriticalSection(&sample->attributes.cs); + refcount = InterlockedDecrement(&sample->attributes.ref); + if (sample->tracked_result && sample->tracked_refcount == refcount) { - for (i = 0; i < sample->buffer_count; ++i) - IMFMediaBuffer_Release(sample->buffers[i]); - clear_attributes_object(&sample->attributes); - heap_free(sample->buffers); - heap_free(sample); + /* Call could fail if queue system is not initialized, it's not critical. */ + if (FAILED(hr = RtwqInvokeCallback(sample->tracked_result))) + WARN("Failed to invoke tracking callback, hr %#x.\n", hr); + IRtwqAsyncResult_Release(sample->tracked_result); + sample->tracked_result = NULL; + sample->tracked_refcount = 0; } + LeaveCriticalSection(&sample->attributes.cs); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + release_sample_object(sample);
return refcount; } @@ -1484,9 +1520,34 @@ static ULONG WINAPI tracked_sample_Release(IMFTrackedSample *iface) static HRESULT WINAPI tracked_sample_SetAllocator(IMFTrackedSample *iface, IMFAsyncCallback *sample_allocator, IUnknown *state) { - FIXME("%p, %p, %p.\n", iface, sample_allocator, state); + struct sample *sample = impl_from_IMFTrackedSample(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, sample_allocator, state); + + EnterCriticalSection(&sample->attributes.cs); + + if (sample->tracked_result) + hr = MF_E_NOTACCEPTING; + else + { + if (SUCCEEDED(hr = RtwqCreateAsyncResult((IUnknown *)iface, (IRtwqAsyncCallback *)sample_allocator, + state, &sample->tracked_result))) + { + /* Account for additional refcount brought by 'state' object. This threshold is used + on Release() to invoke tracker callback. */ + sample->tracked_refcount = 1; + if (state == (IUnknown *)&sample->IMFTrackedSample_iface || + state == (IUnknown *)&sample->IMFSample_iface) + { + ++sample->tracked_refcount; + } + } + } + + LeaveCriticalSection(&sample->attributes.cs); + + return hr; }
static const IMFTrackedSampleVtbl tracked_sample_vtbl = @@ -1497,6 +1558,58 @@ static const IMFTrackedSampleVtbl tracked_sample_vtbl = tracked_sample_SetAllocator, };
+static const IMFSampleVtbl sample_tracked_vtbl = +{ + sample_QueryInterface, + sample_AddRef, + sample_tracked_Release, + sample_GetItem, + sample_GetItemType, + sample_CompareItem, + sample_Compare, + sample_GetUINT32, + sample_GetUINT64, + sample_GetDouble, + sample_GetGUID, + sample_GetStringLength, + sample_GetString, + sample_GetAllocatedString, + sample_GetBlobSize, + sample_GetBlob, + sample_GetAllocatedBlob, + sample_GetUnknown, + sample_SetItem, + sample_DeleteItem, + sample_DeleteAllItems, + sample_SetUINT32, + sample_SetUINT64, + sample_SetDouble, + sample_SetGUID, + sample_SetString, + sample_SetBlob, + sample_SetUnknown, + sample_LockStore, + sample_UnlockStore, + sample_GetCount, + sample_GetItemByIndex, + sample_CopyAllItems, + sample_GetSampleFlags, + sample_SetSampleFlags, + sample_GetSampleTime, + sample_SetSampleTime, + sample_GetSampleDuration, + sample_SetSampleDuration, + sample_GetBufferCount, + sample_GetBufferByIndex, + sample_ConvertToContiguousBuffer, + sample_AddBuffer, + sample_RemoveBufferByIndex, + sample_RemoveAllBuffers, + sample_GetTotalLength, + sample_CopyToBuffer, +}; + + /*********************************************************************** * MFCreateSample (mfplat.@) */ @@ -1546,7 +1659,7 @@ HRESULT WINAPI MFCreateTrackedSample(IMFTrackedSample **sample) return hr; }
- object->IMFSample_iface.lpVtbl = &samplevtbl; + object->IMFSample_iface.lpVtbl = &sample_tracked_vtbl; object->IMFTrackedSample_iface.lpVtbl = &tracked_sample_vtbl;
*sample = &object->IMFTrackedSample_iface;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/Makefile.in | 1 + dlls/mf/evr.c | 218 ++++++++++++++++++++++++++++++++++++++++++++ dlls/mf/main.c | 38 -------- dlls/mf/tests/mf.c | 9 +- 4 files changed, 224 insertions(+), 42 deletions(-) create mode 100644 dlls/mf/evr.c
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in index fe156e43abf..1d2bfc8a782 100644 --- a/dlls/mf/Makefile.in +++ b/dlls/mf/Makefile.in @@ -5,6 +5,7 @@ IMPORTS = advapi32 mfplat ole32 uuid mfuuid EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \ + evr.c \ main.c \ samplegrabber.c \ sar.c \ diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c new file mode 100644 index 00000000000..27238339031 --- /dev/null +++ b/dlls/mf/evr.c @@ -0,0 +1,218 @@ +/* + * Copyright 2020 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 + */ + +#define COBJMACROS + +#include "mf_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); + +struct video_renderer +{ + IMFMediaSink IMFMediaSink_iface; + LONG refcount; +}; + +static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface) +{ + return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSink_iface); +} + +static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFMediaSink) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + } + else + { + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*obj); + + return S_OK; +} + +static ULONG WINAPI video_renderer_sink_AddRef(IMFMediaSink *iface) +{ + struct video_renderer *renderer = impl_from_IMFMediaSink(iface); + ULONG refcount = InterlockedIncrement(&renderer->refcount); + TRACE("%p, refcount %u.\n", iface, refcount); + return refcount; +} + +static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface) +{ + struct video_renderer *renderer = impl_from_IMFMediaSink(iface); + ULONG refcount = InterlockedDecrement(&renderer->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + heap_free(renderer); + } + + return refcount; +} + +static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags) +{ + FIXME("%p, %p.\n", iface, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD stream_sink_id, + IMFMediaType *media_type, IMFStreamSink **stream_sink) +{ + FIXME("%p, %#x, %p, %p.\n", iface, stream_sink_id, media_type, stream_sink); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD stream_sink_id) +{ + FIXME("%p, %#x.\n", iface, stream_sink_id); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count) +{ + FIXME("%p, %p.\n", iface, count); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index, + IMFStreamSink **stream) +{ + FIXME("%p, %u, %p.\n", iface, index, stream); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD stream_sink_id, + IMFStreamSink **stream) +{ + FIXME("%p, %#x, %p.\n", iface, stream_sink_id, stream); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock) +{ + FIXME("%p, %p.\n", iface, clock); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock) +{ + FIXME("%p, %p.\n", iface, clock); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static const IMFMediaSinkVtbl video_renderer_sink_vtbl = +{ + video_renderer_sink_QueryInterface, + video_renderer_sink_AddRef, + video_renderer_sink_Release, + video_renderer_sink_GetCharacteristics, + video_renderer_sink_AddStreamSink, + video_renderer_sink_RemoveStreamSink, + video_renderer_sink_GetStreamSinkCount, + video_renderer_sink_GetStreamSinkByIndex, + video_renderer_sink_GetStreamSinkById, + video_renderer_sink_SetPresentationClock, + video_renderer_sink_GetPresentationClock, + video_renderer_sink_Shutdown, +}; + +static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) +{ + struct video_renderer *object; + + TRACE("%p, %p, %p.\n", attributes, user_context, obj); + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl; + object->refcount = 1; + + *obj = (IUnknown *)&object->IMFMediaSink_iface; + + return S_OK; +} + +static void evr_shutdown_object(void *user_context, IUnknown *obj) +{ + IMFMediaSink *sink; + + if (SUCCEEDED(IUnknown_QueryInterface(obj, &IID_IMFMediaSink, (void **)&sink))) + { + IMFMediaSink_Shutdown(sink); + IMFMediaSink_Release(sink); + } +} + +static void evr_free_private(void *user_context) +{ +} + +static const struct activate_funcs evr_activate_funcs = +{ + evr_create_object, + evr_shutdown_object, + evr_free_private, +}; + +/*********************************************************************** + * MFCreateVideoRendererActivate (mf.@) + */ +HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate) +{ + HRESULT hr; + + TRACE("%p, %p.\n", hwnd, activate); + + if (!activate) + return E_POINTER; + + hr = create_activation_object(hwnd, &evr_activate_funcs, activate); + if (SUCCEEDED(hr)) + IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd); + + return hr; +} diff --git a/dlls/mf/main.c b/dlls/mf/main.c index 3546caa6912..4d9f5a7ea39 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -1267,44 +1267,6 @@ HRESULT WINAPI MFEnumDeviceSources(IMFAttributes *attributes, IMFActivate ***sou return S_OK; }
-static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) -{ - FIXME("%p, %p, %p.\n", attributes, user_context, obj); - - return E_NOTIMPL; -} - -static void evr_shutdown_object(void *user_context, IUnknown *obj) -{ -} - -static void evr_free_private(void *user_context) -{ -} - -static const struct activate_funcs evr_activate_funcs = -{ - evr_create_object, - evr_shutdown_object, - evr_free_private, -}; - -HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate) -{ - HRESULT hr; - - TRACE("%p, %p.\n", hwnd, activate); - - if (!activate) - return E_POINTER; - - hr = create_activation_object(hwnd, &evr_activate_funcs, activate); - if (SUCCEEDED(hr)) - IMFActivate_SetUINT64(*activate, &MF_ACTIVATE_VIDEO_WINDOW, (ULONG_PTR)hwnd); - - return hr; -} - struct simple_type_handler { IMFMediaTypeHandler IMFMediaTypeHandler_iface; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index d252bab9b3b..72444dd2482 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3250,23 +3250,23 @@ static void test_evr(void) ok(!value, "Unexpected value.\n");
hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); -todo_wine ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
-if (hr == S_OK) -{ hr = IMFMediaSink_GetCharacteristics(sink, &flags); +todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFActivate_ShutdownObject(activate); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
hr = IMFMediaSink_GetCharacteristics(sink, &flags); +todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
/* Activate again. */ hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2); ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); +todo_wine ok(sink == sink2, "Unexpected instance.\n"); IMFMediaSink_Release(sink2);
@@ -3274,6 +3274,7 @@ if (hr == S_OK) ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
hr = IMFMediaSink_GetCharacteristics(sink, &flags); +todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2); @@ -3284,7 +3285,7 @@ if (hr == S_OK)
IMFMediaSink_Release(sink2); IMFMediaSink_Release(sink); -} + IMFActivate_Release(activate);
CoUninitialize();
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 48 +++++++++++++++++++++++++++++++++++++++++++++- dlls/mf/tests/mf.c | 9 ++++++++- 2 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 27238339031..2ac85fab795 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); struct video_renderer { IMFMediaSink IMFMediaSink_iface; + IMFMediaSinkPreroll IMFMediaSinkPreroll_iface; LONG refcount; };
@@ -33,14 +34,25 @@ static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface) return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSink_iface); }
+static struct video_renderer *impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll *iface) +{ + return CONTAINING_RECORD(iface, struct video_renderer, IMFMediaSinkPreroll_iface); +} + static HRESULT WINAPI video_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj) { + struct video_renderer *renderer = impl_from_IMFMediaSink(iface); + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFMediaSink) || IsEqualIID(riid, &IID_IUnknown)) { - *obj = iface; + *obj = &renderer->IMFMediaSink_iface; + } + else if (IsEqualIID(riid, &IID_IMFMediaSinkPreroll)) + { + *obj = &renderer->IMFMediaSinkPreroll_iface; } else { @@ -159,6 +171,39 @@ static const IMFMediaSinkVtbl video_renderer_sink_vtbl = video_renderer_sink_Shutdown, };
+static HRESULT WINAPI video_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj) +{ + struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface); + return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj); +} + +static ULONG WINAPI video_renderer_preroll_AddRef(IMFMediaSinkPreroll *iface) +{ + struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface); + return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface); +} + +static ULONG WINAPI video_renderer_preroll_Release(IMFMediaSinkPreroll *iface) +{ + struct video_renderer *renderer = impl_from_IMFMediaSinkPreroll(iface); + return IMFMediaSink_Release(&renderer->IMFMediaSink_iface); +} + +static HRESULT WINAPI video_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *iface, MFTIME start_time) +{ + FIXME("%p, %s.\n", iface, debugstr_time(start_time)); + + return E_NOTIMPL; +} + +static const IMFMediaSinkPrerollVtbl video_renderer_preroll_vtbl = +{ + video_renderer_preroll_QueryInterface, + video_renderer_preroll_AddRef, + video_renderer_preroll_Release, + video_renderer_preroll_NotifyPreroll, +}; + static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) { struct video_renderer *object; @@ -169,6 +214,7 @@ static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, return E_OUTOFMEMORY;
object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl; + object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl; object->refcount = 1;
*obj = (IUnknown *)&object->IMFMediaSink_iface; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 72444dd2482..44d69a7a8cc 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3226,6 +3226,7 @@ todo_wine
static void test_evr(void) { + IMFMediaSinkPreroll *preroll; IMFMediaSink *sink, *sink2; IMFActivate *activate; DWORD flags, count; @@ -3252,9 +3253,15 @@ static void test_evr(void) hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
+ flags = 0; hr = IMFMediaSink_GetCharacteristics(sink, &flags); -todo_wine +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#x.\n", flags); +} + hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaSinkPreroll, (void **)&preroll); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFMediaSinkPreroll_Release(preroll);
hr = IMFActivate_ShutdownObject(activate); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 6 ++++-- dlls/mf/tests/mf.c | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 2ac85fab795..a5a39fe7786 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -91,9 +91,11 @@ static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags) { - FIXME("%p, %p.\n", iface, flags); + TRACE("%p, %p.\n", iface, flags);
- return E_NOTIMPL; + *flags = MEDIASINK_CLOCK_REQUIRED | MEDIASINK_CAN_PREROLL; + + return S_OK; }
static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD stream_sink_id, diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 44d69a7a8cc..c274c3263d3 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3253,12 +3253,10 @@ static void test_evr(void) hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
- flags = 0; hr = IMFMediaSink_GetCharacteristics(sink, &flags); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#x.\n", flags); -} + hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaSinkPreroll, (void **)&preroll); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); IMFMediaSinkPreroll_Release(preroll);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/evr.c | 27 +++++++++++++++++++++++++-- dlls/mf/main.c | 1 - dlls/mf/mf_private.h | 1 + dlls/mf/samplegrabber.c | 1 - dlls/mf/sar.c | 1 - dlls/mf/session.c | 1 - dlls/mf/tests/mf.c | 2 -- dlls/mf/topology.c | 1 - 8 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index a5a39fe7786..64944673d5a 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -22,11 +22,18 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+enum video_renderer_flags +{ + EVR_SHUT_DOWN = 0x1, +}; + struct video_renderer { IMFMediaSink IMFMediaSink_iface; IMFMediaSinkPreroll IMFMediaSinkPreroll_iface; LONG refcount; + unsigned int flags; + CRITICAL_SECTION cs; };
static struct video_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface) @@ -83,6 +90,7 @@ static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
if (!refcount) { + DeleteCriticalSection(&renderer->cs); heap_free(renderer); }
@@ -91,8 +99,13 @@ static ULONG WINAPI video_renderer_sink_Release(IMFMediaSink *iface)
static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags) { + struct video_renderer *renderer = impl_from_IMFMediaSink(iface); + TRACE("%p, %p.\n", iface, flags);
+ if (renderer->flags & EVR_SHUT_DOWN) + return MF_E_SHUTDOWN; + *flags = MEDIASINK_CLOCK_REQUIRED | MEDIASINK_CAN_PREROLL;
return S_OK; @@ -152,9 +165,18 @@ static HRESULT WINAPI video_renderer_sink_GetPresentationClock(IMFMediaSink *ifa
static HRESULT WINAPI video_renderer_sink_Shutdown(IMFMediaSink *iface) { - FIXME("%p.\n", iface); + struct video_renderer *renderer = impl_from_IMFMediaSink(iface);
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + if (renderer->flags & EVR_SHUT_DOWN) + return MF_E_SHUTDOWN; + + EnterCriticalSection(&renderer->cs); + renderer->flags |= EVR_SHUT_DOWN; + LeaveCriticalSection(&renderer->cs); + + return S_OK; }
static const IMFMediaSinkVtbl video_renderer_sink_vtbl = @@ -218,6 +240,7 @@ static HRESULT evr_create_object(IMFAttributes *attributes, void *user_context, object->IMFMediaSink_iface.lpVtbl = &video_renderer_sink_vtbl; object->IMFMediaSinkPreroll_iface.lpVtbl = &video_renderer_preroll_vtbl; object->refcount = 1; + InitializeCriticalSection(&object->cs);
*obj = (IUnknown *)&object->IMFMediaSink_iface;
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index 4d9f5a7ea39..8656c6cddf2 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -27,7 +27,6 @@ #include "rpcproxy.h"
#include "mfapi.h" -#include "mferror.h"
#include "mf_private.h"
diff --git a/dlls/mf/mf_private.h b/dlls/mf/mf_private.h index 14f7288c9bb..f4356219731 100644 --- a/dlls/mf/mf_private.h +++ b/dlls/mf/mf_private.h @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "mferror.h" #include "mfidl.h"
#include "wine/heap.h" diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 92330abc9fe..cbf7453d04d 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -20,7 +20,6 @@
#include "mfapi.h" #include "mfidl.h" -#include "mferror.h" #include "mf_private.h"
#include "wine/debug.h" diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 89a517b1358..8a27c0658c3 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -20,7 +20,6 @@
#include "mfapi.h" #include "mfidl.h" -#include "mferror.h" #include "mf_private.h" #include "initguid.h" #include "mmdeviceapi.h" diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 39b5e1a5377..d0365ea8564 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -25,7 +25,6 @@ #include "winbase.h" #include "mfidl.h" #include "mfapi.h" -#include "mferror.h"
#include "wine/debug.h" #include "wine/heap.h" diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index c274c3263d3..691734aa9a9 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3265,7 +3265,6 @@ static void test_evr(void) ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
hr = IMFMediaSink_GetCharacteristics(sink, &flags); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
/* Activate again. */ @@ -3279,7 +3278,6 @@ todo_wine ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
hr = IMFMediaSink_GetCharacteristics(sink, &flags); -todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2); diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 432979206ba..f4cc30a9fc6 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -27,7 +27,6 @@ #undef INITGUID #include <guiddef.h> #include "mfapi.h" -#include "mferror.h" #include "mfidl.h"
#include "wine/debug.h"
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=74874
Your paranoid android.
=== debiant (64 bit WoW report) ===
mfplat: Unhandled exception: page fault on execute access to 0x0a2e7823 in 32-bit code (0x0a2e7823).