diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c index 15ebcd80acc..ba9e09c4e3e 100644 --- a/dlls/evr/presenter.c +++ b/dlls/evr/presenter.c @@ -62,6 +62,8 @@ struct video_presenter MFVideoNormalizedRect src_rect; RECT dst_rect; DWORD rendering_prefs; + SIZE native_size; + SIZE native_ratio; unsigned int state; CRITICAL_SECTION cs; }; @@ -377,6 +379,51 @@ static void video_presenter_set_mixer_rect(struct video_presenter *presenter) } } +static unsigned int get_gcd(unsigned int a, unsigned int b) +{ + unsigned int m; + + while (b) + { + m = a % b; + a = b; + b = m; + } + + return a; +} + +static void video_presenter_get_native_video_size(struct video_presenter *presenter) +{ + IMFMediaType *media_type; + UINT64 frame_size = 0; + + memset(&presenter->native_size, 0, sizeof(presenter->native_size)); + memset(&presenter->native_ratio, 0, sizeof(presenter->native_ratio)); + + if (!presenter->mixer) + return; + + if (FAILED(IMFTransform_GetInputCurrentType(presenter->mixer, 0, &media_type))) + return; + + if (SUCCEEDED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size))) + { + unsigned int gcd; + + presenter->native_size.cx = frame_size >> 32; + presenter->native_size.cy = frame_size; + + if ((gcd = get_gcd(presenter->native_size.cx, presenter->native_size.cy))) + { + presenter->native_ratio.cx = presenter->native_size.cx / gcd; + presenter->native_ratio.cy = presenter->native_size.cy / gcd; + } + } + + IMFMediaType_Release(media_type); +} + static HRESULT video_presenter_attach_mixer(struct video_presenter *presenter, IMFTopologyServiceLookup *service_lookup) { IMFVideoDeviceID *device_id; @@ -410,6 +457,7 @@ static HRESULT video_presenter_attach_mixer(struct video_presenter *presenter, I } video_presenter_set_mixer_rect(presenter); + video_presenter_get_native_video_size(presenter); return hr; } @@ -508,9 +556,21 @@ static ULONG WINAPI video_presenter_control_Release(IMFVideoDisplayControl *ifac static HRESULT WINAPI video_presenter_control_GetNativeVideoSize(IMFVideoDisplayControl *iface, SIZE *video_size, SIZE *aspect_ratio) { - FIXME("%p, %p, %p.\n", iface, video_size, aspect_ratio); + struct video_presenter *presenter = impl_from_IMFVideoDisplayControl(iface); - return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, video_size, aspect_ratio); + + if (!video_size && !aspect_ratio) + return E_POINTER; + + EnterCriticalSection(&presenter->cs); + if (video_size) + *video_size = presenter->native_size; + if (aspect_ratio) + *aspect_ratio = presenter->native_ratio; + LeaveCriticalSection(&presenter->cs); + + return S_OK; } static HRESULT WINAPI video_presenter_control_GetIdealVideoSize(IMFVideoDisplayControl *iface, SIZE *min_size, diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index ce2803bcb34..39d2ed72a06 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -1578,21 +1578,18 @@ static void test_presenter_native_video_size(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, NULL, NULL); -todo_wine ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); memset(&size, 0xcc, sizeof(size)); hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, &size, NULL); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(size.cx == 0 && size.cy == 0, "Unexpected size.\n"); -} + memset(&ratio, 0xcc, sizeof(ratio)); hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, NULL, &ratio); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(ratio.cx == 0 && ratio.cy == 0, "Unexpected ratio.\n"); -} + hr = IMFVideoPresenter_QueryInterface(presenter, &IID_IMFTopologyServiceLookupClient, (void **)&lookup_client); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); @@ -1623,12 +1620,11 @@ todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, &size, &ratio); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(size.cx == 640 && size.cy == 480, "Unexpected size %u x %u.\n", size.cx, size.cy); ok((ratio.cx == 4 && ratio.cy == 3) || broken(!memcmp(&ratio, &size, sizeof(ratio))) /* < Win10 */, "Unexpected ratio %u x %u.\n", ratio.cx, ratio.cy); -} + /* Update input type. */ hr = IMFVideoMediaType_SetUINT64(video_type, &MF_MT_FRAME_SIZE, (UINT64)320 << 32 | 240); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); @@ -1637,24 +1633,23 @@ todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, &size, &ratio); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(size.cx == 640 && size.cy == 480, "Unexpected size %u x %u.\n", size.cx, size.cy); ok((ratio.cx == 4 && ratio.cy == 3) || broken(!memcmp(&ratio, &size, sizeof(ratio))) /* < Win10 */, "Unexpected ratio %u x %u.\n", ratio.cx, ratio.cy); -} + /* Negotiating types updates native video size. */ hr = IMFVideoPresenter_ProcessMessage(presenter, MFVP_MESSAGE_INVALIDATEMEDIATYPE, 0); todo_wine ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = IMFVideoDisplayControl_GetNativeVideoSize(display_control, &size, &ratio); -todo_wine { ok(hr == S_OK, "Unexpected hr %#x.\n", hr); +todo_wine ok(size.cx == 320 && size.cy == 240, "Unexpected size %u x %u.\n", size.cx, size.cy); ok((ratio.cx == 4 && ratio.cy == 3) || broken(!memcmp(&ratio, &size, sizeof(ratio))) /* < Win10 */, "Unexpected ratio %u x %u.\n", ratio.cx, ratio.cy); -} + IMFVideoMediaType_Release(video_type); IMFVideoDisplayControl_Release(display_control); IMFVideoPresenter_Release(presenter);