blob: 770aa49f052f5d5f84185ca6420c674a6dadb765 [file] [log] [blame]
<!doctype html>
<meta charset=utf-8>
<title>RTCRtpParameters encodings</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webrtc/dictionary-helper.js"></script>
<script src="/webrtc/RTCRtpParameters-helper.js"></script>
<script src="/webrtc/third_party/sdp/sdp.js"></script>
<script>
'use strict';
async function negotiate(pc1, pc2) {
await pc1.setLocalDescription();
await pc2.setRemoteDescription(pc1.localDescription);
await pc2.setLocalDescription();
await pc1.setRemoteDescription(pc2.localDescription);
}
test(function(t) {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('video');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
let capability = capabilities.find((capability) => {
return capability.uri == "urn:ietf:params:rtp-hdrext:sdes:mid" &&
capability.direction != "stopped";
});
assert_not_equals(capability, undefined);
}, `the video transceiver.getHeaderExtensionsToNegotiate() includes mandatory extensions`);
test(function(t) {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('audio');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
let capability = capabilities.find((capability) => {
return capability.uri == "urn:ietf:params:rtp-hdrext:sdes:mid" &&
capability.direction != "stopped";
});
assert_not_equals(capability, undefined);
}, `the audio transceiver.getHeaderExtensionsToNegotiate() includes mandatory extensions`);
test(function(t) {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('audio');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
capabilities[0].uri = "";
assert_throws_js(TypeError, () => {
transceiver.setHeaderExtensionsToNegotiate(capabilities);
}, 'transceiver should throw TypeError when setting an empty URI');
}, `setHeaderExtensionsToNegotiate throws TypeError on encountering missing URI`);
test(function(t) {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('audio');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
capabilities[0].uri = "4711";
assert_throws_dom("NotSupportedError", () => {
transceiver.setHeaderExtensionsToNegotiate(capabilities);
}, 'transceiver should throw NotSupported when setting an unknown URI');
}, `setHeaderExtensionsToNegotiate throws NotSupported on encountering unknown URI`);
test(function(t) {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('audio');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
let capability = capabilities.find((capability) => {
return capability.uri == "urn:ietf:params:rtp-hdrext:sdes:mid";
});
["sendonly", "recvonly", "inactive", "stopped"].map(direction => {
capability.direction = direction;
assert_throws_dom("InvalidModificationError", () => {
transceiver.setHeaderExtensionsToNegotiate(capabilities);
}, `transceiver should throw InvalidModificationError when setting a mandatory header extension\'s direction to ${direction}`);
});
}, `setHeaderExtensionsToNegotiate throws InvalidModificationError when setting a mandatory header extension\'s direction to something else than "sendrecv"`);
test(function(t) {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('audio');
let capabilities = transceiver.getHeaderExtensionsToNegotiate();
let selected_capability = capabilities.find((capability) => {
return capability.direction == "sendrecv" &&
capability.uri != "urn:ietf:params:rtp-hdrext:sdes:mid";
});
selected_capability.direction = "stopped";
const offered_capabilities = transceiver.getHeaderExtensionsToNegotiate;
let altered_capability = capabilities.find((capability) => {
return capability.uri == selected_capability.uri &&
capability.direction == "stopped";
});
assert_not_equals(altered_capability, undefined);
}, `modified direction set by setHeaderExtensionsToNegotiate is visible in headerExtensionsOffered`);
promise_test(async t => {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('video');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
const offer = await pc.createOffer();
const extmaps = offer
.sdp
.split("\n")
.filter(line => { return line.includes("a=extmap:"); })
.join("\n");
for (const capability of capabilities) {
if (capability.direction == "stopped") {
assert_false(extmaps.includes(capability.uri));
} else {
assert_true(extmaps.includes(capability.uri));
}
}
}, `unstopped extensions turn up in offer`);
promise_test(async t => {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const transceiver = pc.addTransceiver('video');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
const selected_capability = capabilities.find((capability) => {
return capability.direction == "sendrecv" &&
capability.uri != "urn:ietf:params:rtp-hdrext:sdes:mid";
});
selected_capability.direction = "stopped";
transceiver.setHeaderExtensionsToNegotiate(capabilities);
const offer = await pc.createOffer();
const extmaps = offer
.sdp
.split("\n")
.filter(line => { return line.includes("a=extmap:"); })
.join("\n");
for (const capability of capabilities) {
if (capability.direction == "stopped") {
assert_false(extmaps.includes(capability.uri));
} else {
assert_true(extmaps.includes(capability.uri));
}
}
}, `stopped extensions do not turn up in offers`);
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());
// Disable a non-mandatory extension before first negotiation.
const transceiver = pc1.addTransceiver('video');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
const selected_capability = capabilities.find((capability) => {
return capability.direction == "sendrecv" &&
capability.uri != "urn:ietf:params:rtp-hdrext:sdes:mid";
});
selected_capability.direction = "stopped";
transceiver.setHeaderExtensionsToNegotiate(capabilities);
await negotiate(pc1, pc2);
const negotiated_capabilites = transceiver.getNegotiatedHeaderExtensions();
// Attempt enabling the extension.
selected_capability.direction = "sendrecv";
// The enabled extension should not be part of the negotiated set.
transceiver.setHeaderExtensionsToNegotiate(capabilities);
await negotiate(pc1, pc2);
assert_not_equals(
transceiver.getNegotiatedHeaderExtensions().find(capability => {
return capability.uri == selected_capability.uri &&
capability.direction == "sendrecv";
}), undefined);
}, `the set of negotiated extensions grows with subsequent offers`);
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());
// Disable a non-mandatory extension before first negotiation.
const transceiver = pc1.addTransceiver('video');
const capabilities = transceiver.getHeaderExtensionsToNegotiate();
const selected_capability = capabilities.find((capability) => {
return capability.direction == "sendrecv" &&
capability.uri != "urn:ietf:params:rtp-hdrext:sdes:mid";
});
selected_capability.direction = "stopped";
transceiver.setHeaderExtensionsToNegotiate(capabilities);
await negotiate(pc1, pc2);
const negotiated_capabilites = transceiver.getNegotiatedHeaderExtensions();
for (const capability of negotiated_capabilites) {
assert_not_equals(capabilities.find((cap) => {
return cap.uri == capability.uri && cap.direction != "stopped";
}), undefined);
}
for (const capability of capabilities) {
if (capability.direction != "stopped") {
assert_not_equals(negotiated_capabilites.find((cap) => {
return cap.uri == capability.uri;
}), undefined);
}
}
}, `the set of negotiated extensions is the set of unstopped extensions`);
promise_test(async t => {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());
const t1 = pc.addTransceiver('video');
const t2 = pc.addTransceiver('video');
const extensionUri = 'urn:3gpp:video-orientation';
assert_true(!!t1.getHeaderExtensionsToNegotiate().find(ext => ext.uri === extensionUri));
const ext1 = t1.getHeaderExtensionsToNegotiate();
ext1.find(ext => ext.uri === extensionUri).direction = 'stopped';
t1.setHeaderExtensionsToNegotiate(ext1);
assert_true(!!t2.getHeaderExtensionsToNegotiate().find(ext => ext.uri === extensionUri));
const ext2 = t2.getHeaderExtensionsToNegotiate();
ext2.find(ext => ext.uri === extensionUri).direction = 'sendrecv';
t2.setHeaderExtensionsToNegotiate(ext2);
const offer = await pc.createOffer();
const sections = SDPUtils.splitSections(offer.sdp);
sections.shift();
const extensions = sections.map(section => {
return SDPUtils.matchPrefix(section, 'a=extmap:')
.map(SDPUtils.parseExtmap);
});
assert_equals(extensions.length, 2);
assert_false(!!extensions[0].find(extension => extension.uri === extensionUri));
assert_true(!!extensions[1].find(extension => extension.uri === extensionUri));
}, 'Extensions can be deactivated on a per-mline basis');
</script>