Skip to content

Commit

Permalink
Add a test to check the video detector helper function.
Browse files Browse the repository at this point in the history
This also checks that the video luma settles to a reasonable value
for a large range of values, so could be considered a codec test.
WPT bug: #23340

Bug: none
Change-Id: I6ce0537b90903d823945e2fe3c5389fa4c132608
  • Loading branch information
alvestrand authored and chromium-wpt-export-bot committed May 11, 2020
1 parent 409d250 commit 0e0ed58
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 2 deletions.
9 changes: 7 additions & 2 deletions webrtc/RTCPeerConnection-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,8 @@ const trackFactories = {
ctx.fillStyle = `rgb(${count%255}, ${count*count%255}, ${count%255})`;
count += 1;
ctx.fillRect(0, 0, width, height);
// If signal is set, add a constant-color box to the video frame.
// If signal is set, add a constant-color box to the video frame
// at coordinates 10 to 30 in both X and Y direction.
if (signal !== null) {
ctx.fillStyle = `rgb(${signal}, ${signal}, ${signal})`;
ctx.fillRect(10, 10, 20, 20);
Expand Down Expand Up @@ -623,7 +624,9 @@ function getVideoSignal(v) {
context.drawImage(v, 0, 0, v.videoWidth, v.videoHeight);
// Extract pixel value at position 20, 20
let pixel = context.getImageData(20, 20, 1, 1);
return (pixel.data[0] + pixel.data[1] + pixel.data[2]) / 3;
// Use luma reconstruction to get back original value according to
// ITU-R rec BT.709
return (pixel.data[0] * 0.21 + pixel.data[1] * 0.72 + pixel.data[2] * 0.07);
}

function detectSignal(t, v, value) {
Expand All @@ -633,6 +636,8 @@ function detectSignal(t, v, value) {
if (signal !== null && signal < value + 1 && signal > value - 1) {
resolve();
} else {
// We would like to wait for each new frame instead here,
// but there seems to be no such callback.
t.step_timeout(check, 100);
}
}
Expand Down
84 changes: 84 additions & 0 deletions webrtc/RTCPeerConnection-videoDetectorTest.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<title>RTCPeerConnection Video detector test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script>
'use strict';

// This test verifies that the helper function "detectSignal" from
// RTCPeerConnectionHelper, which is used to detect changes in a video
// signal, performs properly for a range of "signal" values.

// If it fails, it indicates that the video codec used in this particular
// browser at this time doesn't reproduce the luma signal reliably enough
// for this particular application, which may lead to other tests that
// use the "detectSignal" helper failing without an obvious cause.

// The most likely failure is timeout - which will happen if the
// luma value detected doesn't settle within the margin of error before
// the test times out.

async function signalSettlementTime(t, v, sender, signal, backgroundTrack) {
const detectionStream = await getNoiseStream({video: {signal: signal}});
const [detectionTrack] = detectionStream.getTracks();
await sender.replaceTrack(detectionTrack);
const framesBefore = v.getVideoPlaybackQuality().totalVideoFrames;
await detectSignal(t, v, signal);
const framesAfter = v.getVideoPlaybackQuality().totalVideoFrames;
await sender.replaceTrack(backgroundTrack);
await detectSignal(t, v, 100);
detectionStream.getTracks().forEach(track => track.stop());
return (framesAfter - framesBefore);
}

promise_test(async t => {
const v = document.createElement('video');
v.autoplay = true;
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());
const stream1 = await getNoiseStream({video: {signal: 100}});
t.add_cleanup(() => stream1.getTracks().forEach(track => track.stop()));
const [track1] = stream1.getTracks();
const sender = pc1.addTrack(track1);
pc2.ontrack = t.step_func((e) => {
v.srcObject = new MediaStream([e.track]);
});
const metadataToBeLoaded = new Promise((resolve) => {
v.addEventListener('loadedmetadata', resolve);
});
exchangeIceCandidates(pc1, pc2);
doSignalingHandshake(pc1, pc2);
await metadataToBeLoaded;
// The basic signal is a track with signal 100. We replace this
// with tracks with signal from 0 to 255 and see if they are all
// reliably detected.
await detectSignal(t, v, 100);
// A few buffered frames are received with the old content, and a few
// frames may not have settled on exactly the right value. In testing,
// this test passes with maxFrames = 3; give a little more margin.
const maxFrames = 7;
// Test values 0 and 255
let maxCount = await signalSettlementTime(t, v, sender, 0, track1);
assert_less_than(maxCount, maxFrames,
'Should get the black value within ' + maxFrames + ' frames');
maxCount = Math.max(
await signalSettlementTime(t, v, sender, 255, track1), maxCount);
assert_less_than(maxCount, maxFrames,
'Should get the white value within ' + maxFrames + ' frames');
// Test a set of other values - far enough apart to make the test fast.
for (let signal = 2; signal <= 255; signal += 47) {
if (Math.abs(signal - 100) > 10) {
const count = await signalSettlementTime(t, v, sender, signal, track1);
maxCount = Math.max(count, maxCount);
assert_less_than(maxCount, 10,
'Should get value ' + signal + ' within ' + maxFrames + ' frames');
}
}
assert_less_than(maxCount, 10, 'Should get the right value within 10 frames');
}, 'Signal detector detects track change within reasonable time');
</script>

0 comments on commit 0e0ed58

Please sign in to comment.