quartz/filtergraph: Always try to query IMediaSeeking if it's not cached yet.
Signed-off-by: Anton Baskanov <baskanov@gmail.com> Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
343043153b
commit
609a832a56
|
@ -588,6 +588,21 @@ static BOOL has_output_pins(IBaseFilter *filter)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void update_seeking(struct filter *filter)
|
||||
{
|
||||
if (!filter->seeking)
|
||||
{
|
||||
/* The Legend of Heroes: Trails of Cold Steel II destroys its filter when
|
||||
* its IMediaSeeking interface is released, so cache the interface instead
|
||||
* of querying for it every time.
|
||||
* Some filters (e.g. MediaStreamFilter) can become seekable when they are
|
||||
* already in the graph, so always try to query IMediaSeeking if it's not
|
||||
* cached yet. */
|
||||
if (FAILED(IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&filter->seeking)))
|
||||
filter->seeking = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL is_renderer(struct filter *filter)
|
||||
{
|
||||
IAMFilterMiscFlags *flags;
|
||||
|
@ -599,8 +614,12 @@ static BOOL is_renderer(struct filter *filter)
|
|||
ret = TRUE;
|
||||
IAMFilterMiscFlags_Release(flags);
|
||||
}
|
||||
else if (filter->seeking && !has_output_pins(filter->filter))
|
||||
ret = TRUE;
|
||||
else
|
||||
{
|
||||
update_seeking(filter);
|
||||
if (filter->seeking && !has_output_pins(filter->filter))
|
||||
ret = TRUE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -666,15 +685,10 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface,
|
|||
|
||||
IBaseFilter_AddRef(entry->filter = filter);
|
||||
|
||||
/* The Legend of Heroes: Trails of Cold Steel II destroys its filter when
|
||||
* its IMediaSeeking interface is released, so cache the interface instead
|
||||
* of querying for it every time. */
|
||||
if (FAILED(IBaseFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&entry->seeking)))
|
||||
entry->seeking = NULL;
|
||||
|
||||
list_add_head(&graph->filters, &entry->entry);
|
||||
list_add_head(&graph->sorted_filters, &entry->sorted_entry);
|
||||
entry->sorting = FALSE;
|
||||
entry->seeking = NULL;
|
||||
++graph->version;
|
||||
|
||||
if (is_renderer(entry))
|
||||
|
@ -2252,6 +2266,7 @@ static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek,
|
|||
|
||||
LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
|
||||
{
|
||||
update_seeking(filter);
|
||||
if (!filter->seeking)
|
||||
continue;
|
||||
hr = FoundSeek(This, filter->seeking, arg);
|
||||
|
@ -2457,6 +2472,7 @@ static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLON
|
|||
|
||||
LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry)
|
||||
{
|
||||
update_seeking(filter);
|
||||
if (!filter->seeking)
|
||||
continue;
|
||||
|
||||
|
@ -2565,6 +2581,7 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *
|
|||
{
|
||||
LONGLONG current = current_ptr ? *current_ptr : 0, stop = stop_ptr ? *stop_ptr : 0;
|
||||
|
||||
update_seeking(filter);
|
||||
if (!filter->seeking)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -3619,6 +3619,17 @@ static void test_ec_complete(void)
|
|||
ok(filter3.ref == 1, "Got outstanding refcount %d.\n", filter3.ref);
|
||||
}
|
||||
|
||||
/* Remove and re-add the filter, to flush the graph's internal
|
||||
* IMediaSeeking cache. Don't expose IMediaSeeking when adding, to show
|
||||
* that it's only queried when needed. */
|
||||
static void flush_cached_seeking(IFilterGraph2 *graph, struct testfilter *filter)
|
||||
{
|
||||
IFilterGraph2_RemoveFilter(graph, &filter->IBaseFilter_iface);
|
||||
filter->IMediaSeeking_iface.lpVtbl = NULL;
|
||||
IFilterGraph2_AddFilter(graph, &filter->IBaseFilter_iface, NULL);
|
||||
filter->IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
|
||||
}
|
||||
|
||||
static void test_graph_seeking(void)
|
||||
{
|
||||
struct testfilter filter1, filter2;
|
||||
|
@ -3659,9 +3670,6 @@ static void test_graph_seeking(void)
|
|||
testfilter_init(&filter1, NULL, 0);
|
||||
testfilter_init(&filter2, NULL, 0);
|
||||
|
||||
filter1.IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
|
||||
filter2.IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
|
||||
|
||||
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
|
||||
IFilterGraph2_QueryInterface(graph, &IID_IMediaSeeking, (void **)&seeking);
|
||||
IFilterGraph2_QueryInterface(graph, &IID_IMediaFilter, (void **)&filter);
|
||||
|
@ -3824,6 +3832,8 @@ static void test_graph_seeking(void)
|
|||
|
||||
IFilterGraph2_AddFilter(graph, &filter1.IBaseFilter_iface, NULL);
|
||||
IFilterGraph2_AddFilter(graph, &filter2.IBaseFilter_iface, NULL);
|
||||
filter1.IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
|
||||
filter2.IMediaSeeking_iface.lpVtbl = &testseek_vtbl;
|
||||
|
||||
filter1.seek_caps = AM_SEEKING_CanDoSegments | AM_SEEKING_CanGetCurrentPos;
|
||||
filter2.seek_caps = AM_SEEKING_CanDoSegments | AM_SEEKING_CanGetDuration;
|
||||
|
@ -3833,6 +3843,9 @@ static void test_graph_seeking(void)
|
|||
ok(filter1.seeking_ref > 0, "Unexpected seeking refcount %d.\n", filter1.seeking_ref);
|
||||
ok(filter2.seeking_ref > 0, "Unexpected seeking refcount %d.\n", filter2.seeking_ref);
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
caps = AM_SEEKING_CanDoSegments | AM_SEEKING_CanGetCurrentPos;
|
||||
hr = IMediaSeeking_CheckCapabilities(seeking, &caps);
|
||||
ok(hr == S_FALSE, "Got hr %#x.\n", hr);
|
||||
|
@ -3848,6 +3861,9 @@ static void test_graph_seeking(void)
|
|||
ok(hr == E_FAIL, "Got hr %#x.\n", hr);
|
||||
ok(!caps, "Got caps %#x.\n", caps);
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
hr = IMediaSeeking_IsFormatSupported(seeking, &testguid);
|
||||
ok(hr == S_FALSE, "Got hr %#x.\n", hr);
|
||||
|
||||
|
@ -3905,6 +3921,9 @@ static void test_graph_seeking(void)
|
|||
hr = IMediaSeeking_ConvertTimeFormat(seeking, &time, &testguid, 0x123456789a, &TIME_FORMAT_NONE);
|
||||
todo_wine ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
filter1.seek_duration = 0x12345;
|
||||
filter2.seek_duration = 0x23456;
|
||||
hr = IMediaSeeking_GetDuration(seeking, &time);
|
||||
|
@ -3917,6 +3936,9 @@ static void test_graph_seeking(void)
|
|||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(time == 0x23456, "Got time %s.\n", wine_dbgstr_longlong(time));
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
filter1.seek_stop = 0x54321;
|
||||
filter2.seek_stop = 0x65432;
|
||||
hr = IMediaSeeking_GetStopPosition(seeking, &time);
|
||||
|
@ -3948,16 +3970,25 @@ static void test_graph_seeking(void)
|
|||
ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
|
||||
filter1.seek_hr = filter2.seek_hr = S_OK;
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
hr = IMediaSeeking_GetCurrentPosition(seeking, &time);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(!time, "Got time %s.\n", wine_dbgstr_longlong(time));
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
current = stop = 0xdeadbeef;
|
||||
hr = IMediaSeeking_GetPositions(seeking, ¤t, &stop);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
ok(!current, "Got time %s.\n", wine_dbgstr_longlong(current));
|
||||
ok(stop == 0x65432, "Got time %s.\n", wine_dbgstr_longlong(stop));
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
current = 0x123;
|
||||
stop = 0x321;
|
||||
hr = IMediaSeeking_SetPositions(seeking, ¤t, AM_SEEKING_AbsolutePositioning,
|
||||
|
@ -4025,6 +4056,9 @@ static void test_graph_seeking(void)
|
|||
ok(filter2.seek_current == 0x123, "Got time %s.\n", wine_dbgstr_longlong(filter2.seek_current));
|
||||
ok(filter2.seek_stop == 0x321, "Got time %s.\n", wine_dbgstr_longlong(filter2.seek_stop));
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
hr = IMediaSeeking_SetRate(seeking, 2.0);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
todo_wine ok(filter1.seek_rate == 2.0, "Got rate %.16e.\n", filter1.seek_rate);
|
||||
|
@ -4040,6 +4074,9 @@ static void test_graph_seeking(void)
|
|||
todo_wine ok(filter1.seek_rate == -1.0, "Got rate %.16e.\n", filter1.seek_rate);
|
||||
todo_wine ok(filter2.seek_rate == -1.0, "Got rate %.16e.\n", filter2.seek_rate);
|
||||
|
||||
flush_cached_seeking(graph, &filter1);
|
||||
flush_cached_seeking(graph, &filter2);
|
||||
|
||||
hr = IMediaSeeking_GetRate(seeking, &rate);
|
||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||
todo_wine ok(rate == -1.0, "Got rate %.16e.\n", rate);
|
||||
|
|
Loading…
Reference in New Issue