mfplay: Partially implement SetMediaItem().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
14b4492086
commit
57dd39384b
|
@ -19,6 +19,7 @@
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
@ -28,8 +29,12 @@
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
|
#include "initguid.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||||
|
|
||||||
|
DEFINE_GUID(_MF_TOPO_MEDIA_ITEM, 0x6c1bb4df, 0x59ba, 0x4020, 0x85, 0x0c, 0x35, 0x79, 0xa2, 0x7a, 0xe2, 0x51);
|
||||||
|
|
||||||
static const WCHAR eventclassW[] = L"MediaPlayerEventCallbackClass";
|
static const WCHAR eventclassW[] = L"MediaPlayerEventCallbackClass";
|
||||||
|
|
||||||
static LONG startup_refcount;
|
static LONG startup_refcount;
|
||||||
|
@ -549,6 +554,14 @@ static const IMFPMediaItemVtbl media_item_vtbl =
|
||||||
media_item_GetMetadata,
|
media_item_GetMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct media_item *unsafe_impl_from_IMFPMediaItem(IMFPMediaItem *iface)
|
||||||
|
{
|
||||||
|
if (!iface)
|
||||||
|
return NULL;
|
||||||
|
assert(iface->lpVtbl == (IMFPMediaItemVtbl *)&media_item_vtbl);
|
||||||
|
return CONTAINING_RECORD(iface, struct media_item, IMFPMediaItem_iface);
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT create_media_item(IMFPMediaPlayer *player, DWORD_PTR user_data, struct media_item **item)
|
static HRESULT create_media_item(IMFPMediaPlayer *player, DWORD_PTR user_data, struct media_item **item)
|
||||||
{
|
{
|
||||||
struct media_item *object;
|
struct media_item *object;
|
||||||
|
@ -822,11 +835,106 @@ static HRESULT WINAPI media_player_CreateMediaItemFromObject(IMFPMediaPlayer *if
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI media_player_SetMediaItem(IMFPMediaPlayer *iface, IMFPMediaItem *item)
|
static HRESULT media_item_get_stream_type(IMFStreamDescriptor *sd, GUID *major)
|
||||||
{
|
{
|
||||||
FIXME("%p, %p.\n", iface, item);
|
IMFMediaTypeHandler *handler;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
if (SUCCEEDED(hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler)))
|
||||||
|
{
|
||||||
|
hr = IMFMediaTypeHandler_GetMajorType(handler, major);
|
||||||
|
IMFMediaTypeHandler_Release(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT media_item_create_topology(struct media_player *player, struct media_item *item, IMFTopology **out)
|
||||||
|
{
|
||||||
|
IMFTopologyNode *src_node, *sink_node;
|
||||||
|
IMFActivate *sar_activate;
|
||||||
|
IMFStreamDescriptor *sd;
|
||||||
|
IMFTopology *topology;
|
||||||
|
unsigned int idx;
|
||||||
|
BOOL selected;
|
||||||
|
HRESULT hr;
|
||||||
|
GUID major;
|
||||||
|
|
||||||
|
if (FAILED(hr = MFCreateTopology(&topology)))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
/* FIXME: handle user sinks */
|
||||||
|
|
||||||
|
/* Use first stream if none selected. */
|
||||||
|
if (player->output_window)
|
||||||
|
{
|
||||||
|
FIXME("Video streams are not handled.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up audio branches for all selected streams. */
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(item->pd, idx++, &selected, &sd)))
|
||||||
|
{
|
||||||
|
if (selected && SUCCEEDED(media_item_get_stream_type(sd, &major)) && IsEqualGUID(&major, &MFMediaType_Audio))
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node)))
|
||||||
|
{
|
||||||
|
IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)item->source);
|
||||||
|
IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)item->pd);
|
||||||
|
IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
|
||||||
|
|
||||||
|
IMFTopology_AddNode(topology, src_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node)))
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(MFCreateAudioRendererActivate(&sar_activate)))
|
||||||
|
{
|
||||||
|
IMFTopologyNode_SetObject(sink_node, (IUnknown *)sar_activate);
|
||||||
|
IMFActivate_Release(sar_activate);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMFTopology_AddNode(topology, sink_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_node && sink_node)
|
||||||
|
IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
|
||||||
|
|
||||||
|
if (src_node)
|
||||||
|
IMFTopologyNode_Release(src_node);
|
||||||
|
if (sink_node)
|
||||||
|
IMFTopologyNode_Release(sink_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMFStreamDescriptor_Release(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = topology;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI media_player_SetMediaItem(IMFPMediaPlayer *iface, IMFPMediaItem *item_iface)
|
||||||
|
{
|
||||||
|
struct media_player *player = impl_from_IMFPMediaPlayer(iface);
|
||||||
|
struct media_item *item = unsafe_impl_from_IMFPMediaItem(item_iface);
|
||||||
|
IMFTopology *topology;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("%p, %p.\n", iface, item_iface);
|
||||||
|
|
||||||
|
if (item->player != iface)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if (FAILED(hr = media_item_create_topology(player, item, &topology)))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
IMFTopology_SetUnknown(topology, &_MF_TOPO_MEDIA_ITEM, (IUnknown *)item_iface);
|
||||||
|
hr = IMFMediaSession_SetTopology(player->session, MFSESSION_SETTOPOLOGY_IMMEDIATE, topology);
|
||||||
|
IMFTopology_Release(topology);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI media_player_ClearMediaItem(IMFPMediaPlayer *iface)
|
static HRESULT WINAPI media_player_ClearMediaItem(IMFPMediaPlayer *iface)
|
||||||
|
@ -1267,6 +1375,8 @@ static HRESULT WINAPI media_player_session_events_callback_Invoke(IMFAsyncCallba
|
||||||
MFP_MEDIAPLAYER_STATE state;
|
MFP_MEDIAPLAYER_STATE state;
|
||||||
MFP_EVENT_TYPE event_type;
|
MFP_EVENT_TYPE event_type;
|
||||||
HRESULT hr, event_status;
|
HRESULT hr, event_status;
|
||||||
|
IMFPMediaItem *item = NULL;
|
||||||
|
IMFTopology *topology;
|
||||||
|
|
||||||
if (FAILED(hr = IMFMediaSession_EndGetEvent(player->session, result, &session_event)))
|
if (FAILED(hr = IMFMediaSession_EndGetEvent(player->session, result, &session_event)))
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1274,6 +1384,12 @@ static HRESULT WINAPI media_player_session_events_callback_Invoke(IMFAsyncCallba
|
||||||
IMFMediaEvent_GetType(session_event, &session_event_type);
|
IMFMediaEvent_GetType(session_event, &session_event_type);
|
||||||
IMFMediaEvent_GetStatus(session_event, &event_status);
|
IMFMediaEvent_GetStatus(session_event, &event_status);
|
||||||
|
|
||||||
|
if (SUCCEEDED(IMFMediaSession_GetFullTopology(player->session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology)))
|
||||||
|
{
|
||||||
|
IMFTopology_GetUnknown(topology, &_MF_TOPO_MEDIA_ITEM, &IID_IMFPMediaItem, (void **)&item);
|
||||||
|
IMFTopology_Release(topology);
|
||||||
|
}
|
||||||
|
|
||||||
switch (session_event_type)
|
switch (session_event_type)
|
||||||
{
|
{
|
||||||
case MESessionStarted:
|
case MESessionStarted:
|
||||||
|
@ -1302,17 +1418,27 @@ static HRESULT WINAPI media_player_session_events_callback_Invoke(IMFAsyncCallba
|
||||||
|
|
||||||
/* FIXME: set pMediaItem */
|
/* FIXME: set pMediaItem */
|
||||||
media_player_queue_event(player, event);
|
media_player_queue_event(player, event);
|
||||||
IUnknown_Release(&event->IUnknown_iface);
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MESessionTopologySet:
|
||||||
|
|
||||||
|
media_event_create(player, MFP_EVENT_TYPE_MEDIAITEM_SET, event_status, &event);
|
||||||
|
event->u.generic.item = item;
|
||||||
|
if (event->u.generic.item)
|
||||||
|
IMFPMediaItem_AddRef(event->u.generic.item);
|
||||||
|
media_player_queue_event(player, event);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item)
|
||||||
|
IMFPMediaItem_Release(item);
|
||||||
|
|
||||||
if (event)
|
if (event)
|
||||||
{
|
|
||||||
IUnknown_Release(&event->IUnknown_iface);
|
IUnknown_Release(&event->IUnknown_iface);
|
||||||
}
|
|
||||||
|
|
||||||
IMFMediaSession_BeginGetEvent(player->session, &player->session_events_callback, NULL);
|
IMFMediaSession_BeginGetEvent(player->session, &player->session_events_callback, NULL);
|
||||||
IMFMediaEvent_Release(session_event);
|
IMFMediaEvent_Release(session_event);
|
||||||
|
|
Loading…
Reference in New Issue