Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v3: Retain the old code path for the VMR7. It's obviously wrong in some ways, but without tests it's not clear how the VMR7 does format type negotiation—it doesn't seem to be solely based on the subtype—and it's better to change the algorithm for one filter at a time.
dlls/quartz/tests/vmr9.c | 16 ++--- dlls/quartz/vmr9.c | 127 ++++++++++++++++++++++++++++----------- 2 files changed, 99 insertions(+), 44 deletions(-)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index 387f4f0a93e..352268dae5e 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -1388,17 +1388,13 @@ static void test_connect_pin(void) skip("Got E_FAIL when connecting.\n"); goto out; } - todo_wine_if (bpp_tests[j] == 24) - ok(hr == S_OK, "Got hr %#x for subtype %s and bpp %u.\n", hr, - wine_dbgstr_guid(subtype_tests[i]), bpp_tests[j]); + ok(hr == S_OK, "Got hr %#x for subtype %s and bpp %u.\n", hr, + wine_dbgstr_guid(subtype_tests[i]), bpp_tests[j]);
- if (hr == S_OK) - { - hr = IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface); - ok(hr == S_OK, "Got hr %#x.\n", hr); - hr = IFilterGraph2_Disconnect(graph, pin); - ok(hr == S_OK, "Got hr %#x.\n", hr); - } + hr = IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IFilterGraph2_Disconnect(graph, pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); } }
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c index d1110572303..35d625ddd7e 100644 --- a/dlls/quartz/vmr9.c +++ b/dlls/quartz/vmr9.c @@ -349,58 +349,117 @@ static HRESULT WINAPI VMR9_CheckMediaType(struct strmbase_renderer *iface, const return S_OK; }
-static HRESULT VMR9_maybe_init(struct quartz_vmr *This, BOOL force) +static HRESULT initialize_device(struct quartz_vmr *filter, VMR9AllocationInfo *info) { - VMR9AllocationInfo info; - DWORD buffers; + DWORD buffer_count = 2; HRESULT hr;
- TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow); - if (This->num_surfaces) + if (FAILED(hr = IVMRSurfaceAllocatorEx9_InitializeDevice(filter->allocator, + filter->cookie, info, &buffer_count))) + { + WARN("Failed to initialize device (flags %#x), hr %#x.\n", info->dwFlags, hr); + return hr; + } + + SetRect(&filter->source_rect, 0, 0, filter->bmiheader.biWidth, filter->bmiheader.biHeight); + filter->num_surfaces = buffer_count; + + return hr; +} + +static HRESULT VMR9_maybe_init(struct quartz_vmr *filter, BOOL force, const AM_MEDIA_TYPE *mt) +{ + VMR9AllocationInfo info = {}; + HRESULT hr = E_FAIL; + unsigned int i; + + static const struct + { + const GUID *subtype; + D3DFORMAT format; + DWORD flags; + } + formats[] = + { + {&MEDIASUBTYPE_ARGB1555, D3DFMT_A1R5G5B5, VMR9AllocFlag_TextureSurface}, + {&MEDIASUBTYPE_ARGB32, D3DFMT_A8R8G8B8, VMR9AllocFlag_TextureSurface}, + {&MEDIASUBTYPE_ARGB4444, D3DFMT_A4R4G4B4, VMR9AllocFlag_TextureSurface}, + + {&MEDIASUBTYPE_RGB24, D3DFMT_R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface}, + {&MEDIASUBTYPE_RGB32, D3DFMT_X8R8G8B8, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface}, + {&MEDIASUBTYPE_RGB555, D3DFMT_X1R5G5B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface}, + {&MEDIASUBTYPE_RGB565, D3DFMT_R5G6B5, VMR9AllocFlag_TextureSurface | VMR9AllocFlag_OffscreenSurface}, + + {&MEDIASUBTYPE_NV12, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface}, + {&MEDIASUBTYPE_UYVY, D3DFMT_UYVY, VMR9AllocFlag_OffscreenSurface}, + {&MEDIASUBTYPE_YUY2, D3DFMT_YUY2, VMR9AllocFlag_OffscreenSurface}, + {&MEDIASUBTYPE_YV12, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface}, + }; + + TRACE("Initializing in mode %u, our window %p, clipping window %p.\n", + filter->mode, filter->baseControlWindow.baseWindow.hWnd, filter->hWndClippingWindow); + if (filter->num_surfaces) return S_OK;
- if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow) + if (filter->mode == VMR9Mode_Windowless && !filter->hWndClippingWindow) return (force ? VFW_E_RUNTIME_ERROR : S_OK);
- TRACE("Initializing\n"); - info.dwFlags = VMR9AllocFlag_TextureSurface; - info.dwHeight = This->source_rect.bottom; - info.dwWidth = This->source_rect.right; + info.dwWidth = filter->source_rect.right; + info.dwHeight = filter->source_rect.bottom; info.Pool = D3DPOOL_DEFAULT; info.MinBuffers = 2; - FIXME("Reduce ratio to least common denominator\n"); info.szAspectRatio.cx = info.dwWidth; info.szAspectRatio.cy = info.dwHeight; - info.szNativeSize.cx = This->bmiheader.biWidth; - info.szNativeSize.cy = This->bmiheader.biHeight; - buffers = 2; + info.szNativeSize.cx = filter->bmiheader.biWidth; + info.szNativeSize.cy = filter->bmiheader.biHeight;
- switch (This->bmiheader.biBitCount) + filter->cur_surface = 0; + if (filter->num_surfaces) { - case 8: info.Format = D3DFMT_R3G3B2; break; - case 15: info.Format = D3DFMT_X1R5G5B5; break; - case 16: info.Format = D3DFMT_R5G6B5; break; - case 24: info.Format = D3DFMT_R8G8B8; break; - case 32: info.Format = D3DFMT_X8R8G8B8; break; - default: - FIXME("Unknown bpp %u\n", This->bmiheader.biBitCount); - hr = E_INVALIDARG; + ERR("num_surfaces or d3d9_surfaces not 0\n"); + return E_FAIL; }
- This->cur_surface = 0; - if (This->num_surfaces) + if (IsEqualGUID(&filter->renderer.filter.clsid, &CLSID_VideoMixingRenderer)) { - ERR("num_surfaces or d3d9_surfaces not 0\n"); - return E_FAIL; + switch (filter->bmiheader.biBitCount) + { + case 8: info.Format = D3DFMT_R3G3B2; break; + case 15: info.Format = D3DFMT_X1R5G5B5; break; + case 16: info.Format = D3DFMT_R5G6B5; break; + case 24: info.Format = D3DFMT_R8G8B8; break; + case 32: info.Format = D3DFMT_X8R8G8B8; break; + default: + FIXME("Unhandled bit depth %u.\n", filter->bmiheader.biBitCount); + return E_INVALIDARG; + } + + info.dwFlags = VMR9AllocFlag_TextureSurface; + return initialize_device(filter, &info); }
- hr = IVMRSurfaceAllocatorEx9_InitializeDevice(This->allocator, This->cookie, &info, &buffers); - if (SUCCEEDED(hr)) + for (i = 0; i < ARRAY_SIZE(formats); ++i) { - SetRect(&This->source_rect, 0, 0, This->bmiheader.biWidth, This->bmiheader.biHeight); + if (IsEqualGUID(&mt->subtype, formats[i].subtype)) + { + info.Format = formats[i].format; + + if (formats[i].flags & VMR9AllocFlag_TextureSurface) + { + info.dwFlags = VMR9AllocFlag_TextureSurface; + if (SUCCEEDED(hr = initialize_device(filter, &info))) + return hr; + }
- This->num_surfaces = buffers; + if (formats[i].flags & VMR9AllocFlag_OffscreenSurface) + { + info.dwFlags = VMR9AllocFlag_OffscreenSurface; + if (SUCCEEDED(hr = initialize_device(filter, &info))) + return hr; + } + } } + return hr; }
@@ -411,7 +470,7 @@ static void vmr_start_stream(struct strmbase_renderer *iface) TRACE("(%p)\n", This);
if (This->renderer.sink.pin.peer) - VMR9_maybe_init(This, TRUE); + VMR9_maybe_init(This, TRUE, &This->renderer.sink.pin.mt); IVMRImagePresenter9_StartPresenting(This->presenter, This->cookie); SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, This->source_rect.left, @@ -470,7 +529,7 @@ static HRESULT vmr_connect(struct strmbase_renderer *iface, const AM_MEDIA_TYPE
if (filter->mode || SUCCEEDED(hr = IVMRFilterConfig9_SetRenderingMode(&filter->IVMRFilterConfig9_iface, VMR9Mode_Windowed))) - hr = VMR9_maybe_init(filter, FALSE); + hr = VMR9_maybe_init(filter, FALSE, mt);
return hr; } @@ -1772,7 +1831,7 @@ static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowles EnterCriticalSection(&This->renderer.filter.csFilter); This->hWndClippingWindow = hwnd; if (This->renderer.sink.pin.peer) - VMR9_maybe_init(This, FALSE); + VMR9_maybe_init(This, FALSE, &This->renderer.sink.pin.mt); if (!hwnd) IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie); LeaveCriticalSection(&This->renderer.filter.csFilter);