This tests that the resolution should be quick enough to not trigger an Unreal Engine race condition. This also checks the determinism of the media source presentation descriptor stream ordering, as well as the stream selection updates when the media source is started.
-- v2: mf/tests: Test media source presentation stream descriptor update. winegstreamer: Keep a reference on the media source start descriptor. mf/tests: Test media sources stream descriptors attributes. mf/tests: Test media sources with multiple audio/video streams. mf/tests: Test byte stream handler to media source resolution time.
From: Rémi Bernon rbernon@codeweavers.com
Unreal Engine has a race condition in its media player where it starts the resolution of a media source, waiting for its completion in an async task, and expects to set the media player source from its result.
At the same time, the media player uses timer to tick every 200ms or so, and if the first tick happens before the media source resolution end, the media player ends up in a corrupted state and playback may fail or get stuck.
On Windows, the media source resolution takes very little time, and usually less than 1ms. On Wine, because of the current design of the media soruce, it can often take more than 200ms depending on the setup, and very rarely less than 50ms. --- dlls/mf/tests/mf.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 18488649523..5afaaf86a3e 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7053,6 +7053,89 @@ static void test_mpeg4_media_sink(void) IMFMediaType_Release(audio_type); }
+static void load_resource_stream(const WCHAR *name, IMFByteStream **stream) +{ + HRSRC resource = FindResourceW(NULL, name, (const WCHAR *)RT_RCDATA); + void *resource_data; + DWORD resource_len; + HRESULT hr; + + ok(resource != 0, "FindResourceW %s failed, error %lu\n", debugstr_w(name), GetLastError()); + resource_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource)); + resource_len = SizeofResource(GetModuleHandleW(NULL), resource); + + hr = MFCreateTempFile(MF_ACCESSMODE_READWRITE, MF_OPENMODE_DELETE_IF_EXIST, MF_FILEFLAGS_NONE, stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFByteStream_Write(*stream, resource_data, resource_len, &resource_len); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFByteStream_SetCurrentPosition(*stream, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +} + +static void subtest_media_source_streams(const WCHAR *resource) +{ + IMFMediaSource *media_source; + IMFSourceResolver *resolver; + MF_OBJECT_TYPE object_type; + DWORD i, min_time = -1; + IMFByteStream *stream; + HRESULT hr; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "got hr %#lx\n", hr); + hr = MFCreateSourceResolver(&resolver); + ok(hr == S_OK, "got hr %#lx\n", hr); + + + load_resource_stream(resource, &stream); + hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, resource, MF_RESOLUTION_MEDIASOURCE, + NULL, &object_type, (IUnknown **)&media_source); + ok(hr == S_OK || broken(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE), "got hr %#lx\n", hr); + IMFByteStream_Release(stream); + if (hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE) + { + win_skip("MP4 media source is not supported, skipping tests.\n"); + goto skip_tests; + } + + /* the testbot Windows VMs might be very slow, take the minimum time over a couple of resolutions */ + for (i = 0; i < 10 && min_time > 0; ++i) + { + DWORD time = 0; + + hr = IMFMediaSource_Shutdown(media_source); + ok(hr == S_OK, "got hr %#lx\n", hr); + IMFMediaSource_Release(media_source); + + load_resource_stream(resource, &stream); + time -= GetTickCount(); + hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, resource, MF_RESOLUTION_MEDIASOURCE, + NULL, &object_type, (IUnknown **)&media_source); + time += GetTickCount(); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(object_type == MF_OBJECT_MEDIASOURCE, "got type %#x\n", object_type); + IMFByteStream_Release(stream); + + min_time = min(time, min_time); + } + todo_wine ok(min_time <= 2, "source resolution took %lums\n", min_time); + + hr = IMFMediaSource_Shutdown(media_source); + ok(hr == S_OK, "got hr %#lx\n", hr); + IMFMediaSource_Release(media_source); + +skip_tests: + IMFSourceResolver_Release(resolver); + + hr = MFShutdown(); + ok(hr == S_OK, "got hr %#lx\n", hr); +} + +static void test_media_source_streams(void) +{ + subtest_media_source_streams(L"test.mp4"); +} + START_TEST(mf) { init_functions(); @@ -7087,4 +7170,5 @@ START_TEST(mf) test_MFGetTopoNodeCurrentType(); test_MFRequireProtectedEnvironment(); test_mpeg4_media_sink(); + test_media_source_streams(); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 57 +++++++++++++++++++++++++++-- dlls/mf/tests/mf_test.h | 1 + dlls/mf/tests/multiple-streams.avi | Bin 0 -> 47250 bytes dlls/mf/tests/multiple-streams.mp4 | Bin 0 -> 33041 bytes dlls/mf/tests/resource.rc | 53 +++++++++++++++++++++++++++ dlls/mf/tests/transform.c | 1 + 6 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 dlls/mf/tests/multiple-streams.avi create mode 100644 dlls/mf/tests/multiple-streams.mp4
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 5afaaf86a3e..c8a2fe931ca 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -41,6 +41,8 @@ #include "initguid.h" #include "evr9.h"
+static BOOL has_mp4_media_source; + #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
@@ -4953,6 +4955,7 @@ static void test_sample_grabber_orientation(GUID subtype) win_skip("MP4 media source is not supported, skipping tests.\n"); return; } + has_mp4_media_source = TRUE;
callback = create_test_callback(TRUE); grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); @@ -7072,15 +7075,24 @@ static void load_resource_stream(const WCHAR *name, IMFByteStream **stream) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
-static void subtest_media_source_streams(const WCHAR *resource) +struct presentation_desc { + UINT stream_count; + struct attribute_desc attributes[16]; +}; + +static void subtest_media_source_streams(const WCHAR *resource, const struct presentation_desc *expect) +{ + IMFPresentationDescriptor *presentation; + DWORD i, min_time = -1, stream_count; IMFMediaSource *media_source; IMFSourceResolver *resolver; MF_OBJECT_TYPE object_type; - DWORD i, min_time = -1; IMFByteStream *stream; HRESULT hr;
+ winetest_push_context("%s", debugstr_w(resource)); + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "got hr %#lx\n", hr); hr = MFCreateSourceResolver(&resolver); @@ -7120,6 +7132,16 @@ static void subtest_media_source_streams(const WCHAR *resource) } todo_wine ok(min_time <= 2, "source resolution took %lums\n", min_time);
+ hr = IMFMediaSource_CreatePresentationDescriptor(media_source, &presentation); + ok(hr == S_OK, "got hr %#lx\n", hr); + + hr = IMFPresentationDescriptor_GetStreamDescriptorCount(presentation, &stream_count); + ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine_if(expect->stream_count == 5 && sizeof(void *) == 4) /* only 3 streams for the mp4 the 32-bit testbot VMs */ + ok(stream_count == expect->stream_count, "got stream_count %lu\n", stream_count); + check_attributes((IMFAttributes *)presentation, expect->attributes, -1); + IMFPresentationDescriptor_Release(presentation); + hr = IMFMediaSource_Shutdown(media_source); ok(hr == S_OK, "got hr %#lx\n", hr); IMFMediaSource_Release(media_source); @@ -7129,11 +7151,40 @@ skip_tests:
hr = MFShutdown(); ok(hr == S_OK, "got hr %#lx\n", hr); + + winetest_pop_context(); }
static void test_media_source_streams(void) { - subtest_media_source_streams(L"test.mp4"); +/* w7 doesn't have MF_PD_MIME_TYPE */ +#define ATTR_WSTR_OR_NONE(k, v, ...) {.key = has_video_processor ? &k : NULL, .name = #k, {.vt = VT_LPWSTR, .pwszVal = (WCHAR *)v}, __VA_ARGS__ } + const struct presentation_desc mp4_desc = + { + .stream_count = 5, + .attributes = + { + ATTR_RATIO(MF_PD_DURATION, 0, 25000000), + ATTR_RATIO(MF_PD_TOTAL_FILE_SIZE, 0, 33041, .todo = TRUE), + ATTR_WSTR_OR_NONE(MF_PD_MIME_TYPE, L"video/mp4", .todo = TRUE), + }, + }; + const struct presentation_desc avi_desc = + { + .stream_count = 3, + .attributes = + { + ATTR_RATIO(MF_PD_DURATION, 0, 20020000), + ATTR_RATIO(MF_PD_TOTAL_FILE_SIZE, 0, 47250, .todo = TRUE), + ATTR_UINT32(MF_PD_AUDIO_ENCODING_BITRATE, 106176, .todo = TRUE), + ATTR_UINT32(MF_PD_VIDEO_ENCODING_BITRATE, 1125200, .todo = TRUE), + ATTR_WSTR_OR_NONE(MF_PD_MIME_TYPE, L"video/avi", .todo = TRUE), + }, + }; +#undef ATTR_WSTR_OR_NONE + + subtest_media_source_streams(L"multiple-streams.mp4", &mp4_desc); + subtest_media_source_streams(L"multiple-streams.avi", &avi_desc); }
START_TEST(mf) diff --git a/dlls/mf/tests/mf_test.h b/dlls/mf/tests/mf_test.h index 0f23e2aeb02..c5481c324a3 100644 --- a/dlls/mf/tests/mf_test.h +++ b/dlls/mf/tests/mf_test.h @@ -54,6 +54,7 @@ typedef struct attribute_desc media_type_desc[32]; #define ATTR_BLOB(k, p, n, ...) {.key = &k, .name = #k, {.vt = VT_VECTOR | VT_UI1, .caub = {.pElems = (void *)p, .cElems = n}}, __VA_ARGS__ } #define ATTR_RATIO(k, n, d, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.HighPart = n, .LowPart = d}}, .ratio = TRUE, __VA_ARGS__ } #define ATTR_UINT64(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.QuadPart = v}}, __VA_ARGS__ } +#define ATTR_WSTR(k, v, ...) {.key = &k, .name = #k, {.vt = VT_LPWSTR, .pwszVal = (WCHAR *)v}, __VA_ARGS__ }
#define check_media_type(a, b, c) check_attributes_(__FILE__, __LINE__, (IMFAttributes *)a, b, c) #define check_attributes(a, b, c) check_attributes_(__FILE__, __LINE__, a, b, c) diff --git a/dlls/mf/tests/multiple-streams.avi b/dlls/mf/tests/multiple-streams.avi new file mode 100644 index 0000000000000000000000000000000000000000..8ed6f1ceb6026c4db79716ff2cd96826f50a7445 GIT binary patch literal 47250 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
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/multiple-streams.mp4 b/dlls/mf/tests/multiple-streams.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..ddb005113c55889f39e3a050661ded6454340bca GIT binary patch literal 33041 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
literal 0 HcmV?d00001
diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc index e3df92e375f..25646851b45 100644 --- a/dlls/mf/tests/resource.rc +++ b/dlls/mf/tests/resource.rc @@ -115,3 +115,56 @@ rgb24frame.bmp RCDATA rgb24frame.bmp */ /* @makedep: test.mp4 */ test.mp4 RCDATA test.mp4 + +/* Generated with: +gst-launch-1.0 videotestsrc num-buffers=60 pattern=smpte100 ! \ + taginject tags="language-code=ger" ! \ + video/x-raw,format=I420,width=72,height=72,framerate=30000/1000 ! \ + videoflip method=clockwise ! videoconvert ! x264enc ! mux. \ + \ + audiotestsrc num-buffers=60 ! audio/x-raw,format=F32LE,channels=1 ! \ + taginject tags="language-code=eng" ! \ + audioconvert ! audioresample ! avenc_aac ! mux. \ + \ + videotestsrc num-buffers=60 pattern=smpte100 ! \ + video/x-raw,format=I420,width=64,height=64,framerate=24000/1000 ! \ + videoflip method=clockwise ! videoconvert ! x264enc ! mux. \ + \ + audiotestsrc num-buffers=60 ! audio/x-raw,format=S16LE,layout=interleaved ! \ + taginject tags="language-code=fre" ! \ + audioconvert ! audioresample ! lamemp3enc ! mux. \ + \ + videotestsrc num-buffers=60 pattern=smpte100 ! \ + video/x-raw,format=I420,width=96,height=64,framerate=30000/1000 ! \ + videoflip method=clockwise ! videoconvert ! x264enc ! mux. \ + \ + mp4mux name=mux ! filesink location=dlls/mf/tests/multiple-streams.tmp && \ +ffmpeg -y -i dlls/mf/tests/multiple-streams.tmp \ + -metadata:s:v:0 title="Other Video" -metadata:s:v:2 title="First Video" \ + -metadata:s:a:0 title="This is a very long audio stream title string" \ + -codec copy -map 0 dlls/mf/tests/multiple-streams.mp4 +*/ +/* @makedep: multiple-streams.mp4 */ +multiple-streams.mp4 RCDATA multiple-streams.mp4 + +/* Generated with: +gst-launch-1.0 videotestsrc num-buffers=60 pattern=smpte100 ! \ + taginject tags="title='Video 1',language-code=ger" ! \ + video/x-raw,format=I420,width=64,height=64,framerate=30000/1001 ! \ + videoflip method=clockwise ! videoconvert ! mpeg2enc ! mux. \ + \ + audiotestsrc num-buffers=60 ! audio/x-raw,format=F32LE,channels=1 ! \ + taginject tags="language-code=eng" ! \ + audioconvert ! audioresample ! avenc_aac ! mux. \ + \ + audiotestsrc num-buffers=60 ! audio/x-raw,format=S16LE,layout=interleaved ! \ + taginject tags="language-code=fre" ! \ + audioconvert ! audioresample ! lamemp3enc ! mux. \ + \ + avimux name=mux ! filesink location=dlls/mf/tests/multiple-streams.tmp && \ +ffmpeg -y -i dlls/mf/tests/multiple-streams.tmp -metadata:s:v:0 title="Video" \ + -metadata:s:a:0 title="This is a very long audio stream title string" \ + -codec copy -map 0:a:0 -map 0:v:0 -map 0:a:1 dlls/mf/tests/multiple-streams.avi +*/ +/* @makedep: multiple-streams.avi */ +multiple-streams.avi RCDATA multiple-streams.avi diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index b1ac3ffbb14..b5f215fb869 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -257,6 +257,7 @@ void check_attributes_(const char *file, int line, IMFAttributes *attributes, switch (value.vt) { default: sprintf(buffer, "??"); break; + case VT_LPWSTR: sprintf(buffer, "%s", debugstr_w(value.pwszVal)); break; case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break; case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break; case VT_UI8:
From: Rémi Bernon rbernon@codeweavers.com
The tests are all flaky because of the current media source design, which uses high-level GStreamer abstractions, like decodebin, which internally create threads and queues, and which cannot provide any deterministic stream ordering. --- dlls/mf/tests/mf.c | 124 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index c8a2fe931ca..6a556837f81 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7075,20 +7075,30 @@ static void load_resource_stream(const WCHAR *name, IMFByteStream **stream) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
+struct stream_desc +{ + UINT id; + BOOL selected; + struct attribute_desc attributes[16]; +}; + struct presentation_desc { UINT stream_count; struct attribute_desc attributes[16]; + struct stream_desc streams[16]; };
static void subtest_media_source_streams(const WCHAR *resource, const struct presentation_desc *expect) { IMFPresentationDescriptor *presentation; + IMFStreamDescriptor *stream_descriptor; DWORD i, min_time = -1, stream_count; IMFMediaSource *media_source; IMFSourceResolver *resolver; MF_OBJECT_TYPE object_type; IMFByteStream *stream; + BOOL selected; HRESULT hr;
winetest_push_context("%s", debugstr_w(resource)); @@ -7140,6 +7150,47 @@ static void subtest_media_source_streams(const WCHAR *resource, const struct pre todo_wine_if(expect->stream_count == 5 && sizeof(void *) == 4) /* only 3 streams for the mp4 the 32-bit testbot VMs */ ok(stream_count == expect->stream_count, "got stream_count %lu\n", stream_count); check_attributes((IMFAttributes *)presentation, expect->attributes, -1); + + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(presentation, 1, &selected, &stream_descriptor); + ok(hr == S_OK, "got hr %#lx\n", hr); + hr = IMFStreamDescriptor_GetItem(stream_descriptor, &MF_SD_STREAM_NAME, NULL); + flaky_wine + ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND), "got hr %#lx\n", hr); + IMFStreamDescriptor_Release(stream_descriptor); + + /* w7 and w1064v1507 miss the MF_SD_STREAM_NAME attribute */ + if (broken(hr == MF_E_ATTRIBUTENOTFOUND)) + win_skip("Skipping stream attributes checks\n"); + else for (i = 0; i < stream_count; ++i) + { + const struct stream_desc *expect_stream = expect->streams + i; + IMFMediaTypeHandler *type_handler; + DWORD id, type_count; + + winetest_push_context("%lu", i); + + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(presentation, i, &selected, &stream_descriptor); + ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine_if(!expect_stream->selected) + ok(selected == expect_stream->selected, "got selected %u\n", selected); + hr = IMFStreamDescriptor_GetStreamIdentifier(stream_descriptor, &id); + ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(id == expect_stream->id, "got id %lu\n", id); + + flaky_wine check_attributes((IMFAttributes *)stream_descriptor, expect_stream->attributes, -1); + + hr = IMFStreamDescriptor_GetMediaTypeHandler(stream_descriptor, &type_handler); + ok(hr == S_OK, "got hr %#lx\n", hr); + hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &type_count); + ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(type_count == 1, "got type_count %lu\n", type_count); + + IMFMediaTypeHandler_Release(type_handler); + IMFStreamDescriptor_Release(stream_descriptor); + + winetest_pop_context(); + } + IMFPresentationDescriptor_Release(presentation);
hr = IMFMediaSource_Shutdown(media_source); @@ -7168,6 +7219,52 @@ static void test_media_source_streams(void) ATTR_RATIO(MF_PD_TOTAL_FILE_SIZE, 0, 33041, .todo = TRUE), ATTR_WSTR_OR_NONE(MF_PD_MIME_TYPE, L"video/mp4", .todo = TRUE), }, + .streams = + { + { + .id = 1, + .attributes = + { + ATTR_WSTR(MF_SD_LANGUAGE, L"fr", /* flaky, .todo = TRUE */), + ATTR_UINT32(MF_SD_MUTUALLY_EXCLUSIVE, 1, .todo = TRUE), + }, + }, + { + .id = 2, + .selected = 1, + .attributes = + { + ATTR_WSTR(MF_SD_LANGUAGE, L"en", /* flaky, .todo_value = TRUE */), + ATTR_UINT32(MF_SD_MUTUALLY_EXCLUSIVE, 1, .todo = TRUE), + ATTR_WSTR(MF_SD_STREAM_NAME, L"This is a very long audio stream title string", /* flaky, .todo_value = TRUE */), + }, + }, + { + .id = 3, + .attributes = + { + ATTR_UINT32(MF_SD_MUTUALLY_EXCLUSIVE, 1, .todo = TRUE), + ATTR_WSTR(MF_SD_STREAM_NAME, L"First Video", /* flaky, .todo = TRUE */), + }, + }, + { + .id = 4, + .attributes = + { + ATTR_UINT32(MF_SD_MUTUALLY_EXCLUSIVE, 1, .todo = TRUE), + }, + }, + { + .id = 5, + .selected = 1, + .attributes = + { + ATTR_WSTR(MF_SD_LANGUAGE, L"de", /* flaky, .todo_value = TRUE */), + ATTR_UINT32(MF_SD_MUTUALLY_EXCLUSIVE, 1, .todo = TRUE), + ATTR_WSTR(MF_SD_STREAM_NAME, L"Other Video", /* flaky, .todo = TRUE */), + }, + }, + }, }; const struct presentation_desc avi_desc = { @@ -7180,6 +7277,33 @@ static void test_media_source_streams(void) ATTR_UINT32(MF_PD_VIDEO_ENCODING_BITRATE, 1125200, .todo = TRUE), ATTR_WSTR_OR_NONE(MF_PD_MIME_TYPE, L"video/avi", .todo = TRUE), }, + .streams = + { + { + .id = 1, + .selected = 1, + .attributes = + { + ATTR_UINT32(MF_SD_MUTUALLY_EXCLUSIVE, 1, .todo = TRUE), + ATTR_WSTR(MF_SD_STREAM_NAME, L"This is a very long audio stream title string", /* flaky, .todo = TRUE */), + }, + }, + { + .id = 2, + .selected = 1, + .attributes = + { + ATTR_WSTR(MF_SD_STREAM_NAME, L"Video", /* flaky, .todo = TRUE */), + }, + }, + { + .id = 3, + .attributes = + { + ATTR_UINT32(MF_SD_MUTUALLY_EXCLUSIVE, 1, .todo = TRUE), + }, + }, + }, }; #undef ATTR_WSTR_OR_NONE
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 41271585454..c3362cea5e5 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -174,7 +174,10 @@ static ULONG WINAPI source_async_command_Release(IUnknown *iface) if (!refcount) { if (command->op == SOURCE_ASYNC_START) + { + IMFPresentationDescriptor_Release(command->u.start.descriptor); PropVariantClear(&command->u.start.position); + } else if (command->op == SOURCE_ASYNC_REQUEST_SAMPLE) { if (command->u.request_sample.token) @@ -1357,6 +1360,7 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD { struct source_async_command *command = impl_from_async_command_IUnknown(op); command->u.start.descriptor = descriptor; + IMFPresentationDescriptor_AddRef(descriptor); command->u.start.format = *time_format; PropVariantCopy(&command->u.start.position, position);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 6a556837f81..fac7d0f5f14 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1972,8 +1972,8 @@ static IMFAsyncCallback *create_test_callback(BOOL check_media_event) return &callback->IMFAsyncCallback_iface; }
-#define wait_media_event(a, b, c, d, e) wait_media_event_(__LINE__, a, b, c, d, e) -static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCallback *callback, +#define wait_media_event(a, b, c, d, e) wait_media_event_(__LINE__, (IMFMediaEventGenerator *)a, b, c, d, e) +static HRESULT wait_media_event_(int line, IMFMediaEventGenerator *session, IMFAsyncCallback *callback, MediaEventType expect_type, DWORD timeout, PROPVARIANT *value) { struct test_callback *impl = impl_from_IMFAsyncCallback(callback); @@ -1984,7 +1984,7 @@ static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCal
do { - hr = IMFMediaSession_BeginGetEvent(session, &impl->IMFAsyncCallback_iface, (IUnknown *)session); + hr = IMFMediaEventGenerator_BeginGetEvent(session, &impl->IMFAsyncCallback_iface, (IUnknown *)session); ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); ret = WaitForSingleObject(impl->event, timeout); ok_(__FILE__, line)(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %lu\n", ret); @@ -7096,8 +7096,10 @@ static void subtest_media_source_streams(const WCHAR *resource, const struct pre DWORD i, min_time = -1, stream_count; IMFMediaSource *media_source; IMFSourceResolver *resolver; + IMFAsyncCallback *callback; MF_OBJECT_TYPE object_type; IMFByteStream *stream; + PROPVARIANT propvar; BOOL selected; HRESULT hr;
@@ -7191,6 +7193,38 @@ static void subtest_media_source_streams(const WCHAR *resource, const struct pre winetest_pop_context(); }
+ /* check that Start stream selection is reflected by CreatePresentationDescriptor */ + + for (i = 0; i < stream_count; ++i) + { + hr = IMFPresentationDescriptor_DeselectStream(presentation, i); + ok(hr == S_OK, "got hr %#lx\n", hr); + } + hr = IMFPresentationDescriptor_SelectStream(presentation, 2); + ok(hr == S_OK, "got hr %#lx\n", hr); + PropVariantInit(&propvar); + hr = IMFMediaSource_Start(media_source, presentation, &GUID_NULL, &propvar); + ok(hr == S_OK, "got hr %#lx\n", hr); + IMFPresentationDescriptor_Release(presentation); + + callback = create_test_callback(TRUE); + ok(!!callback, "got callback %p\n", callback); + hr = wait_media_event(media_source, callback, MESourceStarted, INFINITE, &propvar); + ok(hr == S_OK, "got hr %#lx\n", hr); + IMFAsyncCallback_Release(callback); + + hr = IMFMediaSource_CreatePresentationDescriptor(media_source, &presentation); + ok(hr == S_OK, "got hr %#lx\n", hr); + for (i = 0; i < stream_count; ++i) + { + IMFStreamDescriptor *stream; + BOOL selected; + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(presentation, i, &selected, &stream); + ok(hr == S_OK, "got hr %#lx\n", hr); + if (i == 2) ok(selected, "got selected %u\n", selected); + else todo_wine ok(!selected, "got selected %u\n", selected); + IMFStreamDescriptor_Release(stream); + } IMFPresentationDescriptor_Release(presentation);
hr = IMFMediaSource_Shutdown(media_source);
On Wed May 10 14:44:49 2023 +0000, Rémi Bernon wrote:
I think it adds some unnecessary level of indirection, which would add even more variance to the timing?
I'm using the resolver now, seems to be working well enough with the repetition and it makes the code simpler.
On Fri May 26 11:20:09 2023 +0000, Rémi Bernon wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/2782/diffs?diff_id=48930&start_sha=072831ffa9f17f08500fd86259db1b49849c7ac3#38af2002cdac18e4819839775ba914609caa73df_6808_7115)
I'm now repeating the resolution a couple of times. After running it several times it seems to be stable on Windows, where the minimum time will usually be ~0ms. I've kept a small tolerance of 2ms to be safe.
On Wine testbot, the minimum resolution time seems to be around 10ms-20ms.
On Fri May 26 11:20:11 2023 +0000, Rémi Bernon wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/2782/diffs?diff_id=48930&start_sha=072831ffa9f17f08500fd86259db1b49849c7ac3#38af2002cdac18e4819839775ba914609caa73df_6845_7130)
I dropped these.
Should I do something differently here?
I don't like the idea of testing timings, I don't think we have such performance tests anywhere else. Obviously making it faster is valuable, but testing how much time something took seems weird to me.
Alright, what about the flaky tests? I can also postpone the tests until they are not flaky anymore.
This merge request was closed by Rémi Bernon.