On 3/25/21 6:41 PM, Giovanni Mascellani wrote:
This also fixes a bug happening when the reader has only one stream, in which case the iteration body was not even executed once.
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com
dlls/mfreadwrite/reader.c | 14 ++-- dlls/mfreadwrite/tests/mfplat.c | 142 ++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 7 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 2819b800eb9..ab9f6c83674 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -1087,13 +1087,10 @@ static BOOL source_reader_get_read_result(struct source_reader *reader, struct m
static HRESULT source_reader_get_next_selected_stream(struct source_reader *reader, unsigned int *stream_index) {
- unsigned int i, start_idx, stop_idx, first_selected = ~0u, requests = ~0u;
- unsigned int i, first_selected = ~0u, requests = ~0u; BOOL selected, stream_drained;
- start_idx = (reader->last_read_index + 1) % reader->stream_count;
- stop_idx = reader->last_read_index == ~0u ? reader->stream_count : reader->last_read_index;
- for (i = start_idx; i < reader->stream_count && i != stop_idx; i = (i + 1) % (reader->stream_count + 1))
- for (i = (reader->last_read_index + 1) % reader->stream_count; ; i = (i + 1) % reader->stream_count) { stream_drained = reader->streams[i].state == STREAM_STATE_EOS && !reader->streams[i].responses; selected = SUCCEEDED(source_reader_get_stream_selection(reader, i, &selected)) && selected;
@@ -1110,6 +1107,9 @@ static HRESULT source_reader_get_next_selected_stream(struct source_reader *read *stream_index = i; } }
if (i == reader->last_read_index)
}break;
This looks good.
/* If all selected streams reached EOS, use first selected. */
@@ -1477,7 +1477,7 @@ static HRESULT WINAPI src_reader_SetStreamSelection(IMFSourceReader *iface, DWOR }
if (selection_changed)
reader->last_read_index = ~0u;
reader->last_read_index = reader->stream_count - 1;
LeaveCriticalSection(&reader->cs);
@@ -2360,7 +2360,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri /* At least one major type has to be set. */ object->first_audio_stream_index = reader_get_first_stream_index(object->descriptor, &MFMediaType_Audio); object->first_video_stream_index = reader_get_first_stream_index(object->descriptor, &MFMediaType_Video);
- object->last_read_index = ~0u;
object->last_read_index = object->stream_count - 1;
if (object->first_audio_stream_index == MF_SOURCE_READER_INVALID_STREAM_INDEX && object->first_video_stream_index == MF_SOURCE_READER_INVALID_STREAM_INDEX)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 25aa29ac272..e3ac0ae8006 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -564,6 +564,105 @@ static void test_factory(void) CoUninitialize(); }
+struct read_all_async_callback +{
- IMFSourceReaderCallback IMFSourceReaderCallback_iface;
- LONG refcount;
- HANDLE event;
- IMFSourceReader *reader;
+};
+static struct read_all_async_callback *impl_read_all_async_callback_from_IMFSourceReaderCallback(IMFSourceReaderCallback *iface) +{
- return CONTAINING_RECORD(iface, struct read_all_async_callback, IMFSourceReaderCallback_iface);
+}
+static HRESULT WINAPI read_all_async_callback_QueryInterface(IMFSourceReaderCallback *iface, REFIID riid, void **out) +{
- if (IsEqualIID(riid, &IID_IMFSourceReaderCallback) ||
IsEqualIID(riid, &IID_IUnknown))
- {
*out = iface;
IMFSourceReaderCallback_AddRef(iface);
return S_OK;
- }
- *out = NULL;
- return E_NOINTERFACE;
+}
+static ULONG WINAPI read_all_async_callback_AddRef(IMFSourceReaderCallback *iface) +{
- struct read_all_async_callback *callback = impl_read_all_async_callback_from_IMFSourceReaderCallback(iface);
- return InterlockedIncrement(&callback->refcount);
+}
+static ULONG WINAPI read_all_async_callback_Release(IMFSourceReaderCallback *iface) +{
- struct read_all_async_callback *callback = impl_read_all_async_callback_from_IMFSourceReaderCallback(iface);
- ULONG refcount = InterlockedDecrement(&callback->refcount);
- if (!refcount)
- {
CloseHandle(callback->event);
heap_free(callback);
- }
- return refcount;
+}
+static HRESULT WINAPI read_all_async_callback_OnReadSample(IMFSourceReaderCallback *iface, HRESULT hr, DWORD stream_index,
DWORD stream_flags, LONGLONG timestamp, IMFSample *sample)
+{
- struct read_all_async_callback *callback = impl_read_all_async_callback_from_IMFSourceReaderCallback(iface);
- ok(hr == S_OK, "Failed to read sample, hr %#x.\n", hr);
- if (stream_flags & MF_SOURCE_READERF_ENDOFSTREAM)
SetEvent(callback->event);
- else
- {
hr = IMFSourceReader_ReadSample(callback->reader, MF_SOURCE_READER_ANY_STREAM, 0, NULL, NULL, NULL, NULL);
ok(hr == S_OK, "Failed to read sample, hr %#x.\n", hr);
- }
- return S_OK;
+}
+static HRESULT WINAPI read_all_async_callback_OnFlush(IMFSourceReaderCallback *iface, DWORD stream_index) +{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
+}
+static HRESULT WINAPI read_all_async_callback_OnEvent(IMFSourceReaderCallback *iface, DWORD stream_index, IMFMediaEvent *event) +{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
+}
+static const IMFSourceReaderCallbackVtbl read_all_async_callback_vtbl = +{
- read_all_async_callback_QueryInterface,
- read_all_async_callback_AddRef,
- read_all_async_callback_Release,
- read_all_async_callback_OnReadSample,
- read_all_async_callback_OnFlush,
- read_all_async_callback_OnEvent,
+};
+static struct read_all_async_callback *create_read_all_async_callback(void) +{
- struct read_all_async_callback *callback;
- callback = heap_alloc(sizeof(*callback));
- callback->IMFSourceReaderCallback_iface.lpVtbl = &read_all_async_callback_vtbl;
- callback->refcount = 1;
- callback->event = CreateEventW(NULL, FALSE, FALSE, NULL);
- return callback;
+}
struct async_callback { IMFSourceReaderCallback IMFSourceReaderCallback_iface; @@ -1144,6 +1243,48 @@ done: DestroyWindow(window); }
+static void test_read_all(void) +{
- IMFByteStream *stream;
- IMFSourceReader *reader;
- IMFAttributes *attributes;
- struct read_all_async_callback *callback;
- HRESULT hr;
- if (!pMFCreateMFByteStreamOnStream)
- {
win_skip("MFCreateMFByteStreamOnStream() not found\n");
return;
- }
- stream = get_resource_stream("test.wav");
- callback = create_read_all_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);
- hr = MFCreateSourceReaderFromByteStream(stream, attributes, &reader);
- ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
- callback->reader = reader;
- hr = IMFSourceReader_SetStreamSelection(reader, MF_SOURCE_READER_ALL_STREAMS, TRUE);
- ok(hr == S_OK, "Failed to select streams, hr %#x.\n", hr);
- hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_ANY_STREAM, 0, NULL, NULL, NULL, NULL);
- ok(hr == S_OK, "Failed to read sample, hr %#x.\n", hr);
- WaitForSingleObject(callback->event, INFINITE);
- IMFSourceReader_Release(reader);
- IMFAttributes_Release(attributes);
- IMFSourceReaderCallback_Release(&callback->IMFSourceReaderCallback_iface);
- IMFByteStream_Release(stream);
+}
START_TEST(mfplat) { HRESULT hr; @@ -1157,6 +1298,7 @@ START_TEST(mfplat) test_source_reader(); test_source_reader_from_media_source(); test_reader_d3d9();
test_read_all();
hr = MFShutdown(); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
I don't see why such test complexity is necessary.We have some tests for ANY_STREAM already, with a simple loop. It will be enough to extend create_test_source() to have a limit of total number of streams, 1 for this test, 3 otherwise.