From: Zebediah Figura Subject: [PATCH v4] quartz: Cache IMediaSeeking for filters. Message-Id: <20200408193814.1217280-1-z.figura12@gmail.com> Date: Wed, 8 Apr 2020 14:38:14 -0500 From: Gabriel Ivăncescu Signed-off-by: Gabriel Ivăncescu Signed-off-by: Zebediah Figura --- This supersedes patch 183026. v4: Add a more detailed comment to the code, instead of in the commit message. dlls/quartz/filtergraph.c | 47 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index c659cf96e4c..7a9db402ec3 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -153,6 +153,7 @@ struct filter { struct list entry, sorted_entry; IBaseFilter *filter; + IMediaSeeking *seeking; WCHAR *name; BOOL sorting; }; @@ -593,24 +594,19 @@ static BOOL has_output_pins(IBaseFilter *filter) return FALSE; } -static BOOL is_renderer(IBaseFilter *filter) +static BOOL is_renderer(struct filter *filter) { IAMFilterMiscFlags *flags; - IMediaSeeking *seeking; BOOL ret = FALSE; - if (SUCCEEDED(IBaseFilter_QueryInterface(filter, &IID_IAMFilterMiscFlags, (void **)&flags))) + if (SUCCEEDED(IBaseFilter_QueryInterface(filter->filter, &IID_IAMFilterMiscFlags, (void **)&flags))) { if (IAMFilterMiscFlags_GetMiscFlags(flags) & AM_FILTER_MISC_FLAGS_IS_RENDERER) ret = TRUE; IAMFilterMiscFlags_Release(flags); } - else if (SUCCEEDED(IBaseFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&seeking))) - { - IMediaSeeking_Release(seeking); - if (!has_output_pins(filter)) - ret = TRUE; - } + else if (filter->seeking && !has_output_pins(filter->filter)) + ret = TRUE; return ret; } @@ -675,12 +671,19 @@ 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; ++graph->version; - if (is_renderer(filter)) + if (is_renderer(entry)) ++graph->nRenderers; return duplicate_name ? VFW_S_DUPLICATE_NAME : hr; @@ -755,11 +758,13 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, NULL); if (SUCCEEDED(hr)) { - if (is_renderer(pFilter)) + if (is_renderer(entry)) --This->nRenderers; IBaseFilter_SetSyncSource(pFilter, NULL); IBaseFilter_Release(pFilter); + if (entry->seeking) + IMediaSeeking_Release(entry->seeking); list_remove(&entry->entry); list_remove(&entry->sorted_entry); CoTaskMemFree(entry->name); @@ -2219,13 +2224,9 @@ static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry) { - IMediaSeeking *seek = NULL; - - IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seek); - if (!seek) + if (!filter->seeking) continue; - hr = FoundSeek(This, seek, arg); - IMediaSeeking_Release(seek); + hr = FoundSeek(This, filter->seeking, arg); if (hr_return != E_NOTIMPL) allnotimpl = FALSE; if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return))) @@ -2414,7 +2415,6 @@ static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLON { IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface); HRESULT hr = E_NOTIMPL, filter_hr; - IMediaSeeking *seeking; struct filter *filter; LONGLONG filter_stop; @@ -2429,11 +2429,10 @@ static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLON LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry) { - if (FAILED(IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seeking))) + if (!filter->seeking) continue; - filter_hr = IMediaSeeking_GetStopPosition(seeking, &filter_stop); - IMediaSeeking_Release(seeking); + filter_hr = IMediaSeeking_GetStopPosition(filter->seeking, &filter_stop); if (SUCCEEDED(filter_hr)) { hr = S_OK; @@ -2507,7 +2506,6 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG * { IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface); HRESULT hr = E_NOTIMPL, filter_hr; - IMediaSeeking *seeking; struct filter *filter; FILTER_STATE state; @@ -2539,12 +2537,11 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG * { LONGLONG current = current_ptr ? *current_ptr : 0, stop = stop_ptr ? *stop_ptr : 0; - if (FAILED(IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seeking))) + if (!filter->seeking) continue; - filter_hr = IMediaSeeking_SetPositions(seeking, ¤t, + filter_hr = IMediaSeeking_SetPositions(filter->seeking, ¤t, current_flags | AM_SEEKING_ReturnTime, &stop, stop_flags); - IMediaSeeking_Release(seeking); if (SUCCEEDED(filter_hr)) { hr = S_OK; -- 2.26.0