[PATCH 2/5] mfmediaengine: Set media type flags on source resolution.
Nikolay Sivov
nsivov at codeweavers.com
Wed Jun 3 12:08:38 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfmediaengine/main.c | 203 ++++++++++++++++++++++++++++++++++++--
1 file changed, 193 insertions(+), 10 deletions(-)
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
index b9a5fb46d6f..4136382566d 100644
--- a/dlls/mfmediaengine/main.c
+++ b/dlls/mfmediaengine/main.c
@@ -65,12 +65,15 @@ enum media_engine_flags
FLAGS_ENGINE_PAUSED = 0x100,
FLAGS_ENGINE_WAITING = 0x200,
FLAGS_ENGINE_MUTED = 0x400,
+ FLAGS_ENGINE_HAS_AUDIO = 0x800,
+ FLAGS_ENGINE_HAS_VIDEO = 0x1000,
};
struct media_engine
{
IMFMediaEngine IMFMediaEngine_iface;
IMFAsyncCallback session_events;
+ IMFAsyncCallback load_handler;
LONG refcount;
IMFMediaEngineNotify *callback;
IMFAttributes *attributes;
@@ -80,6 +83,7 @@ struct media_engine
double default_playback_rate;
double volume;
IMFMediaSession *session;
+ IMFSourceResolver *resolver;
CRITICAL_SECTION cs;
};
@@ -101,7 +105,12 @@ static struct media_engine *impl_from_session_events_IMFAsyncCallback(IMFAsyncCa
return CONTAINING_RECORD(iface, struct media_engine, session_events);
}
-static HRESULT WINAPI media_engine_session_events_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
+static struct media_engine *impl_from_load_handler_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+ return CONTAINING_RECORD(iface, struct media_engine, load_handler);
+}
+
+static HRESULT WINAPI media_engine_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
IsEqualIID(riid, &IID_IUnknown))
@@ -128,7 +137,7 @@ static ULONG WINAPI media_engine_session_events_Release(IMFAsyncCallback *iface)
return IMFMediaEngine_Release(&engine->IMFMediaEngine_iface);
}
-static HRESULT WINAPI media_engine_session_events_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
+static HRESULT WINAPI media_engine_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
{
return E_NOTIMPL;
}
@@ -175,13 +184,142 @@ failed:
static const IMFAsyncCallbackVtbl media_engine_session_events_vtbl =
{
- media_engine_session_events_QueryInterface,
+ media_engine_callback_QueryInterface,
media_engine_session_events_AddRef,
media_engine_session_events_Release,
- media_engine_session_events_GetParameters,
+ media_engine_callback_GetParameters,
media_engine_session_events_Invoke,
};
+static ULONG WINAPI media_engine_load_handler_AddRef(IMFAsyncCallback *iface)
+{
+ struct media_engine *engine = impl_from_load_handler_IMFAsyncCallback(iface);
+ return IMFMediaEngine_AddRef(&engine->IMFMediaEngine_iface);
+}
+
+static ULONG WINAPI media_engine_load_handler_Release(IMFAsyncCallback *iface)
+{
+ struct media_engine *engine = impl_from_load_handler_IMFAsyncCallback(iface);
+ return IMFMediaEngine_Release(&engine->IMFMediaEngine_iface);
+}
+
+static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMediaSource *source)
+{
+ IMFStreamDescriptor *sd_audio = NULL, *sd_video = NULL;
+ unsigned int stream_count = 0, i;
+ IMFPresentationDescriptor *pd;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd)))
+ return hr;
+
+ if (FAILED(hr = IMFPresentationDescriptor_GetStreamDescriptorCount(pd, &stream_count)))
+ WARN("Failed to get stream count, hr %#x.\n", hr);
+
+ /* Enable first video stream and first audio stream. */
+
+ for (i = 0; i < stream_count; ++i)
+ {
+ IMFMediaTypeHandler *type_handler;
+ IMFStreamDescriptor *sd;
+ BOOL selected;
+
+ IMFPresentationDescriptor_DeselectStream(pd, i);
+
+ if (sd_audio && sd_video)
+ continue;
+
+ IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, i, &selected, &sd);
+
+ if (SUCCEEDED(IMFStreamDescriptor_GetMediaTypeHandler(sd, &type_handler)))
+ {
+ GUID major = { 0 };
+
+ IMFMediaTypeHandler_GetMajorType(type_handler, &major);
+
+ if (IsEqualGUID(&major, &MFMediaType_Audio) && !sd_audio)
+ {
+ sd_audio = sd;
+ IMFStreamDescriptor_AddRef(sd_audio);
+ IMFPresentationDescriptor_SelectStream(pd, i);
+ }
+ else if (IsEqualGUID(&major, &MFMediaType_Video) && !sd_video && !(engine->flags & MF_MEDIA_ENGINE_AUDIOONLY))
+ {
+ sd_video = sd;
+ IMFStreamDescriptor_AddRef(sd_video);
+ IMFPresentationDescriptor_SelectStream(pd, i);
+ }
+
+ IMFMediaTypeHandler_Release(type_handler);
+ }
+ }
+
+ if (!sd_video && !sd_audio)
+ {
+ IMFPresentationDescriptor_Release(pd);
+ return E_UNEXPECTED;
+ }
+
+ if (sd_video)
+ engine->flags |= FLAGS_ENGINE_HAS_VIDEO;
+ if (sd_audio)
+ engine->flags |= FLAGS_ENGINE_HAS_AUDIO;
+
+ /* TODO: set duration */
+
+ if (sd_video)
+ IMFStreamDescriptor_Release(sd_video);
+ if (sd_audio)
+ IMFStreamDescriptor_Release(sd_audio);
+
+ IMFPresentationDescriptor_Release(pd);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI media_engine_load_handler_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+ struct media_engine *engine = impl_from_load_handler_IMFAsyncCallback(iface);
+ MF_OBJECT_TYPE obj_type;
+ IMFMediaSource *source;
+ IUnknown *object = NULL;
+ HRESULT hr;
+
+ EnterCriticalSection(&engine->cs);
+
+ IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_LOADSTART, 0, 0);
+
+ if (FAILED(hr = IMFSourceResolver_EndCreateObjectFromURL(engine->resolver, result, &obj_type, &object)))
+ WARN("Failed to create source object, hr %#x.\n", hr);
+
+ if (object)
+ {
+ if (SUCCEEDED(hr = IUnknown_QueryInterface(object, &IID_IMFMediaSource, (void **)&source)))
+ {
+ hr = media_engine_create_topology(engine, source);
+ IMFMediaSource_Release(source);
+ }
+ IUnknown_Release(object);
+ }
+
+ if (FAILED(hr))
+ IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_ERROR,
+ MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED, hr);
+
+ LeaveCriticalSection(&engine->cs);
+
+ return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl media_engine_load_handler_vtbl =
+{
+ media_engine_callback_QueryInterface,
+ media_engine_load_handler_AddRef,
+ media_engine_load_handler_Release,
+ media_engine_callback_GetParameters,
+ media_engine_load_handler_Invoke,
+};
+
static HRESULT WINAPI media_engine_QueryInterface(IMFMediaEngine *iface, REFIID riid, void **obj)
{
TRACE("(%p, %s, %p).\n", iface, debugstr_guid(riid), obj);
@@ -217,6 +355,8 @@ static void free_media_engine(struct media_engine *engine)
IMFMediaSession_Release(engine->session);
if (engine->attributes)
IMFAttributes_Release(engine->attributes);
+ if (engine->resolver)
+ IMFSourceResolver_Release(engine->resolver);
DeleteCriticalSection(&engine->cs);
heap_free(engine);
}
@@ -257,9 +397,34 @@ static HRESULT WINAPI media_engine_SetSourceElements(IMFMediaEngine *iface, IMFM
static HRESULT WINAPI media_engine_SetSource(IMFMediaEngine *iface, BSTR url)
{
- FIXME("(%p, %s): stub.\n", iface, debugstr_w(url));
+ struct media_engine *engine = impl_from_IMFMediaEngine(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %s.\n", iface, debugstr_w(url));
+
+ EnterCriticalSection(&engine->cs);
+
+ IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_PURGEQUEUEDEVENTS, 0, 0);
+
+ if (url)
+ {
+ IPropertyStore *props = NULL;
+ unsigned int flags;
+
+ flags = MF_RESOLUTION_MEDIASOURCE;
+ if (engine->flags & MF_MEDIA_ENGINE_DISABLE_LOCAL_PLUGINS)
+ flags |= MF_RESOLUTION_DISABLE_LOCAL_PLUGINS;
+
+ IMFAttributes_GetUnknown(engine->attributes, &MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE,
+ &IID_IPropertyStore, (void **)&props);
+ hr = IMFSourceResolver_BeginCreateObjectFromURL(engine->resolver, url, flags, props, NULL, &engine->load_handler, NULL);
+ if (props)
+ IPropertyStore_Release(props);
+ }
+
+ LeaveCriticalSection(&engine->cs);
+
+ return hr;
}
static HRESULT WINAPI media_engine_GetCurrentSource(IMFMediaEngine *iface, BSTR *url)
@@ -633,16 +798,30 @@ static HRESULT WINAPI media_engine_SetVolume(IMFMediaEngine *iface, double volum
static BOOL WINAPI media_engine_HasVideo(IMFMediaEngine *iface)
{
- FIXME("(%p): stub.\n", iface);
+ struct media_engine *engine = impl_from_IMFMediaEngine(iface);
+ BOOL value;
- return FALSE;
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&engine->cs);
+ value = !!(engine->flags & FLAGS_ENGINE_HAS_VIDEO);
+ LeaveCriticalSection(&engine->cs);
+
+ return value;
}
static BOOL WINAPI media_engine_HasAudio(IMFMediaEngine *iface)
{
- FIXME("(%p): stub.\n", iface);
+ struct media_engine *engine = impl_from_IMFMediaEngine(iface);
+ BOOL value;
- return FALSE;
+ TRACE("%p.\n", iface);
+
+ EnterCriticalSection(&engine->cs);
+ value = !!(engine->flags & FLAGS_ENGINE_HAS_AUDIO);
+ LeaveCriticalSection(&engine->cs);
+
+ return value;
}
static HRESULT WINAPI media_engine_GetNativeVideoSize(IMFMediaEngine *iface, DWORD *cx, DWORD *cy)
@@ -777,6 +956,7 @@ static HRESULT init_media_engine(DWORD flags, IMFAttributes *attributes, struct
engine->IMFMediaEngine_iface.lpVtbl = &media_engine_vtbl;
engine->session_events.lpVtbl = &media_engine_session_events_vtbl;
+ engine->load_handler.lpVtbl = &media_engine_load_handler_vtbl;
engine->refcount = 1;
engine->flags = (flags & MF_MEDIA_ENGINE_CREATEFLAGS_MASK) | FLAGS_ENGINE_PAUSED;
engine->default_playback_rate = 1.0;
@@ -795,6 +975,9 @@ static HRESULT init_media_engine(DWORD flags, IMFAttributes *attributes, struct
if (FAILED(hr = IMFMediaSession_BeginGetEvent(engine->session, &engine->session_events, NULL)))
return hr;
+ if (FAILED(hr = MFCreateSourceResolver(&engine->resolver)))
+ return hr;
+
if (FAILED(hr = MFCreateAttributes(&engine->attributes, 0)))
return hr;
--
2.26.2
More information about the wine-devel
mailing list