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 WINAPI video_mixer_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, - MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) +static HRESULT video_mixer_get_sample_surface(IMFSample *sample, IDirect3DSurface9 **surface) { - FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status); + IMFMediaBuffer *buffer; + IMFGetService *gs; + HRESULT hr; - return E_NOTIMPL; + 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 *buffers, DWORD *status) +{ + struct video_mixer *mixer = impl_from_IMFTransform(iface); + IDirect3DSurface9 *surface; + IDirect3DDevice9 *device; + HRESULT hr; + + 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);