blob: d1f8d1e1840c8018c5ec9a70bf1a720346fc7bd6 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>RTCRtpSender.setParameters</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
</head>
<body>
<script>
promise_test(async () => {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({ video: true });
let videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
let videoParameters = videoSender.getParameters();
videoParameters.encodings[0].active = false;
videoParameters.encodings[0].priority = 'high';
videoParameters.encodings[0].maxBitrate = 1337000;
await videoSender.setParameters(videoParameters);
videoParameters = videoSender.getParameters();
assert_equals(videoParameters.encodings[0].active, false);
assert_equals(videoParameters.encodings[0].priority, 'high');
assert_equals(videoParameters.encodings[0].maxBitrate, 1337000);
}, 'setParameters() changes getParameters() returned values');
promise_test(async () => {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({ video: true });
let videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
let videoParameters = videoSender.getParameters();
videoParameters.encodings[0].maxBitrate = 0xFFFFFFFF;
await videoSender.setParameters(videoParameters);
videoParameters = videoSender.getParameters();
assert_equals(videoParameters.encodings[0].maxBitrate, 0xFFFFFFFF);
}, 'setParameters() with large maxBitrate changes getParameters() returned values');
promise_test(async (t) => {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({ video: true }, 1);
let videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
let videoParameters = videoSender.getParameters();
videoParameters.encodings[0].active = false;
videoParameters.encodings[0].priority = 'high';
videoParameters.encodings[0].maxBitrate = 1337000;
await videoSender.setParameters(videoParameters);
videoParameters.encodings[0].active = true;
videoParameters.encodings[0].priority = 'low';
videoParameters.encodings[0].maxBitrate = 1337001;
return promise_rejects(
t,
new DOMException(
"getParameters() needs to be called before setParameters().",
"InvalidStateError"),
videoSender.setParameters(videoParameters));
}, 'setParameters() with multiple calls after single getParameters()');
promise_test(async (t) => {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({ video: true }, 1);
let videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
return promise_rejects(
t,
new DOMException(
"getParameters() needs to be called before setParameters().",
"InvalidStateError"),
videoSender.setParameters({
transactionId: "",
codecs: [],
encodings: [],
rtcp: {},
headerExtensions: []
}));
}, 'setParameters() fails without getParameters()');
/**
* Tests for read only parameters check.
* Those are mostly similar, so an array of object is used to generate them.
* They have the following properties:
* - name: name of the test
* - transform: function transforming the parameters to trigger an error
* - check: function checking if the transform can be applied
*/
var readOnlyParameters = [
{
name: "transactionId modification",
transform: (p) => { p.transactionId = "foo"; },
},
{
name: "codecs remove one",
transform: (p) => { p.codecs.pop(); },
},
{
name: "codecs add one",
transform: (p) => {
p.codecs.push({
payloadType: 26,
mimeType: "video/dummy",
clockRate: 24000,
channels: 0,
sdpFmtpLine: "sdpFmtpLine",
});
},
},
{
name: "codecs reorder",
transform: (p) => { p.codecs.concat(p.codecs.splice(0, 1)); },
},
{
name: "codecs.payloadtype modification",
transform: (p) => { p.codecs[0].payloadType = 1337; },
},
{
name: "codecs.mimeType modification",
transform: (p) => { p.codecs[0].mimeType = "mime"; },
},
{
name: "codecs.clockRate modification",
transform: (p) => { p.codecs[0].clockRate = 42; },
},
{
name: "codecs.channels modification",
transform: (p) => { p.codecs[0].channels = 16; },
},
{
name: "codecs.channels removed",
transform: (p) => { delete p.codecs[0].channels; },
check: (p) => { p.codecs[0].channels !== undefined },
},
{
name: "codecs.sdpFmtpLine modification",
transform: (p) => { p.codecs[0].sdpFmtpLine = "sdpFmtpLine"; },
},
{
name: "codecs.sdpFmtpLine removed",
transform: (p) => { delete p.codecs[0].sdpFmtpLine; },
check: (p) => { return p.codecs[0].sdpFmtpLine !== undefined; },
},
{
name: "encodings remove one",
transform: (p) => { p.encodings.pop(); },
},
{
name: "encodings add one",
transform: (p) => { p.encodings.push({}); },
},
{
name: "encodings.rid modification",
transform: (p) => { p.encodings[0].rid = "rid"; },
},
{
name: "headerExtensions remove one",
transform: (p) => { p.headerExtensions.pop(); },
check: (p) => { return p.headerExtensions.length != 0; },
},
{
name: "headerExtensions add one",
transform: (p) => {
p.headerExtensions.push({
uri: "uri",
id: 42,
encrypted: false,
});
},
},
{
name: "headerExtensions.uri modification",
transform: (p) => { p.headerExtensions[0].uri = "uri"; },
check: (p) => { return p.headerExtensions.length != 0; },
},
{
name: "headerExtensions.id modification",
transform: (p) => {
p.headerExtensions[0].id = p.headerExtensions[0].id + 1;
},
check: (p) => {
return p.headerExtensions.length != 0;
},
},
{
name: "headerExtensions.encrypted modification",
transform: (p) => {
p.headerExtensions[0].encrypted = !p.headerExtensions[0].encrypted;
},
check: (p) => {
return p.headerExtensions.length != 0;
},
},
{
name: "headerExtensions.encrypted removed",
transform: (p) => {
p.headerExtensions[0].encrypted = !p.headerExtensions[0].encrypted;
},
check: (p) => {
return p.headerExtensions.length != 0
&& p.headerExtensions[0].encrypted !== undefined;
},
},
{
name: "rtcp.cname modification",
transform: (p) => { p.rtcp.cname = "cname"; },
},
{
name: "rtcp.reducedSize modification",
transform: (p) => { p.rtcp.reducedSize = !p.rtcp.reducedSize; },
},
];
for (testCase of readOnlyParameters) {
promise_test((async (name, transform, check, t) => {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({ video: true }, 1);
let videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
let videoParameters = videoSender.getParameters();
if (!check || check(videoParameters)) {
transform(videoParameters);
return promise_rejects(t,
new DOMException("Read-only field modified in setParameters().",
"InvalidModificationError"),
videoSender.setParameters(videoParameters));
}
}).bind(undefined, testCase.name, testCase.transform, testCase.check),
'video setParameters() check for ' + testCase.name);
}
for (testCase of readOnlyParameters) {
promise_test((async (name, transform, check, t) => {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({ audio: true }, 1);
let audioSender = pc1.addTrack(stream.getAudioTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
let audioParameters = audioSender.getParameters();
if (!check || check(audioParameters)) {
transform(audioParameters);
return promise_rejects(t,
new DOMException("Read-only field modified in setParameters().",
"InvalidModificationError"),
audioSender.setParameters(audioParameters));
}
}).bind(undefined, testCase.name, testCase.transform, testCase.check),
'audio setParameters() check for ' + testCase.name);
}
var requiredParameters = [
{
name: "transactionId is required",
transform: (p) => { delete p.transactionId; },
},
{
name: "codecs is required",
transform: (p) => { delete p.codecs; },
},
{
name: "codecs.payloadType is required",
transform: (p) => { delete p.codecs[0].payloadType; },
},
{
name: "codecs.mimeType is required",
transform: (p) => { delete p.codecs[0].mimeType; },
},
{
name: "codecs.clockRate is required",
transform: (p) => { delete p.codecs[0].clockRate; },
},
{
name: "encodings is required",
transform: (p) => { delete p.encodings; },
},
{
name: "headerExtensions is required",
transform: (p) => { delete p.headerExtensions; },
},
{
name: "headerExtensions.uri is required",
transform: (p) => { delete p.headerExtensions[0].uri; },
},
{
name: "headerExtensions.id is required",
transform: (p) => { delete p.headerExtensions[0].id; },
},
{
name: "rtcp is required",
transform: (p) => { delete p.rtcp; },
},
];
for (testCase of requiredParameters) {
promise_test((async (name, transform, check, t) => {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({ video: true }, 1);
let videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
let videoParameters = videoSender.getParameters();
transform(videoParameters);
return promise_rejects(t,
new TypeError(),
videoSender.setParameters(videoParameters));
}).bind(undefined, testCase.name, testCase.transform, testCase.check),
'video setParameters() check for ' + testCase.name);
}
promise_test(async function() {
let pc1 = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let stream = await navigator.mediaDevices.getUserMedia({video:true});
let videoSender = pc1.addTrack(stream.getVideoTracks()[0], stream);
await doSignalingHandshake(pc1, pc2);
let videoParameters = videoSender.getParameters();
videoParameters.encodings[0].maxBitrate = 50;
await videoSender.setParameters(videoParameters);
videoParameters = videoSender.getParameters();
assert_equals(videoParameters.encodings[0].maxBitrate, 50);
}, 'setParameters() set low maxBitrate value');
/**
* Helper functions to tests.
*/
async function doSignalingHandshake(localPc, remotePc) {
let offer = await localPc.createOffer();
await localPc.setLocalDescription(offer);
await remotePc.setRemoteDescription(offer);
let answer = await remotePc.createAnswer();
await remotePc.setLocalDescription(answer);
await localPc.setRemoteDescription(answer);
}
</script>
</body>
</html>