Nikolay Sivov : mfplat: Implement MFAverageTimePerFrameToFrameRate().

Alexandre Julliard julliard at winehq.org
Thu Feb 10 16:10:29 CST 2022


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Thu Feb 10 11:21:32 2022 +0300

mfplat: Implement MFAverageTimePerFrameToFrameRate().

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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,




More information about the wine-cvs mailing list