summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webcodecs/video-encoder-utils.js
blob: 0838260d31bc8f90d2d294341f078bef544d29bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
async function checkEncoderSupport(test, config) {
  assert_equals("function", typeof VideoEncoder.isConfigSupported);
  let supported = false;
  try {
    const support = await VideoEncoder.isConfigSupported(config);
    supported = support.supported;
  } catch (e) {}

  assert_implements_optional(supported, 'Unsupported config: ' +
                             JSON.stringify(config));
}

function fourColorsFrame(ctx, width, height, text) {
  const kYellow = "#FFFF00";
  const kRed = "#FF0000";
  const kBlue = "#0000FF";
  const kGreen = "#00FF00";

  ctx.fillStyle = kYellow;
  ctx.fillRect(0, 0, width / 2, height / 2);

  ctx.fillStyle = kRed;
  ctx.fillRect(width / 2, 0, width / 2, height / 2);

  ctx.fillStyle = kBlue;
  ctx.fillRect(0, height / 2, width / 2, height / 2);

  ctx.fillStyle = kGreen;
  ctx.fillRect(width / 2, height / 2, width / 2, height / 2);

  ctx.fillStyle = 'white';
  ctx.font = (height / 10) + 'px sans-serif';
  ctx.fillText(text, width / 2, height / 2);
}

// Paints |count| black dots on the |ctx|, so their presence can be validated
// later. This is an analog of the most basic bar code.
function putBlackDots(ctx, width, height, count) {
  ctx.fillStyle = 'black';
  const dot_size = 20;
  const step = dot_size * 2;

  for (let i = 1; i <= count; i++) {
    let x = i * step;
    let y = step * (x / width + 1);
    x %= width;
    ctx.fillRect(x, y, dot_size, dot_size);
  }
}

// Validates that frame has |count| black dots in predefined places.
function validateBlackDots(frame, count) {
  const width = frame.displayWidth;
  const height = frame.displayHeight;
  let cnv = new OffscreenCanvas(width, height);
  var ctx = cnv.getContext('2d', {willReadFrequently: true});
  ctx.drawImage(frame, 0, 0);
  const dot_size = 20;
  const step = dot_size * 2;

  for (let i = 1; i <= count; i++) {
    let x = i * step + dot_size / 2;
    let y = step * (x / width + 1) + dot_size / 2;
    x %= width;

    if (x)
      x = x -1;
    if (y)
      y = y -1;

    let rgba = ctx.getImageData(x, y, 2, 2).data;
    const tolerance = 60;
    if ((rgba[0] > tolerance || rgba[1] > tolerance || rgba[2] > tolerance)
      && (rgba[4] > tolerance || rgba[5] > tolerance || rgba[6] > tolerance)
      && (rgba[8] > tolerance || rgba[9] > tolerance || rgba[10] > tolerance)
      && (rgba[12] > tolerance || rgba[13] > tolerance || rgba[14] > tolerance)) {
      // The dot is too bright to be a black dot.
      return false;
    }
  }
  return true;
}

function createFrame(width, height, ts = 0) {
  let duration = 33333;  // 30fps
  let text = ts.toString();
  let cnv = new OffscreenCanvas(width, height);
  var ctx = cnv.getContext('2d');
  fourColorsFrame(ctx, width, height, text);
  return new VideoFrame(cnv, { timestamp: ts, duration });
}

function createDottedFrame(width, height, dots, ts) {
  if (ts === undefined)
    ts = dots;
  let duration = 33333;  // 30fps
  let text = ts.toString();
  let cnv = new OffscreenCanvas(width, height);
  var ctx = cnv.getContext('2d');
  fourColorsFrame(ctx, width, height, text);
  putBlackDots(ctx, width, height, dots);
  return new VideoFrame(cnv, { timestamp: ts, duration });
}