[PATCH 2/2] evr/mixer: Flush on MFT_MESSAGE_NOTIFY_END_STREAMING.

Nikolay Sivov nsivov at codeweavers.com
Wed Nov 10 06:33:22 CST 2021


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/evr/mixer.c     |  21 +++-----
 dlls/evr/tests/evr.c | 121 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+), 14 deletions(-)

diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index b9a28c4ad75..8fe80c2f4a9 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -1125,34 +1125,27 @@ static HRESULT WINAPI video_mixer_transform_ProcessMessage(IMFTransform *iface,
 
     TRACE("%p, %#x, %#lx.\n", iface, message, param);
 
+    EnterCriticalSection(&mixer->cs);
+
     switch (message)
     {
         case MFT_MESSAGE_SET_D3D_MANAGER:
-
-            EnterCriticalSection(&mixer->cs);
-
             video_mixer_release_device_manager(mixer);
             if (param)
                 hr = IUnknown_QueryInterface((IUnknown *)param, &IID_IDirect3DDeviceManager9, (void **)&mixer->device_manager);
 
-            LeaveCriticalSection(&mixer->cs);
-
             break;
 
         case MFT_MESSAGE_COMMAND_FLUSH:
-
-            EnterCriticalSection(&mixer->cs);
             video_mixer_flush_input(mixer);
-            LeaveCriticalSection(&mixer->cs);
 
             break;
 
         case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
         case MFT_MESSAGE_NOTIFY_END_STREAMING:
-
-            EnterCriticalSection(&mixer->cs);
-
-            if (!mixer->is_streaming)
+            if (mixer->is_streaming)
+                video_mixer_flush_input(mixer);
+            else
             {
                 for (i = 0; i < mixer->input_count; ++i)
                     video_mixer_request_sample(mixer, i);
@@ -1160,8 +1153,6 @@ static HRESULT WINAPI video_mixer_transform_ProcessMessage(IMFTransform *iface,
 
             mixer->is_streaming = message == MFT_MESSAGE_NOTIFY_BEGIN_STREAMING;
 
-            LeaveCriticalSection(&mixer->cs);
-
             break;
 
         case MFT_MESSAGE_COMMAND_DRAIN:
@@ -1172,6 +1163,8 @@ static HRESULT WINAPI video_mixer_transform_ProcessMessage(IMFTransform *iface,
             hr = E_NOTIMPL;
     }
 
+    LeaveCriticalSection(&mixer->cs);
+
     return hr;
 }
 
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index 57b64937b79..046a7e4db59 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -94,6 +94,15 @@ static IFilterGraph2 *create_graph(void)
     return ret;
 }
 
+#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
+static void _expect_ref(IUnknown *obj, ULONG ref, int line)
+{
+    ULONG rc;
+    IUnknown_AddRef(obj);
+    rc = IUnknown_Release(obj);
+    ok_(__FILE__,line)(rc == ref, "Unexpected refcount %d, expected %d.\n", rc, ref);
+}
+
 static ULONG get_refcount(void *iface)
 {
     IUnknown *unknown = iface;
@@ -3061,6 +3070,117 @@ static void test_MFIsFormatYUV(void)
     }
 }
 
+static void test_mixer_render(void)
+{
+    IMFMediaType *video_type, *output_type;
+    IMFVideoMixerControl *mixer_control;
+    IDirect3DDeviceManager9 *manager;
+    IMFVideoProcessor *processor;
+    IDirect3DSurface9 *surface;
+    IDirect3DDevice9 *device;
+    IMFTransform *mixer;
+    IMFSample *sample;
+    DWORD status;
+    HWND window;
+    UINT token;
+    HRESULT hr;
+
+    window = create_window();
+    if (!(device = create_device(window)))
+    {
+        skip("Failed to create a D3D device, skipping tests.\n");
+        goto done;
+    }
+
+    hr = MFCreateVideoMixer(NULL, &IID_IDirect3DDevice9, &IID_IMFTransform, (void **)&mixer);
+    ok(hr == S_OK, "Failed to create a mixer, hr %#x.\n", hr);
+
+    hr = IMFTransform_QueryInterface(mixer, &IID_IMFVideoProcessor, (void **)&processor);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTransform_QueryInterface(mixer, &IID_IMFVideoMixerControl, (void **)&mixer_control);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    /* Configure device and media types. */
+    hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token);
+    ok(hr == S_OK, "Failed to set a device, hr %#x.\n", hr);
+
+    hr = IMFTransform_ProcessMessage(mixer, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)manager);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    video_type = create_video_type(&MFVideoFormat_RGB32);
+
+    hr = IMFMediaType_SetUINT64(video_type, &MF_MT_FRAME_SIZE, (UINT64)64 << 32 | 64);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    hr = IMFMediaType_SetUINT32(video_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTransform_SetInputType(mixer, 0, video_type, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTransform_GetOutputAvailableType(mixer, 0, 0, &output_type);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTransform_SetOutputType(mixer, 0, output_type, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    IMFMediaType_Release(output_type);
+    IMFMediaType_Release(video_type);
+
+    surface = create_surface(manager, 64, 64);
+    ok(!!surface, "Failed to create input surface.\n");
+
+    hr = MFCreateVideoSampleFromSurface((IUnknown *)surface, &sample);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    EXPECT_REF(sample, 1);
+    hr = IMFTransform_ProcessInput(mixer, 0, sample, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    EXPECT_REF(sample, 2);
+
+    hr = IMFTransform_GetOutputStatus(mixer, &status);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(status == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected status %#x.\n", status);
+
+    /* FLUSH/END_STREAMING releases input */
+    hr = IMFTransform_ProcessMessage(mixer, MFT_MESSAGE_NOTIFY_END_STREAMING, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    EXPECT_REF(sample, 1);
+
+    hr = IMFTransform_GetOutputStatus(mixer, &status);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!status, "Unexpected status %#x.\n", status);
+
+    hr = IMFTransform_ProcessInput(mixer, 0, sample, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    EXPECT_REF(sample, 2);
+
+    hr = IMFTransform_GetOutputStatus(mixer, &status);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(status == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected status %#x.\n", status);
+
+    hr = IMFTransform_ProcessMessage(mixer, MFT_MESSAGE_COMMAND_FLUSH, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    EXPECT_REF(sample, 1);
+
+    hr = IMFTransform_GetOutputStatus(mixer, &status);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!status, "Unexpected status %#x.\n", status);
+
+    IMFSample_Release(sample);
+    IDirect3DSurface9_Release(surface);
+    IMFTransform_Release(mixer);
+
+    IDirect3DDevice9_Release(device);
+    IDirect3DDeviceManager9_Release(manager);
+
+done:
+    DestroyWindow(window);
+}
+
 START_TEST(evr)
 {
     IMFVideoPresenter *presenter;
@@ -3099,6 +3219,7 @@ START_TEST(evr)
     test_mixer_output_rectangle();
     test_mixer_zorder();
     test_mixer_samples();
+    test_mixer_render();
     test_MFIsFormatYUV();
 
     CoUninitialize();
-- 
2.33.0




More information about the wine-devel mailing list