Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/quartz/vmr9.c | 60 +++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 25 deletions(-)
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c index 2562b74932a..546af3d2a39 100644 --- a/dlls/quartz/vmr9.c +++ b/dlls/quartz/vmr9.c @@ -206,6 +206,37 @@ static inline struct quartz_vmr *impl_from_IBaseFilter(IBaseFilter *iface) return CONTAINING_RECORD(iface, struct quartz_vmr, renderer.filter.IBaseFilter_iface); }
+static void copy_plane(int height, int row_size, int src_pitch, int dst_pitch, BYTE *src, BYTE *dst) +{ + BYTE *row_src; + BYTE *row_dst; + int row; + + if (src_pitch >= 0) + { + if (src_pitch == dst_pitch) + { + memcpy(dst, src, src_pitch * height); + return; + } + TRACE("Source pitch %d does not match dest pitch %d; copying manually.\n", + src_pitch, dst_pitch); + } + else + { + TRACE("Inverting image.\n"); + } + + row_src = src; + row_dst = dst; + for (row = 0; row < height; ++row) + { + memcpy(row_dst, row_src, row_size); + row_src += src_pitch; + row_dst += dst_pitch; + } +} + static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) { struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface); @@ -273,34 +304,13 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample)
if (height > 0 && bitmap_header->biCompression == BI_RGB) { - 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 += src_pitch; - } + copy_plane(height, width * depth / 8, -(int)src_pitch, locked_rect.Pitch, + data + src_pitch * (height - 1), locked_rect.pBits); } else if (locked_rect.Pitch != src_pitch) { - BYTE *dst = locked_rect.pBits; - const BYTE *src = data; - - height = abs(height); - - TRACE("Source pitch %u does not match dest pitch %u; copying manually.\n", - src_pitch, locked_rect.Pitch); - - while (height--) - { - memcpy(dst, src, width * depth / 8); - src += src_pitch; - dst += locked_rect.Pitch; - } + copy_plane(abs(height), width * depth / 8, src_pitch, locked_rect.Pitch, + data, locked_rect.pBits); } else {
DirectShow has stricter chroma plane alignment requirements than D3D. Fixes crash when playing back some videos with non-multiple-of-8 width.
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/quartz/vmr9.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c index 546af3d2a39..ed1cc6b729c 100644 --- a/dlls/quartz/vmr9.c +++ b/dlls/quartz/vmr9.c @@ -302,7 +302,25 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) return hr; }
- if (height > 0 && bitmap_header->biCompression == BI_RGB) + if (bitmap_header->biCompression == mmioFOURCC('N','V','1','2')) + { + BYTE *chroma_src = data + src_pitch * ((height + 1) & ~1); + BYTE *chroma_dst = (BYTE *)locked_rect.pBits + locked_rect.Pitch * height; + copy_plane(height, width, src_pitch, locked_rect.Pitch, data, locked_rect.pBits); + copy_plane(height / 2, width, src_pitch, locked_rect.Pitch, chroma_src, chroma_dst); + } + else if (bitmap_header->biCompression == mmioFOURCC('Y','V','1','2')) + { + int chroma_src_pitch = ((width + 1) / 2 + 3) & ~3; + BYTE *v_src = data + src_pitch * ((height + 1) & ~1); + BYTE *v_dst = (BYTE *)locked_rect.pBits + locked_rect.Pitch * height; + BYTE *u_src = v_src + chroma_src_pitch * ((height + 1) / 2); + BYTE *u_dst = v_dst + locked_rect.Pitch / 2 * (height / 2); + copy_plane(height, width, src_pitch, locked_rect.Pitch, data, locked_rect.pBits); + copy_plane(height / 2, width / 2, chroma_src_pitch, locked_rect.Pitch / 2, v_src, v_dst); + copy_plane(height / 2, width / 2, chroma_src_pitch, locked_rect.Pitch / 2, u_src, u_dst); + } + else if (height > 0 && bitmap_header->biCompression == BI_RGB) { copy_plane(height, width * depth / 8, -(int)src_pitch, locked_rect.Pitch, data + src_pitch * (height - 1), locked_rect.pBits);
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/quartz/vmr9.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c index ed1cc6b729c..09160e53337 100644 --- a/dlls/quartz/vmr9.c +++ b/dlls/quartz/vmr9.c @@ -240,8 +240,8 @@ static void copy_plane(int height, int row_size, int src_pitch, int dst_pitch, B static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) { struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface); - unsigned int data_size, width, depth, src_pitch; const BITMAPINFOHEADER *bitmap_header; + unsigned int width, depth, src_pitch; REFERENCE_TIME start_time, end_time; VMR9PresentationInfo info = {}; D3DLOCKED_RECT locked_rect; @@ -278,7 +278,6 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) ERR("Failed to get pointer to sample data, hr %#x.\n", hr); return hr; } - data_size = IMediaSample_GetActualDataLength(sample);
bitmap_header = get_bitmap_header(&filter->renderer.sink.pin.mt); width = bitmap_header->biWidth; @@ -325,15 +324,11 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) copy_plane(height, width * depth / 8, -(int)src_pitch, locked_rect.Pitch, data + src_pitch * (height - 1), locked_rect.pBits); } - else if (locked_rect.Pitch != src_pitch) + else { copy_plane(abs(height), width * depth / 8, src_pitch, locked_rect.Pitch, data, locked_rect.pBits); } - else - { - memcpy(locked_rect.pBits, data, data_size); - }
IDirect3DSurface9_UnlockRect(info.lpSurf);
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/quartz/vmr9.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c index 09160e53337..6eabd73d78c 100644 --- a/dlls/quartz/vmr9.c +++ b/dlls/quartz/vmr9.c @@ -285,7 +285,7 @@ static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) depth = bitmap_header->biBitCount; if (bitmap_header->biCompression == mmioFOURCC('N','V','1','2') || bitmap_header->biCompression == mmioFOURCC('Y','V','1','2')) - src_pitch = width; + src_pitch = (width + 3) & ~3; else /* packed YUV (UYVY or YUY2) or RGB */ src_pitch = ((width * depth / 8) + 3) & ~3;