Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/main.c | 19 +++++++++++++++++++ dlls/mf/mf.spec | 2 +- dlls/mf/tests/mf.c | 39 +++++++++++++++++++++++++++++++++++++++ include/mfidl.idl | 1 + 4 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index bf7066ad032..b59ad466c73 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -1460,3 +1460,22 @@ HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler)
return S_OK; } + +HRESULT WINAPI MFRequireProtectedEnvironment(IMFPresentationDescriptor *pd) +{ + BOOL selected, protected = FALSE; + unsigned int i = 0, value; + IMFStreamDescriptor *sd; + + TRACE("%p.\n", pd); + + while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, i++, &selected, &sd))) + { + value = 0; + protected = SUCCEEDED(IMFStreamDescriptor_GetUINT32(sd, &MF_SD_PROTECTED, &value)) && value; + IMFStreamDescriptor_Release(sd); + if (protected) break; + } + + return protected ? S_OK : S_FALSE; +} diff --git a/dlls/mf/mf.spec b/dlls/mf/mf.spec index 2927d9f8a88..8f340243fc2 100644 --- a/dlls/mf/mf.spec +++ b/dlls/mf/mf.spec @@ -77,7 +77,7 @@ @ stdcall MFGetSupportedSchemes(ptr) @ stdcall MFGetTopoNodeCurrentType(ptr long long ptr) @ stub MFReadSequencerSegmentOffset -@ stub MFRequireProtectedEnvironment +@ stdcall MFRequireProtectedEnvironment(ptr) @ stdcall MFShutdownObject(ptr) @ stub MFTranscodeGetAudioOutputAvailableTypes @ stub MergePropertyStore diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 40d8561bb06..df286db6385 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -5185,6 +5185,44 @@ static void init_functions(void) #undef X }
+static void test_MFRequireProtectedEnvironment(void) +{ + IMFPresentationDescriptor *pd; + IMFMediaType *mediatype; + IMFStreamDescriptor *sd; + HRESULT hr; + + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd); + ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr); + + hr = MFCreatePresentationDescriptor(1, &sd, &pd); + ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr); + + hr = IMFPresentationDescriptor_SelectStream(pd, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFRequireProtectedEnvironment(pd); + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + + hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SD_PROTECTED, 1); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFRequireProtectedEnvironment(pd); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFPresentationDescriptor_DeselectStream(pd, 0); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFRequireProtectedEnvironment(pd); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IMFStreamDescriptor_Release(sd); + IMFPresentationDescriptor_Release(pd); +} + START_TEST(mf) { init_functions(); @@ -5216,4 +5254,5 @@ START_TEST(mf) test_sample_copier(); test_sample_copier_output_processing(); test_MFGetTopoNodeCurrentType(); + test_MFRequireProtectedEnvironment(); } diff --git a/include/mfidl.idl b/include/mfidl.idl index 46c715a3752..138b899ffdb 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -698,6 +698,7 @@ cpp_quote("MFTIME WINAPI MFGetSystemTime(void);") cpp_quote("HRESULT WINAPI MFGetTopoNodeCurrentType(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type);") cpp_quote("HRESULT WINAPI MFShutdownObject(IUnknown *object);") cpp_quote("HRESULT WINAPI MFCreateTrackedSample(IMFTrackedSample **sample);") +cpp_quote("HRESULT WINAPI MFRequireProtectedEnvironment(IMFPresentationDescriptor *pd);")
typedef enum _MFMEDIASOURCE_CHARACTERISTICS {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 8 +++++++ dlls/mfplay/tests/Makefile.in | 2 +- dlls/mfplay/tests/mfplay.c | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index 1e2a3a8f189..6905812835a 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -33,6 +33,7 @@ struct media_player { IMFPMediaPlayer IMFPMediaPlayer_iface; LONG refcount; + IMFPMediaPlayerCallback *callback; };
static struct media_player *impl_from_IMFPMediaPlayer(IMFPMediaPlayer *iface) @@ -76,7 +77,11 @@ static ULONG WINAPI media_player_Release(IMFPMediaPlayer *iface) TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount) + { + if (player->callback) + IMFPMediaPlayerCallback_Release(player->callback); heap_free(player); + }
return refcount; } @@ -396,6 +401,9 @@ HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_C
object->IMFPMediaPlayer_iface.lpVtbl = &media_player_vtbl; object->refcount = 1; + object->callback = callback; + if (object->callback) + IMFPMediaPlayerCallback_AddRef(object->callback);
*player = &object->IMFPMediaPlayer_iface;
diff --git a/dlls/mfplay/tests/Makefile.in b/dlls/mfplay/tests/Makefile.in index ca08c65ce24..43c7ec26240 100644 --- a/dlls/mfplay/tests/Makefile.in +++ b/dlls/mfplay/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mfplay.dll -IMPORTS = mfplay +IMPORTS = mfplay uuid mfuuid
C_SRCS = \ mfplay.c diff --git a/dlls/mfplay/tests/mfplay.c b/dlls/mfplay/tests/mfplay.c index e9b5df95039..ef8aaddc76f 100644 --- a/dlls/mfplay/tests/mfplay.c +++ b/dlls/mfplay/tests/mfplay.c @@ -26,14 +26,55 @@
#include "wine/test.h"
+static HRESULT WINAPI test_callback_QueryInterface(IMFPMediaPlayerCallback *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IMFPMediaPlayerCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFPMediaPlayerCallback_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI test_callback_AddRef(IMFPMediaPlayerCallback *iface) +{ + return 2; +} + +static ULONG WINAPI test_callback_Release(IMFPMediaPlayerCallback *iface) +{ + return 1; +} + +static void WINAPI test_callback_OnMediaPlayerEvent(IMFPMediaPlayerCallback *iface, MFP_EVENT_HEADER *event_header) +{ +} + +static const IMFPMediaPlayerCallbackVtbl test_callback_vtbl = +{ + test_callback_QueryInterface, + test_callback_AddRef, + test_callback_Release, + test_callback_OnMediaPlayerEvent, +}; + static void test_create_player(void) { + IMFPMediaPlayerCallback callback = { &test_callback_vtbl }; IMFPMediaPlayer *player; HRESULT hr;
hr = MFPCreateMediaPlayer(NULL, FALSE, 0, NULL, NULL, &player); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); IMFPMediaPlayer_Release(player); + + hr = MFPCreateMediaPlayer(NULL, FALSE, 0, &callback, NULL, &player); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + IMFPMediaPlayer_Release(player); }
START_TEST(mfplay)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88238
Your paranoid android.
=== w2008s64 (32 bit report) ===
mfplay: mfplay.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== w2008s64 (task log) ===
TestLauncher32.exe:error: Unexpected return value 1 from wait for child
=== wvistau64 (64 bit report) ===
mfplay: mfplay.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== wvistau64 (task log) ===
TestLauncher64.exe:error: Unexpected return value 1 from wait for child
=== w2008s64 (64 bit report) ===
mfplay: mfplay.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== w2008s64 (task log) ===
TestLauncher64.exe:error: Unexpected return value 1 from wait for child
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/Makefile.in | 2 +- dlls/mfplay/player.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplay/Makefile.in b/dlls/mfplay/Makefile.in index b21ce0e2161..91a8e5cc5a6 100644 --- a/dlls/mfplay/Makefile.in +++ b/dlls/mfplay/Makefile.in @@ -1,6 +1,6 @@ MODULE = mfplay.dll IMPORTLIB = mfplay -IMPORTS = uuid mfuuid +IMPORTS = mfplat uuid mfuuid
EXTRADLLFLAGS = -mno-cygwin -Wb,--prefer-native
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index 6905812835a..0305f663924 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -22,6 +22,7 @@
#include "windef.h" #include "winbase.h" +#include "mfapi.h" #include "mfplay.h"
#include "wine/debug.h" @@ -29,6 +30,20 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+static LONG startup_refcount; + +static void platform_startup(void) +{ + if (InterlockedIncrement(&startup_refcount) == 1) + MFStartup(MF_VERSION, MFSTARTUP_FULL); +} + +static void platform_shutdown(void) +{ + if (InterlockedDecrement(&startup_refcount) == 0) + MFShutdown(); +} + struct media_player { IMFPMediaPlayer IMFPMediaPlayer_iface; @@ -81,6 +96,8 @@ static ULONG WINAPI media_player_Release(IMFPMediaPlayer *iface) if (player->callback) IMFPMediaPlayerCallback_Release(player->callback); heap_free(player); + + platform_shutdown(); }
return refcount; @@ -405,6 +422,8 @@ HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_C if (object->callback) IMFPMediaPlayerCallback_AddRef(object->callback);
+ platform_startup(); + *player = &object->IMFPMediaPlayer_iface;
return S_OK;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 120 ++++++++++++++++++++++++++++++++++--- dlls/mfplay/tests/mfplay.c | 36 +++++++++++ 2 files changed, 148 insertions(+), 8 deletions(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index 0305f663924..e729a863da9 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -47,8 +47,10 @@ static void platform_shutdown(void) struct media_player { IMFPMediaPlayer IMFPMediaPlayer_iface; + IPropertyStore IPropertyStore_iface; LONG refcount; IMFPMediaPlayerCallback *callback; + IPropertyStore *propstore; };
static struct media_player *impl_from_IMFPMediaPlayer(IMFPMediaPlayer *iface) @@ -56,22 +58,36 @@ static struct media_player *impl_from_IMFPMediaPlayer(IMFPMediaPlayer *iface) return CONTAINING_RECORD(iface, struct media_player, IMFPMediaPlayer_iface); }
+static struct media_player *impl_from_IPropertyStore(IPropertyStore *iface) +{ + return CONTAINING_RECORD(iface, struct media_player, IPropertyStore_iface); +} + static HRESULT WINAPI media_player_QueryInterface(IMFPMediaPlayer *iface, REFIID riid, void **obj) { + struct media_player *player = impl_from_IMFPMediaPlayer(iface); + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFPMediaPlayer) || IsEqualIID(riid, &IID_IUnknown)) { - *obj = iface; - IMFPMediaPlayer_AddRef(iface); - return S_OK; + *obj = &player->IMFPMediaPlayer_iface; + } + else if (IsEqualIID(riid, &IID_IPropertyStore)) + { + *obj = &player->IPropertyStore_iface; } + else + { + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL;
- WARN("Unsupported interface %s.\n", debugstr_guid(riid)); - *obj = NULL; + return E_NOINTERFACE; + }
- return E_NOINTERFACE; + IUnknown_AddRef((IUnknown *)*obj); + return S_OK; }
static ULONG WINAPI media_player_AddRef(IMFPMediaPlayer *iface) @@ -95,6 +111,8 @@ static ULONG WINAPI media_player_Release(IMFPMediaPlayer *iface) { if (player->callback) IMFPMediaPlayerCallback_Release(player->callback); + if (player->propstore) + IPropertyStore_Release(player->propstore); heap_free(player);
platform_shutdown(); @@ -406,25 +424,111 @@ static const IMFPMediaPlayerVtbl media_player_vtbl = media_player_Shutdown, };
+static HRESULT WINAPI media_player_propstore_QueryInterface(IPropertyStore *iface, + REFIID riid, void **obj) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + return IMFPMediaPlayer_QueryInterface(&player->IMFPMediaPlayer_iface, riid, obj); +} + +static ULONG WINAPI media_player_propstore_AddRef(IPropertyStore *iface) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + return IMFPMediaPlayer_AddRef(&player->IMFPMediaPlayer_iface); +} + +static ULONG WINAPI media_player_propstore_Release(IPropertyStore *iface) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface); +} + +static HRESULT WINAPI media_player_propstore_GetCount(IPropertyStore *iface, DWORD *count) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + + TRACE("%p, %p.\n", iface, count); + + return IPropertyStore_GetCount(player->propstore, count); +} + +static HRESULT WINAPI media_player_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + + TRACE("%p, %u, %p.\n", iface, prop, key); + + return IPropertyStore_GetAt(player->propstore, prop, key); +} + +static HRESULT WINAPI media_player_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + + TRACE("%p, %p, %p.\n", iface, key, value); + + return IPropertyStore_GetValue(player->propstore, key, value); +} + +static HRESULT WINAPI media_player_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + + TRACE("%p, %p, %p.\n", iface, key, value); + + return IPropertyStore_SetValue(player->propstore, key, value); +} + +static HRESULT WINAPI media_player_propstore_Commit(IPropertyStore *iface) +{ + struct media_player *player = impl_from_IPropertyStore(iface); + + TRACE("%p.\n", iface); + + return IPropertyStore_Commit(player->propstore); +} + +static const IPropertyStoreVtbl media_player_propstore_vtbl = +{ + media_player_propstore_QueryInterface, + media_player_propstore_AddRef, + media_player_propstore_Release, + media_player_propstore_GetCount, + media_player_propstore_GetAt, + media_player_propstore_GetValue, + media_player_propstore_SetValue, + media_player_propstore_Commit, +}; + HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_CREATION_OPTIONS options, IMFPMediaPlayerCallback *callback, HWND hwnd, IMFPMediaPlayer **player) { struct media_player *object; + HRESULT hr;
TRACE("%s, %d, %#x, %p, %p, %p.\n", debugstr_w(url), start_playback, options, callback, hwnd, player);
if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY;
+ platform_startup(); + object->IMFPMediaPlayer_iface.lpVtbl = &media_player_vtbl; + object->IPropertyStore_iface.lpVtbl = &media_player_propstore_vtbl; object->refcount = 1; object->callback = callback; if (object->callback) IMFPMediaPlayerCallback_AddRef(object->callback); - - platform_startup(); + if (FAILED(hr = CreatePropertyStore(&object->propstore))) + goto failed;
*player = &object->IMFPMediaPlayer_iface;
return S_OK; + +failed: + + IMFPMediaPlayer_Release(&object->IMFPMediaPlayer_iface); + + return hr; } diff --git a/dlls/mfplay/tests/mfplay.c b/dlls/mfplay/tests/mfplay.c index ef8aaddc76f..64347265c40 100644 --- a/dlls/mfplay/tests/mfplay.c +++ b/dlls/mfplay/tests/mfplay.c @@ -26,6 +26,21 @@
#include "wine/test.h"
+#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) +static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) +{ + IUnknown *iface = iface_ptr; + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); + ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + static HRESULT WINAPI test_callback_QueryInterface(IMFPMediaPlayerCallback *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFPMediaPlayerCallback) || @@ -65,11 +80,32 @@ static const IMFPMediaPlayerCallbackVtbl test_callback_vtbl = static void test_create_player(void) { IMFPMediaPlayerCallback callback = { &test_callback_vtbl }; + IPropertyStore *propstore; IMFPMediaPlayer *player; + IUnknown *unk, *unk2; HRESULT hr;
hr = MFPCreateMediaPlayer(NULL, FALSE, 0, NULL, NULL, &player); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + check_interface(player, &IID_IMFPMediaPlayer, TRUE); + check_interface(player, &IID_IPropertyStore, TRUE); + + hr = IMFPMediaPlayer_QueryInterface(player, &IID_IPropertyStore, (void **)&propstore); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + check_interface(propstore, &IID_IMFPMediaPlayer, TRUE); + + hr = IPropertyStore_QueryInterface(propstore, &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFPMediaPlayer_QueryInterface(player, &IID_IUnknown, (void **)&unk2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(unk == unk2, "Unexpected interface.\n"); + IUnknown_Release(unk); + IUnknown_Release(unk2); + + IPropertyStore_Release(propstore); + IMFPMediaPlayer_Release(player);
hr = MFPCreateMediaPlayer(NULL, FALSE, 0, &callback, NULL, &player);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88240
Your paranoid android.
=== w2008s64 (32 bit report) ===
mfplay: mfplay.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== w2008s64 (task log) ===
TestLauncher32.exe:error: Unexpected return value 1 from wait for child
=== wvistau64 (64 bit report) ===
mfplay: mfplay.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== wvistau64 (task log) ===
TestLauncher64.exe:error: Unexpected return value 1 from wait for child
=== w2008s64 (64 bit report) ===
mfplay: mfplay.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== w2008s64 (task log) ===
TestLauncher64.exe:error: Unexpected return value 1 from wait for child
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 383 ++++++++++++++++++++++++++++++++++++++++++- include/mfplay.idl | 90 ++++++++++ 2 files changed, 470 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index e729a863da9..0a953dde10f 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -44,13 +44,24 @@ static void platform_shutdown(void) MFShutdown(); }
+struct media_item +{ + IMFPMediaItem IMFPMediaItem_iface; + LONG refcount; + IMFPMediaPlayer *player; + IMFMediaSource *source; + DWORD_PTR user_data; +}; + struct media_player { IMFPMediaPlayer IMFPMediaPlayer_iface; IPropertyStore IPropertyStore_iface; + IMFAsyncCallback resolver_callback; LONG refcount; IMFPMediaPlayerCallback *callback; IPropertyStore *propstore; + IMFSourceResolver *resolver; };
static struct media_player *impl_from_IMFPMediaPlayer(IMFPMediaPlayer *iface) @@ -63,6 +74,263 @@ static struct media_player *impl_from_IPropertyStore(IPropertyStore *iface) return CONTAINING_RECORD(iface, struct media_player, IPropertyStore_iface); }
+static struct media_player *impl_from_resolver_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct media_player, resolver_callback); +} + +static struct media_item *impl_from_IMFPMediaItem(IMFPMediaItem *iface) +{ + return CONTAINING_RECORD(iface, struct media_item, IMFPMediaItem_iface); +} + +static HRESULT WINAPI media_item_QueryInterface(IMFPMediaItem *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFPMediaItem) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFPMediaItem_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI media_item_AddRef(IMFPMediaItem *iface) +{ + struct media_item *item = impl_from_IMFPMediaItem(iface); + ULONG refcount = InterlockedIncrement(&item->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI media_item_Release(IMFPMediaItem *iface) +{ + struct media_item *item = impl_from_IMFPMediaItem(iface); + ULONG refcount = InterlockedDecrement(&item->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + if (item->player) + IMFPMediaPlayer_Release(item->player); + if (item->source) + IMFMediaSource_Release(item->source); + heap_free(item); + } + + return refcount; +} + +static HRESULT WINAPI media_item_GetMediaPlayer(IMFPMediaItem *iface, + IMFPMediaPlayer **player) +{ + struct media_item *item = impl_from_IMFPMediaItem(iface); + + TRACE("%p, %p.\n", iface, player); + + *player = item->player; + IMFPMediaPlayer_AddRef(*player); + + return S_OK; +} + +static HRESULT WINAPI media_item_GetURL(IMFPMediaItem *iface, LPWSTR *url) +{ + FIXME("%p, %p.\n", iface, url); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetObject(IMFPMediaItem *iface, IUnknown **obj) +{ + FIXME("%p, %p.\n", iface, obj); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetUserData(IMFPMediaItem *iface, DWORD_PTR *user_data) +{ + struct media_item *item = impl_from_IMFPMediaItem(iface); + + TRACE("%p, %p.\n", iface, user_data); + + *user_data = item->user_data; + + return S_OK; +} + +static HRESULT WINAPI media_item_SetUserData(IMFPMediaItem *iface, DWORD_PTR user_data) +{ + struct media_item *item = impl_from_IMFPMediaItem(iface); + + TRACE("%p, %lx.\n", iface, user_data); + + item->user_data = user_data; + + return S_OK; +} + +static HRESULT WINAPI media_item_GetStartStopPosition(IMFPMediaItem *iface, GUID *start_format, + PROPVARIANT *start_position, GUID *stop_format, PROPVARIANT *stop_position) +{ + FIXME("%p, %p, %p, %p, %p.\n", iface, start_format, start_position, stop_format, stop_position); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_SetStartStopPosition(IMFPMediaItem *iface, const GUID *start_format, + const PROPVARIANT *start_position, const GUID *stop_format, const PROPVARIANT *stop_position) +{ + FIXME("%p, %s, %p, %s, %p.\n", iface, debugstr_guid(start_format), start_position, + debugstr_guid(stop_format), stop_position); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_HasVideo(IMFPMediaItem *iface, BOOL *has_video, BOOL *selected) +{ + FIXME("%p, %p, %p.\n", iface, has_video, selected); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_HasAudio(IMFPMediaItem *iface, BOOL *has_audio, BOOL *selected) +{ + FIXME("%p, %p, %p.\n", iface, has_audio, selected); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_IsProtected(IMFPMediaItem *iface, BOOL *protected) +{ + FIXME("%p, %p.\n", iface, protected); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetDuration(IMFPMediaItem *iface, REFGUID format, PROPVARIANT *value) +{ + FIXME("%p, %s, %p.\n", iface, debugstr_guid(format), value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetNumberOfStreams(IMFPMediaItem *iface, DWORD *count) +{ + FIXME("%p, %p.\n", iface, count); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL *enabled) +{ + FIXME("%p, %u, %p.\n", iface, index, enabled); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_SetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL enabled) +{ + FIXME("%p, %u, %d.\n", iface, index, enabled); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetStreamAttribute(IMFPMediaItem *iface, DWORD index, REFGUID key, + PROPVARIANT *value) +{ + FIXME("%p, %u, %s, %p.\n", iface, index, debugstr_guid(key), value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetPresentationAttribute(IMFPMediaItem *iface, REFGUID key, + PROPVARIANT *value) +{ + FIXME("%p, %s, %p.\n", iface, debugstr_guid(key), value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetCharacteristics(IMFPMediaItem *iface, MFP_MEDIAITEM_CHARACTERISTICS *flags) +{ + FIXME("%p, %p.\n", iface, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_SetStreamSink(IMFPMediaItem *iface, DWORD index, IUnknown *sink) +{ + FIXME("%p, %u, %p.\n", iface, index, sink); + + return E_NOTIMPL; +} + +static HRESULT WINAPI media_item_GetMetadata(IMFPMediaItem *iface, IPropertyStore **metadata) +{ + FIXME("%p, %p.\n", iface, metadata); + + return E_NOTIMPL; +} + +static const IMFPMediaItemVtbl media_item_vtbl = +{ + media_item_QueryInterface, + media_item_AddRef, + media_item_Release, + media_item_GetMediaPlayer, + media_item_GetURL, + media_item_GetObject, + media_item_GetUserData, + media_item_SetUserData, + media_item_GetStartStopPosition, + media_item_SetStartStopPosition, + media_item_HasVideo, + media_item_HasAudio, + media_item_IsProtected, + media_item_GetDuration, + media_item_GetNumberOfStreams, + media_item_GetStreamSelection, + media_item_SetStreamSelection, + media_item_GetStreamAttribute, + media_item_GetPresentationAttribute, + media_item_GetCharacteristics, + media_item_SetStreamSink, + media_item_GetMetadata, +}; + +static HRESULT create_media_item(IMFPMediaPlayer *player, DWORD_PTR user_data, struct media_item **item) +{ + struct media_item *object; + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IMFPMediaItem_iface.lpVtbl = &media_item_vtbl; + object->refcount = 1; + object->user_data = user_data; + object->player = player; + IMFPMediaPlayer_AddRef(object->player); + + *item = object; + + return S_OK; +} + +static HRESULT media_item_set_source(struct media_item *item, IUnknown *object) +{ + return IUnknown_QueryInterface(object, &IID_IMFMediaSource, (void **)&item->source); +} + static HRESULT WINAPI media_player_QueryInterface(IMFPMediaPlayer *iface, REFIID riid, void **obj) { struct media_player *player = impl_from_IMFPMediaPlayer(iface); @@ -113,6 +381,8 @@ static ULONG WINAPI media_player_Release(IMFPMediaPlayer *iface) IMFPMediaPlayerCallback_Release(player->callback); if (player->propstore) IPropertyStore_Release(player->propstore); + if (player->resolver) + IMFSourceResolver_Release(player->resolver); heap_free(player);
platform_shutdown(); @@ -199,11 +469,44 @@ static HRESULT WINAPI media_player_GetState(IMFPMediaPlayer *iface, MFP_MEDIAPLA }
static HRESULT WINAPI media_player_CreateMediaItemFromURL(IMFPMediaPlayer *iface, - const WCHAR *url, BOOL sync, DWORD_PTR user_data, IMFPMediaItem **item) + const WCHAR *url, BOOL sync, DWORD_PTR user_data, IMFPMediaItem **ret) { - FIXME("%p, %s, %d, %lx, %p.\n", iface, debugstr_w(url), sync, user_data, item); + struct media_player *player = impl_from_IMFPMediaPlayer(iface); + struct media_item *item; + MF_OBJECT_TYPE obj_type; + IUnknown *object; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %s, %d, %lx, %p.\n", iface, debugstr_w(url), sync, user_data, ret); + + if (FAILED(hr = create_media_item(iface, user_data, &item))) + return hr; + + if (sync) + { + *ret = NULL; + + if (SUCCEEDED(hr = IMFSourceResolver_CreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE, + player->propstore, &obj_type, &object))) + { + hr = media_item_set_source(item, object); + IUnknown_Release(object); + } + + if (SUCCEEDED(hr)) + *ret = &item->IMFPMediaItem_iface; + + return hr; + } + else + { + hr = IMFSourceResolver_BeginCreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE, + player->propstore, NULL, &player->resolver_callback, (IUnknown *)&item->IMFPMediaItem_iface); + + IMFPMediaItem_Release(&item->IMFPMediaItem_iface); + } + + return hr; }
static HRESULT WINAPI media_player_CreateMediaItemFromObject(IMFPMediaPlayer *iface, @@ -500,6 +803,77 @@ static const IPropertyStoreVtbl media_player_propstore_vtbl = media_player_propstore_Commit, };
+static HRESULT WINAPI media_player_resolver_callback_QueryInterface(IMFAsyncCallback *iface, + REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IMFAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFAsyncCallback_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI media_player_resolver_callback_AddRef(IMFAsyncCallback *iface) +{ + struct media_player *player = impl_from_resolver_IMFAsyncCallback(iface); + return IMFPMediaPlayer_AddRef(&player->IMFPMediaPlayer_iface); +} + +static ULONG WINAPI media_player_resolver_callback_Release(IMFAsyncCallback *iface) +{ + struct media_player *player = impl_from_resolver_IMFAsyncCallback(iface); + return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface); +} + +static HRESULT WINAPI media_player_resolver_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, + DWORD *queue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI media_player_resolver_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct media_player *player = impl_from_resolver_IMFAsyncCallback(iface); + struct media_item *item; + IUnknown *object, *state; + MF_OBJECT_TYPE obj_type; + HRESULT hr; + + if (FAILED(IMFAsyncResult_GetState(result, &state))) + return S_OK; + + item = impl_from_IMFPMediaItem((IMFPMediaItem *)state); + + if (SUCCEEDED(hr = IMFSourceResolver_EndCreateObjectFromURL(player->resolver, result, &obj_type, &object))) + { + hr = media_item_set_source(item, object); + IUnknown_Release(object); + } + + if (FAILED(hr)) + WARN("Failed to set media source, hr %#x.\n", hr); + + /* FIXME: callback notification */ + + IUnknown_Release(state); + + return S_OK; +} + +static const IMFAsyncCallbackVtbl media_player_resolver_callback_vtbl = +{ + media_player_resolver_callback_QueryInterface, + media_player_resolver_callback_AddRef, + media_player_resolver_callback_Release, + media_player_resolver_callback_GetParameters, + media_player_resolver_callback_Invoke, +}; + HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_CREATION_OPTIONS options, IMFPMediaPlayerCallback *callback, HWND hwnd, IMFPMediaPlayer **player) { @@ -515,12 +889,15 @@ HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_C
object->IMFPMediaPlayer_iface.lpVtbl = &media_player_vtbl; object->IPropertyStore_iface.lpVtbl = &media_player_propstore_vtbl; + object->resolver_callback.lpVtbl = &media_player_resolver_callback_vtbl; object->refcount = 1; object->callback = callback; if (object->callback) IMFPMediaPlayerCallback_AddRef(object->callback); if (FAILED(hr = CreatePropertyStore(&object->propstore))) goto failed; + if (FAILED(hr = MFCreateSourceResolver(&object->resolver))) + goto failed;
*player = &object->IMFPMediaPlayer_iface;
diff --git a/include/mfplay.idl b/include/mfplay.idl index 415a6f52414..1a20a6b8900 100644 --- a/include/mfplay.idl +++ b/include/mfplay.idl @@ -54,6 +54,16 @@ typedef enum MFP_EVENT_TYPE MFP_EVENT_TYPE_ACQUIRE_USER_CREDENTIAL, } MFP_EVENT_TYPE;
+typedef UINT32 MFP_MEDIAITEM_CHARACTERISTICS; + +typedef [v1_enum] enum _MFP_MEDIAITEM_CHARACTERISTICS +{ + MFP_MEDIAITEM_IS_LIVE = 0x00000001, + MFP_MEDIAITEM_CAN_SEEK = 0x00000002, + MFP_MEDIAITEM_CAN_PAUSE = 0x00000004, + MFP_MEDIAITEM_HAS_SLOW_SEEK = 0x00000008, +} _MFP_MEDIAITEM_CHARACTERISTICS; + interface IMFPMediaPlayer; interface IMFPMediaItem;
@@ -198,5 +208,85 @@ interface IMFPMediaPlayer : IUnknown HRESULT Shutdown(); }
+[ + object, + uuid(90eb3e6b-ecbf-45cc-b1da-c6fe3ea70d57), + local, +] +interface IMFPMediaItem : IUnknown +{ + HRESULT GetMediaPlayer( + [out] IMFPMediaPlayer **player); + + HRESULT GetURL( + [out] LPWSTR *url); + + HRESULT GetObject( + [out] IUnknown **obj); + + HRESULT GetUserData( + [out] DWORD_PTR *user_data); + + HRESULT SetUserData( + [in] DWORD_PTR user_data); + + HRESULT GetStartStopPosition( + [out] GUID *start_format, + [out] PROPVARIANT *start_position, + [out] GUID *stop_format, + [out] PROPVARIANT *stop_position); + + HRESULT SetStartStopPosition( + [in] const GUID *start_format, + [in] const PROPVARIANT *start_position, + [in] const GUID *stop_format, + [in] const PROPVARIANT *stop_position); + + HRESULT HasVideo( + [out] BOOL *has_video, + [out] BOOL *selected); + + HRESULT HasAudio( + [out] BOOL *has_audio, + [out] BOOL *selected); + + HRESULT IsProtected( + [out] BOOL *protected); + + HRESULT GetDuration( + [in] REFGUID format, + [out] PROPVARIANT *value); + + HRESULT GetNumberOfStreams( + [out] DWORD *count); + + HRESULT GetStreamSelection( + [in] DWORD index, + [out] BOOL *enabled); + + HRESULT SetStreamSelection( + [in] DWORD index, + [in] BOOL enabled); + + HRESULT GetStreamAttribute( + [in] DWORD index, + [in] REFGUID key, + [out] PROPVARIANT *value); + + HRESULT GetPresentationAttribute( + [in] REFGUID key, + [out] PROPVARIANT *value); + + HRESULT GetCharacteristics( + [out] MFP_MEDIAITEM_CHARACTERISTICS *flags); + + HRESULT SetStreamSink( + [in] DWORD index, + [in] IUnknown *sink); + + HRESULT GetMetadata( + [out] IPropertyStore **metadata); +} + cpp_quote("HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_CREATION_OPTIONS options, ") cpp_quote(" IMFPMediaPlayerCallback *callback, HWND hwnd, IMFPMediaPlayer **player);")
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88237
Your paranoid android.
=== w2008s64 (32 bit report) ===
mf: mf.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== w2008s64 (task log) ===
TestLauncher32.exe:error: Unexpected return value 1 from wait for child
=== w2008s64 (64 bit report) ===
mf: mf.c:0: Test failed: missing manifest for side-by-side dll (details below)
=== w2008s64 (task log) ===
TestLauncher64.exe:error: Unexpected return value 1 from wait for child