[PATCH xf86-video-vmware] vmwgfx: Fix YV12 video corruption issue
Matt Turner
mattst88 at gmail.com
Fri Feb 25 21:51:07 UTC 2022
On Sun, Mar 28, 2021 at 10:57 AM Doug Brown <doug at schmorgal.com> wrote:
>
> This fixes an issue I discovered with YV12 video that isn't a multiple
> of 8 pixels in width (after the round up to an even width value). Due to
> extra padding because the pitch doesn't match the width, the wrong data
> gets copied into the buffer.
>
> Example GStreamer command demonstrating the issue:
> gst-launch-1.0 videotestsrc ! \
> video/x-raw,format=YV12,width=782,height=482 ! xvimagesink
>
> Working width values:
> 775, 776, 783, 784
> Broken widths prior to this patch:
> 777-782
>
> Signed-off-by: Doug Brown <doug at schmorgal.com>
> ---
> To test the change to vmwgfx_overlay.c, use a VMware VM with 3D
> acceleration turned off. To test the change to vmwgfx_tex_video.c, use a
> VMware VM with 3D acceleration turned on, or a VirtualBox VM with VMSVGA
> graphics and 3D acceleration turned on.
>
> I'm concerned that the fix in vmwgfx_overlay.c feels kind of dirty. The
> pitches array is getting passed onto the kernel driver, which I believe
> passes it onto the virtual hardware. I feel like it should be the
> responsibility of the virtual hardware to interpret the data correctly
> given that it is aware of the difference between width and pitch. But it
> doesn't seem to be paying attention to it. Is there somewhere else where
> the patch for that should go instead? Perhaps I should change the
> pitches array being sent out so it matches the data I send?
>
> vmwgfx/vmwgfx_overlay.c | 34 +++++++++++++++++++++++++++++++++-
> vmwgfx/vmwgfx_tex_video.c | 19 +++++++++++++++----
> 2 files changed, 48 insertions(+), 5 deletions(-)
>
> diff --git a/vmwgfx/vmwgfx_overlay.c b/vmwgfx/vmwgfx_overlay.c
> index 94d738c..e02c6fa 100644
> --- a/vmwgfx/vmwgfx_overlay.c
> +++ b/vmwgfx/vmwgfx_overlay.c
> @@ -478,7 +478,39 @@ vmw_video_port_play(ScrnInfoPtr pScrn, struct vmwgfx_overlay_port *port,
> clipBoxes, pDraw);
> }
>
> - memcpy(port->bufs[port->currBuf].data, buf, port->size);
> + switch (format) {
> + case FOURCC_YV12: {
> + unsigned char *ystart, *vstart, *ustart;
> + unsigned char *yp, *up, *vp;
> + int yidx, uidx, vidx;
> + int i, j;
> + yidx = uidx = vidx = 0;
> + ystart = port->bufs[port->currBuf].data;
> + vstart = ystart + w*h;
> + ustart = vstart + w*h/4;
> + yp = buf + port->offsets[0];
> + vp = buf + port->offsets[1];
> + up = buf + port->offsets[2];
> + for (i = 0; i < h; ++i) {
> + for (j = 0; j < w; ++j) {
> + ystart[yidx++] = yp[j];
> + }
> + yp += port->pitches[0];
> + if (i % 2 == 0) {
> + for (j = 0; j < w>>1; ++j) {
> + vstart[vidx++] = vp[j];
> + ustart[uidx++] = up[j];
> + }
> + vp += port->pitches[1];
> + up += port->pitches[2];
> + }
> + }
> + break;
> + }
> + default:
> + memcpy(port->bufs[port->currBuf].data, buf, port->size);
> + break;
> + }
>
> memset(&arg, 0, sizeof(arg));
>
> diff --git a/vmwgfx/vmwgfx_tex_video.c b/vmwgfx/vmwgfx_tex_video.c
> index acc2b56..0c79220 100644
> --- a/vmwgfx/vmwgfx_tex_video.c
> +++ b/vmwgfx/vmwgfx_tex_video.c
> @@ -603,7 +603,7 @@ copy_packed_data(ScrnInfoPtr pScrn,
> int top,
> unsigned short w, unsigned short h)
> {
> - int i;
> + int i, j;
> struct xa_surface **yuv = port->yuv[port->current_set];
> char *ymap, *vmap, *umap;
> unsigned char _y1, _y2, u, v;
> @@ -634,9 +634,20 @@ copy_packed_data(ScrnInfoPtr pScrn,
> yp = buf + offsets[0];
> vp = buf + offsets[1];
> up = buf + offsets[2];
> - memcpy(ymap, yp, w*h);
> - memcpy(vmap, vp, w*h/4);
> - memcpy(umap, up, w*h/4);
> + for (i = 0; i < h; ++i) {
> + for (j = 0; j < w; ++j) {
> + ymap[yidx++] = yp[j];
> + }
> + yp += pitches[0];
> + if (i % 2 == 0) {
> + for (j = 0; j < w>>1; ++j) {
> + vmap[vidx++] = vp[j];
> + umap[uidx++] = up[j];
> + }
> + vp += pitches[1];
> + up += pitches[2];
> + }
> + }
> break;
> }
> case FOURCC_UYVY:
> --
FWIW, we finally got them to allow merge requests on gitlab. If you
wouldn't mind and are still interested, please try making a merge
request at https://gitlab.freedesktop.org/xorg/driver/xf86-video-vmware
More information about the xorg-devel
mailing list