Signed-off-by: Zebediah Figura z.figura12@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;