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