Module: wine Branch: master Commit: 381c2a9ae151f676a009e89b4b101679fd90b9ae URL: https://source.winehq.org/git/wine.git/?a=commit;h=381c2a9ae151f676a009e89b4...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Thu Feb 10 11:21:32 2022 +0300
mfplat: Implement MFAverageTimePerFrameToFrameRate().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/mfplat/mediatype.c | 68 ++++++++++++++++++++++++++++++++++++++++++---- dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 48 ++++++++++++++++++++++++++++++++ include/mfapi.h | 1 + 4 files changed, 113 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 41758390289..b77db17189f 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -3215,15 +3215,15 @@ HRESULT WINAPI MFConvertColorInfoToDXVA(DWORD *dxva_info, const MFVIDEOFORMAT *f
struct frame_rate { - UINT64 rate; - UINT64 frame_time; + UINT64 key; + UINT64 value; };
static int __cdecl frame_rate_compare(const void *a, const void *b) { - const UINT64 *rate = a; + const UINT64 *key = a; const struct frame_rate *known_rate = b; - return *rate == known_rate->rate ? 0 : ( *rate < known_rate->rate ? 1 : -1 ); + return *key == known_rate->key ? 0 : ( *key < known_rate->key ? 1 : -1 ); }
/*********************************************************************** @@ -3252,7 +3252,7 @@ HRESULT WINAPI MFFrameRateToAverageTimePerFrame(UINT32 numerator, UINT32 denomin if ((entry = bsearch(&rate, known_rates, ARRAY_SIZE(known_rates), sizeof(*known_rates), frame_rate_compare))) { - *avgframetime = entry->frame_time; + *avgframetime = entry->value; } else *avgframetime = numerator ? denominator * (UINT64)10000000 / numerator : 0; @@ -3260,6 +3260,64 @@ HRESULT WINAPI MFFrameRateToAverageTimePerFrame(UINT32 numerator, UINT32 denomin return S_OK; }
+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; +} + +/*********************************************************************** + * MFAverageTimePerFrameToFrameRate (mfplat.@) + */ +HRESULT WINAPI MFAverageTimePerFrameToFrameRate(UINT64 avgtime, UINT32 *numerator, UINT32 *denominator) +{ + static const struct frame_rate known_rates[] = + { +#define KNOWN_RATE(ft,n,d) { ft, ((UINT64)n << 32) | d } + KNOWN_RATE(417188, 24000, 1001), + KNOWN_RATE(416667, 24, 1), + KNOWN_RATE(400000, 25, 1), + KNOWN_RATE(333667, 30000, 1001), + KNOWN_RATE(333333, 30, 1), + KNOWN_RATE(200000, 50, 1), + KNOWN_RATE(166833, 60000, 1001), + KNOWN_RATE(166667, 60, 1), +#undef KNOWN_RATE + }; + const struct frame_rate *entry; + unsigned int gcd; + + TRACE("%s, %p, %p.\n", wine_dbgstr_longlong(avgtime), numerator, denominator); + + if ((entry = bsearch(&avgtime, known_rates, ARRAY_SIZE(known_rates), sizeof(*known_rates), + frame_rate_compare))) + { + *numerator = entry->value >> 32; + *denominator = entry->value; + } + else if (avgtime) + { + if (avgtime > 100000000) avgtime = 100000000; + gcd = get_gcd(10000000, avgtime); + *numerator = 10000000 / gcd; + *denominator = avgtime / gcd; + } + else + { + *numerator = *denominator = 0; + } + + return S_OK; +} + /*********************************************************************** * MFMapDXGIFormatToDX9Format (mfplat.@) */ diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 5d177732fa8..31c80f596c2 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -20,7 +20,7 @@ @ stdcall MFAllocateWorkQueue(ptr) @ stdcall MFAllocateWorkQueueEx(long ptr) rtworkq.RtwqAllocateWorkQueue @ stub MFAppendCollection -@ stub MFAverageTimePerFrameToFrameRate +@ stdcall MFAverageTimePerFrameToFrameRate(int64 ptr ptr) @ stdcall MFBeginCreateFile(long long long wstr ptr ptr ptr) @ stub MFBeginGetHostByName @ stdcall MFBeginRegisterWorkQueueWithMMCSS(long wstr long ptr ptr) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index f89a5202d80..c70d8a9ca81 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -6399,6 +6399,53 @@ static void test_MFFrameRateToAverageTimePerFrame(void) } }
+static void test_MFAverageTimePerFrameToFrameRate(void) +{ + static const struct frame_rate_test + { + unsigned int numerator; + unsigned int denominator; + UINT64 avgtime; + } frame_rate_tests[] = + { + { 60000, 1001, 166833 }, + { 30000, 1001, 333667 }, + { 24000, 1001, 417188 }, + { 60, 1, 166667 }, + { 30, 1, 333333 }, + { 50, 1, 200000 }, + { 25, 1, 400000 }, + { 24, 1, 416667 }, + + { 1000000, 25641, 256410 }, + { 10000000, 83333, 83333 }, + { 1, 10, 100000000 }, + { 1, 10, 100000001 }, + { 1, 10, 200000000 }, + { 1, 1, 10000000 }, + { 1, 2, 20000000 }, + { 5, 1, 2000000 }, + { 10, 1, 1000000 }, + }; + unsigned int i, numerator, denominator; + HRESULT hr; + + numerator = denominator = 1; + hr = MFAverageTimePerFrameToFrameRate(0, &numerator, &denominator); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!numerator && !denominator, "Unexpected output %u/%u.\n", numerator, denominator); + + for (i = 0; i < ARRAY_SIZE(frame_rate_tests); ++i) + { + numerator = denominator = 12345; + hr = MFAverageTimePerFrameToFrameRate(frame_rate_tests[i].avgtime, &numerator, &denominator); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(numerator == frame_rate_tests[i].numerator && denominator == frame_rate_tests[i].denominator, + "%u: unexpected %u/%u, expected %u/%u.\n", i, numerator, denominator, frame_rate_tests[i].numerator, + frame_rate_tests[i].denominator); + } +} + static void test_MFMapDXGIFormatToDX9Format(void) { static const struct format_pair @@ -7874,6 +7921,7 @@ START_TEST(mfplat) test_MFCreateDXSurfaceBuffer(); test_MFCreateTrackedSample(); test_MFFrameRateToAverageTimePerFrame(); + test_MFAverageTimePerFrameToFrameRate(); test_MFMapDXGIFormatToDX9Format(); test_d3d11_surface_buffer(); test_d3d12_surface_buffer(); diff --git a/include/mfapi.h b/include/mfapi.h index 105613693c9..b4e4d095bb4 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -500,6 +500,7 @@ HRESULT WINAPI MFAddPeriodicCallback(MFPERIODICCALLBACK callback, IUnknown *cont HRESULT WINAPI MFAllocateSerialWorkQueue(DWORD target_queue, DWORD *queue); HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue); HRESULT WINAPI MFAllocateWorkQueueEx(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue); +HRESULT WINAPI MFAverageTimePerFrameToFrameRate(UINT64 avgtime, UINT32 *numerator, UINT32 *denominator); HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags, const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie); HRESULT WINAPI MFBeginRegisterWorkQueueWithMMCSS(DWORD queue, const WCHAR *usage_class, DWORD taskid,