[PATCH v2 0/2] MR10305: mfmediaengine: Add IMFMediaEngineClassFactoryEx interface.
-- v2: mfmediaengine: Add IMFMediaEngineClassFactoryEx interface. https://gitlab.winehq.org/wine/wine/-/merge_requests/10305
From: Paul Gofman <pgofman@codeweavers.com> --- include/mfmediaengine.idl | 177 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/include/mfmediaengine.idl b/include/mfmediaengine.idl index 27b6bbcd7d7..11c9a9183e4 100644 --- a/include/mfmediaengine.idl +++ b/include/mfmediaengine.idl @@ -343,6 +343,103 @@ interface IMFMediaEngineClassFactory : IUnknown HRESULT CreateError([out] IMFMediaError **error); } +[ + object, + uuid(a7901327-05dd-4469-a7b7-0e01979e361d), + local, + pointer_default(unique) +] +interface IMFMediaSourceExtensionNotify : IUnknown +{ + void OnSourceOpen(); + void OnSourceEnded(); + void OnSourceClose(); +}; + +[ + object, + uuid(87e47623-2ceb-45d6-9b88-d8520c4dcbbc), + local, + pointer_default(unique) +] +interface IMFSourceBufferNotify : IUnknown +{ + void OnUpdateStart(); + void OnAbort(); + void OnError([in] HRESULT hr); + void OnUpdate(); + void OnUpdateEnd(); +}; + +[ + object, + uuid(e2cd3a4b-af25-4d3d-9110-da0e6f8ee877), + local, + pointer_default(unique) +] +interface IMFSourceBuffer : IUnknown +{ + BOOL GetUpdating(); + HRESULT GetBuffered([out] IMFMediaTimeRange **buffered); + double GetTimeStampOffset(); + HRESULT SetTimeStampOffset([in] double offset); + double GetAppendWindowStart(); + HRESULT SetAppendWindowStart([in] double time); + double GetAppendWindowEnd(); + HRESULT SetAppendWindowEnd([in] double time); + HRESULT Append([in] const BYTE *data,[in] DWORD len); + HRESULT AppendByteStream([in] IMFByteStream *stream, [in] DWORDLONG *max_len); + HRESULT Abort(); + HRESULT Remove([in] double start, [in] double end); +}; + +[ + object, + uuid(249981f8-8325-41f3-b80c-3b9e3aad0cbe), + local, + pointer_default(unique) +] +interface IMFSourceBufferList : IUnknown +{ + DWORD GetLength(); + IMFSourceBuffer *GetSourceBuffer([in] DWORD index); +}; + +typedef enum MF_MSE_READY +{ + MF_MSE_READY_CLOSED = 1, + MF_MSE_READY_OPEN, + MF_MSE_READY_ENDED, +} MF_MSE_READY; + +typedef enum MF_MSE_ERROR +{ + MF_MSE_ERROR_NOERROR, + MF_MSE_ERROR_NETWORK, + MF_MSE_ERROR_DECODE, + MF_MSE_ERROR_UNKNOWN_ERROR +} MF_MSE_ERROR; + +[ + object, + uuid(e467b94e-a713-4562-a802-816a42e9008a), + local, + pointer_default(unique) +] +interface IMFMediaSourceExtension : IUnknown +{ + IMFSourceBufferList *GetSourceBuffers(); + IMFSourceBufferList *GetActiveSourceBuffers(); + MF_MSE_READY GetReadyState(); + double GetDuration(); + HRESULT SetDuration([in] double duration); + HRESULT AddSourceBuffer([in] BSTR type, [in] IMFSourceBufferNotify *notify, [out] IMFSourceBuffer **source_buffer); + HRESULT RemoveSourceBuffer([in] IMFSourceBuffer *source_buffer); + HRESULT SetEndOfStream([in] MF_MSE_ERROR error); + BOOL IsTypeSupported([in] BSTR type); + IMFSourceBuffer *GetSourceBuffer([in] DWORD stream_index); +}; + [ object, uuid(fee7c112-e776-42b5-9bbf-0048524e2bd5), @@ -380,3 +477,83 @@ interface IMFMediaEngineExtension : IUnknown HRESULT CancelObjectCreation([in] IUnknown *cancel_cookie); HRESULT EndCreateObject([in] IMFAsyncResult *result, [out] IUnknown **object); } + +[ + object, + uuid(6a0083f9-8947-4c1d-9ce0-cdee22b23135), + local, + pointer_default(unique) +] +interface IMFMediaKeySessionNotify : IUnknown +{ + void KeyMessage([in] BSTR destination_url, [in] const BYTE *message, [in] DWORD message_len); + void KeyAdded(); + void KeyError([in] USHORT code, [in] DWORD system_code); +} + +[ + object, + uuid(24fa67d5-d1d0-4dc5-995c-c0efdc191fb5), + local, + pointer_default(unique) +] +interface IMFMediaKeySession : IUnknown +{ + HRESULT GetError([out] USHORT *code, [out] DWORD *system_code); + HRESULT get_KeySystem([out] BSTR *key_system); + HRESULT get_SessionId([out] BSTR *session_id); + HRESULT Update([in] const BYTE *key, [in] DWORD key_len); + HRESULT Close(); +} + +[ + object, + uuid(7a5645d2-43bd-47fd-87b7-dcd24cc7d692), + pointer_default(unique) +] +interface IMFCdmSuspendNotify : IUnknown +{ + HRESULT Begin(); + HRESULT End(); +} + +[ + object, + uuid(5cb31c05-61ff-418f-afda-caaf41421a38), + local, + pointer_default(unique) +] +interface IMFMediaKeys : IUnknown +{ + HRESULT CreateSession([in] BSTR mime_type, [in] const BYTE *init_data, [in] DWORD init_data_len, + [in] const BYTE *custom_data, [in] DWORD custom_data_len, + [in] IMFMediaKeySessionNotify *notify, [out] IMFMediaKeySession **session); + HRESULT get_KeySystem([out] BSTR *key_system); + HRESULT Shutdown(); + HRESULT GetSuspendNotify([out] IMFCdmSuspendNotify **notify); +} + +[ + object, + uuid(c56156c6-ea5b-48a5-9df8-fbe035d0929e), + local, + pointer_default(unique) +] +interface IMFMediaEngineClassFactoryEx : IMFMediaEngineClassFactory +{ + HRESULT CreateMediaSourceExtension([in] DWORD flags, [in] IMFAttributes *attr, [out] IMFMediaSourceExtension **mse); + HRESULT CreateMediaKeys([in] BSTR key_system, [in] BSTR cdm_store_path, [out] IMFMediaKeys **keys); + HRESULT IsTypeSupported([in] BSTR type, [in] BSTR key_system, [out] BOOL *is_supported); +} + +[ + object, + uuid(09083cef-867f-4bf6-8776-dee3a7b42fca), + local, + pointer_default(unique) +] +interface IMFMediaEngineClassFactory2 : IUnknown +{ + HRESULT CreateMediaKeys2([in] BSTR key_system, [in] BSTR default_cdm_store_path, + [in] BSTR inprivate_cdm_store_path, [out] IMFMediaKeys **keys); +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10305
From: Paul Gofman <pgofman@codeweavers.com> --- dlls/mfmediaengine/main.c | 46 ++++++++++++++++++------ dlls/mfmediaengine/tests/mfmediaengine.c | 10 ++++++ 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c index 2ababd674d7..61c435240a5 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c @@ -3482,13 +3482,14 @@ static const IMFGetServiceVtbl media_engine_get_service_vtbl = media_engine_gs_GetService, }; -static HRESULT WINAPI media_engine_factory_QueryInterface(IMFMediaEngineClassFactory *iface, REFIID riid, void **obj) +static HRESULT WINAPI media_engine_factory_QueryInterface(IMFMediaEngineClassFactoryEx *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFMediaEngineClassFactory) || + IsEqualIID(riid, &IID_IMFMediaEngineClassFactoryEx) || IsEqualIID(riid, &IID_IUnknown)) { *obj = iface; - IMFMediaEngineClassFactory_AddRef(iface); + IMFMediaEngineClassFactoryEx_AddRef(iface); return S_OK; } @@ -3497,12 +3498,12 @@ static HRESULT WINAPI media_engine_factory_QueryInterface(IMFMediaEngineClassFac return E_NOINTERFACE; } -static ULONG WINAPI media_engine_factory_AddRef(IMFMediaEngineClassFactory *iface) +static ULONG WINAPI media_engine_factory_AddRef(IMFMediaEngineClassFactoryEx *iface) { return 2; } -static ULONG WINAPI media_engine_factory_Release(IMFMediaEngineClassFactory *iface) +static ULONG WINAPI media_engine_factory_Release(IMFMediaEngineClassFactoryEx *iface) { return 1; } @@ -3586,7 +3587,7 @@ static HRESULT init_media_engine(DWORD flags, IMFAttributes *attributes, struct return S_OK; } -static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFactory *iface, DWORD flags, +static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFactoryEx *iface, DWORD flags, IMFAttributes *attributes, IMFMediaEngine **engine) { struct media_engine *object; @@ -3613,7 +3614,7 @@ static HRESULT WINAPI media_engine_factory_CreateInstance(IMFMediaEngineClassFac return S_OK; } -static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFactory *iface, +static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFactoryEx *iface, IMFMediaTimeRange **range) { TRACE("%p, %p.\n", iface, range); @@ -3621,14 +3622,36 @@ static HRESULT WINAPI media_engine_factory_CreateTimeRange(IMFMediaEngineClassFa return create_time_range(range); } -static HRESULT WINAPI media_engine_factory_CreateError(IMFMediaEngineClassFactory *iface, IMFMediaError **error) +static HRESULT WINAPI media_engine_factory_CreateError(IMFMediaEngineClassFactoryEx *iface, IMFMediaError **error) { TRACE("%p, %p.\n", iface, error); return create_media_error(error); } -static const IMFMediaEngineClassFactoryVtbl media_engine_factory_vtbl = +static HRESULT WINAPI media_engine_factory_CreateMediaSourceExtension(IMFMediaEngineClassFactoryEx *iface, DWORD flags, IMFAttributes *attr, IMFMediaSourceExtension **mse) +{ + FIXME("iface %p, flags %#lx, attr %p, mse %p stub.\n", iface, flags, attr, mse); + *mse = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI media_engine_factory_CreateMediaKeys(IMFMediaEngineClassFactoryEx *iface, BSTR key_system, BSTR cdm_store_path, IMFMediaKeys **keys) +{ + FIXME("iface %p, key_system %s, cdm_store_path %s, keys %p stub.\n", + iface, debugstr_w(key_system), debugstr_w(cdm_store_path), keys); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_engine_factory_IsTypeSupported(IMFMediaEngineClassFactoryEx *iface, BSTR type, BSTR key_system, BOOL *is_supported) +{ + FIXME("iface %p, type %s, key_system %s, is_supported %p stub.\n", + iface, debugstr_w(type), debugstr_w(key_system), is_supported); + *is_supported = FALSE; + return S_OK; +} + +static const IMFMediaEngineClassFactoryExVtbl media_engine_factory_vtbl = { media_engine_factory_QueryInterface, media_engine_factory_AddRef, @@ -3636,9 +3659,12 @@ static const IMFMediaEngineClassFactoryVtbl media_engine_factory_vtbl = media_engine_factory_CreateInstance, media_engine_factory_CreateTimeRange, media_engine_factory_CreateError, + media_engine_factory_CreateMediaSourceExtension, + media_engine_factory_CreateMediaKeys, + media_engine_factory_IsTypeSupported, }; -static IMFMediaEngineClassFactory media_engine_factory = { &media_engine_factory_vtbl }; +static IMFMediaEngineClassFactoryEx media_engine_factory = { &media_engine_factory_vtbl }; static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj) { @@ -3676,7 +3702,7 @@ static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown if (outer) return CLASS_E_NOAGGREGATION; - return IMFMediaEngineClassFactory_QueryInterface(&media_engine_factory, riid, obj); + return IMFMediaEngineClassFactoryEx_QueryInterface(&media_engine_factory, riid, obj); } static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock) diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index 3f9adae90d1..c90f4c4d4dc 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -314,6 +314,7 @@ static HRESULT create_media_engine(IMFMediaEngineNotify *callback, IMFDXGIDevice static void test_factory(void) { IMFMediaEngineClassFactory *factory, *factory2; + IMFMediaEngineClassFactoryEx *factory_ex; struct media_engine_notify *notify; IMFDXGIDeviceManager *manager; IMFMediaEngine *media_engine; @@ -330,6 +331,15 @@ static void test_factory(void) return; } + hr = CoCreateInstance(&CLSID_MFMediaEngineClassFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IMFMediaEngineClassFactoryEx, + (void **)&factory_ex); + ok(hr == S_OK, "Failed to create class factory, hr %#lx.\n", hr); + hr = IMFMediaEngineClassFactoryEx_QueryInterface(factory_ex, &IID_IMFMediaEngineClassFactory, (void **)&factory2); + ok(hr == S_OK, "got hr %#lx.\n", hr); + ok((void *)factory_ex == (void *)factory2, "got %p, %p.\n", factory, factory_ex); + IMFMediaEngineClassFactory_Release(factory2); + IMFMediaEngineClassFactoryEx_Release(factory_ex); + notify = create_callback(); /* Aggregation is not supported. */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10305
On Thu Mar 12 13:30:58 2026 +0000, Alfred Agrell wrote:
not gonna ok(hr==S_OK)? Not really necessary, the pointer check is gonna fail if that one isn't S_OK, but it looks kinda odd. Yeah, thanks, the ok was missed.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10305#note_132035
v2: - check QueryInterface result. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10305#note_132036
This merge request was approved by Nikolay Sivov. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10305
participants (3)
-
Nikolay Sivov (@nsivov) -
Paul Gofman -
Paul Gofman (@gofman)