[PATCH 5/5] mfplay: Implement creating media items from URLs.

Nikolay Sivov nsivov at codeweavers.com
Mon Apr 5 01:11:00 CDT 2021


Signed-off-by: Nikolay Sivov <nsivov at 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);")
-- 
2.30.2




More information about the wine-devel mailing list