163 lines
6.4 KiB
HTML
163 lines
6.4 KiB
HTML
<!DOCTYPE HTML>
|
|
<html>
|
|
<head>
|
|
<script type="application/javascript" src="pc.js"></script>
|
|
<script type="application/javascript" src="stats.js"></script>
|
|
<script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script>
|
|
</head>
|
|
<body>
|
|
<pre id="test">
|
|
<script type="application/javascript">
|
|
createHTML({
|
|
bug: "1395853",
|
|
title: "Verify video content over WebRTC for every video codec",
|
|
});
|
|
|
|
async function testVideoCodec(options = {}, codec) {
|
|
const test = new PeerConnectionTest(options);
|
|
test.setMediaConstraints([{video: true}], []);
|
|
|
|
let payloadType;
|
|
test.chain.insertBefore("PC_LOCAL_SET_LOCAL_DESCRIPTION", [
|
|
function PC_LOCAL_FILTER_OUT_CODECS() {
|
|
const otherCodec = codecs.find(c => c != codec);
|
|
const otherId = sdputils.findCodecId(test.originalOffer.sdp, otherCodec.name, otherCodec.offset);
|
|
const otherRtpmapMatcher = new RegExp(`a=rtpmap:${otherId}.*\\r\\n`, "gi");
|
|
|
|
const id = sdputils.findCodecId(test.originalOffer.sdp, codec.name, codec.offset);
|
|
payloadType = Number(id);
|
|
if (codec.offset) {
|
|
isnot(id, sdputils.findCodecId(test.originalOffer.sdp, codec.name, 0),
|
|
"Different offsets should return different payload types");
|
|
}
|
|
test.originalOffer.sdp =
|
|
sdputils.removeAllButPayloadType(test.originalOffer.sdp, id);
|
|
|
|
// Bug 1901160 test receiving signaling with no H264 fmtp.
|
|
if (codec.hasOwnProperty("fmtpOverride")) {
|
|
test.originalOffer.sdp = test.originalOffer.sdp.replace(new RegExp("a=fmtp:" + id + ".*\\r\\n", "gi"), codec.fmtpOverride);
|
|
}
|
|
|
|
ok(!test.originalOffer.sdp.match(new RegExp(`m=.*UDP/TLS/RTP/SAVPF.* ${otherId}[^0-9]`, "gi")),
|
|
`Other codec ${otherId} should be removed after filtering`);
|
|
ok(test.originalOffer.sdp.match(new RegExp(`m=.*UDP/TLS/RTP/SAVPF.* ${id}[^0-9]`, "gi")),
|
|
`Tested codec ${id} should remain after filtering`);
|
|
|
|
// We only set it now, or the framework would remove non-H264 codecs
|
|
// for us.
|
|
options.h264 = codec.name == "H264";
|
|
// Ditto for AV1.
|
|
options.av1 = codec.name == "AV1";
|
|
},
|
|
]);
|
|
|
|
test.chain.insertAfter("PC_LOCAL_WAIT_FOR_MEDIA_FLOW",
|
|
[PC_LOCAL_TEST_LOCAL_STATS]);
|
|
|
|
test.chain.insertAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW",
|
|
[PC_REMOTE_TEST_REMOTE_STATS]);
|
|
|
|
test.chain.append([
|
|
async function PC_LOCAL_TEST_CODEC() {
|
|
const stats = await test.pcLocal._pc.getStats();
|
|
let codecCount = 0;
|
|
stats.forEach(stat => {
|
|
if (stat.type == "codec") {
|
|
is(codecCount++, 0, "expected only one encode codec stat");
|
|
is(stat.payloadType, payloadType, "payloadType as expected");
|
|
is(stat.mimeType, `video/${codec.name}`, "mimeType as expected");
|
|
is(stat.codecType, "encode", "codecType as expected");
|
|
}
|
|
});
|
|
},
|
|
async function PC_REMOTE_TEST_CODEC() {
|
|
const stats = await test.pcRemote._pc.getStats();
|
|
let codecCount = 0;
|
|
stats.forEach(stat => {
|
|
if (stat.type == "codec") {
|
|
is(codecCount++, 0, "expected only one decode codec stat");
|
|
is(stat.payloadType, payloadType, "payloadType as expected");
|
|
is(stat.mimeType, `video/${codec.name}`, "mimeType as expected");
|
|
is(stat.codecType, "decode", "codecType as expected");
|
|
}
|
|
});
|
|
},
|
|
async function CHECK_VIDEO_FLOW() {
|
|
try {
|
|
const h = new VideoStreamHelper();
|
|
await h.checkVideoPlaying(
|
|
test.pcRemote.remoteMediaElements[0],
|
|
10, 10, 128);
|
|
ok(true, `Got video flow for codec ${codec.name}, offset ${codec.offset}`);
|
|
} catch(e) {
|
|
ok(false, `No video flow for codec ${codec.name}, offset ${codec.offset}: ${e}`);
|
|
}
|
|
},
|
|
]);
|
|
|
|
await test.run();
|
|
}
|
|
|
|
// We match the name against the sdp to figure out the payload type,
|
|
// so all other present codecs can be removed.
|
|
// Use `offset` when there are multiple instances of a codec expected in an sdp.
|
|
const codecs = [
|
|
{ name: "VP8" },
|
|
{ name: "VP9" },
|
|
{ name: "H264" },
|
|
{ name: "H264", offset: 1 },
|
|
{ name: "H264", offset: 2 },
|
|
{ name: "H264", offset: 2, fmtpOverride: "a=fmtp:packetization-mode=1" },
|
|
{ name: "H264", offset: 3 },
|
|
{ name: "H264", offset: 3, fmtpOverride: "a=fmtp:packetization-mode=0" },
|
|
{ name: "H264", offset: 3, fmtpOverride: "" },
|
|
{ name: "AV1" },
|
|
];
|
|
|
|
runNetworkTest(async (options) => {
|
|
// This test expects the video being captured will change color. Use fake
|
|
// video device as loopback does not currently change.
|
|
await pushPrefs(
|
|
['media.video_loopback_dev', ''],
|
|
['media.navigator.streams.fake', true],
|
|
["media.navigator.video.disable_h264_baseline", false]);
|
|
for (let codec of codecs) {
|
|
info(`Testing video for codec ${codec.name} offset ${codec.offset}`);
|
|
try {
|
|
let enc = SpecialPowers.getIntPref('media.webrtc.encoder_creation_strategy');
|
|
let dec = SpecialPowers.getBoolPref('media.navigator.mediadatadecoder_h264_enabled');
|
|
if (codec.name == "H264") {
|
|
await matchPlatformH264CodecPrefs();
|
|
if (codec.offset == 1 || codec.offset == 3) {
|
|
// Force fake GMP codec for H.264 mode 0 because not all platforms
|
|
// support slice size control. Re-enable it after
|
|
// a. SW encoder fallback support (bug 1726617), and
|
|
// b. returning valid bitstream from fake GMP encoder (bug 1509012).
|
|
await pushPrefs(
|
|
['media.webrtc.encoder_creation_strategy', 0 /* builtin libwertc encoders */],
|
|
['media.navigator.mediadatadecoder_h264_enabled', false],
|
|
);
|
|
}
|
|
}
|
|
if (codec.name == "AV1" ) {
|
|
const hasAv1 = await matchPlatformAV1CodecPrefs();
|
|
if (!hasAv1.software && !hasAv1.hardware) {
|
|
info("Skipping AV1 test as no AV1 codec is available");
|
|
continue;
|
|
}
|
|
}
|
|
await testVideoCodec(options, codec);
|
|
await pushPrefs(
|
|
['media.webrtc.encoder_creation_strategy', enc],
|
|
['media.navigator.mediadatadecoder_h264_enabled', dec],
|
|
);
|
|
} catch(e) {
|
|
ok(false, `Error in test for codec ${codec.name}: ${e}\n${e.stack}`);
|
|
}
|
|
info(`Tested video for codec ${codec.name}`);
|
|
}
|
|
});
|
|
</script>
|
|
</pre>
|
|
</body>
|
|
</html>
|