Diff
Modified: trunk/LayoutTests/ChangeLog (278275 => 278276)
--- trunk/LayoutTests/ChangeLog 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/LayoutTests/ChangeLog 2021-05-31 13:33:16 UTC (rev 278276)
@@ -1,3 +1,18 @@
+2021-05-31 Miguel Gomez <mago...@igalia.com>
+
+ [GStreamer] Incorrect rendering of VP9 with transparency
+ https://bugs.webkit.org/show_bug.cgi?id=225961
+
+ Reviewed by Žan Doberšek.
+
+ Add a test for the playback of transparent videos. This is initially skipped because it's not supported
+ on Apple ports and won't be working on GTK and WPE until GStreamer is bumped to 1.20.
+
+ * TestExpectations:
+ * media/content/video-with-alpha.webm: Added.
+ * media/video-with-alpha-expected.html: Added.
+ * media/video-with-alpha.html: Added.
+
2021-05-31 Rob Buis <rb...@igalia.com>
Release assert in RenderFlexibleBox::computeInnerFlexBaseSizeForChild via RenderFlexibleBox::layoutFlexItems
Modified: trunk/LayoutTests/TestExpectations (278275 => 278276)
--- trunk/LayoutTests/TestExpectations 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/LayoutTests/TestExpectations 2021-05-31 13:33:16 UTC (rev 278276)
@@ -1034,6 +1034,9 @@
# Tests a setting behind the ENABLE_FULLSCREEN_API flag, which is WK2-only
media/video-supports-fullscreen.html [ Skip ]
+# Support for VP9 encoded videos with transparency is only available on ports that use GStreamer.
+media/video-with-alpha.html [ Skip ]
+
#//////////////////////////////////////////////////////////////////////////////////////////
# End platform-specific tests.
#//////////////////////////////////////////////////////////////////////////////////////////
Added: trunk/LayoutTests/media/content/video-with-alpha.webm (0 => 278276)
--- trunk/LayoutTests/media/content/video-with-alpha.webm (rev 0)
+++ trunk/LayoutTests/media/content/video-with-alpha.webm 2021-05-31 13:33:16 UTC (rev 278276)
@@ -0,0 +1,3 @@
+Eߣ\x9FB\x86\x81B\xF7\x81B\xF2\x81B\xF3\x81B\x82\x84webmB\x87\x81B\x85\x81S\x80g?M\x9Bt\xBAM\xBB\x8BS\xAB\x84I\xA9fS\xAC\x81\xA1M\xBB\x8BS\xAB\x84T\xAEkS\xAC\x81\xD8M\xBB\x8CS\xAB\x84T\xC3gS\xAC\x82#M\xBB\x8CS\xAB\x84S\xBBkS\xAC\x82)\xECYI\xA9f\xB2*ױ\x83B@M\x80\x8DLavf58.45.100WA\x8DLavf58.45.100D\x89\x88@\xA2\xC0T\xAEkƮ=ׁsň,\xAC\xB5\x8CX\xFB\x9C\x81"\xB5\x9C\x83und\x86\x85V_VP9\x83\x81#ツbZ\xE0
+\xB0\x81Ⱥ\x81\xC8S\xC0\x81T\xC3g@\x9Dss'c\xC0\x80g\xC8E\xA3\x87ENCODERD\x87\x8DLavf58.45.100ssbc\xC0\x8Bcň,\xAC\xB5\x8CX\xFBg\xC8%E\xA3\x87ENCODERD\x87\x98Lavc58.91.100 libvpx-vp9gȢE\xA3\x88DURATIOND\x87\x9400:00:02.400000000C\xB6uS]\xE7\x81\xA0k\xA1\xAA\x81\x82I\x83Bpv8$JPa\xF60g\x9A\x84\x9D\xDCU2S\xC3\xFCI$u\xA15\xA6,\xEE\x81\xA5\xA7\x82I\x83Bpv8$
+Pa\xF60g/\xDF{ȝ\xDCU2S\xC3\xFCI$\xA0I\xA1\x98\x81(\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81P\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81x\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xA0\x86@\x92\x9CM@ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CC@ Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xC8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA
5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xF0\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6
\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81@\x86@\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81h\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x90\x86\xC0\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86\xC0\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xB8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"
\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xE0\x86@\x92\x9CM@ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\
xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CC@ Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x810\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81X\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x80\x86@\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xA8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x8
1\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xD0\x86@\x92\x9CN\xE0 Y\
xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xF8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81 \x86\xC0\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86\xC0\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81H\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81p\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x98\x86@\x92\x9CP
Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81
\xC0\x86@\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xE8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x818\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81`\x86@\x92\x9CM@ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CC@ Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81
\x88\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\x
A0I\xA1\x98\x81\xB0\x86\xC0\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86\xC0\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xD8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x86@\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81(\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81P\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x
8D\x90\xA0I\xA1\x98\x81x\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE
Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xA0\x86@\x92\x9CM@ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CC@ Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xC8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xF0\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81@\x86\xC0\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86\xC0\x
92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81h\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\
x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x90\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xB8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xE0\x86@\x92\x9CM@ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CC@ Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x810\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6
\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81X\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1
"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x80\x86@\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xA8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xD0\x86\xC0\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86\xC0\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xF8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81 \x86@\x92\x9CM@ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u
\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CC@ Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81H\x86@\x92\x9CP Y\xEB\xA3Ώ
\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81p\x86@\x92\x9CN\xE0 Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\x98\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xC0\x86@\x92\x9CJ Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CB Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81\xE8\x86@\x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81 \x86@\x92\x9CN\xE0 Y\x
EB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CD Y\xEB\xA3Ώ\x8D\x90\xA0I\xA1\x98\x81 8\x86@\
x92\x9CP Y\xEB\xA3Ώ\x8D\x90\xFB\x81\xD8u\xA1"\xA6\xEE\x81\xA5\x94\x86@\x92\x9CE Y\xEB\xA3Ώ\x8D\x90S\xBBk\x91\xBB\x8F\xB3\x81\xB7\x8A\xF7\x81\xF1\x82\xC6\xF0\x81
\ No newline at end of file
Added: trunk/LayoutTests/media/video-with-alpha-expected.html (0 => 278276)
--- trunk/LayoutTests/media/video-with-alpha-expected.html (rev 0)
+++ trunk/LayoutTests/media/video-with-alpha-expected.html 2021-05-31 13:33:16 UTC (rev 278276)
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>video-with-alpha</title>
+ <style>
+ body {
+ background: white;
+ }
+
+ #spacer {
+ position: absolute;
+ left: 200px;
+ top: 0px;
+ width: 200px;
+ height: 200px;
+ background-color: red;
+ }
+ </style>
+ </head>
+<body>
+ <div id="spacer"></div>
+</body>
+</html>
\ No newline at end of file
Added: trunk/LayoutTests/media/video-with-alpha.html (0 => 278276)
--- trunk/LayoutTests/media/video-with-alpha.html (rev 0)
+++ trunk/LayoutTests/media/video-with-alpha.html 2021-05-31 13:33:16 UTC (rev 278276)
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>video-with-alpha</title>
+ <style>
+ body {
+ background: white;
+ }
+
+ #video {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ }
+ #spacer {
+ position: absolute;
+ left: 200px;
+ top: 0px;
+ background-color: red;
+ }
+ #canvas {
+ position: absolute;
+ left: 400px;
+ top: 0px;
+ }
+ </style>
+ <script src=""
+ <script>
+ // Put a video element to the left, a spacer in the middle and a canvas to the right. The video element will
+ // play a transparent video, and a video frame will be copied into the canvas.
+ // As the video and the canvas are invisible, to visually check that the video element is really playing something,
+ // set the size of the spacer to the size of the video frames (200x200).
+
+ var requirePixelDump = true;
+
+ function seeked() {
+ let canvas = document.getElementById("canvas");
+ context = canvas.getContext("2d");
+ context.drawImage(video, 0, 0);
+ if (window.testRunner)
+ setTimeout("testRunner.notifyDone()", 0);
+ }
+
+ function buffered() {
+ video.width = video.videoWidth;
+ video.height = video.videoHeight;
+
+ let spacer = document.getElementById("spacer");
+ spacer.style.width = video.width + "px";
+ spacer.style.height = video.height + "px";
+
+ canvas.width = video.width;
+ canvas.height = video.height;
+
+ video.currentTime = .5;
+ }
+
+ function start() {
+ findMediaElement();
+ video.src = ""
+ video.addEventListener("seeked", seeked);
+ video.addEventListener("canplaythrough", buffered, false);
+ }
+ </script>
+ <script src=""
+</head>
+
+<body _onload_="start()">
+ <video id="video"></video>
+ <div id="spacer"></div>
+ <canvas id="canvas"></canvas>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (278275 => 278276)
--- trunk/Source/WebCore/ChangeLog 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/ChangeLog 2021-05-31 13:33:16 UTC (rev 278276)
@@ -1,3 +1,44 @@
+2021-05-31 Miguel Gomez <mago...@igalia.com>
+
+ [GStreamer] Incorrect rendering of VP9 with transparency
+ https://bugs.webkit.org/show_bug.cgi?id=225961
+
+ Reviewed by Žan Doberšek.
+
+ Fix the rendering of videos with transparency. This is done both AC and non AC modes and
+ with and without GSTREAMER_GL enabled.
+
+ On AC mode and using GSTREAMER_GL, a new option is added to TextureMapperGL and TextureMapperShaderProgram
+ to support premultiplying the components of a pixel. This is required because GStreamer uses straight alpha,
+ and we need it premultiplied in order to perform the correct blending blending of the video frames. Then we
+ use that new option to render video frames. This new option is also used when copying the video frame into
+ an external texture if premultiplyAlpha is requested.
+
+ On non AC mode, or when GStreamer-gl is disabled, add support to ImageGStreamerCairo to premultiply the alpha
+ of the video frame before creating the cairo surface to paint, and pass the appropriate composite operator when
+ drawing with alpha.
+
+ Test: media/video-with-alpha.html
+
+ * platform/graphics/gstreamer/GStreamerVideoFrameHolder.cpp:
+ (WebCore::GstVideoFrameHolder::GstVideoFrameHolder):
+ * platform/graphics/gstreamer/ImageGStreamerCairo.cpp:
+ (WebCore::ImageGStreamer::ImageGStreamer):
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+ (WebCore::MediaPlayerPrivateGStreamer::pushTextureToCompositor):
+ (WebCore::MediaPlayerPrivateGStreamer::paint): update the caps of the conversion to make them match the format
+ expected by cairo, so we can avoid a component swap.
+ (WebCore::MediaPlayerPrivateGStreamer::copyVideoTextureToPlatformTexture):
+ * platform/graphics/gstreamer/VideoTextureCopierGStreamer.cpp:
+ (WebCore::VideoTextureCopierGStreamer::copyVideoTextureToPlatformTexture):
+ * platform/graphics/gstreamer/VideoTextureCopierGStreamer.h:
+ * platform/graphics/texmap/TextureMapperGL.cpp:
+ (WebCore::TextureMapperGL::drawTexture):
+ * platform/graphics/texmap/TextureMapperGL.h:
+ * platform/graphics/texmap/TextureMapperShaderProgram.cpp:
+ (WebCore::TextureMapperShaderProgram::create):
+ * platform/graphics/texmap/TextureMapperShaderProgram.h:
+
2021-05-31 Rob Buis <rb...@igalia.com>
Treat width: intrinsic as non definite
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerVideoFrameHolder.cpp (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerVideoFrameHolder.cpp 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerVideoFrameHolder.cpp 2021-05-31 13:33:16 UTC (rev 278276)
@@ -46,7 +46,7 @@
return;
#if USE(GSTREAMER_GL)
- m_flags = flags | (m_hasAlphaChannel ? TextureMapperGL::ShouldBlend : 0);
+ m_flags = flags | (m_hasAlphaChannel ? TextureMapperGL::ShouldBlend | TextureMapperGL::ShouldPremultiply : 0);
GstMemory* memory = gst_buffer_peek_memory(m_buffer.get(), 0);
if (gst_is_gl_memory(memory))
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp 2021-05-31 13:33:16 UTC (rev 278276)
@@ -39,11 +39,9 @@
if (!gst_video_info_from_caps(&videoInfo, caps))
return;
- // Right now the TextureMapper only supports chromas with one plane
- ASSERT(GST_VIDEO_INFO_N_PLANES(&videoInfo) == 1);
+ // The frame has to RGB so we can paint it.
+ ASSERT(GST_VIDEO_INFO_IS_RGB(&videoInfo));
- m_hasAlpha = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo);
-
GstBuffer* buffer = gst_sample_get_buffer(sample);
if (UNLIKELY(!GST_IS_BUFFER(buffer)))
return;
@@ -52,50 +50,109 @@
if (!m_frameMapped)
return;
+ // The video buffer may have these formats in these cases:
+ // { BGRx, BGRA }: on little endian:
+ // - When GStreamer-gl is disabled (being AC enabled or not) as VideoSinkGStreamer is used.
+ // - When GStreamer-gl is enabled, but the caps used in the sink are not RGB and it's converted by the player to paint it.
+ // { xRGB, ARGB }: on big endian:
+ // - When GStreamer-gl is disabled (being AC enabled or not) as VideoSinkGStreamer is used.
+ // - When GStreamer-gl is enabled, but the caps used in the sink are not RGB and it's converted by the player to paint it.
+ // { RGBx, RGBA }
+ // - When GStreamer-gl is enabled and the caps used in the sink are RGBx/RGBA.
+ //
+ // Internally cairo uses BGRA for CAIRO_FORMAT_ARGB32 on little endian and ARGB on big endian, so both { BGRx, BGRA }
+ // and { xRGB, ARGB } can be passed directly to cairo. But for { RGBx, RGBA } we need to swap the R and B components.
+ // Also, GStreamer uses straight alpha while cairo requires it to be premultiplied, so if the format has alpha
+ // we need to premultiply the color components. So in these cases we need to create a modified copy of the original
+ // buffer.
+ m_hasAlpha = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo);
+ bool componentSwapRequired = GST_VIDEO_FRAME_FORMAT(&m_videoFrame) == GST_VIDEO_FORMAT_RGBA || GST_VIDEO_FRAME_FORMAT(&m_videoFrame) == GST_VIDEO_FORMAT_RGBx;
unsigned char* bufferData = reinterpret_cast<unsigned char*>(GST_VIDEO_FRAME_PLANE_DATA(&m_videoFrame, 0));
int stride = GST_VIDEO_FRAME_PLANE_STRIDE(&m_videoFrame, 0);
int width = GST_VIDEO_FRAME_WIDTH(&m_videoFrame);
int height = GST_VIDEO_FRAME_HEIGHT(&m_videoFrame);
-
RefPtr<cairo_surface_t> surface;
- cairo_format_t cairoFormat;
- cairoFormat = (GST_VIDEO_FRAME_FORMAT(&m_videoFrame) == GST_VIDEO_FORMAT_RGBA) ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
- // GStreamer doesn't use premultiplied alpha, but cairo does. So if the video format has an alpha component
- // we need to premultiply it before passing the data to cairo. This needs to be both using gstreamer-gl and not
- // using it.
- //
- // This method could be called several times for the same buffer, for example if we are rendering the video frames
- // in several non accelerated canvases. Due to this, we cannot modify the buffer, so we need to create a copy.
- if (cairoFormat == CAIRO_FORMAT_ARGB32) {
- unsigned char* surfaceData = static_cast<unsigned char*>(fastMalloc(height * stride));
- unsigned char* surfacePixel = surfaceData;
+ if (m_hasAlpha || componentSwapRequired) {
+ uint8_t* surfaceData = static_cast<uint8_t*>(fastMalloc(height * stride));
+ uint8_t* surfacePixel = surfaceData;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
- unsigned short alpha = bufferData[3];
+ // These store the source pixel components.
+ uint16_t red;
+ uint16_t green;
+ uint16_t blue;
+ uint16_t alpha;
+ // These store the component offset inside the pixel for the destination surface.
+ uint8_t redIndex;
+ uint8_t greenIndex;
+ uint8_t blueIndex;
+ uint8_t alphaIndex;
+ if (componentSwapRequired) {
+ // Source is RGBA or RGBx.
+ red = bufferData[0];
+ green = bufferData[1];
+ blue = bufferData[2];
+ alpha = bufferData[3];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- // Video frames use RGBA in little endian.
- surfacePixel[0] = (bufferData[2] * alpha + 128) / 255;
- surfacePixel[1] = (bufferData[1] * alpha + 128) / 255;
- surfacePixel[2] = (bufferData[0] * alpha + 128) / 255;
- surfacePixel[3] = alpha;
+ // Destination is BGRA.
+ redIndex = 2;
+ greenIndex = 1;
+ blueIndex = 0;
+ alphaIndex = 3;
#else
- // Video frames use RGBA in big endian.
- surfacePixel[0] = alpha;
- surfacePixel[1] = (bufferData[0] * alpha + 128) / 255;
- surfacePixel[2] = (bufferData[1] * alpha + 128) / 255;
- surfacePixel[3] = (bufferData[2] * alpha + 128) / 255;
+ // Destination is ARGB.
+ redIndex = 1;
+ greenIndex = 2;
+ blueIndex = 3;
+ alphaIndex = 0;
#endif
+ } else {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ // BGRA or BGRx both source and destination.
+ red = bufferData[2];
+ green = bufferData[1];
+ blue = bufferData[0];
+ alpha = bufferData[3];
+ redIndex = 2;
+ greenIndex = 1;
+ blueIndex = 0;
+ alphaIndex = 3;
+#else
+ // ARGB ot xRGB both source and destination.
+ red = bufferData[1];
+ green = bufferData[2];
+ blue = bufferData[3];
+ alpha = bufferData[0];
+ redIndex = 1;
+ greenIndex = 2;
+ blueIndex = 3;
+ alphaIndex = 0;
+#endif
+ }
+
+ if (m_hasAlpha) {
+ surfacePixel[redIndex] = red * alpha / 255;
+ surfacePixel[greenIndex] = green * alpha / 255;
+ surfacePixel[blueIndex] = blue * alpha / 255;
+ surfacePixel[alphaIndex] = alpha;
+ } else {
+ surfacePixel[redIndex] = red;
+ surfacePixel[greenIndex] = green;
+ surfacePixel[blueIndex] = blue;
+ surfacePixel[alphaIndex] = alpha;
+ }
+
bufferData += 4;
surfacePixel += 4;
}
}
- surface = adoptRef(cairo_image_surface_create_for_data(surfaceData, cairoFormat, width, height, stride));
+ surface = adoptRef(cairo_image_surface_create_for_data(surfaceData, CAIRO_FORMAT_ARGB32, width, height, stride));
static cairo_user_data_key_t s_surfaceDataKey;
cairo_surface_set_user_data(surface.get(), &s_surfaceDataKey, surfaceData, [](void* data) { fastFree(data); });
} else
- surface = adoptRef(cairo_image_surface_create_for_data(bufferData, cairoFormat, width, height, stride));
+ surface = adoptRef(cairo_image_surface_create_for_data(bufferData, CAIRO_FORMAT_ARGB32, width, height, stride));
ASSERT(cairo_surface_status(surface.get()) == CAIRO_STATUS_SUCCESS);
m_image = BitmapImage::create(WTFMove(surface));
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp 2021-05-31 13:33:16 UTC (rev 278276)
@@ -2946,7 +2946,7 @@
layerBuffer = makeUnique<TextureMapperPlatformLayerBuffer>(WTFMove(texture));
}
frameHolder->updateTexture(layerBuffer->textureGL());
- layerBuffer->setExtraFlags(m_textureMapperFlags | (frameHolder->hasAlphaChannel() ? TextureMapperGL::ShouldBlend : 0));
+ layerBuffer->setExtraFlags(m_textureMapperFlags | (frameHolder->hasAlphaChannel() ? TextureMapperGL::ShouldBlend | TextureMapperGL::ShouldPremultiply : 0));
}
proxy.pushNextBuffer(WTFMove(layerBuffer));
};
@@ -3298,10 +3298,13 @@
if (!m_colorConvertInputCaps || !gst_caps_is_equal(m_colorConvertInputCaps.get(), caps)) {
m_colorConvertInputCaps = caps;
m_colorConvertOutputCaps = adoptGRef(gst_caps_copy(caps));
+
+ // These caps must match the internal format of a cairo surface with CAIRO_FORMAT_ARGB32,
+ // so we don't need to perform color conversions when painting the video frame.
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- const char* formatString = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? "RGBA" : "BGRx";
+ const char* formatString = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? "BGRA" : "BGRx";
#else
- const char* formatString = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? "RGBA" : "RGBx";
+ const char* formatString = GST_VIDEO_INFO_HAS_ALPHA(&videoInfo) ? "ARGB" : "xRGB";
#endif
gst_caps_set_simple(m_colorConvertOutputCaps.get(), "format", G_TYPE_STRING, formatString,
"texture-target", G_TYPE_STRING, GST_GL_TEXTURE_TARGET_2D_STR, nullptr);
@@ -3323,7 +3326,7 @@
if (!gstImage)
return;
- context.drawImage(gstImage->image(), rect, gstImage->rect(), { CompositeOperator::Copy, m_shouldHandleOrientationTags ? m_videoSourceOrientation : ImageOrientation() });
+ context.drawImage(gstImage->image(), rect, gstImage->rect(), { gstImage->hasAlpha() ? CompositeOperator::SourceOver : CompositeOperator::Copy, m_shouldHandleOrientationTags ? m_videoSourceOrientation : ImageOrientation() });
}
#if USE(GSTREAMER_GL)
@@ -3334,9 +3337,6 @@
if (m_isUsingFallbackVideoSink)
return false;
- if (premultiplyAlpha)
- return false;
-
Locker sampleLocker { m_sampleMutex };
if (!GST_IS_SAMPLE(m_sample.get()))
@@ -3357,7 +3357,7 @@
frameHolder->waitForCPUSync();
- return m_videoTextureCopier->copyVideoTextureToPlatformTexture(*layerBuffer.get(), size, outputTexture, outputTarget, level, internalFormat, format, type, flipY, m_videoSourceOrientation);
+ return m_videoTextureCopier->copyVideoTextureToPlatformTexture(*layerBuffer.get(), size, outputTexture, outputTarget, level, internalFormat, format, type, flipY, m_videoSourceOrientation, premultiplyAlpha);
}
RefPtr<NativeImage> MediaPlayerPrivateGStreamer::nativeImageForCurrentTime()
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/VideoTextureCopierGStreamer.cpp (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/gstreamer/VideoTextureCopierGStreamer.cpp 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/VideoTextureCopierGStreamer.cpp 2021-05-31 13:33:16 UTC (rev 278276)
@@ -136,7 +136,7 @@
-1, 1, -(farValue + nearValue) / (farValue - nearValue), 1);
}
-bool VideoTextureCopierGStreamer::copyVideoTextureToPlatformTexture(TextureMapperPlatformLayerBuffer& inputTexture, IntSize& frameSize, GLuint outputTexture, GLenum outputTarget, GLint level, GLenum internalFormat, GLenum format, GLenum type, bool flipY, ImageOrientation sourceOrientation)
+bool VideoTextureCopierGStreamer::copyVideoTextureToPlatformTexture(TextureMapperPlatformLayerBuffer& inputTexture, IntSize& frameSize, GLuint outputTexture, GLenum outputTarget, GLint level, GLenum internalFormat, GLenum format, GLenum type, bool flipY, ImageOrientation sourceOrientation, bool premultiplyAlpha)
{
if (!m_framebuffer || !m_vbo || frameSize.isEmpty())
return false;
@@ -161,7 +161,7 @@
using Buffer = TextureMapperPlatformLayerBuffer;
TextureMapperShaderProgram::Options options;
WTF::switchOn(inputTexture.textureVariant(),
- [&](const Buffer::RGBTexture&) { options = TextureMapperShaderProgram::TextureRGB; },
+ [&](const Buffer::RGBTexture&) { options = TextureMapperShaderProgram::TextureRGB | (premultiplyAlpha ? TextureMapperShaderProgram::Premultiply : 0); },
[&](const Buffer::YUVTexture& texture) {
switch (texture.numberOfPlanes) {
case 1:
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/VideoTextureCopierGStreamer.h (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/gstreamer/VideoTextureCopierGStreamer.h 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/VideoTextureCopierGStreamer.h 2021-05-31 13:33:16 UTC (rev 278276)
@@ -45,7 +45,7 @@
VideoTextureCopierGStreamer(ColorConversion);
~VideoTextureCopierGStreamer();
- bool copyVideoTextureToPlatformTexture(TextureMapperPlatformLayerBuffer& inputTexture, IntSize& frameSize, GLuint outputTexture, GLenum outputTarget, GLint level, GLenum internalFormat, GLenum format, GLenum type, bool flipY, ImageOrientation sourceOrientation);
+ bool copyVideoTextureToPlatformTexture(TextureMapperPlatformLayerBuffer& inputTexture, IntSize& frameSize, GLuint outputTexture, GLenum outputTarget, GLint level, GLenum internalFormat, GLenum format, GLenum type, bool flipY, ImageOrientation sourceOrientation, bool premultiplyAlpha);
void updateColorConversionMatrix(ColorConversion);
void updateTextureSpaceMatrix();
void updateTransformationMatrix();
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp 2021-05-31 13:33:16 UTC (rev 278276)
@@ -504,6 +504,9 @@
flags |= ShouldBlend;
}
+ if (flags & ShouldPremultiply)
+ options |= TextureMapperShaderProgram::Premultiply;
+
Ref<TextureMapperShaderProgram> program = data().getShaderProgram(options);
if (filter)
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h 2021-05-31 13:33:16 UTC (rev 278276)
@@ -57,7 +57,8 @@
ShouldConvertTextureBGRAToRGBA = 0x80,
ShouldConvertTextureARGBToRGBA = 0x100,
ShouldNotBlend = 0x200,
- ShouldUseExternalOESTextureRect = 0x400
+ ShouldUseExternalOESTextureRect = 0x400,
+ ShouldPremultiply = 0x800
};
typedef int Flags;
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.cpp 2021-05-31 13:33:16 UTC (rev 278276)
@@ -264,6 +264,8 @@
void applyTextureRGB(inout vec4 color, vec2 texCoord) { color = u_textureColorSpaceMatrix * SamplerFunction(s_sampler, texCoord); }
+ void applyPremultiply(inout vec4 color) { color = vec4(color.rgb * color.a, color.a); }
+
vec3 yuvToRgb(float y, float u, float v)
{
// yuv is either bt601 or bt709 so the offset is the same
@@ -483,6 +485,7 @@
vec2 texCoord = transformTexCoord();
applyManualRepeatIfNeeded(texCoord);
applyTextureRGBIfNeeded(color, texCoord);
+ applyPremultiplyIfNeeded(color);
applyTextureYUVIfNeeded(color, texCoord);
applyTextureNV12IfNeeded(color, texCoord);
applyTextureNV21IfNeeded(color, texCoord);
@@ -537,6 +540,7 @@
SET_APPLIER_FROM_OPTIONS(ManualRepeat);
SET_APPLIER_FROM_OPTIONS(TextureExternalOES);
SET_APPLIER_FROM_OPTIONS(RoundedRectClip);
+ SET_APPLIER_FROM_OPTIONS(Premultiply);
StringBuilder vertexShaderBuilder;
Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h (278275 => 278276)
--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h 2021-05-31 09:22:14 UTC (rev 278275)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderProgram.h 2021-05-31 13:33:16 UTC (rev 278276)
@@ -103,6 +103,7 @@
TexturePackedYUV = 1L << 21,
TextureExternalOES = 1L << 22,
RoundedRectClip = 1L << 23,
+ Premultiply = 1L << 24,
};
enum class VariableID {