Nikolay Sivov : mfreadwrite: Handle MENewStream event.

Alexandre Julliard julliard at winehq.org
Tue Apr 9 16:31:04 CDT 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Apr  9 13:45:09 2019 +0300

mfreadwrite: Handle MENewStream event.

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

---

 dlls/mfreadwrite/Makefile.in |   2 +-
 dlls/mfreadwrite/main.c      | 142 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 141 insertions(+), 3 deletions(-)

diff --git a/dlls/mfreadwrite/Makefile.in b/dlls/mfreadwrite/Makefile.in
index edc7ebd..ce8a4d4 100644
--- a/dlls/mfreadwrite/Makefile.in
+++ b/dlls/mfreadwrite/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = mfreadwrite.dll
 IMPORTLIB = mfreadwrite
-IMPORTS   = mfuuid uuid mfplat
+IMPORTS   = mfuuid uuid mfplat ole32
 
 C_SRCS = \
 	main.c
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c
index e41bdf6..e6ddce0 100644
--- a/dlls/mfreadwrite/main.c
+++ b/dlls/mfreadwrite/main.c
@@ -74,6 +74,7 @@ HRESULT WINAPI DllUnregisterServer(void)
 
 struct media_stream
 {
+    IMFMediaStream *stream;
     IMFMediaType *current;
     DWORD id;
 };
@@ -82,6 +83,7 @@ typedef struct source_reader
 {
     IMFSourceReader IMFSourceReader_iface;
     IMFAsyncCallback source_events_callback;
+    IMFAsyncCallback stream_events_callback;
     LONG refcount;
     IMFMediaSource *source;
     IMFPresentationDescriptor *descriptor;
@@ -110,6 +112,11 @@ static struct source_reader *impl_from_source_callback_IMFAsyncCallback(IMFAsync
     return CONTAINING_RECORD(iface, struct source_reader, source_events_callback);
 }
 
+static struct source_reader *impl_from_stream_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+    return CONTAINING_RECORD(iface, struct source_reader, stream_events_callback);
+}
+
 static inline struct sink_writer *impl_from_IMFSinkWriter(IMFSinkWriter *iface)
 {
     return CONTAINING_RECORD(iface, struct sink_writer, IMFSinkWriter_iface);
@@ -151,6 +158,77 @@ static HRESULT WINAPI source_reader_source_events_callback_GetParameters(IMFAsyn
     return E_NOTIMPL;
 }
 
+static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IMFMediaEvent *event)
+{
+    IMFStreamDescriptor *sd;
+    IMFMediaStream *stream;
+    PROPVARIANT value;
+    unsigned int i;
+    DWORD id = 0;
+    HRESULT hr;
+
+    PropVariantInit(&value);
+    if (FAILED(hr = IMFMediaEvent_GetValue(event, &value)))
+    {
+        WARN("Failed to get event value, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (value.vt != VT_UNKNOWN || !value.u.punkVal)
+    {
+        WARN("Unexpected value type %d.\n", value.vt);
+        PropVariantClear(&value);
+        return E_UNEXPECTED;
+    }
+
+    hr = IUnknown_QueryInterface(value.u.punkVal, &IID_IMFMediaStream, (void **)&stream);
+    PropVariantClear(&value);
+    if (FAILED(hr))
+    {
+        WARN("Unexpected object type.\n");
+        return hr;
+    }
+
+    TRACE("Got new stream %p.\n", stream);
+
+    if (SUCCEEDED(hr = IMFMediaStream_GetStreamDescriptor(stream, &sd)))
+    {
+        hr = IMFStreamDescriptor_GetStreamIdentifier(sd, &id);
+        IMFStreamDescriptor_Release(sd);
+    }
+
+    if (FAILED(hr))
+    {
+        WARN("Unidentified stream %p, hr %#x.\n", stream, hr);
+        IMFMediaStream_Release(stream);
+        return hr;
+    }
+
+    for (i = 0; i < reader->stream_count; ++i)
+    {
+        if (id == reader->streams[i].id)
+        {
+            if (!InterlockedCompareExchangePointer((void **)&reader->streams[i].stream, stream, NULL))
+            {
+                IMFMediaStream_AddRef(reader->streams[i].stream);
+                if (FAILED(hr = IMFMediaStream_BeginGetEvent(stream, &reader->stream_events_callback,
+                        (IUnknown *)stream)))
+                {
+                    WARN("Failed to subscribe to stream events, hr %#x.\n", hr);
+                }
+            }
+            break;
+        }
+    }
+
+    if (i == reader->stream_count)
+        WARN("Stream with id %#x was not present in presentation descriptor.\n", id);
+
+    IMFMediaStream_Release(stream);
+
+    return hr;
+}
+
 static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
 {
     struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface);
@@ -170,10 +248,21 @@ static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallba
 
     TRACE("Got event %u.\n", event_type);
 
+    switch (event_type)
+    {
+        case MENewStream:
+            hr = source_reader_new_stream_handler(reader, event);
+            break;
+        default:
+            ;
+    }
+
+    if (FAILED(hr))
+        WARN("Failed while handling %d event, hr %#x.\n", event_type, hr);
+
     IMFMediaEvent_Release(event);
 
-    IMFMediaSource_BeginGetEvent(source, &reader->source_events_callback,
-        (IUnknown *)source);
+    IMFMediaSource_BeginGetEvent(source, iface, (IUnknown *)source);
 
     return S_OK;
 }
@@ -187,6 +276,52 @@ static const IMFAsyncCallbackVtbl source_events_callback_vtbl =
     source_reader_source_events_callback_Invoke,
 };
 
+static ULONG WINAPI source_reader_stream_events_callback_AddRef(IMFAsyncCallback *iface)
+{
+    struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface);
+    return IMFSourceReader_AddRef(&reader->IMFSourceReader_iface);
+}
+
+static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallback *iface)
+{
+    struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface);
+    return IMFSourceReader_Release(&reader->IMFSourceReader_iface);
+}
+
+static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+    MediaEventType event_type;
+    IMFMediaStream *stream;
+    IMFMediaEvent *event;
+    HRESULT hr;
+
+    TRACE("%p, %p.\n", iface, result);
+
+    stream = (IMFMediaStream *)IMFAsyncResult_GetStateNoAddRef(result);
+
+    if (FAILED(hr = IMFMediaStream_EndGetEvent(stream, result, &event)))
+        return hr;
+
+    IMFMediaEvent_GetType(event, &event_type);
+
+    TRACE("Got event %u.\n", event_type);
+
+    IMFMediaEvent_Release(event);
+
+    IMFMediaStream_BeginGetEvent(stream, iface, (IUnknown *)stream);
+
+    return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl stream_events_callback_vtbl =
+{
+    source_reader_source_events_callback_QueryInterface,
+    source_reader_stream_events_callback_AddRef,
+    source_reader_stream_events_callback_Release,
+    source_reader_source_events_callback_GetParameters,
+    source_reader_stream_events_callback_Invoke,
+};
+
 static HRESULT WINAPI src_reader_QueryInterface(IMFSourceReader *iface, REFIID riid, void **out)
 {
     srcreader *This = impl_from_IMFSourceReader(iface);
@@ -239,6 +374,8 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
 
         for (i = 0; i < reader->stream_count; ++i)
         {
+            if (reader->streams[i].stream)
+                IMFMediaStream_Release(reader->streams[i].stream);
             if (reader->streams[i].current)
                 IMFMediaType_Release(reader->streams[i].current);
         }
@@ -614,6 +751,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
 
     object->IMFSourceReader_iface.lpVtbl = &srcreader_vtbl;
     object->source_events_callback.lpVtbl = &source_events_callback_vtbl;
+    object->stream_events_callback.lpVtbl = &stream_events_callback_vtbl;
     object->refcount = 1;
     object->source = source;
     IMFMediaSource_AddRef(object->source);




More information about the wine-cvs mailing list