summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/media-capabilities
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /testing/web-platform/tests/media-capabilities
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/media-capabilities')
-rw-r--r--testing/web-platform/tests/media-capabilities/META.yml3
-rw-r--r--testing/web-platform/tests/media-capabilities/README.md14
-rw-r--r--testing/web-platform/tests/media-capabilities/decodingInfo.any.js406
-rw-r--r--testing/web-platform/tests/media-capabilities/decodingInfo.webrtc.html217
-rw-r--r--testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.http.html31
-rw-r--r--testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.https.html262
-rw-r--r--testing/web-platform/tests/media-capabilities/encodingInfo.any.js310
-rw-r--r--testing/web-platform/tests/media-capabilities/encodingInfo.webrtc.html217
-rw-r--r--testing/web-platform/tests/media-capabilities/idlharness.any.js25
9 files changed, 1485 insertions, 0 deletions
diff --git a/testing/web-platform/tests/media-capabilities/META.yml b/testing/web-platform/tests/media-capabilities/META.yml
new file mode 100644
index 0000000000..2bd00efb9a
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/META.yml
@@ -0,0 +1,3 @@
+spec: https://w3c.github.io/media-capabilities/
+suggested_reviewers:
+ - mounirlamouri
diff --git a/testing/web-platform/tests/media-capabilities/README.md b/testing/web-platform/tests/media-capabilities/README.md
new file mode 100644
index 0000000000..cfe994976c
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/README.md
@@ -0,0 +1,14 @@
+# Media Capabilities specification Tests
+
+The Media Capabilities specification is available here: https://wicg.github.io/media-capabilities
+
+GitHub repository: https://github.com/WICG/media-capabilities
+
+File an issue: https://github.com/wicg/media-capabilities/issues/new
+
+## Status of these tests
+
+These tests are still very early. The specification is still WIP and they try to
+reflect as much as possible the current state of the specification. Please file
+issues if there are inconsistencies between the specification and the tests or
+if tests are obviously missing.
diff --git a/testing/web-platform/tests/media-capabilities/decodingInfo.any.js b/testing/web-platform/tests/media-capabilities/decodingInfo.any.js
new file mode 100644
index 0000000000..061a226e3f
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/decodingInfo.any.js
@@ -0,0 +1,406 @@
+// META: timeout=long
+'use strict';
+
+// Minimal VideoConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalVideoConfiguration = {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+};
+
+// Minimal AudioConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalAudioConfiguration = {
+ contentType: 'audio/webm; codecs="opus"',
+};
+
+// AudioConfiguration with optional spatialRendering param.
+var audioConfigurationWithSpatialRendering = {
+ contentType: 'audio/webm; codecs="opus"',
+ spatialRendering: true,
+};
+
+// VideoConfiguration with optional hdrMetadataType, colorGamut, and
+// transferFunction properties.
+var videoConfigurationWithDynamicRange = {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ hdrMetadataType: "smpteSt2086",
+ colorGamut: "srgb",
+ transferFunction: "srgb",
+}
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo());
+}, "Test that decodingInfo rejects if it doesn't get a configuration");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({}));
+}, "Test that decodingInfo rejects if the MediaConfiguration isn't valid");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }));
+}, "Test that decodingInfo rejects if the MediaConfiguration does not have a type");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ }));
+}, "Test that decodingInfo rejects if the configuration doesn't have an audio or video field");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: -1,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a negative framerate");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 0,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a framerate set to 0");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: Infinity,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a framerate set to Infinity");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration contentType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'audio/fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration contentType isn't of type video");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'application/ogg; codec=vorbis',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration contentType is of type audio");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: {
+ contentType: 'application/ogg; codec=theora',
+ channels: 2,
+ },
+ }));
+}, "Test that decodingInfo rejects if the audio configuration contentType is of type video");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"; foo="bar"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration contentType has more than one parameter");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; foo="bar"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration contentType has one parameter that isn't codecs");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/1001',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of x/y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/0',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of x/0");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '0/10001',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of 0/y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '-24000/10001',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of -x/y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/-10001',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of x/-y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of x/");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '1/3x',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate with trailing unallowed characters");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: { contentType: 'fgeoa' },
+ }));
+}, "Test that decodingInfo rejects if the audio configuration contenType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: { contentType: 'video/fgeoa' },
+ }));
+}, "Test that decodingInfo rejects if the audio configuration contentType isn't of type audio");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: { contentType: 'audio/webm; codecs="opus"; foo="bar"' },
+ }));
+}, "Test that decodingInfo rejects if the audio configuration contentType has more than one parameters");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: { contentType: 'audio/webm; foo="bar"' },
+ }));
+}, "Test that decodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }).then(ability => {
+ assert_equals(typeof ability.supported, "boolean");
+ assert_equals(typeof ability.smooth, "boolean");
+ assert_equals(typeof ability.powerEfficient, "boolean");
+ assert_equals(typeof ability.keySystemAccess, "object");
+ });
+}, "Test that decodingInfo returns a valid MediaCapabilitiesInfo objects");
+
+async_test(t => {
+ var validTypes = [ 'file', 'media-source' ];
+ var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource',
+ 'record', 'transmission' ];
+
+ var validPromises = [];
+ var invalidCaught = 0;
+
+ validTypes.forEach(type => {
+ validPromises.push(navigator.mediaCapabilities.decodingInfo({
+ type: type,
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }));
+ });
+
+ // validTypes are tested via Promise.all(validPromises) because if one of the
+ // promises fail, Promise.all() will reject. This mechanism can't be used for
+ // invalid types which will be tested individually and increment invalidCaught
+ // when rejected until the amount of rejection matches the expectation.
+ Promise.all(validPromises).then(t.step_func(() => {
+ for (var i = 0; i < invalidTypes.length; ++i) {
+ navigator.mediaCapabilities.decodingInfo({
+ type: invalidTypes[i],
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }).then(t.unreached_func(), t.step_func(e => {
+ assert_equals(e.name, 'TypeError');
+ ++invalidCaught;
+ if (invalidCaught == invalidTypes.length)
+ t.done();
+ }));
+ }
+ }), t.unreached_func('Promise.all should not reject for valid types'));
+}, "Test that decodingInfo rejects if the MediaConfiguration does not have a valid type");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: audioConfigurationWithSpatialRendering,
+ }).then(ability => {
+ assert_equals(typeof ability.supported, "boolean");
+ assert_equals(typeof ability.smooth, "boolean");
+ assert_equals(typeof ability.powerEfficient, "boolean");
+ assert_equals(typeof ability.keySystemAccess, "object");
+ });
+}, "Test that decodingInfo with spatialRendering set returns a valid MediaCapabilitiesInfo objects");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: videoConfigurationWithDynamicRange,
+ }).then(ability => {
+ assert_equals(typeof ability.supported, "boolean");
+ assert_equals(typeof ability.smooth, "boolean");
+ assert_equals(typeof ability.powerEfficient, "boolean");
+ assert_equals(typeof ability.keySystemAccess, "object");
+ });
+}, "Test that decodingInfo with hdrMetadataType, colorGamut, and transferFunction set returns a valid MediaCapabilitiesInfo objects");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ hdrMetadataType: ""
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has an empty hdrMetadataType");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ colorGamut: true
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a colorGamut set to true");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ transferFunction: 3
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a transferFunction set to 3");
diff --git a/testing/web-platform/tests/media-capabilities/decodingInfo.webrtc.html b/testing/web-platform/tests/media-capabilities/decodingInfo.webrtc.html
new file mode 100644
index 0000000000..f283956100
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/decodingInfo.webrtc.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html>
+<title>MediaCapabilities.decodingInfo() for webrtc</title>
+<script src=/resources/testharness.js></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Minimal VideoConfiguration that will be allowed per spec. All optional
+// properties are missing.
+const minimalVideoConfiguration = {
+ contentType: 'video/VP9; profile-level="0"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+};
+
+// Minimal AudioConfiguration that will be allowed per spec. All optional
+// properties are missing.
+const minimalAudioConfiguration = {
+ contentType: 'audio/opus',
+};
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ }));
+}, "Test that decodingInfo rejects if the configuration doesn't have an audio or video field");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/VP9',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: -1,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a negative framerate");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/VP9"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 0,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a framerate set to 0");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/VP9"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: Infinity,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration has a framerate set to Infinity");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration contentType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'audio/fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that decodingInfo rejects if the video configuration contentType isn't of type video");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ audio: { contentType: 'fgeoa' },
+ }));
+}, "Test that decodingInfo rejects if the audio configuration contentType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ audio: { contentType: 'video/fgeoa' },
+ }));
+}, "Test that decodingInfo rejects if the audio configuration contentType isn't of type audio");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }).then(ability => {
+ assert_equals(typeof ability.supported, "boolean");
+ assert_equals(typeof ability.smooth, "boolean");
+ assert_equals(typeof ability.powerEfficient, "boolean");
+ });
+}, "Test that decodingInfo returns a valid MediaCapabilitiesInfo objects");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ audio: minimalAudioConfiguration,
+ }).then(ability => {
+ assert_false(ability.supported);
+ assert_false(ability.smooth);
+ assert_false(ability.powerEfficient);
+ });
+}, "Test that decodingInfo returns supported, smooth, and powerEfficient set to false for non-webrtc video content type.");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: minimalVideoConfiguration,
+ audio: {
+ contentType: 'audio/webm; codecs="opus"',
+ },
+ }).then(ability => {
+ assert_false(ability.supported);
+ assert_false(ability.smooth);
+ assert_false(ability.powerEfficient);
+ });
+}, "Test that decodingInfo returns supported, smooth, and powerEfficient set to false for non-webrtc audio content type.");
+
+const validAudioCodecs = (() => {
+ // Some codecs that are returned by getCapabilities() are not real codecs,
+ // exclude these from the test.
+ const excludeList = [ 'audio/CN', 'audio/telephone-event', 'audio/red' ];
+ const audioCodecs = [];
+ RTCRtpReceiver.getCapabilities("audio")['codecs'].forEach(codec => {
+ if (excludeList.indexOf(codec.mimeType) < 0 &&
+ audioCodecs.indexOf(codec.mimeType) < 0) {
+ audioCodecs.push(codec.mimeType);
+ }
+ });
+ return audioCodecs;
+})();
+
+validAudioCodecs.forEach(codec => {
+ promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ audio: {
+ contentType: codec
+ }
+ }).then(ability => {
+ assert_true(ability.supported);
+ });
+}, "Test that decodingInfo returns supported true for the codec " + codec + " returned by RTCRtpReceiver.getCapabilities()")}
+);
+
+const validVideoCodecs = (() => {
+ // Some codecs that are returned by getCapabilities() are not real codecs but
+ // only used for error correction, exclude these from the test.
+ const excludeList = [ 'video/rtx', 'video/red', 'video/ulpfec',
+ 'video/flexfec-03' ];
+ const videoCodecs = [];
+
+ RTCRtpReceiver.getCapabilities("video")['codecs'].forEach(codec => {
+ if (excludeList.indexOf(codec.mimeType) < 0) {
+ let mimeType = codec.mimeType;
+ if ('sdpFmtpLine' in codec) {
+ mimeType += "; " + codec.sdpFmtpLine;
+ }
+ if (!(mimeType in videoCodecs)) {
+ videoCodecs.push(mimeType);
+ }
+ }
+ });
+ return videoCodecs;
+})();
+
+validVideoCodecs.forEach(codec => {
+ promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: codec,
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ }
+ }).then(ability => {
+ assert_true(ability.supported);
+ });
+}, "Test that decodingInfo returns supported true for the codec " + codec + " returned by RTCRtpReceiver.getCapabilities()")}
+);
+
+</script>
diff --git a/testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.http.html b/testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.http.html
new file mode 100644
index 0000000000..267b23431b
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.http.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>MediaCapabilities.decodingInfo() for encrypted media (non-secure context)</title>
+<script src=/resources/testharness.js></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Minimal VideoConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalVideoConfiguration = {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+};
+
+// Minimal MediaCapabilitiesKeySystemConfiguration that will be allowed per
+// spec. All optional properties are missing.
+var minimalKeySystemConfiguration = {
+ keySystem: 'org.w3.clearkey'
+};
+
+promise_test(t => {
+ return promise_rejects_dom(t, 'SecurityError', navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: minimalKeySystemConfiguration,
+ }));
+}, "Test that decodingInfo() with a keySystemConfiguration fails on a non-secure context.");
+
+</script>
diff --git a/testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.https.html b/testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.https.html
new file mode 100644
index 0000000000..7ac914de89
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/decodingInfoEncryptedMedia.https.html
@@ -0,0 +1,262 @@
+<!DOCTYPE html>
+<title>MediaCapabilities.decodingInfo() for encrypted media</title>
+<meta name="timeout" content="long">
+<script src=/resources/testharness.js></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Minimal VideoConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalVideoConfiguration = {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+};
+
+// Minimal AudioConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalAudioConfiguration = {
+ contentType: 'audio/webm; codecs="opus"',
+};
+
+// Minimal MediaCapabilitiesKeySystemConfiguration that will be allowed per
+// spec. All optional properties are missing.
+var minimalKeySystemConfiguration = {
+ keySystem: 'org.w3.clearkey',
+};
+
+// Config with bogus name not provided by any UA.
+var bogusKeySystemConfiguration = {
+ keySystem: 'bogus',
+};
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: minimalKeySystemConfiguration,
+ });
+}, "Test that decodingInfo() accepts a stub key system configuration (w/video).");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: minimalAudioConfiguration,
+ keySystemConfiguration: minimalKeySystemConfiguration,
+ });
+}, "Test that decodingInfo() accepts a stub key system configuration (w/audio).");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ video: {
+ robustness: '',
+ },
+ },
+ });
+}, "Test that decodingInfo() accepts a key system configuration with video info.");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: minimalAudioConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ audio : {
+ robustness: '',
+ },
+ },
+ });
+}, "Test that decodingInfo() accepts a key system configuration with audio info.");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: minimalAudioConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ video: {
+ robustness: '',
+ },
+ },
+ }));
+}, "Test that decodingInfo() rejects if robustness and configuration do not match (1).");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ audio : {
+ robustness: '',
+ },
+ },
+ }));
+}, "Test that decodingInfo() rejects if robustness and configuration do not match (2).");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ audio : {
+ robustness: '',
+ },
+ video: {
+ robustness: '',
+ },
+ },
+ }));
+}, "Test that decodingInfo() rejects if robustness and configuration do not match (3).");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: minimalAudioConfiguration,
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ audio : {
+ robustness: '',
+ },
+ video: {
+ robustness: '',
+ },
+ persistentState: "foobar",
+ },
+ }));
+}, "Test that decodingInfo() rejects if persistentState isn't valid.");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: minimalAudioConfiguration,
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ audio : {
+ robustness: '',
+ },
+ video: {
+ robustness: '',
+ },
+ distinctiveIdentifier: "foobar",
+ },
+ }));
+}, "Test that decodingInfo() rejects if distinctiveIdentifier isn't valid.");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: minimalAudioConfiguration,
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'org.w3.clearkey',
+ audio : {
+ robustness: '',
+ },
+ video: {
+ robustness: '',
+ },
+ sessionTypes: "foobar",
+ },
+ }));
+}, "Test that decodingInfo() rejects if sessionTypes isn't a sequence.");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ audio: minimalAudioConfiguration,
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: {},
+ initDataType: {},
+ audio : {
+ robustness: '',
+ },
+ video: {
+ robustness: '',
+ },
+ },
+ });
+}, "Test that decodingInfo() does not reject when properties are set to unexpected values.");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ keySystemConfiguration: minimalKeySystemConfiguration,
+ }).then(ability => {
+ assert_equals(typeof ability.supported, "boolean");
+ assert_equals(typeof ability.smooth, "boolean");
+ assert_equals(typeof ability.powerEfficient, "boolean");
+ assert_equals(typeof ability.keySystemAccess, "object");
+ });
+}, "Test that decodingInfo returns a valid MediaCapabilitiesDecodingInfo objects with encrypted media");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: {
+ keySystem: 'foobar',
+ video: {
+ robustness: '',
+ },
+ }
+ }).then(ability => {
+ assert_false(ability.supported);
+ assert_false(ability.smooth);
+ assert_false(ability.powerEfficient);
+ assert_equals(ability.keySystemAccess, null);
+ });
+}, "Test that random key systems are reported as non supported.");
+
+// TODO(mlamouri): this test could be split in two tests for which codec support
+// across browsers is widely compatible: one when all browsers wouldn't support
+// and one where all browsers do support. The current approach is to check that
+// the answer is consistent to the spec.
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ keySystemConfiguration: minimalKeySystemConfiguration,
+ }).then(ability => {
+ if (ability.supported)
+ assert_not_equals(ability.keySystemAccess, null);
+ else
+ assert_equals(ability.keySystemAccess, null);
+ });
+}, "Test that keySystemAccess is only null when not supported if keySystemConfiguration was used.");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ // Supply bogus config to reliably result in a null keySystemAccess.
+ keySystemConfiguration: bogusKeySystemConfiguration,
+ }).then(ability => {
+ assert_equals(ability.keySystemAccess, null);
+ assert_false(ability.supported);
+ });
+}, "Test that supported=false when keySystemConfiguration is unsupported.");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
+ type: 'webrtc',
+ video: minimalVideoConfiguration,
+ keySystemConfiguration: minimalKeySystemConfiguration,
+ }));
+}, "Test that decodingInfo() with type webrtc rejects key system configuration.");
+
+</script>
diff --git a/testing/web-platform/tests/media-capabilities/encodingInfo.any.js b/testing/web-platform/tests/media-capabilities/encodingInfo.any.js
new file mode 100644
index 0000000000..6882b0ae91
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/encodingInfo.any.js
@@ -0,0 +1,310 @@
+// Minimal VideoConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalVideoConfiguration = {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+};
+
+// Minimal WebRTC VideoConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalWebrtcVideoConfiguration = {
+ contentType: 'video/VP9',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+};
+
+// Minimal AudioConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalAudioConfiguration = {
+ contentType: 'audio/webm; codecs="opus"',
+};
+
+// Minimal WebRTC AudioConfiguration that will be allowed per spec. All optional
+// properties are missing.
+var minimalWebrtcAudioConfiguration = {
+ contentType: 'audio/opus',
+};
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo());
+}, "Test that encodingInfo rejects if it doesn't get a configuration");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({}));
+}, "Test that encodingInfo rejects if the MediaConfiguration isn't valid");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }));
+}, "Test that encodingInfo rejects if the MediaConfiguration does not have a type");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ }));
+}, "Test that encodingInfo rejects if the configuration doesn't have an audio or video field");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: -1,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration has a negative framerate");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 0,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration has a framerate set to 0");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: Infinity,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration has a framerate set to Infinity");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration contentType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'audio/fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration contentType isn't of type video");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"; foo="bar"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration contentType has more than one parameter");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; foo="bar"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration contentType has one parameter that isn't codecs");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/1001',
+ }
+ }));
+}, "Test that encodingInfo() rejects framerate in the form of x/y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/0',
+ }
+ }));
+}, "Test that encodingInfo() rejects framerate in the form of x/0");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '0/10001',
+ }
+ }));
+}, "Test that encodingInfo() rejects framerate in the form of 0/y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '-24000/10001',
+ }
+ }));
+}, "Test that encodingInfo() rejects framerate in the form of -x/y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/-10001',
+ }
+ }));
+}, "Test that encodingInfo() rejects framerate in the form of x/-y");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/',
+ }
+ }));
+}, "Test that encodingInfo() rejects framerate in the form of x/");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '1/3x',
+ }
+ }));
+}, "Test that encodingInfo() rejects framerate with trailing unallowed characters");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ audio: { contentType: 'fgeoa' },
+ }));
+}, "Test that encodingInfo rejects if the audio configuration contenType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ audio: { contentType: 'video/fgeoa' },
+ }));
+}, "Test that encodingInfo rejects if the audio configuration contentType isn't of type audio");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ audio: { contentType: 'audio/webm; codecs="opus"; foo="bar"' },
+ }));
+}, "Test that encodingInfo rejects if the audio configuration contentType has more than one parameters");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ audio: { contentType: 'audio/webm; foo="bar"' },
+ }));
+}, "Test that encodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.encodingInfo({
+ type: 'record',
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }).then(ability => {
+ assert_equals(typeof ability.supported, "boolean");
+ assert_equals(typeof ability.smooth, "boolean");
+ assert_equals(typeof ability.powerEfficient, "boolean");
+ });
+}, "Test that encodingInfo returns a valid MediaCapabilitiesInfo objects for record type");
+
+async_test(t => {
+ var validTypes = [ 'record', 'webrtc' ];
+ var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource',
+ 'file', 'media-source', ];
+
+ var validPromises = [];
+ var invalidCaught = 0;
+
+ validTypes.forEach(type => {
+ validPromises.push(navigator.mediaCapabilities.encodingInfo({
+ type: type,
+ video: type != "webrtc" ? minimalVideoConfiguration : minimalWebrtcVideoConfiguration,
+ audio: type != "webrtc" ? minimalAudioConfiguration : minimalWebrtcAudioConfiguration,
+ }));
+ });
+
+ // validTypes are tested via Promise.all(validPromises) because if one of the
+ // promises fail, Promise.all() will reject. This mechanism can't be used for
+ // invalid types which will be tested individually and increment invalidCaught
+ // when rejected until the amount of rejection matches the expectation.
+ Promise.all(validPromises).then(t.step_func(() => {
+ for (var i = 0; i < invalidTypes.length; ++i) {
+ navigator.mediaCapabilities.encodingInfo({
+ type: invalidTypes[i],
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }).then(t.unreached_func(), t.step_func(e => {
+ assert_equals(e.name, 'TypeError');
+ ++invalidCaught;
+ if (invalidCaught == invalidTypes.length)
+ t.done();
+ }));
+ }
+ }), t.unreached_func('Promise.all should not reject for valid types'));
+}, "Test that encodingInfo rejects if the MediaConfiguration does not have a valid type");
diff --git a/testing/web-platform/tests/media-capabilities/encodingInfo.webrtc.html b/testing/web-platform/tests/media-capabilities/encodingInfo.webrtc.html
new file mode 100644
index 0000000000..414b7944f6
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/encodingInfo.webrtc.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html>
+<title>MediaCapabilities.encodingInfo() for webrtc</title>
+<script src=/resources/testharness.js></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Minimal VideoConfiguration that will be allowed per spec. All optional
+// properties are missing.
+const minimalVideoConfiguration = {
+ contentType: 'video/VP9; profile-level="0"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+};
+
+// Minimal AudioConfiguration that will be allowed per spec. All optional
+// properties are missing.
+const minimalAudioConfiguration = {
+ contentType: 'audio/opus',
+};
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ }));
+}, "Test that encodingInfo rejects if the configuration doesn't have an audio or video field");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/VP9',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: -1,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration has a negative framerate");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/VP9"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 0,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration has a framerate set to 0");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/VP9"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: Infinity,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration has a framerate set to Infinity");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration contentType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'audio/fgeoa',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ }));
+}, "Test that encodingInfo rejects if the video configuration contentType isn't of type video");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ audio: { contentType: 'fgeoa' },
+ }));
+}, "Test that encodingInfo rejects if the audio configuration contentType doesn't parse");
+
+promise_test(t => {
+ return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ audio: { contentType: 'video/fgeoa' },
+ }));
+}, "Test that encodingInfo rejects if the audio configuration contentType isn't of type audio");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: minimalVideoConfiguration,
+ audio: minimalAudioConfiguration,
+ }).then(ability => {
+ assert_equals(typeof ability.supported, "boolean");
+ assert_equals(typeof ability.smooth, "boolean");
+ assert_equals(typeof ability.powerEfficient, "boolean");
+ });
+}, "Test that encodingInfo returns a valid MediaCapabilitiesInfo objects");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ },
+ audio: minimalAudioConfiguration,
+ }).then(ability => {
+ assert_false(ability.supported);
+ assert_false(ability.smooth);
+ assert_false(ability.powerEfficient);
+ });
+}, "Test that encodingInfo returns supported, smooth, and powerEfficient set to false for non-webrtc video content type.");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: minimalVideoConfiguration,
+ audio: {
+ contentType: 'audio/webm; codecs="opus"',
+ },
+ }).then(ability => {
+ assert_false(ability.supported);
+ assert_false(ability.smooth);
+ assert_false(ability.powerEfficient);
+ });
+}, "Test that encodingInfo returns supported, smooth, and powerEfficient set to false for non-webrtc audio content type.");
+
+const validAudioCodecs = (() => {
+ // Some codecs that are returned by getCapabilities() are not real codecs,
+ // exclude these from the test.
+ const excludeList = [ 'audio/CN', 'audio/telephone-event', 'audio/red' ];
+ const audioCodecs = [];
+ RTCRtpSender.getCapabilities("audio")['codecs'].forEach(codec => {
+ if (excludeList.indexOf(codec.mimeType) < 0 &&
+ audioCodecs.indexOf(codec.mimeType) < 0) {
+ audioCodecs.push(codec.mimeType);
+ }
+ });
+ return audioCodecs;
+})();
+
+validAudioCodecs.forEach(codec => {
+ promise_test(t => {
+ return navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ audio: {
+ contentType: codec
+ }
+ }).then(ability => {
+ assert_true(ability.supported);
+ });
+}, "Test that encodingInfo returns supported true for the codec " + codec + " returned by RTCRtpSender.getCapabilities()")}
+);
+
+const validVideoCodecs = (() => {
+ // Some codecs that are returned by getCapabilities() are not real codecs but
+ // only used for error correction, exclude these from the test.
+ const excludeList = [ 'video/rtx', 'video/red', 'video/ulpfec',
+ 'video/flexfec-03' ];
+ const videoCodecs = [];
+
+ RTCRtpSender.getCapabilities("video")['codecs'].forEach(codec => {
+ if (excludeList.indexOf(codec.mimeType) < 0) {
+ let mimeType = codec.mimeType;
+ if ('sdpFmtpLine' in codec) {
+ mimeType += "; " + codec.sdpFmtpLine;
+ }
+ if (!(mimeType in videoCodecs)) {
+ videoCodecs.push(mimeType);
+ }
+ }
+ });
+ return videoCodecs;
+})();
+
+validVideoCodecs.forEach(codec => {
+ promise_test(t => {
+ return navigator.mediaCapabilities.encodingInfo({
+ type: 'webrtc',
+ video: {
+ contentType: codec,
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: 24,
+ }
+ }).then(ability => {
+ assert_true(ability.supported);
+ });
+}, "Test that encodingInfo returns supported true for the codec " + codec + " returned by RTCRtpSender.getCapabilities()")}
+);
+
+</script>
diff --git a/testing/web-platform/tests/media-capabilities/idlharness.any.js b/testing/web-platform/tests/media-capabilities/idlharness.any.js
new file mode 100644
index 0000000000..6da5c7d284
--- /dev/null
+++ b/testing/web-platform/tests/media-capabilities/idlharness.any.js
@@ -0,0 +1,25 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://wicg.github.io/media-capabilities/
+
+'use strict';
+
+promise_test(async () => {
+ idl_test(
+ ['media-capabilities'],
+ ['html', 'cssom-view'],
+ idl_array => {
+ if (self.GLOBAL.isWorker()) {
+ idl_array.add_objects({ WorkerNavigator: ['navigator'] });
+ } else {
+ idl_array.add_objects({ Navigator: ['navigator'] });
+ }
+ idl_array.add_objects({
+ MediaCapabilities: ['navigator.mediaCapabilities'],
+ Screen: ['screen'],
+ ScreenLuminance: ['screen.luminance'],
+ });
+ }
+ );
+});