quartz: Implement IFilterGraph2::RenderEx().

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35215
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2020-06-15 22:51:26 -05:00 committed by Alexandre Julliard
parent c603a5bfbc
commit 15303e5401
2 changed files with 56 additions and 21 deletions

View file

@ -1119,10 +1119,12 @@ static HRESULT create_filter(IFilterGraphImpl *graph, IMoniker *moniker, IBaseFi
return IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void **)filter);
}
static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsigned int recursion_depth);
static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink,
BOOL render_to_existing, unsigned int recursion_depth);
static HRESULT autoplug_through_sink(IFilterGraphImpl *graph, IPin *source,
IBaseFilter *filter, IPin *middle_sink, IPin *sink, unsigned int recursion_depth)
IBaseFilter *filter, IPin *middle_sink, IPin *sink,
BOOL render_to_existing, BOOL allow_renderers, unsigned int recursion_depth)
{
BOOL any = FALSE, all = TRUE;
IPin *middle_source, *peer;
@ -1171,7 +1173,7 @@ static HRESULT autoplug_through_sink(IFilterGraphImpl *graph, IPin *source,
continue;
}
hr = autoplug(graph, middle_source, sink, recursion_depth + 1);
hr = autoplug(graph, middle_source, sink, render_to_existing, recursion_depth + 1);
IPin_Release(middle_source);
if (SUCCEEDED(hr) && sink)
{
@ -1187,7 +1189,7 @@ static HRESULT autoplug_through_sink(IFilterGraphImpl *graph, IPin *source,
if (!sink)
{
if (all)
if (all && (any || allow_renderers))
return S_OK;
if (any)
return VFW_S_PARTIAL_RENDER;
@ -1200,7 +1202,8 @@ err:
}
static HRESULT autoplug_through_filter(IFilterGraphImpl *graph, IPin *source,
IBaseFilter *filter, IPin *sink, unsigned int recursion_depth)
IBaseFilter *filter, IPin *sink, BOOL render_to_existing,
BOOL allow_renderers, unsigned int recursion_depth)
{
IEnumPins *sink_enum;
IPin *filter_sink;
@ -1213,7 +1216,8 @@ static HRESULT autoplug_through_filter(IFilterGraphImpl *graph, IPin *source,
while (IEnumPins_Next(sink_enum, 1, &filter_sink, NULL) == S_OK)
{
hr = autoplug_through_sink(graph, source, filter, filter_sink, sink, recursion_depth);
hr = autoplug_through_sink(graph, source, filter, filter_sink, sink,
render_to_existing, allow_renderers, recursion_depth);
IPin_Release(filter_sink);
if (SUCCEEDED(hr))
{
@ -1227,7 +1231,8 @@ static HRESULT autoplug_through_filter(IFilterGraphImpl *graph, IPin *source,
/* Common helper for IGraphBuilder::Connect() and IGraphBuilder::Render(), which
* share most of the same code. Render() calls this with a NULL sink. */
static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsigned int recursion_depth)
static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink,
BOOL render_to_existing, unsigned int recursion_depth)
{
IAMGraphBuilderCallback *callback = NULL;
IEnumMediaTypes *enummt;
@ -1259,7 +1264,8 @@ static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsig
/* Always prefer filters in the graph. */
LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry)
{
if (SUCCEEDED(hr = autoplug_through_filter(graph, source, filter->filter, sink, recursion_depth)))
if (SUCCEEDED(hr = autoplug_through_filter(graph, source, filter->filter,
sink, render_to_existing, TRUE, recursion_depth)))
return hr;
}
@ -1334,7 +1340,8 @@ static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsig
continue;
}
hr = autoplug_through_filter(graph, source, filter, sink, recursion_depth);
hr = autoplug_through_filter(graph, source, filter, sink,
render_to_existing, !render_to_existing, recursion_depth);
if (SUCCEEDED(hr))
{
IBaseFilter_Release(filter);
@ -1383,7 +1390,7 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *source, I
EnterCriticalSection(&graph->cs);
hr = autoplug(graph, source, sink, 0);
hr = autoplug(graph, source, sink, FALSE, 0);
LeaveCriticalSection(&graph->cs);
@ -1399,7 +1406,7 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *source)
TRACE("graph %p, source %p.\n", graph, source);
EnterCriticalSection(&graph->cs);
hr = autoplug(graph, source, NULL, 0);
hr = autoplug(graph, source, NULL, FALSE, 0);
LeaveCriticalSection(&graph->cs);
if (hr == VFW_E_CANNOT_CONNECT)
hr = VFW_E_CANNOT_RENDER;
@ -1598,14 +1605,24 @@ static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *pin,
return hr;
}
static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
DWORD *pvContext)
static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *source, DWORD flags, DWORD *context)
{
IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface);
HRESULT hr;
TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
TRACE("graph %p, source %p, flags %#x, context %p.\n", graph, source, flags, context);
return S_OK;
if (flags & ~AM_RENDEREX_RENDERTOEXISTINGRENDERERS)
FIXME("Unknown flags %#x.\n", flags);
EnterCriticalSection(&graph->cs);
hr = autoplug(graph, source, NULL, !!(flags & AM_RENDEREX_RENDERTOEXISTINGRENDERERS), 0);
LeaveCriticalSection(&graph->cs);
if (hr == VFW_E_CANNOT_CONNECT)
hr = VFW_E_CANNOT_RENDER;
TRACE("Returning %#x.\n", hr);
return hr;
}

View file

@ -1978,9 +1978,6 @@ static void test_graph_builder_render(void)
/* Test enumeration of filters from the registry. */
graph = create_graph();
IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
CoRegisterClassObject(&sink1_clsid, (IUnknown *)&sink1_cf.IClassFactory_iface,
CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie1);
CoRegisterClassObject(&sink2_clsid, (IUnknown *)&sink2_cf.IClassFactory_iface,
@ -2007,6 +2004,9 @@ static void test_graph_builder_render(void)
}
ok(hr == S_OK, "Got hr %#x.\n", hr);
graph = create_graph();
IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
regpins.dwFlags = REG_PINFLAG_B_RENDERER;
IFilterMapper2_RegisterFilter(mapper, &sink2_clsid, L"test", NULL, NULL, NULL, &regfilter);
@ -2086,6 +2086,26 @@ static void test_graph_builder_render(void)
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(source_pin.peer == &sink1_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
ref = IFilterGraph2_Release(graph);
ok(!ref, "Got outstanding refcount %d.\n", ref);
/* Test AM_RENDEREX_RENDERTOEXISTINGRENDERERS. */
graph = create_graph();
IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
hr = IFilterGraph2_RenderEx(graph, &source_pin.IPin_iface, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
ok(hr == VFW_E_CANNOT_RENDER, "Got hr %#x.\n", hr);
IFilterGraph2_AddFilter(graph, &sink1.IBaseFilter_iface, NULL);
hr = IFilterGraph2_RenderEx(graph, &source_pin.IPin_iface, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(source_pin.peer == &sink1_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
ref = IFilterGraph2_Release(graph);
ok(!ref, "Got outstanding refcount %d.\n", ref);
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink1_clsid);
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink2_clsid);
@ -2093,8 +2113,6 @@ out:
CoRevokeClassObject(cookie1);
CoRevokeClassObject(cookie2);
IFilterMapper2_Release(mapper);
ref = IFilterGraph2_Release(graph);
ok(!ref, "Got outstanding refcount %d.\n", ref);
ok(source.ref == 1, "Got outstanding refcount %d.\n", source.ref);
ok(source_pin.ref == 1, "Got outstanding refcount %d.\n", source_pin.ref);
ok(sink1.ref == 1, "Got outstanding refcount %d.\n", sink1.ref);