Nikolay Sivov : evr/mixer: Fill output surfaces when not streaming.

Alexandre Julliard julliard at winehq.org
Thu Oct 22 15:27:31 CDT 2020


Module: wine
Branch: master
Commit: 775daad7efcd272a35dc01178b18d701d0924e89
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=775daad7efcd272a35dc01178b18d701d0924e89

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Thu Oct 22 14:02:46 2020 +0300

evr/mixer: Fill output surfaces when not streaming.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/evr/mixer.c     | 91 ++++++++++++++++++++++++++++++++++++++++++++++++----
 dlls/evr/tests/evr.c | 19 ++++++++---
 2 files changed, 100 insertions(+), 10 deletions(-)

diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index 2c2fda51cd1..b4bf1ed0967 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -712,6 +712,13 @@ static HRESULT video_mixer_collect_output_types(struct video_mixer *mixer, const
     return count ? S_OK : hr;
 }
 
+static HRESULT video_mixer_open_device_handle(struct video_mixer *mixer)
+{
+    IDirect3DDeviceManager9_CloseDeviceHandle(mixer->device_manager, mixer->device_handle);
+    mixer->device_handle = NULL;
+    return IDirect3DDeviceManager9_OpenDeviceHandle(mixer->device_manager, &mixer->device_handle);
+}
+
 static HRESULT video_mixer_get_processor_service(struct video_mixer *mixer, IDirectXVideoProcessorService **service)
 {
     HRESULT hr;
@@ -728,9 +735,7 @@ static HRESULT video_mixer_get_processor_service(struct video_mixer *mixer, IDir
                 &IID_IDirectXVideoProcessorService, (void **)service);
         if (hr == DXVA2_E_NEW_VIDEO_DEVICE)
         {
-            IDirect3DDeviceManager9_CloseDeviceHandle(mixer->device_manager, mixer->device_handle);
-            mixer->device_handle = NULL;
-            if (SUCCEEDED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(mixer->device_manager, &mixer->device_handle)))
+            if (SUCCEEDED(hr = video_mixer_open_device_handle(mixer)))
                 continue;
         }
         break;
@@ -1083,12 +1088,86 @@ static HRESULT WINAPI video_mixer_transform_ProcessInput(IMFTransform *iface, DW
     return hr;
 }
 
+static HRESULT video_mixer_get_sample_surface(IMFSample *sample, IDirect3DSurface9 **surface)
+{
+    IMFMediaBuffer *buffer;
+    IMFGetService *gs;
+    HRESULT hr;
+
+    if (FAILED(hr = IMFSample_GetBufferByIndex(sample, 0, &buffer)))
+        return hr;
+
+    hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMFGetService, (void **)&gs);
+    IMFMediaBuffer_Release(buffer);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IMFGetService_GetService(gs, &MR_BUFFER_SERVICE, &IID_IDirect3DSurface9, (void **)surface);
+    IMFGetService_Release(gs);
+    return hr;
+}
+
+static HRESULT video_mixer_get_d3d_device(struct video_mixer *mixer, IDirect3DDevice9 **device)
+{
+    HRESULT hr;
+
+    for (;;)
+    {
+        hr = IDirect3DDeviceManager9_LockDevice(mixer->device_manager, mixer->device_handle,
+                device, TRUE);
+        if (hr == DXVA2_E_NEW_VIDEO_DEVICE)
+        {
+            if (SUCCEEDED(hr = video_mixer_open_device_handle(mixer)))
+                continue;
+        }
+        break;
+    }
+
+    return hr;
+}
+
 static HRESULT WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
-        MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
+        MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
 {
-    FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+    struct video_mixer *mixer = impl_from_IMFTransform(iface);
+    IDirect3DSurface9 *surface;
+    IDirect3DDevice9 *device;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, buffers, status);
+
+    if (!buffers || !count || !buffers->pSample)
+        return E_INVALIDARG;
+
+    if (count > 1)
+        FIXME("Multiple buffers are not handled.\n");
+
+    *status = 0;
+
+    EnterCriticalSection(&mixer->cs);
+
+    if (SUCCEEDED(hr = video_mixer_get_sample_surface(buffers->pSample, &surface)))
+    {
+        if (mixer->is_streaming)
+        {
+            FIXME("Streaming state is not handled.\n");
+            hr = E_NOTIMPL;
+        }
+        else
+        {
+            if (SUCCEEDED(hr = video_mixer_get_d3d_device(mixer, &device)))
+            {
+                IDirect3DDevice9_ColorFill(device, surface, NULL, 0);
+                IDirect3DDeviceManager9_UnlockDevice(mixer->device_manager, mixer->device_handle, FALSE);
+                IDirect3DDevice9_Release(device);
+            }
+        }
+        IDirect3DSurface9_Release(surface);
+    }
+
+    LeaveCriticalSection(&mixer->cs);
+
+    return hr;
 }
 
 static const IMFTransformVtbl video_mixer_transform_vtbl =
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index 7cf127d4d8c..fc74a11496b 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -2062,6 +2062,7 @@ static void test_mixer_samples(void)
 {
     IDirect3DDeviceManager9 *manager;
     MFT_OUTPUT_DATA_BUFFER buffer;
+    IMFVideoProcessor *processor;
     IDirect3DSurface9 *surface;
     IMFDesiredSample *desired;
     IDirect3DDevice9 *device;
@@ -2086,6 +2087,9 @@ static void test_mixer_samples(void)
     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_GetInputStatus(mixer, 0, NULL);
     ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
 
@@ -2147,7 +2151,6 @@ static void test_mixer_samples(void)
 
     memset(&buffer, 0, sizeof(buffer));
     hr = IMFTransform_ProcessOutput(mixer, 0, 1, &buffer, &status);
-todo_wine
     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
 
     /* It needs a sample with a backing surface. */
@@ -2156,7 +2159,6 @@ todo_wine
 
     buffer.pSample = sample;
     hr = IMFTransform_ProcessOutput(mixer, 0, 1, &buffer, &status);
-todo_wine
     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
 
     IMFSample_Release(sample);
@@ -2175,17 +2177,25 @@ todo_wine
     ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#x.\n", hr);
 
     color = get_surface_color(surface, 0, 0);
+todo_wine
     ok(color == D3DCOLOR_ARGB(0x10, 0xff, 0x00, 0x00), "Unexpected color %#x.\n", color);
 
     /* Streaming is not started yet. Output is colored black, but only if desired timestamps were set. */
     IMFDesiredSample_SetDesiredSampleTimeAndDuration(desired, 100, 0);
 
     hr = IMFTransform_ProcessOutput(mixer, 0, 1, &buffer, &status);
-todo_wine
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
 
     color = get_surface_color(surface, 0, 0);
-todo_wine
+    ok(!color, "Unexpected color %#x.\n", color);
+
+    hr = IMFVideoProcessor_SetBackgroundColor(processor, RGB(0, 0, 255));
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTransform_ProcessOutput(mixer, 0, 1, &buffer, &status);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    color = get_surface_color(surface, 0, 0);
     ok(!color, "Unexpected color %#x.\n", color);
 
     IMFDesiredSample_Clear(desired);
@@ -2231,6 +2241,7 @@ todo_wine
 
     IDirect3DSurface9_Release(surface);
 
+    IMFVideoProcessor_Release(processor);
     IMFTransform_Release(mixer);
 
     IDirect3DDevice9_Release(device);




More information about the wine-cvs mailing list