Signed-off-by: Sven Baars sven.wine@gmail.com ---
v4: Rebased on top of Alistair's commit. I also used his naming convention while at it.
dlls/mfplat/main.c | 187 +++++++++++++++++++++++++++++++++++++ dlls/mfplat/tests/mfplat.c | 78 +++++++++++++++- include/mfidl.idl | 36 +++++++ 3 files changed, 299 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 46a697538c..62461bb5f7 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -1315,6 +1315,174 @@ HRESULT WINAPI MFGetPluginControl(IMFPluginControl **ret) return S_OK; }
+typedef struct _mfsource +{ + IMFMediaSource IMFMediaSource_iface; + LONG ref; +} mfsource; + +static inline mfsource *impl_from_IMFMediaSource(IMFMediaSource *iface) +{ + return CONTAINING_RECORD(iface, mfsource, IMFMediaSource_iface); +} + +static HRESULT WINAPI mfsource_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), out); + + if (IsEqualIID(riid, &IID_IMFMediaSource) || + IsEqualIID(riid, &IID_IMFMediaEventGenerator) || + IsEqualIID(riid, &IID_IUnknown)) + { + *out = &This->IMFMediaSource_iface; + } + else + { + FIXME("(%s, %p)\n", debugstr_guid(riid), out); + *out = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*out); + return S_OK; +} + +static ULONG WINAPI mfsource_AddRef(IMFMediaSource *iface) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%u\n", This, ref); + + return ref; +} + +static ULONG WINAPI mfsource_Release(IMFMediaSource *iface) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%u\n", This, ref); + + if (!ref) + { + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI mfsource_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p)->(%#x, %p)\n", This, flags, event); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p)->(%p, %p)\n", This, callback, state); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p)->(%p, %p)\n", This, result, event); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type, + HRESULT hr, const PROPVARIANT *value) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p)->(%d, %s, %#x, %p)\n", This, event_type, debugstr_guid(ext_type), hr, value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_GetCharacteristics(IMFMediaSource *iface, DWORD *characteristics) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p)->(%p): stub\n", This, characteristics); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **descriptor) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p)->(%p): stub\n", This, descriptor); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor, + const GUID *time_format, const PROPVARIANT *start_position) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p)->(%p, %p, %p): stub\n", This, descriptor, time_format, start_position); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_Stop(IMFMediaSource *iface) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p): stub\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_Pause(IMFMediaSource *iface) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p): stub\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI mfsource_Shutdown(IMFMediaSource *iface) +{ + mfsource *This = impl_from_IMFMediaSource(iface); + + FIXME("(%p): stub\n", This); + + return S_OK; +} + +static const IMFMediaSourceVtbl mfsourcevtbl = +{ + mfsource_QueryInterface, + mfsource_AddRef, + mfsource_Release, + mfsource_GetEvent, + mfsource_BeginGetEvent, + mfsource_EndGetEvent, + mfsource_QueueEvent, + mfsource_GetCharacteristics, + mfsource_CreatePresentationDescriptor, + mfsource_Start, + mfsource_Stop, + mfsource_Pause, + mfsource_Shutdown, +}; + typedef struct _mfsourceresolver { IMFSourceResolver IMFSourceResolver_iface; @@ -1388,6 +1556,25 @@ static HRESULT WINAPI mfsourceresolver_CreateObjectFromByteStream(IMFSourceResol
FIXME("(%p)->(%p, %s, %#x, %p, %p, %p): stub\n", This, stream, debugstr_w(url), flags, props, obj_type, object);
+ if (!stream || !obj_type || !object) + return E_POINTER; + + if (flags & MF_RESOLUTION_MEDIASOURCE) + { + mfsource *new_object; + + new_object = HeapAlloc( GetProcessHeap(), 0, sizeof(*object) ); + if (!new_object) + return E_OUTOFMEMORY; + + new_object->IMFMediaSource_iface.lpVtbl = &mfsourcevtbl; + new_object->ref = 1; + + *object = (IUnknown *)&new_object->IMFMediaSource_iface; + *obj_type = MF_OBJECT_MEDIASOURCE; + return S_OK; + } + return E_NOTIMPL; }
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 48a8d0d361..d0f7ea4c98 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -42,6 +42,8 @@ static HRESULT (WINAPI *pMFCreateMemoryBuffer)(DWORD max_length, IMFMediaBuffer
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+DEFINE_GUID(MF_BYTESTREAM_CONTENT_TYPE, 0xfc358289,0x3cb6,0x460c,0xa4,0x24,0xb6,0x68,0x12,0x60,0x37,0x5a); + DEFINE_GUID(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0xa634a91c, 0x822b, 0x41b9, 0xa4, 0x94, 0x4d, 0xe4, 0x64, 0x36, 0x12, 0xb0);
DEFINE_GUID(MFT_CATEGORY_OTHER, 0x90175d57,0xb7ea,0x4901,0xae,0xb3,0x93,0x3a,0x87,0x47,0x75,0x6f); @@ -200,7 +202,14 @@ if(0) static void test_source_resolver(void) { IMFSourceResolver *resolver, *resolver2; + IMFByteStream *bytestream; + IMFAttributes *attributes; + IMFMediaSource *mediasource; + MF_OBJECT_TYPE obj_type; HRESULT hr; + WCHAR *filename; + + static const WCHAR file_type[] = {'v','i','d','e','o','/','m','p','4',0};
if (!pMFCreateSourceResolver) { @@ -208,6 +217,9 @@ static void test_source_resolver(void) return; }
+ hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + hr = pMFCreateSourceResolver(NULL); ok(hr == E_POINTER, "got %#x\n", hr);
@@ -218,8 +230,70 @@ static void test_source_resolver(void) ok(hr == S_OK, "got %#x\n", hr); ok(resolver != resolver2, "Expected new instance\n");
- IMFSourceResolver_Release(resolver); IMFSourceResolver_Release(resolver2); + + filename = load_resource(mp4file); + + hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, + MF_FILEFLAGS_NONE, filename, &bytestream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IMFSourceResolver_CreateObjectFromByteStream( + resolver, NULL, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, + &obj_type, (IUnknown **)&mediasource); + ok(hr == E_POINTER, "got 0x%08x\n", hr); + + hr = IMFSourceResolver_CreateObjectFromByteStream( + resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, + NULL, (IUnknown **)&mediasource); + ok(hr == E_POINTER, "got 0x%08x\n", hr); + + hr = IMFSourceResolver_CreateObjectFromByteStream( + resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, + &obj_type, NULL); + ok(hr == E_POINTER, "got 0x%08x\n", hr); + + hr = IMFSourceResolver_CreateObjectFromByteStream( + resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, + &obj_type, (IUnknown **)&mediasource); + todo_wine ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr); + if (hr == S_OK) IMFMediaSource_Release(mediasource); + + hr = IMFSourceResolver_CreateObjectFromByteStream( + resolver, bytestream, NULL, MF_RESOLUTION_BYTESTREAM, NULL, + &obj_type, (IUnknown **)&mediasource); + todo_wine ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr); + + IMFByteStream_Release(bytestream); + + /* We have to create a new bytestream here, because all following + * calls to CreateObjectFromByteStream will fail. */ + hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, + MF_FILEFLAGS_NONE, filename, &bytestream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IUnknown_QueryInterface(bytestream, &IID_IMFAttributes, + (void **)&attributes); + ok(hr == S_OK, "got 0x%08x\n", hr); + hr = IMFAttributes_SetString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, file_type); + todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); + IMFAttributes_Release(attributes); + + hr = IMFSourceResolver_CreateObjectFromByteStream( + resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, + &obj_type, (IUnknown **)&mediasource); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(mediasource != NULL, "got %p\n", mediasource); + ok(obj_type == MF_OBJECT_MEDIASOURCE, "got %d\n", obj_type); + + IMFMediaSource_Release(mediasource); + IMFByteStream_Release(bytestream); + + IMFSourceResolver_Release(resolver); + + MFShutdown(); + + DeleteFileW(filename); }
static void init_functions(void) @@ -619,7 +693,6 @@ START_TEST(mfplat) init_functions();
test_register(); - test_source_resolver(); test_MFCreateMediaType(); test_MFCreateMediaEvent(); test_MFCreateAttributes(); @@ -627,6 +700,7 @@ START_TEST(mfplat) test_MFCreateFile(); test_MFCreateMFByteStreamOnStream(); test_MFCreateMemoryBuffer(); + test_source_resolver();
CoUninitialize(); } diff --git a/include/mfidl.idl b/include/mfidl.idl index 170588bb5f..2373e418be 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -313,3 +313,39 @@ cpp_quote(" IMFMediaType **types, IMFStreamDescriptor **descriptor);") cpp_quote("HRESULT WINAPI MFCreateTopology(IMFTopology **topology);") cpp_quote("HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *array);") cpp_quote("HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID iid, void **obj);") + +[ + object, + uuid(279a808d-aec7-40c8-9c6b-a6b492c78a66), +] +interface IMFMediaSource : IMFMediaEventGenerator +{ + HRESULT GetCharacteristics( + [out] DWORD *characteristics ); + + [local] + HRESULT CreatePresentationDescriptor( + [out] IMFPresentationDescriptor **descriptor ); + [call_as(CreatePresentationDescriptor)] + HRESULT RemoteCreatePresentationDescriptor( + [out] DWORD *count, + [out, size_is(,*count)] BYTE **data, + [out] IMFPresentationDescriptor **descriptor ); + + HRESULT Start( + [in] IMFPresentationDescriptor *descriptor, + [in, unique] const GUID *time_format, + [in, unique] const PROPVARIANT *start_position ); + + HRESULT Stop(); + HRESULT Pause(); + HRESULT Shutdown(); +} + +cpp_quote("#define MF_RESOLUTION_MEDIASOURCE 0x00000001") +cpp_quote("#define MF_RESOLUTION_BYTESTREAM 0x00000002") +cpp_quote("#define MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE 0x00000010") +cpp_quote("#define MF_RESOLUTION_KEEP_BYTE_STREAM_ALIVE_ON_FAIL 0x00000020") +cpp_quote("#define MF_RESOLUTION_READ 0x00010000") +cpp_quote("#define MF_RESOLUTION_WRITE 0x00020000") +cpp_quote("#define MF_RESOLUTION_DISABLE_LOCAL_PLUGINS 0x00000040")