xpra icon
Bug tracker and wiki

Opened 4 years ago

Closed 3 years ago

Last modified 3 years ago

#487 closed defect (fixed)

webp artifacts with transparency

Reported by: Antoine Martin Owned by: alas
Priority: critical Milestone: 0.13
Component: client Version:
Keywords: Cc:

Description (last modified by Antoine Martin)

Split from ticket:385#comment:20

This affects all platforms, with or without opengl rendering. See screenshot:
/raw-attachment/ticket/487/webp-transparency-artifacts.png

Probably a regression since I must have tested transparency when it was added to webp, but 0.10.x is also affected.

Attachments (2)

webp-transparency-artifacts.png (22.6 KB) - added by Antoine Martin 4 years ago.
shows the artifacts on transparent windows when using webp
argb-clamp.patch (937 bytes) - added by Antoine Martin 3 years ago.
clamp rgb values when unpremultiplying to prevent overflow

Download all attachments as: .zip

Change History (17)

Changed 4 years ago by Antoine Martin

shows the artifacts on transparent windows when using webp

comment:1 Changed 4 years ago by Antoine Martin

Description: modified (diff)
Owner: changed from Antoine Martin to Antoine Martin
Status: newassigned

comment:2 Changed 4 years ago by Antoine Martin

Transparency support was added in r3522, and works ok as I expected.
r3884, r4245 and r5091 don't change any of the actual encoder code, so the problem must come from somewhere else..

Bisecting:

So the problem comes from r4151, likely to be in the argb code, I tested byteswapping on RGB components, but maybe it's the (un)premultiply codepath..

comment:3 Changed 4 years ago by Antoine Martin

Milestone: 0.120.11

This is a regression, needs to be in 0.11

Taking out the line:

return byte_buffer_to_buffer(unpremultiply_argb(img_data))

And returning the data as it is instead (premultiplied), the picture looks OK (albeit, with too much in the alpha channel)

What I don't understand is why this affects webp and not the other encodings, which also use the same codepath!? (ie: png via PIL also gives us a string buffer)

comment:4 Changed 4 years ago by Antoine Martin

Milestone: 0.110.12

Since webp is buggy and not going to be used by default (and maybe we should even disable it?), re-scheduling this ticket until after #491

comment:5 Changed 4 years ago by Antoine Martin

Milestone: 0.120.13

re-scheduling all webp stuff

comment:6 Changed 3 years ago by Antoine Martin

The problem: webp's simple API returns unpremultiplied alpha, which is not what we want and when we unpremultiply it again, it goes out of range... not sure about Pillow (the version in Fedora 20 does not seem to be able to decode webp..)

So, we have to:

  • use the advanced API preferably, adding a decoder to the new webp codec module, so we can get unpremultiplied alpha just like with the other encodings
  • add a flag to the webm (and Pillow?) decoded picture options (which will still be used as fallback), so the window backings will know it is unpremultiplied already... some backigns will skip the unpremultiply step, and the opengl case will re-premultiply it!
  • remove webp from the list of encodings when using opengl without the advanced api decoder

Note: the corruption is not directly visible with the opengl backing because we now use the premultiplied alpha directly during rendering (it may just end up oversaturated instead)

Last edited 3 years ago by Antoine Martin (previous) (diff)

comment:7 Changed 3 years ago by Antoine Martin

And... to make matters worse, webp decides if the picture has an alpha channel not using any API flags, but by inspecting the alpha component of every pixel in the input and deciding that if any values are not 0xFF then it is on.. WTH? And whose bright idea was this?

Changed 3 years ago by Antoine Martin

Attachment: argb-clamp.patch added

clamp rgb values when unpremultiplying to prevent overflow

comment:8 Changed 3 years ago by Antoine Martin

Implemented a new "advanced API" webp decoder in r6509:

  • added opengl support for painting from buffer type in r6508
  • use this decoder ahead of the others (python-webm and Pillow)

I'm not going to bother fixing the codepath for the other decoders (I have not tested to see if Pillow uses premultiplied alpha or not), you will just get the wrong transparency levels with those. (and eventually, maybe we should just drop them)

comment:9 Changed 3 years ago by Antoine Martin

r5510 clears out the alpha channel before calling the webp Encode function, not very efficient but it works.

comment:10 Changed 3 years ago by Antoine Martin

Ready for testing. Related to #419.

afarr: please check that webp works as primary encoding:

  • that the transparency is as it should be: using the transparent_colors.py test script (transparency is only supported on Linux clients and must be compared with running native on Linux without xpra - beware, the bug is a fairly subtle difference)
  • that it works with: opengl on and off without any errors in the logs, with different settings for quality settings
  • that the win32 builds show in Encoding_Info.exe: dec_webp and enc_webp at {{0.4.0}}}
  • that the webp data we receive on the client does not contain any alpha when we don't want any: run the client with -d webp and you should see webp decompress found features: ... has_alpha=0 (has_alpha=1 when alpha is present)
    • when the window does not have any alpha channel (most windows do not)
    • when running on platforms that do not support alpha (win32)
  • that it works reasonably well, without too many slowdowns (it isn't going to be as fast as h264..), even at fairly high resolution (the code should switch to more suitable encodings rather than crawl to a halt - see #419 for details)

Important note: because of #419, the actual encoding used for each region of pixels we send may end up being different from the one we specify. The only way to verify what encoding is used is to turn on compression debugging with -d compress on the server and to manually verify what comes out.

Note: I am not applying the attachment/ticket/487/argb-clamp.patch because it would actually hide any overflow, and we want to see it and fix it instead.

comment:11 Changed 3 years ago by Antoine Martin

Owner: changed from Antoine Martin to alas
Status: assignednew

(re-assign)

comment:12 Changed 3 years ago by J. Max Mena

Tested with Windows 7 - 64 bit, Windows 8.1 - 32 bit, and Fedora 20 - 64 bit:

  • Tested transparent_colors.py local and through xpra with and without opengl, both looked identical (xpra and locally running), as far as I could tell
  • win32 and win64 both show dec_webp and enc_webp as 0.4.0
  • With and without opengl works as expected on both Windows and Fedora - no errors are outputted, only webp compress/decompress messages
  • Fedora 20 client shows alpha=1 when using the transparent_colors.py
  • Win7 client shows aplha=0 when using the transparent_colors.py

Of note, using both Windows and Fedora clients, running a high definition youtube video full screen with webp causes the framerate to slow down to a crawl. Otherwise, everything worked as expected.

Last edited 3 years ago by J. Max Mena (previous) (diff)

comment:13 Changed 3 years ago by Antoine Martin

Thanks for testing, this reminds me of just how slow webp can be (see #419): it falls off a cliff in lossless mode, especially at low speed and at high resolutions (1080p and up). So I'll run some more tests tomorrow to ensure that we never use it as a temporary non-video encoding with those problematic combinations of options (this should already be the case, but best to triple check).

What was the resolution you tested at when fullscreen? 1080p? If so, unless you have other options set, it should have switched to high speed which should still be faster than png. Having xpra info of when it is really slow may help me figure things out.

comment:14 Changed 3 years ago by Antoine Martin

Resolution: fixed
Status: newclosed

Re-tested some more today, and made some more tweaks (r6528, r6534, r6535), fixes (r6529, r6531) and improvements to the test code (r6530, r6532, r6533).

Closing.

comment:15 Changed 3 years ago by Antoine Martin

Note: in 0.14, the old python-webm is completely removed in favor of the new webp advanced codec, see r6555.

Note: See TracTickets for help on using tickets.