[PATCH 1/6] quartz/vmr9: Merge VMR9_SendSampleData() into VMR9_DoRenderSample().

Zebediah Figura z.figura12 at gmail.com
Fri Jun 19 19:50:12 CDT 2020


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
videoconvert seems to be faster at converting YUV -> YUV than YUV -> RGB, which
makes sense.

This patch set, as well as following patch sets, aim to improve the speed of
video post-processing in the quartz pipeline. Particularly large video samples
can take long enough to process that not only will the video play back slowly,
but (depending on demuxer) the audio will get "stuck behind" it and stutter.

 dlls/quartz/vmr9.c | 155 ++++++++++++++++++++++-----------------------
 1 file changed, 76 insertions(+), 79 deletions(-)

diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index 6b653e56092..f81d8067059 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -207,89 +207,41 @@ static inline struct quartz_vmr *impl_from_IBaseFilter(IBaseFilter *iface)
     return CONTAINING_RECORD(iface, struct quartz_vmr, renderer.filter.IBaseFilter_iface);
 }
 
-static DWORD VMR9_SendSampleData(struct quartz_vmr *This, VMR9PresentationInfo *info, LPBYTE data,
-                                 DWORD size)
+static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMediaSample *sample)
 {
-    const BITMAPINFOHEADER *bmiHeader = get_bitmap_header(&This->renderer.sink.pin.mt);
-    HRESULT hr = S_OK;
-    int width;
-    int height;
-    D3DLOCKED_RECT lock;
-
-    TRACE("%p %p %d\n", This, data, size);
-
-    width = bmiHeader->biWidth;
-    height = bmiHeader->biHeight;
-
-    hr = IDirect3DSurface9_LockRect(info->lpSurf, &lock, NULL, D3DLOCK_DISCARD);
-    if (FAILED(hr))
-    {
-        ERR("IDirect3DSurface9_LockRect failed (%x)\n",hr);
-        return hr;
-    }
-
-    if (height > 0) {
-        /* Bottom up image needs inverting */
-        lock.pBits = (char *)lock.pBits + (height * lock.Pitch);
-        while (height--)
-        {
-            lock.pBits = (char *)lock.pBits - lock.Pitch;
-            memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
-            data = data + width * bmiHeader->biBitCount / 8;
-        }
-    }
-    else if (lock.Pitch != width * bmiHeader->biBitCount / 8)
-    {
-        WARN("Slow path! %u/%u\n", lock.Pitch, width * bmiHeader->biBitCount/8);
-
-        while (height--)
-        {
-            memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8);
-            data = data + width * bmiHeader->biBitCount / 8;
-            lock.pBits = (char *)lock.pBits + lock.Pitch;
-        }
-    }
-    else memcpy(lock.pBits, data, size);
-
-    IDirect3DSurface9_UnlockRect(info->lpSurf);
-
-    hr = IVMRImagePresenter9_PresentImage(This->presenter, This->cookie, info);
-    return hr;
-}
-
-static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMediaSample *pSample)
-{
-    struct quartz_vmr *This = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
-    const HANDLE events[2] = {This->run_event, This->renderer.flush_event};
+    struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface);
+    const HANDLE events[2] = {filter->run_event, filter->renderer.flush_event};
+    const BITMAPINFOHEADER *bitmap_header;
+    unsigned int data_size, width, depth;
+    REFERENCE_TIME start_time, end_time;
     VMR9PresentationInfo info = {};
-    LPBYTE pbSrcStream = NULL;
-    long cbSrcStream = 0;
-    REFERENCE_TIME tStart, tStop;
+    D3DLOCKED_RECT locked_rect;
+    BYTE *data = NULL;
     HRESULT hr;
+    int height;
 
-    TRACE("%p %p\n", iface, pSample);
+    TRACE("filter %p, sample %p.\n", filter, sample);
 
     /* It is possible that there is no device at this point */
 
-    if (!This->allocator || !This->presenter)
+    if (!filter->allocator || !filter->presenter)
     {
         ERR("NO PRESENTER!!\n");
         return S_FALSE;
     }
 
-    hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
-    if (FAILED(hr))
-        info.dwFlags = VMR9Sample_SrcDstRectsValid;
-    else
-        info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid;
+    info.dwFlags = VMR9Sample_SrcDstRectsValid;
 
-    if (IMediaSample_IsDiscontinuity(pSample) == S_OK)
+    if (SUCCEEDED(hr = IMediaSample_GetTime(sample, &start_time, &end_time)))
+        info.dwFlags |= VMR9Sample_TimeValid;
+
+    if (IMediaSample_IsDiscontinuity(sample) == S_OK)
         info.dwFlags |= VMR9Sample_Discontinuity;
 
-    if (IMediaSample_IsPreroll(pSample) == S_OK)
+    if (IMediaSample_IsPreroll(sample) == S_OK)
         info.dwFlags |= VMR9Sample_Preroll;
 
-    if (IMediaSample_IsSyncPoint(pSample) == S_OK)
+    if (IMediaSample_IsSyncPoint(sample) == S_OK)
         info.dwFlags |= VMR9Sample_SyncPoint;
 
     /* If we render ourselves, and this is a preroll sample, discard it */
@@ -298,28 +250,73 @@ static HRESULT WINAPI VMR9_DoRenderSample(struct strmbase_renderer *iface, IMedi
         return S_OK;
     }
 
-    hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
-    if (FAILED(hr))
+    if (FAILED(hr = IMediaSample_GetPointer(sample, &data)))
     {
-        ERR("Cannot get pointer to sample data (%x)\n", hr);
+        ERR("Failed to get pointer to sample data, hr %#x.\n", hr);
         return hr;
     }
+    data_size = IMediaSample_GetActualDataLength(sample);
 
-    cbSrcStream = IMediaSample_GetActualDataLength(pSample);
+    bitmap_header = get_bitmap_header(&filter->renderer.sink.pin.mt);
+    width = bitmap_header->biWidth;
+    height = bitmap_header->biHeight;
+    depth = bitmap_header->biBitCount;
 
-    info.rtStart = tStart;
-    info.rtEnd = tStop;
-    info.szAspectRatio.cx = This->bmiheader.biWidth;
-    info.szAspectRatio.cy = This->bmiheader.biHeight;
-    info.lpSurf = This->surfaces[(++This->cur_surface) % This->num_surfaces];
+    info.rtStart = start_time;
+    info.rtEnd = end_time;
+    info.szAspectRatio.cx = width;
+    info.szAspectRatio.cy = height;
+    info.lpSurf = filter->surfaces[(++filter->cur_surface) % filter->num_surfaces];
 
-    VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream);
+    if (FAILED(hr = IDirect3DSurface9_LockRect(info.lpSurf, &locked_rect, NULL, D3DLOCK_DISCARD)))
+    {
+        ERR("Failed to lock surface, hr %#x.\n", hr);
+        return hr;
+    }
 
-    if (This->renderer.filter.state == State_Paused)
+    if (height > 0)
+    {
+        BYTE *dst = (BYTE *)locked_rect.pBits + (height * locked_rect.Pitch);
+        const BYTE *src = data;
+
+        TRACE("Inverting image.\n");
+
+        while (height--)
+        {
+            dst -= locked_rect.Pitch;
+            memcpy(dst, src, width * depth / 8);
+            src += width * depth / 8;
+        }
+    }
+    else if (locked_rect.Pitch != width * depth / 8)
     {
-        LeaveCriticalSection(&This->renderer.csRenderLock);
+        BYTE *dst = locked_rect.pBits;
+        const BYTE *src = data;
+
+        TRACE("Source pitch %u does not match dest pitch %u; copying manually.\n",
+                width * depth / 8, locked_rect.Pitch);
+
+        while (height--)
+        {
+            memcpy(dst, src, width * depth / 8);
+            src += width * depth / 8;
+            dst += locked_rect.Pitch;
+        }
+    }
+    else
+    {
+        memcpy(locked_rect.pBits, data, data_size);
+    }
+
+    IDirect3DSurface9_UnlockRect(info.lpSurf);
+
+    hr = IVMRImagePresenter9_PresentImage(filter->presenter, filter->cookie, &info);
+
+    if (filter->renderer.filter.state == State_Paused)
+    {
+        LeaveCriticalSection(&filter->renderer.csRenderLock);
         WaitForMultipleObjects(2, events, FALSE, INFINITE);
-        EnterCriticalSection(&This->renderer.csRenderLock);
+        EnterCriticalSection(&filter->renderer.csRenderLock);
     }
 
     return hr;
-- 
2.27.0




More information about the wine-devel mailing list