[PATCH v4 0/2] MR10885: quartz: Update current and elapsed positions in Stop().
-- v4: quartz: Update current and elapsed positions in Stop(). quartz/tests: Test current position after stopping a graph. https://gitlab.winehq.org/wine/wine/-/merge_requests/10885
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/quartz/tests/filtergraph.c | 139 ++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 087c37be538..7e3e66a6b99 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -5109,6 +5109,52 @@ static void test_graph_seeking(void) ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(time == 12340000, "Got time %s.\n", wine_dbgstr_longlong(time)); + hr = IMediaControl_Run(control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + current = 1000 * 10000; + stop = 8000 * 10000; + hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning, + &stop, AM_SEEKING_AbsolutePositioning); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + Sleep(100); + + hr = IMediaSeeking_GetCurrentPosition(seeking, &time); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (winetest_interactive) /* Timing problems make this test too liable to fail. */ + ok(compare_time(time, 1334 * 10000, 80 * 10000), + "Expected about 1334ms, got %I64d.\n", time / 10000); + current = stop = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (winetest_interactive) /* Timing problems make this test too liable to fail. */ + ok(compare_time(current, 1334 * 10000, 80 * 10000), + "Expected about 1334ms, got %I64d.\n", current / 10000); + ok(stop == 8000 * 10000, "Got time %I64d.\n", stop); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaSeeking_GetCurrentPosition(seeking, &time); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (winetest_interactive) /* Timing problems make this test too liable to fail. */ + ok(compare_time(time, 1234 * 10000, 80 * 10000), + "Expected about 1234ms, got %I64d.\n", time / 10000); + current = stop = 0xdeadbeef; + hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (winetest_interactive) /* Timing problems make this test too liable to fail. */ + ok(compare_time(current, 1234 * 10000, 80 * 10000), + "Expected about 1234ms, got %I64d.\n", current / 10000); + ok(!stop, "Got time %I64d.\n", stop); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IMediaSeeking_GetCurrentPosition(seeking, &time); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(time == 12340000, "Got time %I64d.\n", time); + hr = IMediaFilter_SetSyncSource(filter, NULL); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -6071,6 +6117,98 @@ static void test_event_dispatch(void) ok(!ref, "Got outstanding refcount %ld.\n", ref); } +static void test_stopped_current_position(void) +{ + IEnumFilters *enum_filters; + LONG_PTR lparam1, lparam2; + IMediaEvent *media_event; + IMediaSeeking *seeking; + REFERENCE_TIME current; + IMediaControl *control; + IFilterGraph2 *graph; + IBaseFilter *filter; + unsigned int i = 0; + WCHAR *filename; + ULONG fetched; + long ev_code; + HANDLE event; + HRESULT hr; + LONG code; + + filename = load_resource(L"test.avi"); + + graph = create_graph(); + + hr = IFilterGraph2_RenderFile(graph, filename, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaEvent, (void **)&media_event); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaEvent_GetEventHandle(media_event, (OAEVENT *)&event); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + /* Flush existing events. */ + while ((hr = IMediaEvent_GetEvent(media_event, &code, &lparam1, &lparam2, 0)) == S_OK); + + hr = IMediaControl_Run(control); + ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr); + + ok(WaitForSingleObject(event, 1000) == 0, "Event should be signaled.\n"); + + /* Wait 2.5 seconds of playback time. Source video is 1 fps. */ + IMediaEvent_WaitForCompletion(media_event, 2500, &ev_code); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IFilterGraph2_QueryInterface(graph, &IID_IMediaSeeking, (void **)&seeking); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IMediaSeeking_GetCurrentPosition(seeking, ¤t); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine + ok(compare_time(current, 2500 * 10000, 100 * 10000), "Expected about 2500ms, got %I64d.\n", current); + + IMediaSeeking_Release(seeking); + + hr = IFilterGraph2_EnumFilters(graph, &enum_filters); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + while ((hr = IEnumFilters_Next(enum_filters, 1, &filter, &fetched)) == S_OK) + { + winetest_push_context("Filter %u:", i++); + + ok(fetched, "Filter not fetched.\n"); + + if (FAILED(hr = IBaseFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&seeking))) + { + ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr); + } + else + { + hr = IMediaSeeking_GetCurrentPosition(seeking, ¤t); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine + ok(current == 20000000, "Got current %I64d.\n", current); + + IMediaSeeking_Release(seeking); + } + + IBaseFilter_Release(filter); + winetest_pop_context(); + } + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + IEnumFilters_Release(enum_filters); + IMediaEvent_Release(media_event); + IMediaControl_Release(control); + IFilterGraph2_Release(graph); + DeleteFileW(filename); +} + START_TEST(filtergraph) { CoInitializeEx(NULL, COINIT_MULTITHREADED); @@ -6100,6 +6238,7 @@ START_TEST(filtergraph) test_set_notify_flags(); test_events(); test_event_dispatch(); + test_stopped_current_position(); CoUninitialize(); test_render_with_multithread(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10885
From: Conor McCarthy <cmccarthy@codeweavers.com> --- dlls/quartz/filtergraph.c | 24 ++++++++++++++++-------- dlls/quartz/tests/filtergraph.c | 1 - 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 79fcc425e53..25116cea789 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -5061,6 +5061,17 @@ static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClass return E_NOTIMPL; } +static void graph_update_positions(struct filter_graph *graph) +{ + if (graph->state == State_Running && !graph->needs_async_run && graph->refClock) + { + REFERENCE_TIME time; + IReferenceClock_GetTime(graph->refClock, &time); + graph->stream_elapsed += time - graph->stream_start; + graph->current_pos += graph->stream_elapsed; + } +} + static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface) { struct filter_graph *graph = impl_from_IMediaFilter(iface); @@ -5080,6 +5091,8 @@ static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface) sort_filters(graph); + graph_update_positions(graph); + if (graph->state == State_Running) { LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry) @@ -5101,7 +5114,8 @@ static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface) graph->needs_async_run = 0; work = graph->async_run_work; - /* Update the current position, probably to synchronize multiple streams. */ + /* Update the current position, probably to synchronize multiple streams. + * TODO: on native, filters seem to be set to the position of the latest sample. */ IMediaSeeking_SetPositions(&graph->IMediaSeeking_iface, &graph->current_pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); @@ -5139,13 +5153,7 @@ static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface) if (graph->defaultclock && !graph->refClock) IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface); - if (graph->state == State_Running && !graph->needs_async_run && graph->refClock) - { - REFERENCE_TIME time; - IReferenceClock_GetTime(graph->refClock, &time); - graph->stream_elapsed += time - graph->stream_start; - graph->current_pos += graph->stream_elapsed; - } + graph_update_positions(graph); LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry) { diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 7e3e66a6b99..630b42bf04e 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -6169,7 +6169,6 @@ static void test_stopped_current_position(void) hr = IMediaSeeking_GetCurrentPosition(seeking, ¤t); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(compare_time(current, 2500 * 10000, 100 * 10000), "Expected about 2500ms, got %I64d.\n", current); IMediaSeeking_Release(seeking); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10885
On Fri May 29 06:38:47 2026 +0000, Conor McCarthy wrote:
I rebased and added tests in `test_graph_seeking()`, but the todos there are not fixed by this MR. The stop time is zero after `Stop()` is called, so we would need to call `SetPositions()` to run it again, which wouldn't be useful AFAIK. Oops, forgot to set interactive the last time I ran a native test. There are no new todos in `test_graph_seeking()`.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10885#note_141643
Ok, it looks like the filters are set to the position of the latest sample when `Stop()` is called. We probably don't need to do anything about that unless a bug arises out of it.
I don't think that's true per se. Again, according to our current understanding, and I would be surprised if this is wrong, the only time SetPositions() is ever called by the graph is when SetPositions() is called _on_ the graph. There's not really a reason to seek at any other time.
Okay, so I can't read or remember very well; apologies for this. That said, it's not a matter of the latest sample; it's instead based on the time. Our existing code here seems to be correct. With a slightly better understanding of the problem I've sent !11050, which simplifies things a bit by only testing the relevant behaviour in test_media_seeking(). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10885#note_141956
Thanks for taking care of those tests. The new MR all looks good to me. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10885#note_141959
This merge request was closed by Conor McCarthy. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10885
participants (3)
-
Conor McCarthy -
Conor McCarthy (@cmccarthy) -
Elizabeth Figura (@zfigura)