summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/web_platform/util.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/web_platform/util.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/webgpu/web_platform/util.ts430
1 files changed, 336 insertions, 94 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/web_platform/util.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/web_platform/util.ts
index 84ac6b31d1..56514b2203 100644
--- a/dom/webgpu/tests/cts/checkout/src/webgpu/web_platform/util.ts
+++ b/dom/webgpu/tests/cts/checkout/src/webgpu/web_platform/util.ts
@@ -1,9 +1,10 @@
import { Fixture, SkipTestCase } from '../../common/framework/fixture.js';
import { getResourcePath } from '../../common/framework/resources.js';
-import { makeTable } from '../../common/util/data_tables.js';
+import { keysOf } from '../../common/util/data_tables.js';
import { timeout } from '../../common/util/timeout.js';
import { ErrorWithExtra, raceWithRejectOnTimeout } from '../../common/util/util.js';
import { GPUTest } from '../gpu_test.js';
+import { RGBA, srgbToDisplayP3 } from '../util/color_space_conversion.js';
declare global {
interface HTMLMediaElement {
@@ -13,113 +14,342 @@ declare global {
}
}
-export const kVideoInfo =
- /* prettier-ignore */ makeTable(
- ['mimeType' ] as const,
- [undefined ] as const, {
- // All video names
- 'four-colors-vp8-bt601.webm': ['video/webm; codecs=vp8' ],
- 'four-colors-theora-bt601.ogv': ['video/ogg; codecs=theora' ],
- 'four-colors-h264-bt601.mp4': ['video/mp4; codecs=avc1.4d400c'],
- 'four-colors-vp9-bt601.webm': ['video/webm; codecs=vp9' ],
- 'four-colors-vp9-bt709.webm': ['video/webm; codecs=vp9' ],
- 'four-colors-vp9-bt2020.webm': ['video/webm; codecs=vp9' ],
- 'four-colors-h264-bt601-rotate-90.mp4': ['video/mp4; codecs=avc1.4d400c'],
- 'four-colors-h264-bt601-rotate-180.mp4': ['video/mp4; codecs=avc1.4d400c'],
- 'four-colors-h264-bt601-rotate-270.mp4': ['video/mp4; codecs=avc1.4d400c'],
- } as const);
-export type VideoName = keyof typeof kVideoInfo;
+// MAINTENANCE_TODO: Uses raw floats as expectation in external_texture related cases has some diffs.
+// Remove this conversion utils and uses raw float data as expectation in external_textrue
+// related cases when resolve this.
+export function convertToUnorm8(expectation: Readonly<RGBA>): Uint8Array {
+ const rgba8Unorm = new Uint8ClampedArray(4);
+ rgba8Unorm[0] = Math.round(expectation.R * 255.0);
+ rgba8Unorm[1] = Math.round(expectation.G * 255.0);
+ rgba8Unorm[2] = Math.round(expectation.B * 255.0);
+ rgba8Unorm[3] = Math.round(expectation.A * 255.0);
+ return new Uint8Array(rgba8Unorm.buffer);
+}
+
+// MAINTENANCE_TODO: Add helper function for BT.601 and BT.709 to remove all magic numbers.
// Expectation values about converting video contents to sRGB color space.
// Source video color space affects expected values.
// The process to calculate these expected pixel values can be found:
// https://github.com/gpuweb/cts/pull/2242#issuecomment-1430382811
// and https://github.com/gpuweb/cts/pull/2242#issuecomment-1463273434
const kBt601PixelValue = {
- red: new Float32Array([0.972945567233341, 0.141794376683341, -0.0209589916711088, 1.0]),
- green: new Float32Array([0.248234279433399, 0.984810378661784, -0.0564701319494314, 1.0]),
- blue: new Float32Array([0.10159735826538, 0.135451122863674, 1.00262982899724, 1.0]),
- yellow: new Float32Array([0.995470750775951, 0.992742114518355, -0.0774291236205402, 1.0]),
-};
-
-function convertToUnorm8(expectation: Float32Array): Uint8Array {
- const unorm8 = new Uint8ClampedArray(expectation.length);
+ srgb: {
+ red: { R: 0.972945567233341, G: 0.141794376683341, B: -0.0209589916711088, A: 1.0 },
+ green: { R: 0.248234279433399, G: 0.984810378661784, B: -0.0564701319494314, A: 1.0 },
+ blue: { R: 0.10159735826538, G: 0.135451122863674, B: 1.00262982899724, A: 1.0 },
+ yellow: { R: 0.995470750775951, G: 0.992742114518355, B: -0.0701036235167653, A: 1.0 },
+ },
+} as const;
- for (let i = 0; i < expectation.length; ++i) {
- unorm8[i] = Math.round(expectation[i] * 255.0);
- }
+const kBt709PixelValue = {
+ srgb: {
+ red: { R: 1.0, G: 0.0, B: 0.0, A: 1.0 },
+ green: { R: 0.0, G: 1.0, B: 0.0, A: 1.0 },
+ blue: { R: 0.0, G: 0.0, B: 1.0, A: 1.0 },
+ yellow: { R: 1.0, G: 1.0, B: 0.0, A: 1.0 },
+ },
+} as const;
- return new Uint8Array(unorm8.buffer);
+function makeTable<Table extends { readonly [K: string]: {} }>({
+ table,
+}: {
+ table: Table;
+}): {
+ readonly [F in keyof Table]: {
+ readonly [K in keyof Table[F]]: Table[F][K];
+ };
+} {
+ return Object.fromEntries(
+ Object.entries(table).map(([k, row]) => [k, { ...row }])
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ ) as any;
}
-// kVideoExpectations uses unorm8 results
-const kBt601Red = convertToUnorm8(kBt601PixelValue.red);
-const kBt601Green = convertToUnorm8(kBt601PixelValue.green);
-const kBt601Blue = convertToUnorm8(kBt601PixelValue.blue);
-const kBt601Yellow = convertToUnorm8(kBt601PixelValue.yellow);
-
-export const kVideoExpectations = [
- {
- videoName: 'four-colors-vp8-bt601.webm',
- _redExpectation: kBt601Red,
- _greenExpectation: kBt601Green,
- _blueExpectation: kBt601Blue,
- _yellowExpectation: kBt601Yellow,
- },
- {
- videoName: 'four-colors-theora-bt601.ogv',
- _redExpectation: kBt601Red,
- _greenExpectation: kBt601Green,
- _blueExpectation: kBt601Blue,
- _yellowExpectation: kBt601Yellow,
- },
- {
- videoName: 'four-colors-h264-bt601.mp4',
- _redExpectation: kBt601Red,
- _greenExpectation: kBt601Green,
- _blueExpectation: kBt601Blue,
- _yellowExpectation: kBt601Yellow,
+// Video expected pixel value table. Finding expected pixel value
+// with video color space and dst color space.
+export const kVideoExpectedColors = makeTable({
+ table: {
+ bt601: {
+ 'display-p3': {
+ yellow: srgbToDisplayP3(kBt601PixelValue.srgb.yellow),
+ red: srgbToDisplayP3(kBt601PixelValue.srgb.red),
+ blue: srgbToDisplayP3(kBt601PixelValue.srgb.blue),
+ green: srgbToDisplayP3(kBt601PixelValue.srgb.green),
+ },
+ srgb: {
+ yellow: kBt601PixelValue.srgb.yellow,
+ red: kBt601PixelValue.srgb.red,
+ blue: kBt601PixelValue.srgb.blue,
+ green: kBt601PixelValue.srgb.green,
+ },
+ },
+ bt709: {
+ 'display-p3': {
+ yellow: srgbToDisplayP3(kBt709PixelValue.srgb.yellow),
+ red: srgbToDisplayP3(kBt709PixelValue.srgb.red),
+ blue: srgbToDisplayP3(kBt709PixelValue.srgb.blue),
+ green: srgbToDisplayP3(kBt709PixelValue.srgb.green),
+ },
+ srgb: {
+ yellow: kBt709PixelValue.srgb.yellow,
+ red: kBt709PixelValue.srgb.red,
+ blue: kBt709PixelValue.srgb.blue,
+ green: kBt709PixelValue.srgb.green,
+ },
+ },
},
- {
- videoName: 'four-colors-vp9-bt601.webm',
- _redExpectation: kBt601Red,
- _greenExpectation: kBt601Green,
- _blueExpectation: kBt601Blue,
- _yellowExpectation: kBt601Yellow,
- },
- {
- videoName: 'four-colors-vp9-bt709.webm',
- _redExpectation: new Uint8Array([255, 0, 0, 255]),
- _greenExpectation: new Uint8Array([0, 255, 0, 255]),
- _blueExpectation: new Uint8Array([0, 0, 255, 255]),
- _yellowExpectation: new Uint8Array([255, 255, 0, 255]),
- },
-] as const;
+} as const);
-export const kVideoRotationExpectations = [
- {
- videoName: 'four-colors-h264-bt601-rotate-90.mp4',
- _topLeftExpectation: kBt601Red,
- _topRightExpectation: kBt601Green,
- _bottomLeftExpectation: kBt601Yellow,
- _bottomRightExpectation: kBt601Blue,
- },
- {
- videoName: 'four-colors-h264-bt601-rotate-180.mp4',
- _topLeftExpectation: kBt601Green,
- _topRightExpectation: kBt601Blue,
- _bottomLeftExpectation: kBt601Red,
- _bottomRightExpectation: kBt601Yellow,
- },
- {
- videoName: 'four-colors-h264-bt601-rotate-270.mp4',
- _topLeftExpectation: kBt601Blue,
- _topRightExpectation: kBt601Yellow,
- _bottomLeftExpectation: kBt601Green,
- _bottomRightExpectation: kBt601Red,
+// MAINTENANCE_TODO: Add BT.2020 video in table.
+// Video container and codec defines several transform ops to apply to raw decoded frame to display.
+// Our test cases covers 'visible rect' and 'rotation'.
+// 'visible rect' is associated with the
+// video bitstream and should apply to the raw decoded frames before any transformation.
+// 'rotation' is associated with the track or presentation and should transform
+// the whole visible rect (e.g. 90-degree rotate makes visible rect of vertical video to horizontal)
+// The order to apply these transformations is below:
+
+// [raw decoded frame] ----visible rect clipping ---->[visible frame] ---rotation ---> present
+// ^ ^
+// | |
+// coded size display size
+// The table holds test videos meta infos, including mimeType to check browser compatibility
+// video color space, raw frame content layout and the frame displayed layout.
+export const kVideoInfo = makeTable({
+ table: {
+ 'four-colors-vp8-bt601.webm': {
+ mimeType: 'video/webm; codecs=vp8',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-h264-bt601.mp4': {
+ mimeType: 'video/mp4; codecs=avc1.4d400c',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-vp9-bt601.webm': {
+ mimeType: 'video/webm; codecs=vp9',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-vp9-bt709.webm': {
+ mimeType: 'video/webm; codecs=vp9',
+ colorSpace: 'bt709',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ // video coded content has been rotate
+ 'four-colors-h264-bt601-rotate-90.mp4': {
+ mimeType: 'video/mp4; codecs=avc1.4d400c',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'red',
+ topRightColor: 'green',
+ bottomLeftColor: 'yellow',
+ bottomRightColor: 'blue',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-h264-bt601-rotate-180.mp4': {
+ mimeType: 'video/mp4; codecs=avc1.4d400c',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'green',
+ topRightColor: 'blue',
+ bottomLeftColor: 'red',
+ bottomRightColor: 'yellow',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-h264-bt601-rotate-270.mp4': {
+ mimeType: 'video/mp4; codecs=avc1.4d400c',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'blue',
+ topRightColor: 'yellow',
+ bottomLeftColor: 'green',
+ bottomRightColor: 'red',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-vp9-bt601-rotate-90.mp4': {
+ mimeType: 'video/mp4; codecs=vp09.00.10.08',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'red',
+ topRightColor: 'green',
+ bottomLeftColor: 'yellow',
+ bottomRightColor: 'blue',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-vp9-bt601-rotate-180.mp4': {
+ mimeType: 'video/mp4; codecs=vp09.00.10.08',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'green',
+ topRightColor: 'blue',
+ bottomLeftColor: 'red',
+ bottomRightColor: 'yellow',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-vp9-bt601-rotate-270.mp4': {
+ mimeType: 'video/mp4; codecs=vp09.00.10.08',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'blue',
+ topRightColor: 'yellow',
+ bottomLeftColor: 'green',
+ bottomRightColor: 'red',
+ },
+ display: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ },
+ 'four-colors-h264-bt601-hflip.mp4': {
+ mimeType: 'video/mp4; codecs=avc1.4d400c',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'red',
+ topRightColor: 'yellow',
+ bottomLeftColor: 'green',
+ bottomRightColor: 'blue',
+ },
+ },
+ 'four-colors-h264-bt601-vflip.mp4': {
+ mimeType: 'video/mp4; codecs=avc1.4d400c',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'blue',
+ topRightColor: 'green',
+ bottomLeftColor: 'yellow',
+ bottomRightColor: 'red',
+ },
+ },
+ 'four-colors-vp9-bt601-hflip.mp4': {
+ mimeType: 'video/mp4; codecs=vp09.00.10.08',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'red',
+ topRightColor: 'yellow',
+ bottomLeftColor: 'green',
+ bottomRightColor: 'blue',
+ },
+ },
+ 'four-colors-vp9-bt601-vflip.mp4': {
+ mimeType: 'video/mp4; codecs=vp09.00.10.08',
+ colorSpace: 'bt601',
+ coded: {
+ topLeftColor: 'yellow',
+ topRightColor: 'red',
+ bottomLeftColor: 'blue',
+ bottomRightColor: 'green',
+ },
+ display: {
+ topLeftColor: 'blue',
+ topRightColor: 'green',
+ bottomLeftColor: 'yellow',
+ bottomRightColor: 'red',
+ },
+ },
},
-] as const;
+} as const);
+type VideoName = keyof typeof kVideoInfo;
+export const kVideoNames: readonly VideoName[] = keysOf(kVideoInfo);
+
+export const kPredefinedColorSpace = ['display-p3', 'srgb'] as const;
/**
* Starts playing a video and waits for it to be consumable.
* Returns a promise which resolves after `callback` (which may be async) completes.
@@ -153,7 +383,12 @@ export function startPlayingAndWaitForVideo(
video.addEventListener(
'error',
- event => reject(new ErrorWithExtra('Video received "error" event', () => ({ event }))),
+ event =>
+ reject(
+ new ErrorWithExtra('Video received "error" event, message: ' + event.message, () => ({
+ event,
+ }))
+ ),
true
);
@@ -238,6 +473,7 @@ export async function getVideoFrameFromVideoElement(
const transformer: TransformStream = new TransformStream({
transform(videoFrame, _controller) {
videoTrack.stop();
+ test.trackForCleanup(videoFrame);
resolve(videoFrame);
},
flush(controller) {
@@ -267,6 +503,10 @@ export async function getVideoFrameFromVideoElement(
*
*/
export function getVideoElement(t: GPUTest, videoName: VideoName): HTMLVideoElement {
+ if (typeof HTMLVideoElement === 'undefined') {
+ t.skip('HTMLVideoElement not available');
+ }
+
const videoElement = document.createElement('video');
const videoInfo = kVideoInfo[videoName];
@@ -277,6 +517,8 @@ export function getVideoElement(t: GPUTest, videoName: VideoName): HTMLVideoElem
const videoUrl = getResourcePath(videoName);
videoElement.src = videoUrl;
+ t.trackForCleanup(videoElement);
+
return videoElement;
}