Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- 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);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 2 ++ dlls/mfreadwrite/tests/mfplat.c | 13 +++++++++++++ 2 files changed, 15 insertions(+)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index bffe5cc47f..56ec036089 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -894,6 +894,8 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind *stream_flags = MF_SOURCE_READERF_ERROR; if (actual_index) *actual_index = index; + if (timestamp) + *timestamp = 0; return hr; }
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 081d94c7d5..9678f64efe 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -891,6 +891,19 @@ todo_wine ok(!!sample, "Expected sample object.\n"); IMFSample_Release(sample);
+ /* Request from deselected stream. */ + hr = IMFSourceReader_SetStreamSelection(reader, 1, FALSE); + ok(hr == S_OK, "Failed to select a stream, hr %#x.\n", hr); + + actual_index = 0; + stream_flags = 0; + hr = IMFSourceReader_ReadSample(reader, 1, 0, &actual_index, &stream_flags, ×tamp, &sample); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + ok(actual_index == 1, "Unexpected stream index %u\n", actual_index); + ok(stream_flags == MF_SOURCE_READERF_ERROR, "Unexpected stream flags %#x.\n", stream_flags); + ok(timestamp == 0, "Unexpected timestamp.\n"); + ok(!sample, "Expected sample object.\n"); + IMFSourceReader_Release(reader); IMFMediaSource_Release(source);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/tests/mfplat.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 9678f64efe..e03d74981a 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -309,17 +309,22 @@ static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *i { for (i = 0; i < ARRAY_SIZE(source->streams); ++i) { - MFCreateMediaType(&media_type); + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); - IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
- MFCreateStreamDescriptor(i, 1, &media_type, &sds[i]); + hr = MFCreateStreamDescriptor(i, 1, &media_type, &sds[i]); + ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
IMFMediaType_Release(media_type); }
- MFCreatePresentationDescriptor(ARRAY_SIZE(sds), sds, &source->pd); + hr = MFCreatePresentationDescriptor(ARRAY_SIZE(sds), sds, &source->pd); + ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr); for (i = 0; i < ARRAY_SIZE(sds); ++i) IMFStreamDescriptor_Release(sds[i]);
@@ -349,6 +354,7 @@ static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDe struct test_source *source = impl_from_IMFMediaSource(iface); MediaEventType event_type; PROPVARIANT var; + HRESULT hr; int i;
ok(time_format && IsEqualGUID(time_format, &GUID_NULL), "Unexpected time format %s.\n", @@ -359,7 +365,8 @@ static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDe EnterCriticalSection(&source->cs);
event_type = source->state == SOURCE_RUNNING ? MESourceSeeked : MESourceStarted; - IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, &GUID_NULL, S_OK, NULL); + hr = IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, &GUID_NULL, S_OK, NULL); + ok(hr == S_OK, "Failed to queue event, hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(source->streams); ++i) { @@ -370,11 +377,13 @@ static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDe var.punkVal = (IUnknown *)&source->streams[i]->IMFMediaStream_iface; event_type = source->streams[i]->is_new ? MENewStream : MEUpdatedStream; source->streams[i]->is_new = FALSE; - IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, &GUID_NULL, S_OK, &var); + hr = IMFMediaEventQueue_QueueEventParamVar(source->event_queue, event_type, &GUID_NULL, S_OK, &var); + ok(hr == S_OK, "Failed to queue event, hr %#x.\n", hr);
event_type = source->state == SOURCE_RUNNING ? MEStreamSeeked : MEStreamStarted; - IMFMediaEventQueue_QueueEventParamVar(source->streams[i]->event_queue, event_type, &GUID_NULL, + hr = IMFMediaEventQueue_QueueEventParamVar(source->streams[i]->event_queue, event_type, &GUID_NULL, S_OK, NULL); + ok(hr == S_OK, "Failed to queue event, hr %#x.\n", hr); }
source->state = SOURCE_RUNNING; @@ -399,8 +408,10 @@ static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface) static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface) { struct test_source *source = impl_from_IMFMediaSource(iface); + HRESULT hr;
- IMFMediaEventQueue_Shutdown(source->event_queue); + hr = IMFMediaEventQueue_Shutdown(source->event_queue); + ok(hr == S_OK, "Failed to shut down event queue, hr %#x.\n", hr);
return S_OK; }