Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 114 ++++++++++++++++++-------------- dlls/mfreadwrite/tests/mfplat.c | 4 -- 2 files changed, 65 insertions(+), 53 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 3467746bb8..6fb00b4d37 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -778,14 +778,17 @@ static IMFSample *media_stream_pop_sample(struct media_stream *stream, DWORD *st return ret; }
-static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, DWORD flags, DWORD *actual_index, +static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD index, DWORD flags, DWORD *actual_index, DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample) { - struct source_reader *reader = impl_from_IMFSourceReader(iface); + struct media_stream *stream; DWORD stream_index; - HRESULT hr; + HRESULT hr = S_OK;
- TRACE("%p, %#x, %#x, %p, %p, %p, %p\n", iface, index, flags, actual_index, stream_flags, timestamp, sample); + if (!stream_flags || !sample) + return E_POINTER; + + *sample = NULL;
switch (index) { @@ -802,68 +805,81 @@ static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, stream_index = index; }
- /* FIXME: probably should happen once */ - IMFMediaSource_Start(reader->source, reader->descriptor, NULL, NULL); - - if (reader->async_callback) + if (stream_index >= reader->stream_count) { - FIXME("Async mode is not implemented.\n"); - return E_NOTIMPL; + *stream_flags = MF_SOURCE_READERF_ERROR; + if (actual_index) + *actual_index = index; + return MF_E_INVALIDSTREAMNUMBER; } - else - { - struct media_stream *stream;
- if (!stream_flags || !sample) - return E_POINTER; + if (actual_index) + *actual_index = stream_index;
- *sample = NULL; + stream = &reader->streams[stream_index];
- if (stream_index >= reader->stream_count) + EnterCriticalSection(&stream->cs); + + if (!(flags & MF_SOURCE_READER_CONTROLF_DRAIN)) + { + while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS) { - *stream_flags = MF_SOURCE_READERF_ERROR; - if (actual_index) - *actual_index = index; - return MF_E_INVALIDSTREAMNUMBER; + 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); } + }
- if (actual_index) - *actual_index = stream_index; + *sample = media_stream_pop_sample(stream, stream_flags);
- stream = &reader->streams[stream_index]; + LeaveCriticalSection(&stream->cs);
- EnterCriticalSection(&stream->cs); + TRACE("Got sample %p.\n", *sample);
- if (!(flags & MF_SOURCE_READER_CONTROLF_DRAIN)) - { - while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS) - { - 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); - } - } + if (timestamp) + { + /* TODO: it's possible timestamp has to be set for some events. + For MEEndOfStream it's correct to return 0. */ + *timestamp = 0; + if (*sample) + IMFSample_GetSampleTime(*sample, timestamp); + }
- *sample = media_stream_pop_sample(stream, stream_flags); + return hr; +}
- LeaveCriticalSection(&stream->cs); +static HRESULT source_reader_read_sample_async(struct source_reader *reader, DWORD index, DWORD flags) +{ + FIXME("Async mode is not implemented.\n");
- TRACE("Got sample %p.\n", *sample); + return E_NOTIMPL; +}
- if (timestamp) - { - /* TODO: it's possible timestamp has to be set for some events. - For MEEndOfStream it's correct to return 0. */ - *timestamp = 0; - if (*sample) - IMFSample_GetSampleTime(*sample, timestamp); - } +static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, DWORD flags, DWORD *actual_index, + DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample) +{ + struct source_reader *reader = impl_from_IMFSourceReader(iface); + HRESULT hr; + + 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) + return E_INVALIDARG; + + hr = source_reader_read_sample_async(reader, index, flags); } + else + hr = source_reader_read_sample(reader, index, flags, actual_index, stream_flags, timestamp, sample);
- return S_OK; + return hr; }
static HRESULT WINAPI src_reader_Flush(IMFSourceReader *iface, DWORD index) diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 27ceb0faf1..16bb92b80e 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -894,19 +894,15 @@ todo_wine
/* Return values are delivered to callback only. */ hr = IMFSourceReader_ReadSample(reader, 0, 0, &actual_index, &stream_flags, ×tamp, &sample); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFSourceReader_ReadSample(reader, 0, 0, NULL, &stream_flags, ×tamp, &sample); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFSourceReader_ReadSample(reader, 0, 0, NULL, NULL, ×tamp, &sample); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFSourceReader_ReadSample(reader, 0, 0, NULL, NULL, NULL, &sample); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
IMFSourceReader_Release(reader);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 6fb00b4d37..9fa1445a8f 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -84,6 +84,12 @@ enum media_stream_state STREAM_STATE_EOS, };
+enum media_source_state +{ + SOURCE_STATE_STOPPED = 0, + SOURCE_STATE_STARTED, +}; + struct media_stream { IMFMediaStream *stream; @@ -107,6 +113,7 @@ struct source_reader DWORD first_video_stream_index; IMFSourceReaderCallback *async_callback; BOOL shutdown_on_release; + enum media_source_state source_state; struct media_stream *streams; DWORD stream_count; CRITICAL_SECTION cs; @@ -268,6 +275,30 @@ static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IM return hr; }
+static HRESULT source_reader_source_state_handler(struct source_reader *reader, MediaEventType event_type) +{ + enum media_source_state state; + + switch (event_type) + { + case MESourceStarted: + state = SOURCE_STATE_STARTED; + break; + case MESourceStopped: + state = SOURCE_STATE_STOPPED; + break; + default: + WARN("Unhandled state %d.\n", event_type); + return E_FAIL; + } + + EnterCriticalSection(&reader->cs); + reader->source_state = state; + LeaveCriticalSection(&reader->cs); + + return S_OK; +} + static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface); @@ -292,6 +323,11 @@ static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallba case MENewStream: hr = source_reader_new_stream_handler(reader, event); break; + case MESourceStarted: + case MESourcePaused: + case MESourceStopped: + hr = source_reader_source_state_handler(reader, event_type); + break; default: ; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 9fa1445a8f..f24de690bc 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -591,10 +591,20 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface) return refcount; }
+static HRESULT source_reader_get_stream_selection(const struct source_reader *reader, DWORD index, BOOL *selected) +{ + IMFStreamDescriptor *sd; + + if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(reader->descriptor, index, selected, &sd))) + return MF_E_INVALIDSTREAMNUMBER; + IMFStreamDescriptor_Release(sd); + + return S_OK; +} + static HRESULT WINAPI src_reader_GetStreamSelection(IMFSourceReader *iface, DWORD index, BOOL *selected) { struct source_reader *reader = impl_from_IMFSourceReader(iface); - IMFStreamDescriptor *sd;
TRACE("%p, %#x, %p.\n", iface, index, selected);
@@ -610,11 +620,7 @@ static HRESULT WINAPI src_reader_GetStreamSelection(IMFSourceReader *iface, DWOR ; }
- if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(reader->descriptor, index, selected, &sd))) - return MF_E_INVALIDSTREAMNUMBER; - IMFStreamDescriptor_Release(sd); - - return S_OK; + return source_reader_get_stream_selection(reader, index, selected); }
static HRESULT WINAPI src_reader_SetStreamSelection(IMFSourceReader *iface, DWORD index, BOOL selected) @@ -820,6 +826,7 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind struct media_stream *stream; DWORD stream_index; HRESULT hr = S_OK; + BOOL selected;
if (!stream_flags || !sample) return E_POINTER; @@ -841,12 +848,16 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind stream_index = index; }
- if (stream_index >= reader->stream_count) + /* Can't read from deselected streams. */ + if (SUCCEEDED(hr = source_reader_get_stream_selection(reader, stream_index, &selected)) && !selected) + hr = MF_E_INVALIDREQUEST; + + if (FAILED(hr)) { *stream_flags = MF_SOURCE_READERF_ERROR; if (actual_index) *actual_index = index; - return MF_E_INVALIDSTREAMNUMBER; + return hr; }
if (actual_index)