decodingInfo.any.js (14420B)
1 // META: timeout=long 2 'use strict'; 3 4 // Minimal VideoConfiguration that will be allowed per spec. All optional 5 // properties are missing. 6 const minimalVideoConfiguration = { 7 contentType: 'video/webm; codecs="vp09.00.10.08"', 8 width: 800, 9 height: 600, 10 bitrate: 3000, 11 framerate: 24, 12 }; 13 14 // Minimal AudioConfiguration that will be allowed per spec. All optional 15 // properties are missing. 16 const minimalAudioConfiguration = { 17 contentType: 'audio/webm; codecs="opus"', 18 }; 19 20 // AudioConfiguration with optional spatialRendering param. 21 const audioConfigurationWithSpatialRendering = { 22 contentType: 'audio/webm; codecs="opus"', 23 spatialRendering: true, 24 }; 25 26 // VideoConfiguration with optional hdrMetadataType, colorGamut, and 27 // transferFunction properties. 28 const videoConfigurationWithDynamicRange = { 29 contentType: 'video/webm; codecs="vp09.00.10.08.00.09.16.09.00"', 30 width: 800, 31 height: 600, 32 bitrate: 3000, 33 framerate: 24, 34 hdrMetadataType: 'smpteSt2086', 35 colorGamut: 'rec2020', 36 transferFunction: 'pq', 37 }; 38 39 40 promise_test(t => { 41 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo()); 42 }, "Test that decodingInfo rejects if it doesn't get a configuration"); 43 44 promise_test(t => { 45 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({})); 46 }, "Test that decodingInfo rejects if the MediaConfiguration isn't valid"); 47 48 promise_test(t => { 49 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 50 video: minimalVideoConfiguration, 51 audio: minimalAudioConfiguration, 52 })); 53 }, "Test that decodingInfo rejects if the MediaConfiguration does not have a type"); 54 55 promise_test(t => { 56 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 57 type: 'file', 58 })); 59 }, "Test that decodingInfo rejects if the configuration doesn't have an audio or video field"); 60 61 promise_test(t => { 62 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 63 type: 'file', 64 video: { 65 contentType: 'video/webm; codecs="vp09.00.10.08"', 66 width: 800, 67 height: 600, 68 bitrate: 3000, 69 framerate: -1, 70 }, 71 })); 72 }, "Test that decodingInfo rejects if the video configuration has a negative framerate"); 73 74 promise_test(t => { 75 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 76 type: 'file', 77 video: { 78 contentType: 'video/webm; codecs="vp09.00.10.08"', 79 width: 800, 80 height: 600, 81 bitrate: 3000, 82 framerate: 0, 83 }, 84 })); 85 }, "Test that decodingInfo rejects if the video configuration has a framerate set to 0"); 86 87 promise_test(t => { 88 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 89 type: 'file', 90 video: { 91 contentType: 'video/webm; codecs="vp09.00.10.08"', 92 width: 800, 93 height: 600, 94 bitrate: 3000, 95 framerate: Infinity, 96 }, 97 })); 98 }, "Test that decodingInfo rejects if the video configuration has a framerate set to Infinity"); 99 100 promise_test(t => { 101 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 102 type: 'file', 103 video: { 104 contentType: 'fgeoa', 105 width: 800, 106 height: 600, 107 bitrate: 3000, 108 framerate: 24, 109 }, 110 })); 111 }, "Test that decodingInfo rejects if the video configuration contentType doesn't parse"); 112 113 // See https://mimesniff.spec.whatwg.org/#example-valid-mime-type-string 114 promise_test(t => { 115 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 116 type: 'file', 117 video: { 118 contentType: 'video/webm;', 119 width: 800, 120 height: 600, 121 bitrate: 3000, 122 framerate: 24, 123 }, 124 })); 125 }, "Test that decodingInfo rejects if the video configuration contentType is not a valid MIME type string"); 126 127 promise_test(t => { 128 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 129 type: 'file', 130 video: { 131 contentType: 'audio/fgeoa', 132 width: 800, 133 height: 600, 134 bitrate: 3000, 135 framerate: 24, 136 }, 137 })); 138 }, "Test that decodingInfo rejects if the video configuration contentType isn't of type video"); 139 140 promise_test(t => { 141 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 142 type: 'file', 143 video: { 144 contentType: 'application/ogg; codecs=vorbis', 145 width: 800, 146 height: 600, 147 bitrate: 3000, 148 framerate: 24, 149 }, 150 })); 151 }, "Test that decodingInfo rejects if the video configuration contentType is of type audio"); 152 153 promise_test(t => { 154 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 155 type: 'file', 156 audio: { 157 contentType: 'application/ogg; codecs=theora', 158 channels: 2, 159 }, 160 })); 161 }, "Test that decodingInfo rejects if the audio configuration contentType is of type video"); 162 163 promise_test(t => { 164 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 165 type: 'file', 166 video: { 167 contentType: 'video/webm; codecs="vp09.00.10.08"; foo="bar"', 168 width: 800, 169 height: 600, 170 bitrate: 3000, 171 framerate: 24, 172 }, 173 })); 174 }, "Test that decodingInfo rejects if the video configuration contentType has more than one parameter"); 175 176 promise_test(t => { 177 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 178 type: 'file', 179 video: { 180 contentType: 'video/webm; foo="bar"', 181 width: 800, 182 height: 600, 183 bitrate: 3000, 184 framerate: 24, 185 }, 186 })); 187 }, "Test that decodingInfo rejects if the video configuration contentType has one parameter that isn't codecs"); 188 189 promise_test(t => { 190 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 191 type: 'file', 192 video: { 193 contentType: 'video/webm', 194 width: 800, 195 height: 600, 196 bitrate: 3000, 197 framerate: 24, 198 }, 199 })); 200 }, "Test that decodingInfo rejects if the video configuration contentType does not imply a single media codec but has no codecs parameter"); 201 202 promise_test(t => { 203 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 204 type: 'file', 205 video: { 206 contentType: 'video/webm; codecs="vp09.00.10.08, vp8"', 207 width: 800, 208 height: 600, 209 bitrate: 3000, 210 framerate: 24, 211 } 212 })); 213 }, "Test that decodingInfo rejects if the video configuration contentType has a codecs parameter that indicates multiple video codecs"); 214 215 promise_test(t => { 216 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 217 type: 'file', 218 video: { 219 contentType: 'video/webm; codecs="vp09.00.10.08, opus"', 220 width: 800, 221 height: 600, 222 bitrate: 3000, 223 framerate: 24, 224 } 225 })); 226 }, "Test that decodingInfo rejects if the video configuration contentType has a codecs parameter that indicates both an audio and a video codec"); 227 228 promise_test(t => { 229 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 230 type: 'file', 231 audio: { contentType: 'fgeoa' }, 232 })); 233 }, "Test that decodingInfo rejects if the audio configuration contentType doesn't parse"); 234 235 // See https://mimesniff.spec.whatwg.org/#example-valid-mime-type-string 236 promise_test(t => { 237 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 238 type: 'file', 239 audio: { contentType: 'audio/mpeg;' }, 240 })); 241 }, "Test that decodingInfo rejects if the audio configuration contentType is not a valid MIME type string"); 242 243 promise_test(t => { 244 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 245 type: 'file', 246 audio: { contentType: 'video/fgeoa' }, 247 })); 248 }, "Test that decodingInfo rejects if the audio configuration contentType isn't of type audio"); 249 250 promise_test(t => { 251 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 252 type: 'file', 253 audio: { contentType: 'audio/webm; codecs="opus"; foo="bar"' }, 254 })); 255 }, "Test that decodingInfo rejects if the audio configuration contentType has more than one parameter"); 256 257 promise_test(t => { 258 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 259 type: 'file', 260 audio: { contentType: 'audio/webm; foo="bar"' }, 261 })); 262 }, "Test that decodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs"); 263 264 promise_test(t => { 265 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 266 type: 'file', 267 audio: { contentType: 'audio/webm' }, 268 })); 269 }, "Test that decodingInfo rejects if the audio configuration contentType does not imply a single media codec but has no codecs parameter"); 270 271 promise_test(t => { 272 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 273 type: 'file', 274 audio: { contentType: 'audio/webm; codecs="vorbis, opus"' }, 275 })); 276 }, "Test that decodingInfo rejects if the audio configuration contentType has a codecs parameter that indicates multiple audio codecs"); 277 278 promise_test(t => { 279 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 280 type: 'file', 281 audio: { contentType: 'audio/webm; codecs="vp09.00.10.08, opus"' }, 282 })); 283 }, "Test that decodingInfo rejects if the audio configuration contentType has a codecs parameter that indicates both an audio and a video codec"); 284 285 promise_test(t => { 286 return navigator.mediaCapabilities.decodingInfo({ 287 type: 'file', 288 video: minimalVideoConfiguration, 289 audio: minimalAudioConfiguration, 290 }).then(ability => { 291 assert_equals(typeof ability.supported, "boolean"); 292 assert_equals(typeof ability.smooth, "boolean"); 293 assert_equals(typeof ability.powerEfficient, "boolean"); 294 assert_equals(typeof ability.keySystemAccess, "object"); 295 }); 296 }, "Test that decodingInfo returns a valid MediaCapabilitiesInfo objects"); 297 298 async_test(t => { 299 var validTypes = [ 'file', 'media-source' ]; 300 var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource', 301 'record', 'transmission' ]; 302 303 var validPromises = []; 304 var invalidCaught = 0; 305 306 validTypes.forEach(type => { 307 validPromises.push(navigator.mediaCapabilities.decodingInfo({ 308 type: type, 309 video: minimalVideoConfiguration, 310 audio: minimalAudioConfiguration, 311 })); 312 }); 313 314 // validTypes are tested via Promise.all(validPromises) because if one of the 315 // promises fail, Promise.all() will reject. This mechanism can't be used for 316 // invalid types which will be tested individually and increment invalidCaught 317 // when rejected until the amount of rejection matches the expectation. 318 Promise.all(validPromises).then(t.step_func(() => { 319 for (var i = 0; i < invalidTypes.length; ++i) { 320 navigator.mediaCapabilities.decodingInfo({ 321 type: invalidTypes[i], 322 video: minimalVideoConfiguration, 323 audio: minimalAudioConfiguration, 324 }).then(t.unreached_func(), t.step_func(e => { 325 assert_equals(e.name, 'TypeError'); 326 ++invalidCaught; 327 if (invalidCaught == invalidTypes.length) 328 t.done(); 329 })); 330 } 331 }), t.unreached_func('Promise.all should not reject for valid types')); 332 }, "Test that decodingInfo rejects if the MediaConfiguration does not have a valid type"); 333 334 promise_test(t => { 335 return navigator.mediaCapabilities.decodingInfo({ 336 type: 'file', 337 audio: audioConfigurationWithSpatialRendering, 338 }).then(ability => { 339 assert_equals(typeof ability.supported, "boolean"); 340 assert_equals(typeof ability.smooth, "boolean"); 341 assert_equals(typeof ability.powerEfficient, "boolean"); 342 assert_equals(typeof ability.keySystemAccess, "object"); 343 }); 344 }, "Test that decodingInfo with spatialRendering set returns a valid MediaCapabilitiesInfo objects"); 345 346 promise_test(t => { 347 return navigator.mediaCapabilities.decodingInfo({ 348 type: 'file', 349 video: videoConfigurationWithDynamicRange, 350 }).then(ability => { 351 assert_equals(typeof ability.supported, "boolean"); 352 assert_equals(typeof ability.smooth, "boolean"); 353 assert_equals(typeof ability.powerEfficient, "boolean"); 354 assert_equals(typeof ability.keySystemAccess, "object"); 355 }); 356 }, "Test that decodingInfo with hdrMetadataType, colorGamut, and transferFunction set returns a valid MediaCapabilitiesInfo objects"); 357 358 promise_test(t => { 359 // VP9 has a default color space of BT.709 in the codec string. So this will 360 // mismatch against the provided colorGamut and transferFunction. 361 let bt709Config = videoConfigurationWithDynamicRange; 362 bt709Config.contentType = 'video/webm; codecs="vp09.00.10.08"'; 363 return navigator.mediaCapabilities 364 .decodingInfo({ 365 type: 'file', 366 video: bt709Config, 367 }) 368 .then(ability => { 369 assert_equals(typeof ability.supported, 'boolean'); 370 assert_equals(typeof ability.smooth, 'boolean'); 371 assert_equals(typeof ability.powerEfficient, 'boolean'); 372 assert_equals(typeof ability.keySystemAccess, 'object'); 373 assert_false(ability.supported); 374 }); 375 }, 'Test that decodingInfo with mismatched codec color space is unsupported'); 376 377 promise_test(t => { 378 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 379 type: 'file', 380 video: { 381 contentType: 'video/webm; codecs="vp09.00.10.08"', 382 width: 800, 383 height: 600, 384 bitrate: 3000, 385 framerate: 24, 386 hdrMetadataType: "" 387 }, 388 })); 389 }, "Test that decodingInfo rejects if the video configuration has an empty hdrMetadataType"); 390 391 promise_test(t => { 392 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 393 type: 'file', 394 video: { 395 contentType: 'video/webm; codecs="vp09.00.10.08"', 396 width: 800, 397 height: 600, 398 bitrate: 3000, 399 framerate: 24, 400 colorGamut: true 401 }, 402 })); 403 }, "Test that decodingInfo rejects if the video configuration has a colorGamut set to true"); 404 405 promise_test(t => { 406 return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({ 407 type: 'file', 408 video: { 409 contentType: 'video/webm; codecs="vp09.00.10.08"', 410 width: 800, 411 height: 600, 412 bitrate: 3000, 413 framerate: 24, 414 transferFunction: 3 415 }, 416 })); 417 }, "Test that decodingInfo rejects if the video configuration has a transferFunction set to 3");