Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/main.c | 180 +++++++++++++++++++++++++++++++++++++++++++++ dlls/mf/mf.spec | 2 +- dlls/mf/tests/mf.c | 66 +++++++++++++++++ include/mfidl.idl | 1 + 4 files changed, 248 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index 251d59e1c0..5d645db200 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -1168,3 +1168,183 @@ HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate)
return create_activation_object(hwnd, &evr_activate_funcs, activate); } + +struct simple_type_handler +{ + IMFMediaTypeHandler IMFMediaTypeHandler_iface; + LONG refcount; + IMFMediaType *media_type; + CRITICAL_SECTION cs; +}; + +static struct simple_type_handler *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface) +{ + return CONTAINING_RECORD(iface, struct simple_type_handler, IMFMediaTypeHandler_iface); +} + +static HRESULT WINAPI simple_type_handler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFMediaTypeHandler) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFMediaTypeHandler_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI simple_type_handler_AddRef(IMFMediaTypeHandler *iface) +{ + struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface); + ULONG refcount = InterlockedIncrement(&handler->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI simple_type_handler_Release(IMFMediaTypeHandler *iface) +{ + struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface); + ULONG refcount = InterlockedDecrement(&handler->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + if (handler->media_type) + IMFMediaType_Release(handler->media_type); + DeleteCriticalSection(&handler->cs); + heap_free(handler); + } + + return refcount; +} + +static HRESULT WINAPI simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type, + IMFMediaType **out_type) +{ + FIXME("%p, %p, %p.\n", iface, in_type, out_type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count) +{ + TRACE("%p, %p.\n", iface, count); + + if (!count) + return E_POINTER; + + *count = 1; + + return S_OK; +} + +static HRESULT WINAPI simple_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index, + IMFMediaType **type) +{ + struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface); + + TRACE("%p, %u, %p.\n", iface, index, type); + + if (index > 0) + return MF_E_NO_MORE_TYPES; + + EnterCriticalSection(&handler->cs); + *type = handler->media_type; + if (*type) + IMFMediaType_AddRef(*type); + LeaveCriticalSection(&handler->cs); + + return S_OK; +} + +static HRESULT WINAPI simple_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *media_type) +{ + struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface); + + TRACE("%p, %p.\n", iface, media_type); + + EnterCriticalSection(&handler->cs); + if (handler->media_type) + IMFMediaType_Release(handler->media_type); + handler->media_type = media_type; + if (handler->media_type) + IMFMediaType_AddRef(handler->media_type); + LeaveCriticalSection(&handler->cs); + + return S_OK; +} + +static HRESULT WINAPI simple_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **media_type) +{ + struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface); + + TRACE("%p, %p.\n", iface, media_type); + + if (!media_type) + return E_POINTER; + + EnterCriticalSection(&handler->cs); + *media_type = handler->media_type; + if (*media_type) + IMFMediaType_AddRef(*media_type); + LeaveCriticalSection(&handler->cs); + + return S_OK; +} + +static HRESULT WINAPI simple_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type) +{ + struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface); + HRESULT hr; + + TRACE("%p, %p.\n", iface, type); + + EnterCriticalSection(&handler->cs); + if (handler->media_type) + hr = IMFMediaType_GetGUID(handler->media_type, &MF_MT_MAJOR_TYPE, type); + else + hr = MF_E_NOT_INITIALIZED; + LeaveCriticalSection(&handler->cs); + + return hr; +} + +static const IMFMediaTypeHandlerVtbl simple_type_handler_vtbl = +{ + simple_type_handler_QueryInterface, + simple_type_handler_AddRef, + simple_type_handler_Release, + simple_type_handler_IsMediaTypeSupported, + simple_type_handler_GetMediaTypeCount, + simple_type_handler_GetMediaTypeByIndex, + simple_type_handler_SetCurrentMediaType, + simple_type_handler_GetCurrentMediaType, + simple_type_handler_GetMajorType, +}; + +HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler) +{ + struct simple_type_handler *object; + + TRACE("%p.\n", handler); + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IMFMediaTypeHandler_iface.lpVtbl = &simple_type_handler_vtbl; + object->refcount = 1; + InitializeCriticalSection(&object->cs); + + *handler = &object->IMFMediaTypeHandler_iface; + + return S_OK; +} diff --git a/dlls/mf/mf.spec b/dlls/mf/mf.spec index a8dd314aa3..e396d01519 100644 --- a/dlls/mf/mf.spec +++ b/dlls/mf/mf.spec @@ -56,7 +56,7 @@ @ stub MFCreateSequencerSegmentOffset @ stdcall MFCreateSequencerSource(ptr ptr) @ stub MFCreateSequencerSourceRemoteStream -@ stub MFCreateSimpleTypeHandler +@ stdcall MFCreateSimpleTypeHandler(ptr) @ stdcall MFCreateSourceResolver(ptr) mfplat.MFCreateSourceResolver @ stdcall MFCreateStandardQualityManager(ptr) @ stdcall MFCreateTopoLoader(ptr) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index b353df780b..a1a7d2b05a 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2595,6 +2595,71 @@ static void test_evr(void) IMFActivate_Release(activate); }
+static void test_MFCreateSimpleTypeHandler(void) +{ + IMFMediaType *media_type, *media_type2; + IMFMediaTypeHandler *handler; + DWORD count; + HRESULT hr; + GUID guid; + + hr = MFCreateSimpleTypeHandler(&handler); + ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + count = 0; + hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count); + ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr); + ok(count == 1, "Unexpected count %u.\n", count); + + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + media_type = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type, "Unexpected pointer.\n"); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type); + ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type2 == media_type, "Unexpected type.\n"); + IMFMediaType_Release(media_type2); + + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2); + ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type2); + + IMFMediaType_Release(media_type); + + hr = IMFMediaTypeHandler_GetMajorType(handler, &guid); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL); + ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr); + + media_type = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type, "Unexpected pointer.\n"); + + hr = IMFMediaTypeHandler_GetMajorType(handler, &guid); + ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr); + + IMFMediaTypeHandler_Release(handler); +} + START_TEST(mf) { test_topology(); @@ -2609,4 +2674,5 @@ START_TEST(mf) test_quality_manager(); test_sar(); test_evr(); + test_MFCreateSimpleTypeHandler(); } diff --git a/include/mfidl.idl b/include/mfidl.idl index b301edbbdd..b1568b9b56 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -580,6 +580,7 @@ cpp_quote("HRESULT WINAPI MFCreateMFByteStreamOnStreamEx(IUnknown *stream, IMFBy cpp_quote("HRESULT WINAPI MFCreatePresentationClock(IMFPresentationClock **clock);") cpp_quote("HRESULT WINAPI MFCreatePresentationDescriptor(DWORD count, IMFStreamDescriptor **descriptors,") cpp_quote(" IMFPresentationDescriptor **presentation_desc);") +cpp_quote("HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler);") cpp_quote("HRESULT WINAPI MFCreateSampleGrabberSinkActivate(IMFMediaType *media_type,") cpp_quote(" IMFSampleGrabberSinkCallback *callback, IMFActivate **activate);") cpp_quote("HRESULT WINAPI MFCreateSequencerSource(IUnknown *reserved, IMFSequencerSource **seq_source);" )