quartz: Cache IMediaSeeking for filters.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Gabriel Ivăncescu 2020-04-08 14:38:14 -05:00 committed by Alexandre Julliard
parent 2cc0116da0
commit 0320f165c8
1 changed files with 22 additions and 25 deletions

View File

@ -153,6 +153,7 @@ struct filter
{ {
struct list entry, sorted_entry; struct list entry, sorted_entry;
IBaseFilter *filter; IBaseFilter *filter;
IMediaSeeking *seeking;
WCHAR *name; WCHAR *name;
BOOL sorting; BOOL sorting;
}; };
@ -593,24 +594,19 @@ static BOOL has_output_pins(IBaseFilter *filter)
return FALSE; return FALSE;
} }
static BOOL is_renderer(IBaseFilter *filter) static BOOL is_renderer(struct filter *filter)
{ {
IAMFilterMiscFlags *flags; IAMFilterMiscFlags *flags;
IMediaSeeking *seeking;
BOOL ret = FALSE; 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) if (IAMFilterMiscFlags_GetMiscFlags(flags) & AM_FILTER_MISC_FLAGS_IS_RENDERER)
ret = TRUE; ret = TRUE;
IAMFilterMiscFlags_Release(flags); IAMFilterMiscFlags_Release(flags);
} }
else if (SUCCEEDED(IBaseFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&seeking))) else if (filter->seeking && !has_output_pins(filter->filter))
{ ret = TRUE;
IMediaSeeking_Release(seeking);
if (!has_output_pins(filter))
ret = TRUE;
}
return ret; return ret;
} }
@ -675,12 +671,19 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface,
} }
IBaseFilter_AddRef(entry->filter = filter); 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->filters, &entry->entry);
list_add_head(&graph->sorted_filters, &entry->sorted_entry); list_add_head(&graph->sorted_filters, &entry->sorted_entry);
entry->sorting = FALSE; entry->sorting = FALSE;
++graph->version; ++graph->version;
if (is_renderer(filter)) if (is_renderer(entry))
++graph->nRenderers; ++graph->nRenderers;
return duplicate_name ? VFW_S_DUPLICATE_NAME : hr; 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); hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, NULL);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
if (is_renderer(pFilter)) if (is_renderer(entry))
--This->nRenderers; --This->nRenderers;
IBaseFilter_SetSyncSource(pFilter, NULL); IBaseFilter_SetSyncSource(pFilter, NULL);
IBaseFilter_Release(pFilter); IBaseFilter_Release(pFilter);
if (entry->seeking)
IMediaSeeking_Release(entry->seeking);
list_remove(&entry->entry); list_remove(&entry->entry);
list_remove(&entry->sorted_entry); list_remove(&entry->sorted_entry);
CoTaskMemFree(entry->name); 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) LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
{ {
IMediaSeeking *seek = NULL; if (!filter->seeking)
IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seek);
if (!seek)
continue; continue;
hr = FoundSeek(This, seek, arg); hr = FoundSeek(This, filter->seeking, arg);
IMediaSeeking_Release(seek);
if (hr_return != E_NOTIMPL) if (hr_return != E_NOTIMPL)
allnotimpl = FALSE; allnotimpl = FALSE;
if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return))) 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); IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface);
HRESULT hr = E_NOTIMPL, filter_hr; HRESULT hr = E_NOTIMPL, filter_hr;
IMediaSeeking *seeking;
struct filter *filter; struct filter *filter;
LONGLONG filter_stop; 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) LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry)
{ {
if (FAILED(IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seeking))) if (!filter->seeking)
continue; continue;
filter_hr = IMediaSeeking_GetStopPosition(seeking, &filter_stop); filter_hr = IMediaSeeking_GetStopPosition(filter->seeking, &filter_stop);
IMediaSeeking_Release(seeking);
if (SUCCEEDED(filter_hr)) if (SUCCEEDED(filter_hr))
{ {
hr = S_OK; hr = S_OK;
@ -2507,7 +2506,6 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *
{ {
IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface); IFilterGraphImpl *graph = impl_from_IMediaSeeking(iface);
HRESULT hr = E_NOTIMPL, filter_hr; HRESULT hr = E_NOTIMPL, filter_hr;
IMediaSeeking *seeking;
struct filter *filter; struct filter *filter;
FILTER_STATE state; 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; 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; continue;
filter_hr = IMediaSeeking_SetPositions(seeking, &current, filter_hr = IMediaSeeking_SetPositions(filter->seeking, &current,
current_flags | AM_SEEKING_ReturnTime, &stop, stop_flags); current_flags | AM_SEEKING_ReturnTime, &stop, stop_flags);
IMediaSeeking_Release(seeking);
if (SUCCEEDED(filter_hr)) if (SUCCEEDED(filter_hr))
{ {
hr = S_OK; hr = S_OK;