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, ×tamp, &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