Nikolay Sivov : mfreadwrite: Start media source when stream selection changes.

Alexandre Julliard julliard at winehq.org
Wed Nov 20 16:49:12 CST 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Nov 20 13:12:17 2019 +0300

mfreadwrite: Start media source when stream selection changes.

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

---

 dlls/mfreadwrite/main.c         | 59 +++++++++++++++++++++++++++++++++--------
 dlls/mfreadwrite/tests/mfplat.c | 50 ++++++++++++++++++++++++----------
 2 files changed, 84 insertions(+), 25 deletions(-)

diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c
index f24de690bc..bffe5cc47f 100644
--- a/dlls/mfreadwrite/main.c
+++ b/dlls/mfreadwrite/main.c
@@ -99,6 +99,8 @@ struct media_stream
     CONDITION_VARIABLE sample_event;
     struct list samples;
     enum media_stream_state state;
+    BOOL selected;
+    BOOL presented;
 };
 
 struct source_reader
@@ -820,6 +822,41 @@ static IMFSample *media_stream_pop_sample(struct media_stream *stream, DWORD *st
     return ret;
 }
 
+static HRESULT source_reader_start_source(struct source_reader *reader)
+{
+    BOOL selection_changed = FALSE;
+    PROPVARIANT position;
+    HRESULT hr = S_OK;
+    DWORD i;
+
+    if (reader->source_state == SOURCE_STATE_STARTED)
+    {
+        for (i = 0; i < reader->stream_count; ++i)
+        {
+            if (FAILED(hr = source_reader_get_stream_selection(reader, i, &reader->streams[i].selected)))
+                return hr;
+            selection_changed = reader->streams[i].selected ^ reader->streams[i].presented;
+            if (selection_changed)
+                break;
+        }
+    }
+
+    position.u.hVal.QuadPart = 0;
+    if (reader->source_state != SOURCE_STATE_STARTED || selection_changed)
+    {
+        position.vt = reader->source_state == SOURCE_STATE_STARTED ? VT_EMPTY : VT_I8;
+
+        /* Update cached stream selection if descriptor was accepted. */
+        if (SUCCEEDED(hr = IMFMediaSource_Start(reader->source, reader->descriptor, &GUID_NULL, &position)))
+        {
+            for (i = 0; i < reader->stream_count; ++i)
+                reader->streams[i].presented = reader->streams[i].selected;
+        }
+    }
+
+    return hr;
+}
+
 static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD index, DWORD flags, DWORD *actual_index,
         DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample)
 {
@@ -867,20 +904,23 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind
 
     EnterCriticalSection(&stream->cs);
 
-    if (!(flags & MF_SOURCE_READER_CONTROLF_DRAIN))
+    if (SUCCEEDED(hr = source_reader_start_source(reader)))
     {
-        while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS)
+        if (!(flags & MF_SOURCE_READER_CONTROLF_DRAIN))
         {
-            if (stream->stream)
+            while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS)
             {
-                if (FAILED(hr = IMFMediaStream_RequestSample(stream->stream, NULL)))
-                    WARN("Sample request failed, hr %#x.\n", hr);
+                if (stream->stream)
+                {
+                    if (FAILED(hr = IMFMediaStream_RequestSample(stream->stream, NULL)))
+                        WARN("Sample request failed, hr %#x.\n", hr);
+                }
+                SleepConditionVariableCS(&stream->sample_event, &stream->cs, INFINITE);
             }
-            SleepConditionVariableCS(&stream->sample_event, &stream->cs, INFINITE);
         }
-    }
 
-    *sample = media_stream_pop_sample(stream, stream_flags);
+        *sample = media_stream_pop_sample(stream, stream_flags);
+    }
 
     LeaveCriticalSection(&stream->cs);
 
@@ -913,9 +953,6 @@ static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index,
 
     TRACE("%p, %#x, %#x, %p, %p, %p, %p\n", iface, index, flags, actual_index, stream_flags, timestamp, sample);
 
-    /* FIXME: probably should happen once */
-    IMFMediaSource_Start(reader->source, reader->descriptor, NULL, NULL);
-
     if (reader->async_callback)
     {
         if (actual_index || stream_flags || timestamp || sample)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
index 16bb92b80e..081d94c7d5 100644
--- a/dlls/mfreadwrite/tests/mfplat.c
+++ b/dlls/mfreadwrite/tests/mfplat.c
@@ -351,10 +351,11 @@ static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDe
     PROPVARIANT var;
     int i;
 
-todo_wine {
-    ok(time_format && IsEqualGUID(time_format, &GUID_NULL), "Unexpected time format %s.\n", wine_dbgstr_guid(time_format));
-    ok(start_position && (start_position->vt == VT_I8 || start_position->vt == VT_EMPTY), "Unexpected position type.\n");
-}
+    ok(time_format && IsEqualGUID(time_format, &GUID_NULL), "Unexpected time format %s.\n",
+            wine_dbgstr_guid(time_format));
+    ok(start_position && (start_position->vt == VT_I8 || start_position->vt == VT_EMPTY),
+            "Unexpected position type.\n");
+
     EnterCriticalSection(&source->cs);
 
     event_type = source->state == SOURCE_RUNNING ? MESourceSeeked : MESourceStarted;
@@ -823,16 +824,6 @@ static void test_source_reader_from_media_source(void)
     source = create_test_source();
     ok(!!source, "Failed to create test source.\n");
 
-    callback = create_async_callback();
-
-    hr = MFCreateAttributes(&attributes, 1);
-    ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr);
-
-    hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_ASYNC_CALLBACK,
-            (IUnknown *)&callback->IMFSourceReaderCallback_iface);
-    ok(hr == S_OK, "Failed to set attribute value, hr %#x.\n", hr);
-    IMFSourceReaderCallback_Release(&callback->IMFSourceReaderCallback_iface);
-
     hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader);
     ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
 
@@ -882,10 +873,41 @@ todo_wine
     IMFSourceReader_Release(reader);
     IMFMediaSource_Release(source);
 
+    /* Request from stream 0. */
+    source = create_test_source();
+    ok(!!source, "Failed to create test source.\n");
+
+    hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader);
+    ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
+
+    hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE);
+    ok(hr == S_OK, "Failed to select a stream, hr %#x.\n", hr);
+
+    hr = IMFSourceReader_ReadSample(reader, 0, 0, &actual_index, &stream_flags, &timestamp, &sample);
+    ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
+    ok(actual_index == 0, "Unexpected stream index %u\n", actual_index);
+    ok(!stream_flags, "Unexpected stream flags %#x.\n", stream_flags);
+    ok(timestamp == 123, "Unexpected timestamp.\n");
+    ok(!!sample, "Expected sample object.\n");
+    IMFSample_Release(sample);
+
+    IMFSourceReader_Release(reader);
+    IMFMediaSource_Release(source);
+
     /* Async mode. */
     source = create_test_source();
     ok(!!source, "Failed to create test source.\n");
 
+    callback = create_async_callback();
+
+    hr = MFCreateAttributes(&attributes, 1);
+    ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr);
+
+    hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_ASYNC_CALLBACK,
+            (IUnknown *)&callback->IMFSourceReaderCallback_iface);
+    ok(hr == S_OK, "Failed to set attribute value, hr %#x.\n", hr);
+    IMFSourceReaderCallback_Release(&callback->IMFSourceReaderCallback_iface);
+
     hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader);
     ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
 




More information about the wine-cvs mailing list