From: Francisco Casas franciscojacb@gmail.com
Before this patch, surface data for planar formats is not copied correctly when the application uses a custom allocator-presenter and allocates a surface of different size than the VMR9 source.
This patch adds support for performing this copy corrently when the source dimensions are less or equal than the rendering surface dimensions. --- dlls/quartz/vmr9.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c index 270277f0196..a195a684579 100644 --- a/dlls/quartz/vmr9.c +++ b/dlls/quartz/vmr9.c @@ -181,6 +181,25 @@ 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(BYTE **dstp, unsigned int dst_pitch, unsigned int dst_height, + const BYTE **srcp, unsigned int src_pitch, unsigned int src_height) +{ + const BYTE *src = *srcp; + BYTE *dst = *dstp; + unsigned int i; + + for (i = 0; i < src_height; ++i) + { + memcpy(dst, src, src_pitch); + dst += dst_pitch; + src += src_pitch; + } + dst += (dst_height - src_height) * dst_height; + + *srcp = src; + *dstp = dst; +} + static HRESULT vmr_render(struct strmbase_renderer *iface, IMediaSample *sample) { struct quartz_vmr *filter = impl_from_IBaseFilter(&iface->filter.IBaseFilter_iface); @@ -257,7 +276,24 @@ 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 *dst = locked_rect.pBits; + const BYTE *src = data; + + copy_plane(&dst, locked_rect.Pitch, dst_desc.Height, &src, src_pitch, height); + copy_plane(&dst, locked_rect.Pitch, dst_desc.Height/2, &src, src_pitch, height/2); + } + else if (bitmap_header->biCompression == mmioFOURCC('Y','V','1','2')) + { + BYTE *dst = locked_rect.pBits; + const BYTE *src = data; + + copy_plane(&dst, locked_rect.Pitch, dst_desc.Height, &src, src_pitch, height); + copy_plane(&dst, locked_rect.Pitch/2, dst_desc.Height/2, &src, src_pitch/2, height/2); + copy_plane(&dst, locked_rect.Pitch/2, dst_desc.Height/2, &src, src_pitch/2, height/2); + } + else if (height > 0 && bitmap_header->biCompression == BI_RGB) { BYTE *dst = (BYTE *)locked_rect.pBits + (height * locked_rect.Pitch); const BYTE *src = data;