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:
parent
d7b8526258
commit
db549a680e
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue