Nikolay Sivov : evr/presenter: Initial implementation of GetCurrentImage().
Alexandre Julliard
julliard at winehq.org
Tue Feb 1 15:21:35 CST 2022
Module: wine
Branch: master
Commit: 22fda5990ffc9b22258e914192d23fedf7d75dd7
URL: https://source.winehq.org/git/wine.git/?a=commit;h=22fda5990ffc9b22258e914192d23fedf7d75dd7
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue Feb 1 18:59:07 2022 +0300
evr/presenter: Initial implementation of GetCurrentImage().
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/evr/presenter.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 92 insertions(+), 2 deletions(-)
diff --git a/dlls/evr/presenter.c b/dlls/evr/presenter.c
index 910af2891e3..7e14cb2f720 100644
--- a/dlls/evr/presenter.c
+++ b/dlls/evr/presenter.c
@@ -65,6 +65,7 @@ struct sample_queue
unsigned int used;
unsigned int front;
unsigned int back;
+ IMFSample *last_presented;
};
struct streaming_thread
@@ -120,6 +121,7 @@ struct video_presenter
struct
{
int presented;
+ LONGLONG sampletime;
} frame_stats;
CRITICAL_SECTION cs;
@@ -507,6 +509,13 @@ static void video_presenter_sample_present(struct video_presenter *presenter, IM
IDirect3DSwapChain9_Present(presenter->swapchain, NULL, NULL, NULL, NULL, 0);
presenter->frame_stats.presented++;
+ EnterCriticalSection(&presenter->cs);
+ if (presenter->thread.queue.last_presented)
+ IMFSample_Release(presenter->thread.queue.last_presented);
+ presenter->thread.queue.last_presented = sample;
+ IMFSample_AddRef(presenter->thread.queue.last_presented);
+ LeaveCriticalSection(&presenter->cs);
+
IDirect3DDevice9_Release(device);
IDirect3DSurface9_Release(backbuffer);
IDirect3DSurface9_Release(surface);
@@ -739,6 +748,8 @@ static HRESULT video_presenter_end_streaming(struct video_presenter *presenter)
TRACE("Terminated streaming thread tid %#lx.\n", presenter->thread.tid);
+ if (presenter->thread.queue.last_presented)
+ IMFSample_Release(presenter->thread.queue.last_presented);
memset(&presenter->thread, 0, sizeof(presenter->thread));
video_presenter_set_allocator_callback(presenter, NULL);
@@ -1461,9 +1472,88 @@ static HRESULT WINAPI video_presenter_control_RepaintVideo(IMFVideoDisplayContro
static HRESULT WINAPI video_presenter_control_GetCurrentImage(IMFVideoDisplayControl *iface, BITMAPINFOHEADER *header,
BYTE **dib, DWORD *dib_size, LONGLONG *timestamp)
{
- FIXME("%p, %p, %p, %p, %p.\n", iface, header, dib, dib_size, timestamp);
+ struct video_presenter *presenter = impl_from_IMFVideoDisplayControl(iface);
+ IDirect3DSurface9 *readback = NULL, *surface;
+ D3DSURFACE_DESC surface_desc;
+ D3DLOCKED_RECT mapped_rect;
+ IDirect3DDevice9 *device;
+ IMFSample *sample;
+ LONG stride;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %p, %p, %p, %p.\n", iface, header, dib, dib_size, timestamp);
+
+ EnterCriticalSection(&presenter->cs);
+
+ sample = presenter->thread.queue.last_presented;
+ presenter->thread.queue.last_presented = NULL;
+
+ if (!presenter->swapchain || !sample)
+ {
+ hr = MF_E_INVALIDREQUEST;
+ }
+ else if (SUCCEEDED(hr = video_presenter_get_sample_surface(sample, &surface)))
+ {
+ IDirect3DSwapChain9_GetDevice(presenter->swapchain, &device);
+ IDirect3DSurface9_GetDesc(surface, &surface_desc);
+
+ if (surface_desc.Format != D3DFMT_X8R8G8B8)
+ {
+ FIXME("Unexpected surface format %d.\n", surface_desc.Format);
+ hr = E_FAIL;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (FAILED(hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, surface_desc.Width,
+ surface_desc.Height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &readback, NULL)))
+ {
+ WARN("Failed to create readback surface, hr %#lx.\n", hr);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ hr = IDirect3DDevice9_GetRenderTargetData(device, surface, readback);
+
+ if (SUCCEEDED(hr))
+ {
+ MFGetStrideForBitmapInfoHeader(D3DFMT_X8R8G8B8, surface_desc.Width, &stride);
+ *dib_size = abs(stride) * surface_desc.Height;
+ if (!(*dib = CoTaskMemAlloc(*dib_size)))
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(hr = IDirect3DSurface9_LockRect(readback, &mapped_rect, NULL, D3DLOCK_READONLY)))
+ {
+ memcpy(*dib, mapped_rect.pBits, *dib_size);
+ IDirect3DSurface9_UnlockRect(readback);
+ }
+ }
+
+ memset(header, 0, sizeof(*header));
+ header->biSize = sizeof(*header);
+ header->biWidth = surface_desc.Width;
+ header->biHeight = surface_desc.Height;
+ header->biPlanes = 1;
+ header->biBitCount = 32;
+ header->biSizeImage = *dib_size;
+ IMFSample_GetSampleTime(sample, timestamp);
+
+ if (readback)
+ IDirect3DSurface9_Release(readback);
+ IDirect3DSurface9_Release(surface);
+
+ IDirect3DDevice9_Release(device);
+ }
+
+ if (sample)
+ IMFSample_Release(sample);
+
+ LeaveCriticalSection(&presenter->cs);
+
+ return hr;
}
static HRESULT WINAPI video_presenter_control_SetBorderColor(IMFVideoDisplayControl *iface, COLORREF color)
More information about the wine-cvs
mailing list