Nikolay Sivov : mfmediaengine: Add video output topology branch.

Alexandre Julliard julliard at winehq.org
Tue Nov 3 15:55:55 CST 2020


Module: wine
Branch: master
Commit: 344d3fb8a40e4eb431787187d49156ef4048d19c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=344d3fb8a40e4eb431787187d49156ef4048d19c

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Nov  3 15:56:03 2020 +0300

mfmediaengine: Add video output topology branch.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mfmediaengine/main.c | 166 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 164 insertions(+), 2 deletions(-)

diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c
index 64f0ae6d2a1..0817c249b27 100644
--- a/dlls/mfmediaengine/main.c
+++ b/dlls/mfmediaengine/main.c
@@ -75,6 +75,7 @@ struct media_engine
     IMFMediaEngine IMFMediaEngine_iface;
     IMFAsyncCallback session_events;
     IMFAsyncCallback load_handler;
+    IMFSampleGrabberSinkCallback grabber_callback;
     LONG refcount;
     IMFMediaEngineNotify *callback;
     IMFAttributes *attributes;
@@ -237,6 +238,11 @@ static struct media_engine *impl_from_load_handler_IMFAsyncCallback(IMFAsyncCall
     return CONTAINING_RECORD(iface, struct media_engine, load_handler);
 }
 
+static struct media_engine *impl_from_IMFSampleGrabberSinkCallback(IMFSampleGrabberSinkCallback *iface)
+{
+    return CONTAINING_RECORD(iface, struct media_engine, grabber_callback);
+}
+
 static HRESULT WINAPI media_engine_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
 {
     if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
@@ -373,6 +379,51 @@ static HRESULT media_engine_create_audio_renderer(struct media_engine *engine, I
     return hr;
 }
 
+static HRESULT media_engine_create_video_renderer(struct media_engine *engine, IMFTopologyNode **node)
+{
+    DXGI_FORMAT output_format;
+    IMFMediaType *media_type;
+    IMFActivate *activate;
+    GUID subtype;
+    HRESULT hr;
+
+    *node = NULL;
+
+    if (FAILED(IMFAttributes_GetUINT32(engine->attributes, &MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT, &output_format)))
+    {
+        WARN("Output format was not specified.\n");
+        return E_FAIL;
+    }
+
+    memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
+    if (!(subtype.Data1 = MFMapDXGIFormatToDX9Format(output_format)))
+    {
+        WARN("Unrecognized output format %#x.\n", output_format);
+        return E_FAIL;
+    }
+
+    if (FAILED(hr = MFCreateMediaType(&media_type)))
+        return hr;
+
+    IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
+    IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &subtype);
+
+    hr = MFCreateSampleGrabberSinkActivate(media_type, &engine->grabber_callback, &activate);
+    IMFMediaType_Release(media_type);
+    if (FAILED(hr))
+        return hr;
+
+    if (SUCCEEDED(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, node)))
+    {
+        IMFTopologyNode_SetObject(*node, (IUnknown *)activate);
+        IMFTopologyNode_SetUINT32(*node, &MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
+    }
+
+    IMFActivate_Release(activate);
+
+    return hr;
+}
+
 static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMediaSource *source)
 {
     IMFStreamDescriptor *sd_audio = NULL, *sd_video = NULL;
@@ -455,11 +506,10 @@ static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMedi
 
     IMFMediaEngineNotify_EventNotify(engine->callback, MF_MEDIA_ENGINE_EVENT_LOADEDDATA, 0, 0);
 
-    /* TODO: set up video stream nodes */
-
     if (SUCCEEDED(hr = MFCreateTopology(&topology)))
     {
         IMFTopologyNode *sar_node = NULL, *audio_src = NULL;
+        IMFTopologyNode *grabber_node = NULL, *video_src = NULL;
 
         if (sd_audio)
         {
@@ -481,6 +531,27 @@ static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMedi
             if (audio_src)
                 IMFTopologyNode_Release(audio_src);
         }
+
+        if (SUCCEEDED(hr) && sd_video)
+        {
+            if (FAILED(hr = media_engine_create_source_node(source, pd, sd_video, &video_src)))
+                WARN("Failed to create video source node, hr %#x.\n", hr);
+
+            if (FAILED(hr = media_engine_create_video_renderer(engine, &grabber_node)))
+                WARN("Failed to create video grabber node, hr %#x.\n", hr);
+
+            if (grabber_node && video_src)
+            {
+                IMFTopology_AddNode(topology, video_src);
+                IMFTopology_AddNode(topology, grabber_node);
+                IMFTopologyNode_ConnectOutput(video_src, 0, grabber_node, 0);
+            }
+
+            if (grabber_node)
+                IMFTopologyNode_Release(grabber_node);
+            if (video_src)
+                IMFTopologyNode_Release(video_src);
+        }
     }
 
     if (topology)
@@ -1225,6 +1296,96 @@ static const IMFMediaEngineVtbl media_engine_vtbl =
     media_engine_OnVideoStreamTick,
 };
 
+static HRESULT WINAPI media_engine_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface,
+        REFIID riid, void **obj)
+{
+    if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
+            IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IMFSampleGrabberSinkCallback_AddRef(iface);
+        return S_OK;
+    }
+
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI media_engine_grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
+{
+    struct media_engine *engine = impl_from_IMFSampleGrabberSinkCallback(iface);
+    return IMFMediaEngine_AddRef(&engine->IMFMediaEngine_iface);
+}
+
+static ULONG WINAPI media_engine_grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
+{
+    struct media_engine *engine = impl_from_IMFSampleGrabberSinkCallback(iface);
+    return IMFMediaEngine_Release(&engine->IMFMediaEngine_iface);
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface,
+        MFTIME systime, LONGLONG start_offset)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface,
+        MFTIME systime)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface,
+        MFTIME systime)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface,
+        MFTIME systime)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface,
+        MFTIME systime, float rate)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
+        IMFPresentationClock *clock)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface,
+        REFGUID major_type, DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration,
+        const BYTE *buffer, DWORD sample_size)
+{
+    return S_OK;
+}
+
+static HRESULT WINAPI media_engine_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
+{
+    return S_OK;
+}
+
+static const IMFSampleGrabberSinkCallbackVtbl media_engine_grabber_callback_vtbl =
+{
+    media_engine_grabber_callback_QueryInterface,
+    media_engine_grabber_callback_AddRef,
+    media_engine_grabber_callback_Release,
+    media_engine_grabber_callback_OnClockStart,
+    media_engine_grabber_callback_OnClockStop,
+    media_engine_grabber_callback_OnClockPause,
+    media_engine_grabber_callback_OnClockRestart,
+    media_engine_grabber_callback_OnClockSetRate,
+    media_engine_grabber_callback_OnSetPresentationClock,
+    media_engine_grabber_callback_OnProcessSample,
+    media_engine_grabber_callback_OnShutdown,
+};
+
 static HRESULT WINAPI media_engine_factory_QueryInterface(IMFMediaEngineClassFactory *iface, REFIID riid, void **obj)
 {
     if (IsEqualIID(riid, &IID_IMFMediaEngineClassFactory) ||
@@ -1259,6 +1420,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->grabber_callback.lpVtbl = &media_engine_grabber_callback_vtbl;
     engine->refcount = 1;
     engine->flags = (flags & MF_MEDIA_ENGINE_CREATEFLAGS_MASK) | FLAGS_ENGINE_PAUSED;
     engine->default_playback_rate = 1.0;




More information about the wine-cvs mailing list