mfmediaengine: Add partial implementation of a time range object.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-01-27 17:37:00 +03:00 committed by Alexandre Julliard
parent d7b8526258
commit db549a680e
2 changed files with 307 additions and 3 deletions

View File

@ -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)
@ -1720,9 +1926,9 @@ static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFac
static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFactory *iface,
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)

View File

@ -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);