summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html')
-rw-r--r--testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html322
1 files changed, 322 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html
new file mode 100644
index 0000000000..f779f5a94c
--- /dev/null
+++ b/testing/web-platform/tests/webrtc/RTCRtpTransceiver-setCodecPreferences.html
@@ -0,0 +1,322 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>RTCRtpTransceiver.prototype.setCodecPreferences</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./third_party/sdp/sdp.js"></script>
+<script>
+ 'use strict';
+
+ // Test is based on the following editor draft:
+ // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
+
+ /*
+ 5.4. RTCRtpTransceiver Interface
+ interface RTCRtpTransceiver {
+ ...
+ void setCodecPreferences(sequence<RTCRtpCodecCapability> codecs);
+ };
+
+ setCodecPreferences
+ - Setting codecs to an empty sequence resets codec preferences to any
+ default value.
+
+ - The codecs sequence passed into setCodecPreferences can only contain
+ codecs that are returned by RTCRtpSender.getCapabilities(kind) or
+ RTCRtpReceiver.getCapabilities(kind), where kind is the kind of the
+ RTCRtpTransceiver on which the method is called. Additionally, the
+ RTCRtpCodecParameters dictionary members cannot be modified. If
+ codecs does not fulfill these requirements, the user agent MUST throw
+ an InvalidModificationError.
+ */
+ /*
+ * Chromium note: this requires build bots with H264 support. See
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=840659
+ * for details on how to enable support.
+ */
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('audio');
+ transceiver.setCodecPreferences(capabilities.codecs);
+ }, `setCodecPreferences() on audio transceiver with codecs returned from RTCRtpSender.getCapabilities('audio') should succeed`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('video');
+ const capabilities = RTCRtpReceiver.getCapabilities('video');
+ transceiver.setCodecPreferences(capabilities.codecs);
+ }, `setCodecPreferences() on video transceiver with codecs returned from RTCRtpReceiver.getCapabilities('video') should succeed`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities1 = RTCRtpSender.getCapabilities('audio');
+ const capabilities2 = RTCRtpReceiver.getCapabilities('audio');
+ transceiver.setCodecPreferences([...capabilities1.codecs, ... capabilities2.codecs]);
+ }, `setCodecPreferences() with both sender receiver codecs combined should succeed`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ transceiver.setCodecPreferences([]);
+ }, `setCodecPreferences([]) should succeed`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('audio');
+ const { codecs } = capabilities;
+
+ if(codecs.length >= 2) {
+ const tmp = codecs[0];
+ codecs[0] = codecs[1];
+ codecs[1] = tmp;
+ }
+
+ transceiver.setCodecPreferences(codecs);
+ }, `setCodecPreferences() with reordered codecs should succeed`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('video');
+ const capabilities = RTCRtpSender.getCapabilities('video');
+ const { codecs } = capabilities;
+ // This test verifies that the mandatory VP8 codec is present
+ // and can be set.
+ let tried = false;
+ codecs.forEach(codec => {
+ if (codec.mimeType.toLowerCase() === 'video/vp8') {
+ transceiver.setCodecPreferences([codecs[0]]);
+ tried = true;
+ }
+ });
+ assert_true(tried, 'VP8 video codec was found and tried');
+ }, `setCodecPreferences() with only VP8 should succeed`);
+
+ test(() => {
+ const pc = new RTCPeerConnection();
+ const transceiver = pc.addTransceiver('video');
+ const capabilities = RTCRtpSender.getCapabilities('video');
+ const { codecs } = capabilities;
+ // This test verifies that the mandatory H264 codec is present
+ // and can be set.
+ let tried = false;
+ codecs.forEach(codec => {
+ if (codec.mimeType.toLowerCase() === 'video/h264') {
+ transceiver.setCodecPreferences([codecs[0]]);
+ tried = true;
+ }
+ });
+ assert_true(tried, 'H264 video codec was found and tried');
+ }, `setCodecPreferences() with only H264 should succeed`);
+
+ async function getRTPMapLinesWithCodecAsFirst(firstCodec)
+ {
+ const capabilities = RTCRtpSender.getCapabilities('video').codecs;
+ capabilities.forEach((codec, idx) => {
+ if (codec.mimeType === firstCodec) {
+ capabilities.splice(idx, 1);
+ capabilities.unshift(codec);
+ }
+ });
+
+ const pc = new RTCPeerConnection();
+ const transceiver = pc.addTransceiver('video');
+ transceiver.setCodecPreferences(capabilities);
+ const offer = await pc.createOffer();
+
+ return offer.sdp.split('\r\n').filter(line => line.indexOf("a=rtpmap") === 0);
+ }
+
+ promise_test(async () => {
+ const lines = await getRTPMapLinesWithCodecAsFirst('video/H264');
+
+ assert_greater_than(lines.length, 1);
+ assert_true(lines[0].indexOf("H264") !== -1, "H264 should be the first codec");
+ }, `setCodecPreferences() should allow setting H264 as first codec`);
+
+ promise_test(async () => {
+ const lines = await getRTPMapLinesWithCodecAsFirst('video/VP8');
+
+ assert_greater_than(lines.length, 1);
+ assert_true(lines[0].indexOf("VP8") !== -1, "VP8 should be the first codec");
+ }, `setCodecPreferences() should allow setting VP8 as first codec`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('video');
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(capabilities.codecs));
+ }, `setCodecPreferences() on audio transceiver with codecs returned from getCapabilities('video') should throw InvalidModificationError`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const codecs = [{
+ mimeType: 'data',
+ clockRate: 2000,
+ channels: 2,
+ sdpFmtpLine: '0-15'
+ }];
+
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(codecs));
+ }, `setCodecPreferences() with user defined codec with invalid mimeType should throw InvalidModificationError`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const codecs = [{
+ mimeType: 'audio/piepiper',
+ clockRate: 2000,
+ channels: 2,
+ sdpFmtpLine: '0-15'
+ }];
+
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(codecs));
+ }, `setCodecPreferences() with user defined codec should throw InvalidModificationError`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('audio');
+ const codecs = [
+ ...capabilities.codecs,
+ {
+ mimeType: 'audio/piepiper',
+ clockRate: 2000,
+ channels: 2,
+ sdpFmtpLine: '0-15'
+ }];
+
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(codecs));
+ }, `setCodecPreferences() with user defined codec together with codecs returned from getCapabilities() should throw InvalidModificationError`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('audio');
+ const codecs = [capabilities.codecs[0]];
+ codecs[0].clockRate = codecs[0].clockRate / 2;
+
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(codecs));
+ }, `setCodecPreferences() with modified codec clock rate should throw InvalidModificationError`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('audio');
+ const codecs = [capabilities.codecs[0]];
+ codecs[0].channels = codecs[0].channels + 11;
+
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(codecs));
+ }, `setCodecPreferences() with modified codec channel count should throw InvalidModificationError`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('audio');
+ const codecs = [capabilities.codecs[0]];
+ codecs[0].sdpFmtpLine = "modifiedparameter=1";
+
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(codecs));
+ }, `setCodecPreferences() with modified codec parameters should throw InvalidModificationError`);
+
+ test((t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const capabilities = RTCRtpSender.getCapabilities('audio');
+
+ const { codecs } = capabilities;
+ assert_greater_than(codecs.length, 0,
+ 'Expect at least one codec available');
+
+ const [ codec ] = codecs;
+ const { channels=2 } = codec;
+ codec.channels = channels+1;
+
+ assert_throws_dom('InvalidModificationError', () => transceiver.setCodecPreferences(codecs));
+ }, `setCodecPreferences() with modified codecs returned from getCapabilities() should throw InvalidModificationError`);
+
+ promise_test(async (t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('audio');
+ const {codecs} = RTCRtpSender.getCapabilities('audio');
+ // Reorder codecs, put PCMU/PCMA first.
+ let firstCodec;
+ let i;
+ for (i = 0; i < codecs.length; i++) {
+ const codec = codecs[i];
+ if (codec.mimeType === 'audio/PCMU' || codec.mimeType === 'audio/PCMA') {
+ codecs.splice(i, 1);
+ codecs.unshift(codec);
+ firstCodec = codec.mimeType.substr(6);
+ break;
+ }
+ }
+ assert_not_equals(firstCodec, undefined, 'PCMU or PCMA codec not found');
+ transceiver.setCodecPreferences(codecs);
+
+ const offer = await pc.createOffer();
+ const mediaSection = SDPUtils.getMediaSections(offer.sdp)[0];
+ const rtpParameters = SDPUtils.parseRtpParameters(mediaSection);
+ assert_equals(rtpParameters.codecs[0].name, firstCodec);
+ }, `setCodecPreferences() modifies the order of audio codecs in createOffer`);
+
+ promise_test(async (t) => {
+ const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+ const transceiver = pc.addTransceiver('video');
+ const {codecs} = RTCRtpSender.getCapabilities('video');
+ // Reorder codecs, swap H264 and VP8.
+ let vp8 = -1;
+ let h264 = -1;
+ let firstCodec;
+ let i;
+ for (i = 0; i < codecs.length; i++) {
+ const codec = codecs[i];
+ if (codec.mimeType === 'video/VP8' && vp8 === -1) {
+ vp8 = i;
+ if (h264 !== -1) {
+ codecs[vp8] = codecs[h264];
+ codecs[h264] = codec;
+ firstCodec = 'VP8';
+ break;
+ }
+ }
+ if (codec.mimeType === 'video/H264' && h264 === -1) {
+ h264 = i;
+ if (vp8 !== -1) {
+ codecs[h264] = codecs[vp8];
+ codecs[vp8] = codec;
+ firstCodec = 'H264';
+ break;
+ }
+ }
+ }
+ assert_not_equals(firstCodec, undefined, 'VP8 and H264 codecs not found');
+ transceiver.setCodecPreferences(codecs);
+
+ const offer = await pc.createOffer();
+ const mediaSection = SDPUtils.getMediaSections(offer.sdp)[0];
+ const rtpParameters = SDPUtils.parseRtpParameters(mediaSection);
+ assert_equals(rtpParameters.codecs[0].name, firstCodec);
+ }, `setCodecPreferences() modifies the order of video codecs in createOffer`);
+
+ </script>