Bug 1937776 - Part 2: Add mochitest to verify VideoFrameCallbackMetadata receiveTime/captureTime alignment. r=pehrsons a=pascalc
Differential Revision: https://phabricator.services.mozilla.com/D252022
This commit is contained in:
@@ -77,6 +77,8 @@ run-sequentially = "sets prefs that may disrupt other tests"
|
|||||||
["test_ondevicechange_resistfingerprinting.html"]
|
["test_ondevicechange_resistfingerprinting.html"]
|
||||||
run-sequentially = "sets prefs that may disrupt other tests"
|
run-sequentially = "sets prefs that may disrupt other tests"
|
||||||
|
|
||||||
|
["test_rvfc_timestamp_alignment.html"]
|
||||||
|
|
||||||
["test_setSinkId-echoCancellation.html"]
|
["test_setSinkId-echoCancellation.html"]
|
||||||
skip-if = ["os == 'android'"] # bug 1473346 - no setSinkId()
|
skip-if = ["os == 'android'"] # bug 1473346 - no setSinkId()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="pc.js" type="application/javascript"></script>
|
||||||
|
<script src="/tests/dom/canvas/test/captureStream_common.js" type="application/javascript"></script>
|
||||||
|
<script src="stats.js" type="application/javascript"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1937776",
|
||||||
|
title: "Verify VideoFrameCallback receiveTime/captureTime alignment",
|
||||||
|
});
|
||||||
|
|
||||||
|
const {AppConstants} = SpecialPowers.ChromeUtils.importESModule(
|
||||||
|
"resource://gre/modules/AppConstants.sys.mjs"
|
||||||
|
);
|
||||||
|
|
||||||
|
runNetworkTest(async function(options) {
|
||||||
|
async function WAIT_FOR_SYNCED_RTCP(test, count) {
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
await waitForSyncedRtcp(test.pcLocal._pc);
|
||||||
|
await waitForSyncedRtcp(test.pcRemote._pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function CHECK_TIMESTAMP_ALIGNMENT(test, ok_or_todo, header_text) {
|
||||||
|
const video = test.pcRemote.remoteMediaElements[0];
|
||||||
|
const maxFrames = 10;
|
||||||
|
const maxRecvDelta = 250;
|
||||||
|
const maxCaptDelta = 250;
|
||||||
|
let frameCount = 0;
|
||||||
|
|
||||||
|
// macOS fixes for high jitter on try
|
||||||
|
const recvOffset = AppConstants.platform == "macosx" ? -200 : 0;
|
||||||
|
const captOffset = AppConstants.platform == "macosx" ? -200 : 0;
|
||||||
|
|
||||||
|
// captureTime may not be present for several frames
|
||||||
|
const maxMissedCaptCount = 8;
|
||||||
|
let missedCaptCount = 0;
|
||||||
|
|
||||||
|
info(`***** RUNNING ${header_text} ALIGNMENT TEST`);
|
||||||
|
info(`***** USING ASSERT ${ok_or_todo == ok ? "ok" : "todo"}() FOR captureTime`);
|
||||||
|
info(`***** APPLYING ${recvOffset} ms OFFSET TO receiveTime ASSERTS`);
|
||||||
|
|
||||||
|
while (++frameCount <= maxFrames) {
|
||||||
|
info(`Checking frame #${frameCount} of ${maxFrames}`);
|
||||||
|
const {now, metadata} =
|
||||||
|
await new Promise(r => video.requestVideoFrameCallback(
|
||||||
|
(now, metadata) => r({now, metadata})));
|
||||||
|
const {presentationTime, receiveTime, captureTime} = metadata;
|
||||||
|
|
||||||
|
ok(receiveTime, "receiveTime is present");
|
||||||
|
if (receiveTime) {
|
||||||
|
const dt = presentationTime - receiveTime;
|
||||||
|
ok(dt > recvOffset, `receiveTime (${receiveTime.toFixed(2)} ms) < `
|
||||||
|
+ `presentationTime (${presentationTime.toFixed(2)} ms)`);
|
||||||
|
if (dt > recvOffset) {
|
||||||
|
ok(dt <= maxRecvDelta, `receiveTime delta (${dt.toFixed(2)} ms) <= ${maxRecvDelta} ms`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captureTime) {
|
||||||
|
ok_or_todo(captureTime, `captureTime is present`);
|
||||||
|
const dt = presentationTime - captureTime;
|
||||||
|
ok(dt > captOffset, `captureTime (${captureTime.toFixed(2)} ms) < `
|
||||||
|
+ `presentationTime (${presentationTime.toFixed(2)} ms)`);
|
||||||
|
if (dt > captOffset) {
|
||||||
|
ok(dt <= maxCaptDelta, `captureTime delta (${dt.toFixed(2)} ms) <= ${maxCaptDelta} ms`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info(`!!!!! Missing captureTime!`);
|
||||||
|
// Skip additional asserts if captureTime isn't expected to avoid
|
||||||
|
// overcomplicating the logic that allows for a limited number of misses.
|
||||||
|
if (ok_or_todo == todo) {
|
||||||
|
todo(captureTime, `captureTime is present`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ok(++missedCaptCount <= maxMissedCaptCount,
|
||||||
|
`Miss #${missedCaptCount} <= allowed misses (${maxMissedCaptCount})`);
|
||||||
|
ok(missedCaptCount == frameCount,
|
||||||
|
"missing captureTime occurred sequentially from test start.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function arg_wrapper(fn, argsArr) {
|
||||||
|
return async function wrap() {
|
||||||
|
return fn(...argsArr);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.requestCompleteLog();
|
||||||
|
await pushPrefs(
|
||||||
|
["media.video_loopback_dev", ""],
|
||||||
|
["media.navigator.streams.fake", true]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Note we use two RTCP syncs in these tests as we currently need two
|
||||||
|
// RTCP measurements in order to estimate a NTP timestamp.
|
||||||
|
// See: Use of rtp_to_ntp_.Estimate(rtp_timestamp) in
|
||||||
|
// RemoteNtpTimeEstimator::EstimateNtp() and
|
||||||
|
// the two measurement requirement in
|
||||||
|
// RtpToNtpEstimator::UpdateParameters()
|
||||||
|
// (as of 618678dd32e52dbaa8a56d72c6655032f48068b3)
|
||||||
|
|
||||||
|
// Unidirectional captureTime is currently BROKEN.
|
||||||
|
// See: bug 1971078 , bug 1971117
|
||||||
|
const test_uni = new PeerConnectionTest(options);
|
||||||
|
test_uni.setMediaConstraints([{ video: true }], []);
|
||||||
|
test_uni.chain.append([
|
||||||
|
arg_wrapper(WAIT_FOR_SYNCED_RTCP, [test_uni, 2]),
|
||||||
|
arg_wrapper(CHECK_TIMESTAMP_ALIGNMENT, [test_uni, todo, "UNIDIRECTIONAL"]),
|
||||||
|
]);
|
||||||
|
await test_uni.run();
|
||||||
|
|
||||||
|
// Bidirectional test should pass.
|
||||||
|
const test_bi = new PeerConnectionTest(options);
|
||||||
|
test_bi.setMediaConstraints([{ video: true }], [{ video: true }]);
|
||||||
|
test_bi.chain.append([
|
||||||
|
arg_wrapper(WAIT_FOR_SYNCED_RTCP, [test_bi, 2]),
|
||||||
|
arg_wrapper(CHECK_TIMESTAMP_ALIGNMENT, [test_bi, ok, "BIDIRECTIONAL"]),
|
||||||
|
]);
|
||||||
|
await test_bi.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user