Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 109 ++++++++++++++++++++++++++++++-- dlls/mfreadwrite/tests/mfplat.c | 7 ++ 2 files changed, 109 insertions(+), 7 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 43dfd4e9ed..8145e5b0ed 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -79,13 +79,21 @@ struct sample IMFSample *sample; };
+enum media_stream_state +{ + STREAM_STATE_READY = 0, + STREAM_STATE_EOS, +}; + struct media_stream { IMFMediaStream *stream; IMFMediaType *current; DWORD id; CRITICAL_SECTION cs; + CONDITION_VARIABLE sample_event; struct list samples; + enum media_stream_state state; };
typedef struct source_reader @@ -359,6 +367,8 @@ static HRESULT source_reader_media_sample_handler(struct source_reader *reader, list_add_tail(&reader->streams[i].samples, &pending_sample->entry); LeaveCriticalSection(&reader->streams[i].cs);
+ WakeAllConditionVariable(&reader->streams[i].sample_event); + break; } } @@ -698,14 +708,98 @@ static HRESULT WINAPI src_reader_SetCurrentPosition(IMFSourceReader *iface, REFG return IMFMediaSource_Start(reader->source, reader->descriptor, format, position); }
-static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, - DWORD flags, DWORD *actualindex, DWORD *sampleflags, LONGLONG *timestamp, - IMFSample **sample) +static IMFSample *media_stream_pop_sample(struct media_stream *stream, DWORD *stream_flags) { - srcreader *This = impl_from_IMFSourceReader(iface); - FIXME("%p, 0x%08x, 0x%08x, %p, %p, %p, %p\n", This, index, flags, actualindex, - sampleflags, timestamp, sample); - return E_NOTIMPL; + IMFSample *ret = NULL; + struct list *head; + + if ((head = list_head(&stream->samples))) + { + struct sample *pending_sample = LIST_ENTRY(head, struct sample, entry); + ret = pending_sample->sample; + list_remove(&pending_sample->entry); + heap_free(pending_sample); + } + + *stream_flags = stream->state == STREAM_STATE_EOS ? MF_SOURCE_READERF_ENDOFSTREAM : 0; + + return ret; +} + +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); + + switch (index) + { + case MF_SOURCE_READER_FIRST_VIDEO_STREAM: + index = reader->first_video_stream_index; + break; + case MF_SOURCE_READER_FIRST_AUDIO_STREAM: + index = reader->first_audio_stream_index; + break; + case MF_SOURCE_READER_ANY_STREAM: + FIXME("Non-specific requests are not supported.\n"); + return E_NOTIMPL; + default: + ; + } + + /* FIXME: probably should happen once */ + IMFMediaSource_Start(reader->source, reader->descriptor, NULL, NULL); + + if (reader->async_callback) + { + FIXME("Async mode is not implemented.\n"); + return E_NOTIMPL; + } + else + { + struct media_stream *stream; + + if (!stream_flags || !sample) + return E_POINTER; + + if (actual_index) + *actual_index = index; + + *sample = NULL; + + if (index >= reader->stream_count) + { + *stream_flags = MF_SOURCE_READERF_ERROR; + return MF_E_INVALIDSTREAMNUMBER; + } + + stream = &reader->streams[index]; + + EnterCriticalSection(&stream->cs); + + 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); + } + } + + *sample = media_stream_pop_sample(stream, stream_flags); + + LeaveCriticalSection(&stream->cs); + + TRACE("Got sample %p.\n", *sample); + } + + return S_OK; }
static HRESULT WINAPI src_reader_Flush(IMFSourceReader *iface, DWORD index) @@ -922,6 +1016,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri break;
InitializeCriticalSection(&object->streams[i].cs); + InitializeConditionVariable(&object->streams[i].sample_event); list_init(&object->streams[i].samples); }
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 29e8e08eb7..b86fb060fd 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -315,6 +315,13 @@ todo_wine ok(actual_index == MF_SOURCE_READER_FIRST_VIDEO_STREAM, "Unexpected stream index %u\n", actual_index); ok(stream_flags == MF_SOURCE_READERF_ERROR, "Unexpected stream flags %#x.\n", stream_flags);
+ hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, &stream_flags, ×tamp, + &sample); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, ×tamp, &sample); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &actual_index, &stream_flags, ×tamp, &sample); ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 8145e5b0ed..e27fe82216 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -613,10 +613,12 @@ static HRESULT WINAPI src_reader_GetNativeMediaType(IMFSourceReader *iface, DWOR hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, type_index, &src_type); IMFMediaTypeHandler_Release(handler);
- if (SUCCEEDED(hr = MFCreateMediaType(type))) - hr = IMFMediaType_CopyAllItems(src_type, (IMFAttributes *)*type); - - IMFMediaType_Release(src_type); + if (SUCCEEDED(hr)) + { + if (SUCCEEDED(hr = MFCreateMediaType(type))) + hr = IMFMediaType_CopyAllItems(src_type, (IMFAttributes *)*type); + IMFMediaType_Release(src_type); + }
return hr; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51278
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 error: patch failed: dlls/mfreadwrite/main.c:613 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 error: patch failed: dlls/mfreadwrite/main.c:613 Task: Patch failed to apply
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index e27fe82216..490f238541 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -253,6 +253,9 @@ static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IM { WARN("Failed to subscribe to stream events, hr %#x.\n", hr); } + + /* Wake so any waiting ReadSample() calls have a chance to make requests. */ + WakeAllConditionVariable(&reader->streams[i].sample_event); } break; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51279
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 error: patch failed: dlls/mfreadwrite/main.c:613 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 error: patch failed: dlls/mfreadwrite/main.c:613 Task: Patch failed to apply
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 64 +++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 8 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 490f238541..e396dcd5f5 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -385,6 +385,46 @@ failed: return hr; }
+static HRESULT source_reader_media_stream_state_handler(struct source_reader *reader, IMFMediaStream *stream, + MediaEventType event) +{ + unsigned int i; + HRESULT hr; + DWORD id; + + if (FAILED(hr = media_stream_get_id(stream, &id))) + { + WARN("Unidentified stream %p, hr %#x.\n", stream, hr); + return hr; + } + + for (i = 0; i < reader->stream_count; ++i) + { + if (id == reader->streams[i].id) + { + EnterCriticalSection(&reader->streams[i].cs); + + switch (event) + { + case MEEndOfStream: + reader->streams[i].state = STREAM_STATE_EOS; + break; + case MEStreamSeeked: + case MEStreamStarted: + reader->streams[i].state = STREAM_STATE_READY; + break; + default: + ; + } + + LeaveCriticalSection(&reader->streams[i].cs); + break; + } + } + + return S_OK; +} + static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface); @@ -409,6 +449,11 @@ static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallba case MEMediaSample: hr = source_reader_media_sample_handler(reader, stream, event); break; + case MEStreamSeeked: + case MEStreamStarted: + case MEEndOfStream: + hr = source_reader_media_stream_state_handler(reader, stream, event_type); + break; default: ; } @@ -735,6 +780,7 @@ static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample) { struct source_reader *reader = impl_from_IMFSourceReader(iface); + DWORD stream_index; HRESULT hr;
TRACE("%p, %#x, %#x, %p, %p, %p, %p\n", iface, index, flags, actual_index, stream_flags, timestamp, sample); @@ -742,16 +788,16 @@ static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, switch (index) { case MF_SOURCE_READER_FIRST_VIDEO_STREAM: - index = reader->first_video_stream_index; + stream_index = reader->first_video_stream_index; break; case MF_SOURCE_READER_FIRST_AUDIO_STREAM: - index = reader->first_audio_stream_index; + stream_index = reader->first_audio_stream_index; break; case MF_SOURCE_READER_ANY_STREAM: FIXME("Non-specific requests are not supported.\n"); return E_NOTIMPL; default: - ; + stream_index = index; }
/* FIXME: probably should happen once */ @@ -769,18 +815,20 @@ static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, if (!stream_flags || !sample) return E_POINTER;
- if (actual_index) - *actual_index = index; - *sample = NULL;
- if (index >= reader->stream_count) + if (stream_index >= reader->stream_count) { *stream_flags = MF_SOURCE_READERF_ERROR; + if (actual_index) + *actual_index = index; return MF_E_INVALIDSTREAMNUMBER; }
- stream = &reader->streams[index]; + if (actual_index) + *actual_index = stream_index; + + stream = &reader->streams[stream_index];
EnterCriticalSection(&stream->cs);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51280
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 error: patch failed: dlls/mfreadwrite/main.c:613 error: patch failed: dlls/mfreadwrite/main.c:385 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 error: patch failed: dlls/mfreadwrite/main.c:613 error: patch failed: dlls/mfreadwrite/main.c:385 Task: Patch failed to apply
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=51277
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/mfreadwrite/main.c:79 error: patch failed: dlls/mfreadwrite/tests/mfplat.c:315 Task: Patch failed to apply