Signed-off-by: Sven Baars <sven.wine(a)gmail.com>
---
v3: Don't submit the first two patches of the series.
dlls/mfplat/main.c | 187 +++++++++++++++++++++++++++++++++++++
dlls/mfplat/tests/mfplat.c | 78 +++++++++++++++-
include/mfidl.idl | 47 ++++++++++
3 files changed, 310 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 84be055d09..ac5acc50f5 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -212,6 +212,53 @@ interface IMFStreamDescriptor : IMFAttributes
HRESULT GetMediaTypeHandler([out] IMFMediaTypeHandler **handler);
}
+[
+ object,
+ uuid(03cb2711-24d7-4db6-a17f-f3a7a479a536),
+]
+interface IMFPresentationDescriptor : IMFAttributes
+{
+ HRESULT GetStreamDescriptorCount([out] DWORD *pdwDescriptorCount);
+ HRESULT GetStreamDescriptorByIndex([in] DWORD dwIndex, [out] BOOL *pfSelected, [out] IMFStreamDescriptor **ppDescriptor);
+ HRESULT SelectStream([in] DWORD dwDescriptorIndex);
+ HRESULT DeselectStream([in] DWORD dwDescriptorIndex);
+ HRESULT Clone([out] IMFPresentationDescriptor **ppPresentationDescriptor);
+}
+
+[
+ object,
+ uuid(279a808d-aec7-40c8-9c6b-a6b492c78a66),
+]
+interface IMFMediaSource : IMFMediaEventGenerator
+{
+ HRESULT GetCharacteristics([out] DWORD *pdwCharacteristics);
+
+ [local]
+ HRESULT CreatePresentationDescriptor([out] IMFPresentationDescriptor **ppPresentationDescriptor);
+ [call_as(CreatePresentationDescriptor)]
+ HRESULT RemoteCreatePresentationDescriptor(
+ [out] DWORD *pcbPD,
+ [out, size_is(,*pcbPD)] BYTE **pbPD,
+ [out] IMFPresentationDescriptor **ppRemotePD);
+
+ HRESULT Start(
+ [in] IMFPresentationDescriptor *pPresentationDescriptor,
+ [in, unique] const GUID *pguidTimeFormat,
+ [in, unique] const PROPVARIANT *pvarStartPosition);
+
+ 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")
+
[
object,
uuid(f6696e82-74f7-4f3d-a178-8a5e09c3659f)
--
2.17.1