Nikolay Sivov : mfmediaengine: Add partial implementation of a time range object.

Alexandre Julliard julliard at winehq.org
Wed Jan 27 15:35:04 CST 2021


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Jan 27 17:37:00 2021 +0300

mfmediaengine: Add partial implementation of a time range object.

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

---

 dlls/mfmediaengine/main.c                | 212 ++++++++++++++++++++++++++++++-
 dlls/mfmediaengine/tests/mfmediaengine.c |  98 ++++++++++++++
 2 files changed, 307 insertions(+), 3 deletions(-)

diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
index 5981548c9f8..0573ea844c1 100644
--- a/dlls/mfmediaengine/main.c
+++ b/dlls/mfmediaengine/main.c
@@ -34,6 +34,33 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
+static BOOL mf_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
+{
+    size_t new_capacity, max_capacity;
+    void *new_elements;
+
+    if (count <= *capacity)
+        return TRUE;
+
+    max_capacity = ~(SIZE_T)0 / size;
+    if (count > max_capacity)
+        return FALSE;
+
+    new_capacity = max(4, *capacity);
+    while (new_capacity < count && new_capacity <= max_capacity / 2)
+        new_capacity *= 2;
+    if (new_capacity < count)
+        new_capacity = max_capacity;
+
+    if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
+        return FALSE;
+
+    *elements = new_elements;
+    *capacity = new_capacity;
+
+    return TRUE;
+}
+
 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
 {
     switch (reason)
@@ -106,6 +133,27 @@ struct media_engine
     CRITICAL_SECTION cs;
 };
 
+struct range
+{
+    double start;
+    double end;
+};
+
+struct time_range
+{
+    IMFMediaTimeRange IMFMediaTimeRange_iface;
+    LONG refcount;
+
+    struct range *ranges;
+    size_t count;
+    size_t capacity;
+};
+
+static struct time_range *impl_from_IMFMediaTimeRange(IMFMediaTimeRange *iface)
+{
+    return CONTAINING_RECORD(iface, struct time_range, IMFMediaTimeRange_iface);
+}
+
 struct media_error
 {
     IMFMediaError IMFMediaError_iface;
@@ -226,6 +274,164 @@ static HRESULT create_media_error(IMFMediaError **ret)
     return S_OK;
 }
 
+static HRESULT WINAPI time_range_QueryInterface(IMFMediaTimeRange *iface, REFIID riid, void **obj)
+{
+    TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+    if (IsEqualIID(riid, &IID_IMFMediaTimeRange) ||
+            IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IMFMediaTimeRange_AddRef(iface);
+        return S_OK;
+    }
+
+    WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI time_range_AddRef(IMFMediaTimeRange *iface)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+    ULONG refcount = InterlockedIncrement(&range->refcount);
+
+    TRACE("%p, refcount %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI time_range_Release(IMFMediaTimeRange *iface)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+    ULONG refcount = InterlockedDecrement(&range->refcount);
+
+    TRACE("%p, refcount %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        heap_free(range->ranges);
+        heap_free(range);
+    }
+
+    return refcount;
+}
+
+static DWORD WINAPI time_range_GetLength(IMFMediaTimeRange *iface)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+
+    TRACE("%p.\n", iface);
+
+    return range->count;
+}
+
+static HRESULT WINAPI time_range_GetStart(IMFMediaTimeRange *iface, DWORD idx, double *start)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+
+    TRACE("%p, %u, %p.\n", iface, idx, start);
+
+    if (idx >= range->count)
+        return E_INVALIDARG;
+
+    *start = range->ranges[idx].start;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI time_range_GetEnd(IMFMediaTimeRange *iface, DWORD idx, double *end)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+
+    TRACE("%p, %u, %p.\n", iface, idx, end);
+
+    if (idx >= range->count)
+        return E_INVALIDARG;
+
+    *end = range->ranges[idx].end;
+
+    return S_OK;
+}
+
+static BOOL WINAPI time_range_ContainsTime(IMFMediaTimeRange *iface, double time)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+    size_t i;
+
+    TRACE("%p, %.8e.\n", iface, time);
+
+    for (i = 0; i < range->count; ++i)
+    {
+        if (time >= range->ranges[i].start && time <= range->ranges[i].end)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+static HRESULT WINAPI time_range_AddRange(IMFMediaTimeRange *iface, double start, double end)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+
+    TRACE("%p, %.8e, %.8e.\n", iface, start, end);
+
+    if (range->count)
+    {
+        FIXME("Range merging is not implemented.\n");
+        return E_NOTIMPL;
+    }
+
+    if (!mf_array_reserve((void **)&range->ranges, &range->capacity, range->count + 1, sizeof(*range->ranges)))
+        return E_OUTOFMEMORY;
+
+    range->ranges[range->count].start = start;
+    range->ranges[range->count].end = end;
+    range->count++;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI time_range_Clear(IMFMediaTimeRange *iface)
+{
+    struct time_range *range = impl_from_IMFMediaTimeRange(iface);
+
+    TRACE("%p.\n", iface);
+
+    range->count = 0;
+
+    return S_OK;
+}
+
+static const IMFMediaTimeRangeVtbl time_range_vtbl =
+{
+    time_range_QueryInterface,
+    time_range_AddRef,
+    time_range_Release,
+    time_range_GetLength,
+    time_range_GetStart,
+    time_range_GetEnd,
+    time_range_ContainsTime,
+    time_range_AddRange,
+    time_range_Clear,
+};
+
+static HRESULT create_time_range(IMFMediaTimeRange **range)
+{
+    struct time_range *object;
+
+    object = heap_alloc_zero(sizeof(*object));
+    if (!object)
+        return E_OUTOFMEMORY;
+
+    object->IMFMediaTimeRange_iface.lpVtbl = &time_range_vtbl;
+    object->refcount = 1;
+
+    *range = &object->IMFMediaTimeRange_iface;
+
+    return S_OK;
+}
+
 static void media_engine_set_flag(struct media_engine *engine, unsigned int mask, BOOL value)
 {
     if (value)
@@ -1718,11 +1924,11 @@ static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFac
 }
 
 static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFactory *iface,
-                                                           IMFMediaTimeRange **range)
+        IMFMediaTimeRange **range)
 {
-    FIXME("(%p, %p): stub.\n", iface, range);
+    TRACE("%p, %p.\n", iface, range);
 
-    return E_NOTIMPL;
+    return create_time_range(range);
 }
 
 static HRESULT WINAPI media_engine_factory_CreateError(IMFMediaEngineClassFactory *iface, IMFMediaError **error)
diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c
index f9f8fed4a74..1cc88420568 100644
--- a/dlls/mfmediaengine/tests/mfmediaengine.c
+++ b/dlls/mfmediaengine/tests/mfmediaengine.c
@@ -590,6 +590,103 @@ static void test_error(void)
     IMFMediaError_Release(eo);
 }
 
+static void test_time_range(void)
+{
+    IMFMediaTimeRange *range;
+    double start, end;
+    DWORD count;
+    HRESULT hr;
+    BOOL ret;
+
+    hr = IMFMediaEngineClassFactory_CreateTimeRange(factory, &range);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    /* Empty ranges. */
+    hr = IMFMediaTimeRange_Clear(range);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    ret = IMFMediaTimeRange_ContainsTime(range, 10.0);
+    ok(!ret, "Unexpected return value %d.\n", ret);
+
+    count = IMFMediaTimeRange_GetLength(range);
+    ok(!count, "Unexpected range count.\n");
+
+    hr = IMFMediaTimeRange_GetStart(range, 0, &start);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFMediaTimeRange_GetEnd(range, 0, &end);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    /* Add a range. */
+    hr = IMFMediaTimeRange_AddRange(range, 10.0, 1.0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    count = IMFMediaTimeRange_GetLength(range);
+    ok(count == 1, "Unexpected range count.\n");
+
+    hr = IMFMediaTimeRange_GetStart(range, 0, &start);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(start == 10.0, "Unexpected start %.e.\n", start);
+
+    hr = IMFMediaTimeRange_GetEnd(range, 0, &end);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(end == 1.0, "Unexpected end %.e.\n", end);
+
+    hr = IMFMediaTimeRange_AddRange(range, 2.0, 3.0);
+todo_wine
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    count = IMFMediaTimeRange_GetLength(range);
+    ok(count == 1, "Unexpected range count.\n");
+
+    hr = IMFMediaTimeRange_GetStart(range, 0, &start);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+todo_wine
+    ok(start == 2.0, "Unexpected start %.8e.\n", start);
+
+    hr = IMFMediaTimeRange_GetEnd(range, 0, &end);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+todo_wine
+    ok(end == 3.0, "Unexpected end %.8e.\n", end);
+
+    hr = IMFMediaTimeRange_AddRange(range, 10.0, 9.0);
+todo_wine
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    count = IMFMediaTimeRange_GetLength(range);
+todo_wine
+    ok(count == 2, "Unexpected range count.\n");
+
+    hr = IMFMediaTimeRange_GetStart(range, 0, &start);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+todo_wine
+    ok(start == 2.0, "Unexpected start %.8e.\n", start);
+
+    hr = IMFMediaTimeRange_GetEnd(range, 0, &end);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+todo_wine
+    ok(end == 3.0, "Unexpected end %.8e.\n", end);
+
+    start = 0.0;
+    hr = IMFMediaTimeRange_GetStart(range, 1, &start);
+todo_wine {
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(start == 10.0, "Unexpected start %.8e.\n", start);
+}
+    hr = IMFMediaTimeRange_GetEnd(range, 1, &end);
+todo_wine {
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(end == 9.0, "Unexpected end %.8e.\n", end);
+}
+    hr = IMFMediaTimeRange_Clear(range);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    count = IMFMediaTimeRange_GetLength(range);
+    ok(!count, "Unexpected range count.\n");
+
+    IMFMediaTimeRange_Release(range);
+}
+
 START_TEST(mfmediaengine)
 {
     HRESULT hr;
@@ -617,6 +714,7 @@ START_TEST(mfmediaengine)
     test_playback_rate();
     test_mute();
     test_error();
+    test_time_range();
 
     IMFMediaEngineClassFactory_Release(factory);
 




More information about the wine-cvs mailing list