tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

manifest.js (79557B)


      1 const { AppConstants } = SpecialPowers.ChromeUtils.importESModule(
      2  "resource://gre/modules/AppConstants.sys.mjs"
      3 );
      4 
      5 // In each list of tests below, test file types that are not supported should
      6 // be ignored. To make sure tests respect that, we include a file of type
      7 // "bogus/duh" in each list.
      8 
      9 // Make sure to not touch navigator in here, since we want to push prefs that
     10 // will affect the APIs it exposes, but the set of exposed APIs is determined
     11 // when Navigator.prototype is created.  So if we touch navigator before pushing
     12 // the prefs, the APIs it exposes will not take those prefs into account.  We
     13 // work around this by using a navigator object from a different global for our
     14 // UA string testing.
     15 var gManifestNavigatorSource = document.documentElement.appendChild(
     16  document.createElement("iframe")
     17 );
     18 gManifestNavigatorSource.style.display = "none";
     19 function manifestNavigator() {
     20  return gManifestNavigatorSource.contentWindow.navigator;
     21 }
     22 
     23 // Similarly, use a <video> element from a different global for canPlayType or
     24 // other feature testing.  If we used one from our global and did so before our
     25 // prefs are pushed, then we'd instantiate HTMLMediaElement.prototype before the
     26 // prefs are pushed and APIs we expect to be on that object would not be there.
     27 function manifestVideo() {
     28  return gManifestNavigatorSource.contentDocument.createElement("video");
     29 }
     30 
     31 // Need to get the server url composed with ip:port instead of mochi.test.
     32 // Since we will provide the url to Exoplayer which cannot recognize the domain
     33 // name "mochi.test".
     34 let serverUrl = SpecialPowers.Services.prefs.getCharPref(
     35  "media.hls.server.url"
     36 );
     37 var gHLSTests = [
     38  {
     39    name: serverUrl + "/bipbop_4x3_variant.m3u8",
     40    type: "audio/x-mpegurl",
     41    duration: 20.0,
     42  },
     43 ];
     44 
     45 // These are small test files, good for just seeing if something loads. We
     46 // really only need one test file per backend here.
     47 var gSmallTests = [
     48  { name: "small-shot.ogg", type: "audio/ogg", duration: 0.276 },
     49  { name: "small-shot.m4a", type: "audio/mp4", duration: 0.29 },
     50  { name: "small-shot.mp3", type: "audio/mpeg", duration: 0.27 },
     51  { name: "small-shot-mp3.mp4", type: "audio/mp4; codecs=mp3", duration: 0.34 },
     52  { name: "small-shot.flac", type: "audio/flac", duration: 0.197 },
     53  { name: "r11025_s16_c1-short.wav", type: "audio/x-wav", duration: 0.37 },
     54  {
     55    name: "seek-short.webm",
     56    type: "video/webm",
     57    width: 320,
     58    height: 240,
     59    duration: 0.23,
     60  },
     61  {
     62    name: "vp9-short.webm",
     63    type: "video/webm",
     64    width: 320,
     65    height: 240,
     66    duration: 0.2,
     67  },
     68  {
     69    name: "detodos-short.opus",
     70    type: "audio/ogg; codecs=opus",
     71    duration: 0.22,
     72  },
     73  {
     74    name: "gizmo-short.mp4",
     75    type: "video/mp4",
     76    width: 560,
     77    height: 320,
     78    duration: 0.27,
     79  },
     80  { name: "flac-s24.flac", type: "audio/flac", duration: 4.04 },
     81  { name: "bogus.duh", type: "bogus/duh" },
     82  {
     83    name: "avc-2bytes-nalu.mp4",
     84    type: "video/mp4",
     85    width: 560,
     86    height: 320,
     87    duration: 0.27,
     88  },
     89  {
     90    name: "1967133.mp4",
     91    type: "video/mp4",
     92    width: 1080,
     93    height: 1080,
     94    duration: 0.512,
     95  },
     96 ];
     97 
     98 var gFrameCountTests = [
     99  { name: "bipbop.mp4", type: "video/mp4", totalFrameCount: 297 },
    100  { name: "gizmo.mp4", type: "video/mp4", totalFrameCount: 166 },
    101  { name: "seek-short.webm", type: "video/webm", totalFrameCount: 8 },
    102  { name: "seek.webm", type: "video/webm", totalFrameCount: 120 },
    103  { name: "av1.mp4", type: "video/mp4", totalFrameCount: 24 },
    104 ];
    105 
    106 gSmallTests = gSmallTests.concat([
    107  { name: "sample.3gp", type: "video/3gpp", duration: 4.933 },
    108  { name: "sample.3g2", type: "video/3gpp2", duration: 4.933 },
    109 ]);
    110 
    111 // Used by test_bug654550.html, for videoStats preference
    112 var gVideoTests = [
    113  {
    114    name: "seek-short.webm",
    115    type: "video/webm",
    116    width: 320,
    117    height: 240,
    118    duration: 0.23,
    119  },
    120  { name: "bogus.duh", type: "bogus/duh" },
    121 ];
    122 
    123 // Temp hack for trackIDs and captureStream() -- bug 1215769
    124 var gLongerTests = [
    125  {
    126    name: "seek.webm",
    127    type: "video/webm",
    128    width: 320,
    129    height: 240,
    130    duration: 3.966,
    131  },
    132  {
    133    name: "gizmo.mp4",
    134    type: "video/mp4",
    135    width: 560,
    136    height: 320,
    137    duration: 5.56,
    138  },
    139 ];
    140 
    141 // Used by test_progress to ensure we get the correct progress information
    142 // during resource download.
    143 var gProgressTests = [
    144  { name: "r11025_u8_c1.wav", type: "audio/x-wav", duration: 1.0, size: 11069 },
    145  { name: "big-short.wav", type: "audio/x-wav", duration: 1.11, size: 12366 },
    146  { name: "seek-short.webm", type: "video/webm", duration: 0.23, size: 19267 },
    147  { name: "gizmo-short.mp4", type: "video/mp4", duration: 0.27, size: 29905 },
    148  { name: "bogus.duh", type: "bogus/duh" },
    149 ];
    150 
    151 // Used by test_played.html
    152 var gPlayedTests = [
    153  { name: "big-short.wav", type: "audio/x-wav", duration: 1.11 },
    154  { name: "seek-short.webm", type: "video/webm", duration: 0.23 },
    155  { name: "gizmo-short.mp4", type: "video/mp4", duration: 0.27 },
    156  { name: "owl-short.mp3", type: "audio/mpeg", duration: 0.52 },
    157  { name: "very-short.mp3", type: "audio/mpeg", duration: 0.07 },
    158  // Disable vbr.mp3 to see if it reduces the error of AUDCLNT_E_CPUUSAGE_EXCEEDED.
    159  // See bug 1110922 comment 26.
    160  //{ name:"vbr.mp3", type:"audio/mpeg", duration:10.0 },
    161  { name: "bug495794.ogg", type: "audio/ogg", duration: 0.3 },
    162 ];
    163 
    164 if (
    165  manifestNavigator().userAgent.includes("Windows") &&
    166  manifestVideo().canPlayType('video/mp4; codecs="avc1.64000c"')
    167 ) {
    168  gPlayedTests = gPlayedTests.concat(
    169    { name: "red-46x48.mp4", type: "video/mp4", duration: 1.0 },
    170    { name: "red-48x46.mp4", type: "video/mp4", duration: 1.0 }
    171  );
    172 }
    173 
    174 // Used by test_mozLoadFrom.  Need one test file per decoder backend, plus
    175 // anything for testing clone-specific bugs.
    176 var cloneKey = Math.floor(Math.random() * 100000000);
    177 var gCloneTests = [
    178  // vp9.webm is more like 4s, so if you load this twice you'll get an unexpected duration
    179  {
    180    name:
    181      "dynamic_resource.sjs?key=" +
    182      cloneKey +
    183      "&res1=seek-short.webm&res2=vp9.webm",
    184    type: "video/webm",
    185    duration: 0.23,
    186  },
    187 ];
    188 
    189 // Used by test_play_twice.  Need one test file per decoder backend, plus
    190 // anything for testing bugs that occur when replying a played file.
    191 var gReplayTests = gSmallTests.concat([
    192  { name: "bug533822.ogg", type: "audio/ogg" },
    193 ]);
    194 
    195 // Used by test_paused_after_ended. Need one test file per decoder backend, plus
    196 // anything for testing bugs that occur when replying a played file.
    197 var gPausedAfterEndedTests = gSmallTests.concat([
    198  { name: "r11025_u8_c1.wav", type: "audio/x-wav", duration: 1.0 },
    199  { name: "small-shot.ogg", type: "video/ogg", duration: 0.276 },
    200 ]);
    201 
    202 // Test the mozHasAudio property, and APIs that detect different kinds of
    203 // tracks
    204 var gTrackTests = [
    205  {
    206    name: "big-short.wav",
    207    type: "audio/x-wav",
    208    duration: 1.11,
    209    size: 12366,
    210    hasAudio: true,
    211    hasVideo: false,
    212  },
    213  {
    214    name: "seek-short.webm",
    215    type: "video/webm",
    216    duration: 0.23,
    217    size: 19267,
    218    hasAudio: false,
    219    hasVideo: true,
    220  },
    221  {
    222    name: "flac-s24.flac",
    223    type: "audio/flac",
    224    duration: 4.04,
    225    hasAudio: true,
    226    hasVideo: false,
    227  },
    228  { name: "bogus.duh", type: "bogus/duh" },
    229 ];
    230 
    231 // Used by any media recorder test. Need one test file per decoder backend
    232 // currently supported by the media encoder.
    233 var gMediaRecorderTests = [
    234  // Duration should be greater than 500ms because we will record 2
    235  // time slices (250ms per slice)
    236  {
    237    name: "detodos-recorder-test.opus",
    238    type: "audio/ogg; codecs=opus",
    239    duration: 0.62,
    240  },
    241 ];
    242 
    243 // Used by video media recorder tests
    244 var gMediaRecorderVideoTests = [
    245  {
    246    name: "seek-short.webm",
    247    type: "video/webm",
    248    width: 320,
    249    height: 240,
    250    duration: 0.23,
    251  },
    252 ];
    253 
    254 // These are files that we want to make sure we can play through.  We can
    255 // also check metadata.  Put files of the same type together in this list so if
    256 // something crashes we have some idea of which backend is responsible.
    257 // Used by test_playback, which expects no error event and one ended event.
    258 var gPlayTests = [
    259  // Test playback of a WebM file with vp9 video
    260  { name: "vp9cake-short.webm", type: "video/webm", duration: 1.0 },
    261  // 8-bit samples
    262  { name: "r11025_u8_c1.wav", type: "audio/x-wav", duration: 1.0 },
    263  // 8-bit samples, file is truncated
    264  { name: "r11025_u8_c1_trunc.wav", type: "audio/x-wav", duration: 1.8 },
    265  // file has trailing non-PCM data
    266  { name: "r11025_s16_c1_trailing.wav", type: "audio/x-wav", duration: 1.0 },
    267  // file with list chunk
    268  { name: "r16000_u8_c1_list.wav", type: "audio/x-wav", duration: 4.2 },
    269  // file with 2 extra bytes of metadata
    270  {
    271    name: "16bit_wave_extrametadata.wav",
    272    type: "audio/x-wav",
    273    duration: 1.108,
    274  },
    275  // IEEE float wave file
    276  { name: "wavedata_float.wav", type: "audio/x-wav", duration: 1.0 },
    277  // 24-bit samples
    278  { name: "wavedata_s24.wav", type: "audio/x-wav", duration: 1.0 },
    279  // aLaw compressed wave file
    280  { name: "wavedata_alaw.wav", type: "audio/x-wav", duration: 1.0 },
    281  // uLaw compressed wave file
    282  { name: "wavedata_ulaw.wav", type: "audio/x-wav", duration: 1.0 },
    283  // Data length 0xFFFFFFFF
    284  { name: "bug1301226.wav", type: "audio/x-wav", duration: 0.003673 },
    285  // Data length 0xFFFFFFFF and odd chunk lengths.
    286  { name: "bug1301226-odd.wav", type: "audio/x-wav", duration: 0.003673 },
    287 
    288  // Encoded with vorbis beta1, includes unusually sized codebooks
    289  { name: "beta-phrasebook.ogg", type: "audio/ogg", duration: 4.01 },
    290  // Small file, only 1 frame with audio only.
    291  { name: "bug520493.ogg", type: "audio/ogg", duration: 0.458 },
    292  // Small file with vorbis comments with 0 length values and names.
    293  { name: "bug520500.ogg", type: "audio/ogg", duration: 0.123 },
    294 
    295  { name: "bug495794.ogg", type: "audio/ogg", duration: 0.3 },
    296  { name: "audio-overhang.ogg", type: "video/ogg", duration: 2.3 },
    297  { name: "video-overhang.ogg", type: "video/ogg", duration: 3.966 },
    298 
    299  // bug461281.ogg with the middle second chopped out.
    300  { name: "audio-gaps.ogg", type: "audio/ogg", duration: 2.208 },
    301 
    302  // Test playback/metadata work after a redirect
    303  {
    304    name: "redirect.sjs?domain=mochi.test:8888&file=vp9.webm",
    305    type: "video/webm",
    306  },
    307 
    308  // Test playback of a webm file
    309  { name: "seek-short.webm", type: "video/webm", duration: 0.23 },
    310 
    311  // Test playback of a webm file with 'matroska' doctype
    312  // TODO : re-enable this in bug 1985419 after MKV is supported.
    313  // { name: "bug1377278.webm", type: "video/webm", duration: 4.0 },
    314 
    315  // Test playback of a WebM file with non-zero start time.
    316  { name: "split.webm", type: "video/webm", duration: 1.967 },
    317 
    318  // Test playback of a WebM file with resolution changes.
    319  { name: "resolution-change.webm", type: "video/webm", duration: 6.533 },
    320 
    321  // The following webm files test cases where the webm metadata dimensions do
    322  // not match those in the stream. See bug 1695033 for more info.
    323 
    324  // Reference file with correct dimensions (webm metadata matches stream
    325  // resolution).
    326  { name: "bipbop_short_vp8.webm", type: "video/webm", duration: 1.011 },
    327 
    328  // The webm resolution is greater in both dimensions than the in stream
    329  // resolution.
    330  {
    331    name: "bipbop_short_pixel_metadata_bigger_than_in_stream_vp8.webm",
    332    type: "video/webm",
    333    duration: 1.011,
    334  },
    335 
    336  // The webm resolution is correct for height, but is narrower than the stream
    337  // resolution.
    338  {
    339    name: "bipbop_short_pixel_metadata_narrower_than_in_stream_vp8.webm",
    340    type: "video/webm",
    341    duration: 1.011,
    342  },
    343 
    344  // The webm resolution is smaller in both dimensions than the in stream
    345  // resolution.
    346  {
    347    name: "bipbop_short_pixel_metadata_smaller_than_in_stream_vp8.webm",
    348    type: "video/webm",
    349    duration: 1.011,
    350  },
    351 
    352  // End of webm dimension clashing files.
    353 
    354  // A really short, low sample rate, single channel file. This tests whether
    355  // we can handle playing files when only push very little audio data to the
    356  // hardware.
    357  { name: "spacestorm-1000Hz-100ms.ogg", type: "audio/ogg", duration: 0.099 },
    358 
    359  // Opus data in an ogg container
    360  {
    361    name: "detodos-short.opus",
    362    type: "audio/ogg; codecs=opus",
    363    duration: 0.22,
    364    contentDuration: 0.2135,
    365  },
    366  // Opus data in a webm container
    367  {
    368    name: "detodos-short.webm",
    369    type: "audio/webm; codecs=opus",
    370    duration: 0.26,
    371    contentDuration: 0.2535,
    372  },
    373  // Opus in webm channel mapping=2 sample file
    374  {
    375    name: "opus-mapping2.webm",
    376    type: "audio/webm; codecs=opus",
    377    duration: 10.01,
    378    contentDuration: 9.99,
    379  },
    380  { name: "bug1066943.webm", type: "audio/webm; codecs=opus", duration: 1.383 },
    381 
    382  // Multichannel Opus in an ogg container
    383  { name: "test-1-mono.opus", type: "audio/ogg; codecs=opus", duration: 1.044 },
    384  {
    385    name: "test-2-stereo.opus",
    386    type: "audio/ogg; codecs=opus",
    387    duration: 2.925,
    388  },
    389  { name: "test-3-LCR.opus", type: "audio/ogg; codecs=opus", duration: 4.214 },
    390  { name: "test-4-quad.opus", type: "audio/ogg; codecs=opus", duration: 6.234 },
    391  { name: "test-5-5.0.opus", type: "audio/ogg; codecs=opus", duration: 7.558 },
    392  { name: "test-6-5.1.opus", type: "audio/ogg; codecs=opus", duration: 10.333 },
    393  { name: "test-7-6.1.opus", type: "audio/ogg; codecs=opus", duration: 11.69 },
    394  { name: "test-8-7.1.opus", type: "audio/ogg; codecs=opus", duration: 13.478 },
    395 
    396  {
    397    name: "gizmo-short.mp4",
    398    type: "video/mp4",
    399    duration: 0.27,
    400    contentDuration: 0.267,
    401  },
    402  // Test playback of a MP4 file with a non-zero start time (and audio starting
    403  // a second later).
    404  { name: "bipbop-lateaudio.mp4", type: "video/mp4" },
    405  // Opus in MP4 channel mapping=0 sample file (content shorter due to preskip)
    406  {
    407    name: "opus-sample.mp4",
    408    type: "audio/mp4; codecs=opus",
    409    duration: 10.92,
    410    contentDuration: 10.09,
    411  },
    412  // Opus in MP4 channel mapping=2 sample file
    413  { name: "opus-mapping2.mp4", type: "audio/mp4; codecs=opus", duration: 10.0 },
    414 
    415  { name: "small-shot.m4a", type: "audio/mp4", duration: 0.29 },
    416  { name: "small-shot.mp3", type: "audio/mpeg", duration: 0.27 },
    417  { name: "owl.mp3", type: "audio/mpeg", duration: 3.343 },
    418  // owl.mp3 as above, but with something funny going on in the ID3v2 tag
    419  // that caused DirectShow to fail.
    420  { name: "owl-funny-id3.mp3", type: "audio/mpeg", duration: 3.343 },
    421  // owl.mp3 as above, but with something even funnier going on in the ID3v2 tag
    422  // that caused DirectShow to fail.
    423  { name: "owl-funnier-id3.mp3", type: "audio/mpeg", duration: 3.343 },
    424  // One second of silence with ~140KB of ID3 tags. Usually when the first MP3
    425  // frame is at such a high offset into the file, MP3FrameParser will give up
    426  // and report that the stream is not MP3. However, it does not count ID3 tags
    427  // in that offset. This test case makes sure that ID3 exclusion holds.
    428  { name: "huge-id3.mp3", type: "audio/mpeg", duration: 1.0 },
    429  // Half a second file of a sine with a large ID3v2 tag, followed by an ID3v1
    430  // tag. The ID3v1 tags should be at the end of the file, but software usually
    431  // play it anyway.
    432  { name: "id3v1afterlongid3v2.mp3", type: "audio/mpeg", duration: 0.5 },
    433  // An VBR file with a padding value that is greater than an mp3 packet, and
    434  // also subsequent packets after the theoretical EOF computed from metadata,
    435  // to test padding trimming edge cases.
    436  {
    437    name: "padding-spanning-multiple-packets.mp3",
    438    type: "audio/mpeg",
    439  },
    440  // A truncated VBR MP3 with just enough frames to keep most decoders happy.
    441  // The Xing header reports the length of the file to be around 10 seconds, but
    442  // there is really only one second worth of data. We want MP3FrameParser to
    443  // trust the header, so this should be reported as 10 seconds.
    444  {
    445    name: "vbr-head.mp3",
    446    type: "audio/mpeg",
    447    duration: 10.0,
    448    contentDuration: 1.019,
    449  },
    450 
    451  // A flac file where the STREAMINFO block was removed.
    452  // It is necessary to parse the file to find an audio frame instead.
    453  { name: "flac-noheader-s16.flac", type: "audio/flac", duration: 4.0 },
    454  { name: "flac-s24.flac", type: "audio/flac", duration: 4.04 },
    455  {
    456    name: "flac-sample.mp4",
    457    type: "audio/mp4; codecs=flac",
    458    duration: 4.95,
    459    contentDuration: 5.03,
    460  },
    461  // A file that has no codec delay at the container level, but has a delay at
    462  // the codec level.
    463  {
    464    name: "no-container-codec-delay.webm",
    465    type: "video/webm",
    466  },
    467  // A file that has a codec delay at a container level of 0, but as a delay at
    468  // the codec level that is non-zero.
    469  { name: "invalid-preskip.webm", type: "audio/webm; codecs=opus" },
    470 
    471  // Invalid file
    472  { name: "bogus.duh", type: "bogus/duh", duration: Number.NaN },
    473 ];
    474 
    475 const win32 =
    476  SpecialPowers.Services.appinfo.OS == "WINNT" &&
    477  !SpecialPowers.Services.appinfo.is64Bit;
    478 if (!win32) {
    479  gPlayTests.push({ name: "av1.mp4", type: "video/mp4", duration: 1.0 });
    480 }
    481 
    482 var gMKVtests = [
    483  // ffmpeg -f lavfi -i "sine=frequency=440:duration=1" \
    484  // -c:a aac -b:a 128k output-aac.mkv
    485  {
    486    name: "output_aac.mkv",
    487    type: 'audio/matroska; codecs="mp4a.40.2"',
    488    duration: 1.0,
    489  },
    490  // ffmpeg -f lavfi -i "smptebars=size=1280x720:rate=30:duration=1" \
    491  // -c:v libx264 -pix_fmt yuv420p output-avc.mkv
    492  {
    493    name: "output_avc.mkv",
    494    type: 'video/matroska; codecs="avc1.42C01F"',
    495    duration: 1.0,
    496  },
    497  // ffmpeg \
    498  // -f lavfi -i "testsrc2=size=1920x1080:rate=30:duration=1" \
    499  // -f lavfi -i "sine=frequency=440:duration=1" \
    500  // -c:v libx264 -profile:v high -level:v 4.1 -pix_fmt yuv420p -g 60 \
    501  // -c:a aac -ar 44100 -b:a 128k output_avc_hl41_1080p_aaclc_44100.mkv
    502  {
    503    name: "output_avc_hl41_1080p_aaclc_44100.mkv",
    504    type: 'video/matroska; codecs="avc1.640029, mp4a.40.2"',
    505    duration: 1.0,
    506  },
    507  // ffmpeg -f lavfi -i sine=frequency=1000:duration=1 -c:a libvorbis output_vorbis.mkv
    508  {
    509    name: "output_vorbis.mkv",
    510    type: 'audio/matroska; codecs="vorbis"',
    511    duration: 1.0,
    512  },
    513  // ffmpeg -f lavfi -i sine=frequency=1000:duration=1 -c:a libopus output_opus.mkv
    514  {
    515    name: "output_opus.mkv",
    516    type: 'audio/matroska; codecs="opus"',
    517    duration: 1.0,
    518  },
    519  // ffmpeg -f lavfi -i testsrc=size=320x240:rate=30 -t 1 -c:v libvpx output_vp8.mkv
    520  {
    521    name: "output_vp8.mkv",
    522    type: 'video/matroska; codecs="vp8"',
    523    duration: 1.0,
    524  },
    525  // ffmpeg -f lavfi -i testsrc=size=320x240:rate=30 -t 1 -c:v libvpx-vp9 -pix_fmt yuv420p output_vp9.mkv
    526  {
    527    name: "output_vp9.mkv",
    528    type: 'video/matroska; codecs="vp9"',
    529    duration: 1.0,
    530  },
    531  // ffmpeg -f lavfi -i testsrc=size=320x240:rate=30 -t 1 -c:v libaom-av1 -pix_fmt yuv420p output_av1.mkv
    532  {
    533    name: "output_av1.mkv",
    534    type: 'video/matroska; codecs="av1"',
    535    duration: 1.0,
    536  },
    537 ];
    538 
    539 // HEVC file can only be tested on the gpu worker which has hardware decoder
    540 // support. This pref will only be set on the `media-gpu` task.
    541 if (
    542  SpecialPowers.Services.prefs.getBoolPref(
    543    "media.hardware-video-decoding.force-enabled",
    544    0
    545  )
    546 ) {
    547  // ffmpeg -f lavfi -i testsrc=size=320x240:rate=30 -t 1 -c:v libx265 -pix_fmt yuv420p output_hevc.mkv
    548  gMKVtests.push(
    549    {
    550      name: "output_hevc.mkv",
    551      type: 'video/matroska; codecs="hvc1.1.6.L63.B0"',
    552      duration: 1.0,
    553    }
    554    // TODO : enable this, this will currently fail on MacOS worker on CI.
    555    // {
    556    //   name: "partial_support_hevc_ac3.mkv",
    557    //   type: 'video/matroska; codecs="hvc1.1.6.L63.B0"',
    558    //   duration: 0.1,
    559    // }
    560  );
    561 }
    562 
    563 // Parital support test cases, these files only have one supported track, another
    564 // unsupported track should be ignored. All files are generated by ffmpeg.
    565 gMKVtests.push(
    566  // valid video + invalid audio
    567  {
    568    name: "partial_support_av1_ac3.mkv",
    569    type: 'video/matroska; codecs="av1"',
    570    duration: 0.1,
    571  },
    572  {
    573    name: "partial_support_avc_ac3.mkv",
    574    type: 'video/matroska; codecs="avc1.640029, mp4a.40.2"',
    575    duration: 0.1,
    576  },
    577  {
    578    name: "partial_support_vp8_ac3.mkv",
    579    type: 'video/matroska; codecs="vp8"',
    580    duration: 0.1,
    581  },
    582  {
    583    name: "partial_support_vp9_ac3.mkv",
    584    type: 'video/matroska; codecs="vp9"',
    585    duration: 0.1,
    586  },
    587  // valid audio + invalid video
    588  {
    589    name: "partial_support_theora_aac.mkv",
    590    type: 'audio/matroska; codecs="mp4a.40.2"',
    591    duration: 0.1,
    592  },
    593  {
    594    name: "partial_support_theora_opus.mkv",
    595    type: 'audio/matroska; codecs="opus"',
    596    duration: 0.1,
    597  },
    598  {
    599    name: "partial_support_theora_vorbis.mkv",
    600    type: 'audio/matroska; codecs="vorbis"',
    601    duration: 0.1,
    602  }
    603 );
    604 
    605 // The following files should be added to gMKVtests once they are supported.
    606 var gUnsupportedMKVtests = [
    607  // ffmpeg -f lavfi -i sine=frequency=1000:duration=1 -c:a flac output_flac.mkv
    608  {
    609    name: "output_flac.mkv",
    610    type: "audio/matroska",
    611    duration: 1.0,
    612  },
    613  // ffmpeg -f lavfi -i sine=frequency=1000:duration=1 -c:a libmp3lame output_mp3.mkv
    614  {
    615    name: "output_mp3.mkv",
    616    type: "audio/matroska",
    617    duration: 1.0,
    618  },
    619  // ffmpeg -f lavfi -i sine=frequency=1000:duration=1 -c:a pcm_s16le output_pcm.mkv
    620  {
    621    name: "output_pcm.mkv",
    622    type: "audio/matroska",
    623    duration: 1.0,
    624  },
    625 ];
    626 
    627 // AAC files with different sample rates. We add these here as some are added
    628 // conditionally.
    629 gPlayTests.push(
    630  {
    631    name: "bipbop_audio_aac_8k.mp4",
    632    type: "audio/mp4",
    633    duration: 1.06,
    634  },
    635  {
    636    name: "bipbop_audio_aac_22.05k.mp4",
    637    type: "audio/mp4",
    638    duration: 1.06,
    639  },
    640  {
    641    name: "bipbop_audio_aac_44.1k.mp4",
    642    type: "audio/mp4",
    643    duration: 1.06,
    644  },
    645  {
    646    name: "bipbop_audio_aac_48k.mp4",
    647    type: "audio/mp4",
    648    duration: 1.06,
    649  }
    650 );
    651 
    652 // Disabled for now, will be reenabled in 1982387
    653 // if (
    654 //   AppConstants.isPlatformAndVersionAtLeast("win", "11") ||
    655 //   AppConstants.isPlatformAndVersionAtLeast("macosx", "10.15") ||
    656 //   // Android 9
    657 //   AppConstants.isPlatformAndVersionAtLeast("android", "28")
    658 // ) {
    659 //   gPlayTests.push({
    660 //     name: "sine-3s-xhe-aac-44khz-mono.mp4",
    661 //     type: 'audio/mp4; codecs="mp4a.40.42"',
    662 //     duration: 3.0,
    663 //   });
    664 // }
    665 
    666 if (AppConstants.platform != "win") {
    667  // Windows WMF decoder doesn't do >48K everywhere. See bug 1698639.
    668  gPlayTests.push(
    669    {
    670      name: "bipbop_audio_aac_88.2k.mp4",
    671      type: "audio/mp4",
    672      duration: 1.06,
    673    },
    674    {
    675      name: "bipbop_audio_aac_96k.mp4",
    676      type: "audio/mp4",
    677      duration: 1.06,
    678    }
    679  );
    680 }
    681 
    682 // ambisonics.mp4 causes intermittents, so we conditionally add it until we fix
    683 // the root cause.
    684 const skipAmbisonics =
    685  // Bug 1484451 - skip on mac debug
    686  (AppConstants.platform == "macosx" && AppConstants.DEBUG) ||
    687  // Bug 1483259 - skip on linux64 opt
    688  (AppConstants.platform == "linux" &&
    689    !AppConstants.DEBUG &&
    690    SpecialPowers.Services.appinfo.is64Bit);
    691 if (!skipAmbisonics) {
    692  // Ambisonics AAC, requires AAC extradata to be set when creating decoder (see bug 1431169)
    693  // Also test 4.0 decoding.
    694  gPlayTests.push({
    695    name: "ambisonics.mp4",
    696    type: "audio/mp4",
    697    duration: 16.48,
    698  });
    699 }
    700 
    701 var gSeekToNextFrameTests = [
    702  // Test playback of a WebM file with vp9 video
    703  { name: "vp9-short.webm", type: "video/webm", duration: 0.2 },
    704  { name: "vp9cake-short.webm", type: "video/webm", duration: 1.0 },
    705 
    706  // Test playback/metadata work after a redirect
    707  {
    708    name: "redirect.sjs?domain=mochi.test:8888&file=vp9.webm",
    709    type: "video/webm",
    710  },
    711  // Test playback of a webm file
    712  { name: "seek-short.webm", type: "video/webm", duration: 0.23 },
    713  // Test playback of a WebM file with non-zero start time.
    714  { name: "split.webm", type: "video/webm", duration: 1.967 },
    715 
    716  { name: "gizmo-short.mp4", type: "video/mp4", duration: 0.27 },
    717 
    718  // Test playback of a MP4 file with a non-zero start time (and audio starting
    719  // a second later).
    720  { name: "bipbop-lateaudio.mp4", type: "video/mp4" },
    721 ];
    722 
    723 // A file for each type we can support.
    724 var gSnifferTests = [
    725  { name: "big.wav", type: "audio/x-wav", duration: 9.278982, size: 102444 },
    726  { name: "seek.webm", type: "video/webm", duration: 3.966, size: 215529 },
    727  { name: "gizmo.mp4", type: "video/mp4", duration: 5.56, size: 383631 },
    728  // A mp3 file with id3 tags.
    729  { name: "id3tags.mp3", type: "audio/mpeg", duration: 0.28, size: 3530 },
    730  { name: "bogus.duh", type: "bogus/duh" },
    731 ];
    732 
    733 // Files that contain resolution changes
    734 var gResolutionChangeTests = [
    735  { name: "resolution-change.webm", type: "video/webm", duration: 6.533 },
    736 ];
    737 
    738 // Files we must reject as invalid.
    739 var gInvalidTests = [
    740  { name: "invalid-m0c0.opus", type: "audio/ogg; codecs=opus" },
    741  { name: "invalid-m0c3.opus", type: "audio/ogg; codecs=opus" },
    742  { name: "invalid-m1c0.opus", type: "audio/ogg; codecs=opus" },
    743  { name: "invalid-m1c9.opus", type: "audio/ogg; codecs=opus" },
    744  { name: "invalid-m2c0.opus", type: "audio/ogg; codecs=opus" },
    745  { name: "invalid-m2c1.opus", type: "audio/ogg; codecs=opus" },
    746  { name: "invalid-cmap-short.opus", type: "audio/ogg; codecs=opus" },
    747  { name: "invalid-cmap-s0c0.opus", type: "audio/ogg; codecs=opus" },
    748  { name: "invalid-cmap-s0c2.opus", type: "audio/ogg; codecs=opus" },
    749  { name: "invalid-cmap-s1c2.opus", type: "audio/ogg; codecs=opus" },
    750 ];
    751 
    752 var gInvalidPlayTests = [
    753  { name: "invalid-excess_discard.webm", type: "audio/webm; codecs=opus" },
    754  { name: "invalid-excess_neg_discard.webm", type: "audio/webm; codecs=opus" },
    755  { name: "invalid-neg_discard.webm", type: "audio/webm; codecs=opus" },
    756  {
    757    name: "invalid-discard_on_multi_blocks.webm",
    758    type: "audio/webm; codecs=opus",
    759  },
    760 ];
    761 
    762 // Files to check different cases of ogg skeleton information.
    763 // multiple-bos-more-header-fields.ogg
    764 // - Skeleton v3, w/ Content-Type,Role,Name,Language,Title for vorbis
    765 // audio-gaps-short.ogg
    766 // - No skeleton, but vorbis
    767 var gMultitrackInfoOggPlayList = [
    768  {
    769    name: "multiple-bos-more-header-fileds.ogg",
    770    type: "video/ogg",
    771    duration: 0.431,
    772  },
    773  { name: "audio-gaps-short.ogg", type: "audio/ogg", duration: 0.5 },
    774 ];
    775 // Pre-parsed results of gMultitrackInfoOggPlayList.
    776 var gOggTrackInfoResults = {
    777  "multiple-bos-more-header-fileds.ogg": {
    778    audio_id: "1",
    779    audio_kind: "main",
    780    audio_language: "",
    781    audio_label: "",
    782    video_id: "2",
    783    video_kind: "main",
    784    video_language: "",
    785    video_label: "",
    786  },
    787  "audio-gaps-short.ogg": {
    788    audio_id: "1",
    789    audio_kind: "main",
    790    audio_language: "",
    791    audio_label: "",
    792  },
    793 };
    794 
    795 // Returns a promise that resolves to a function that converts
    796 // relative paths to absolute, to test loading files from file: URIs.
    797 // Optionally checks whether the file actually exists on disk at the location
    798 // we've specified.
    799 function makeAbsolutePathConverter() {
    800  const url = SimpleTest.getTestFileURL("chromeHelper.js");
    801  const script = SpecialPowers.loadChromeScript(url);
    802  return new Promise(resolve => {
    803    script.addMessageListener("media-test:cwd", cwd => {
    804      if (!cwd) {
    805        ok(false, "Failed to find path to test files");
    806      }
    807 
    808      resolve((path, mustExist) => {
    809        // android mochitest doesn't support file://
    810        if (manifestNavigator().appVersion.includes("Android")) {
    811          return path;
    812        }
    813 
    814        const { Ci, Cc } = SpecialPowers;
    815        var f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
    816        f.initWithPath(cwd);
    817        var split = path.split("/");
    818        for (var i = 0; i < split.length; ++i) {
    819          f.append(split[i]);
    820        }
    821        if (mustExist && !f.exists()) {
    822          ok(false, "We expected '" + path + "' to exist, but it doesn't!");
    823        }
    824        return f.path;
    825      });
    826    });
    827    script.sendAsyncMessage("media-test:getcwd");
    828  });
    829 }
    830 
    831 // Returns true if two TimeRanges are equal, false otherwise
    832 function range_equals(r1, r2) {
    833  if (r1.length != r2.length) {
    834    return false;
    835  }
    836  for (var i = 0; i < r1.length; i++) {
    837    if (r1.start(i) != r2.start(i) || r1.end(i) != r2.end(i)) {
    838      return false;
    839    }
    840  }
    841  return true;
    842 }
    843 
    844 // These are URIs to files that we use to check that we don't leak any state
    845 // or other information such that script can determine stuff about a user's
    846 // environment. Used by test_info_leak.
    847 function makeInfoLeakTests() {
    848  return makeAbsolutePathConverter().then(fileUriToSrc => [
    849    {
    850      type: "audio/x-wav",
    851      src: fileUriToSrc("tests/dom/media/test/r11025_s16_c1.wav", true),
    852    },
    853    {
    854      type: "audio/x-wav",
    855      src: fileUriToSrc("tests/dom/media/test/404.wav", false),
    856    },
    857    {
    858      type: "audio/ogg",
    859      src: fileUriToSrc("tests/dom/media/test/404.ogg", false),
    860    },
    861    {
    862      type: "video/webm",
    863      src: fileUriToSrc("tests/dom/media/test/seek.webm", true),
    864    },
    865    {
    866      type: "video/webm",
    867      src: fileUriToSrc("tests/dom/media/test/404.webm", false),
    868    },
    869    {
    870      type: "audio/x-wav",
    871      src: "http://localhost/404.wav",
    872    },
    873    {
    874      type: "video/webm",
    875      src: "http://localhost/404.webm",
    876    },
    877    {
    878      type: "video/ogg",
    879      src: "http://example.com/tests/dom/media/test/test_info_leak.html",
    880    },
    881    {
    882      type: "audio/ogg",
    883      src: "http://example.com/tests/dom/media/test/test_info_leak.html",
    884    },
    885  ]);
    886 }
    887 
    888 // These are files that must fire an error during load or playback, and do not
    889 // cause a crash. Used by test_playback_errors, which expects one error event
    890 // and no ended event. Put files of the same type together in this list so if
    891 // something crashes we have some idea of which backend is responsible.
    892 var gErrorTests = [
    893  { name: "bogus.wav", type: "audio/x-wav" },
    894  { name: "bug501279.ogg", type: "audio/ogg" },
    895  { name: "bug604067.webm", type: "video/webm" },
    896  { name: "bug1535980.webm", type: "video/webm" },
    897  { name: "bug1799787.webm", type: "video/webm" },
    898  { name: "bogus.duh", type: "bogus/duh" },
    899 ];
    900 
    901 // Playing this file errors out after receiving "loadedmetadata", we still want
    902 // to check the duration in "onerror" and make sure it is still available.
    903 var gDurationTests = [{ name: "bug604067.webm", duration: 6.076 }];
    904 
    905 // These are files that have nontrivial duration and are useful for seeking within.
    906 var gSeekTests = [
    907  { name: "r11025_s16_c1.wav", type: "audio/x-wav", duration: 1.0 },
    908  { name: "audio.wav", type: "audio/x-wav", duration: 0.031247 },
    909  { name: "seek.webm", type: "video/webm", duration: 3.966 },
    910  { name: "sine.webm", type: "audio/webm", duration: 4.001 },
    911  { name: "split.webm", type: "video/webm", duration: 1.967 },
    912  { name: "detodos.opus", type: "audio/ogg; codecs=opus", duration: 2.9135 },
    913  { name: "gizmo.mp4", type: "video/mp4", duration: 5.56 },
    914  {
    915    name: "/tests/dom/media/webaudio/test/half-a-second-1ch-44100-aac-afconvert.mp4",
    916    type: 'audio/mp4; codecs="mp4a.40.2"',
    917    duration: 0.5,
    918  },
    919  { name: "owl.mp3", type: "audio/mpeg", duration: 3.343 },
    920  { name: "bogus.duh", type: "bogus/duh", duration: 123 },
    921 ];
    922 
    923 var gFastSeekTests = [
    924  {
    925    name: "gizmo.mp4",
    926    type: "video/mp4",
    927    keyframes: [0, 1.0, 2.0, 3.0, 4.0, 5.0],
    928  },
    929  // Note: Not all keyframes in the file are actually referenced in the Cues in this file.
    930  { name: "seek.webm", type: "video/webm", keyframes: [0, 0.8, 1.6, 2.4, 3.2] },
    931 ];
    932 
    933 // These files are WebMs without cues. They're seekable within their buffered
    934 // ranges. If work renders WebMs fully seekable these files should be moved
    935 // into gSeekTests
    936 var gCuelessWebMTests = [
    937  { name: "no-cues.webm", type: "video/webm", duration: 3.967 },
    938 ];
    939 
    940 // These are files that are non seekable, due to problems with the media,
    941 // for example broken or missing indexes.
    942 var gUnseekableTests = [{ name: "bogus.duh", type: "bogus/duh" }];
    943 
    944 var androidVersion = -1; // non-Android platforms
    945 if (
    946  manifestNavigator().userAgent.includes("Mobile") ||
    947  manifestNavigator().userAgent.includes("Tablet")
    948 ) {
    949  androidVersion = SpecialPowers.Services.sysinfo.getProperty("version");
    950 }
    951 
    952 function getAndroidVersion() {
    953  return androidVersion;
    954 }
    955 
    956 // These are files suitable for using with a "new Audio" constructor.
    957 var gAudioTests = [
    958  { name: "adts.aac", type: "audio/mp4", duration: 1.37 },
    959  { name: "r11025_s16_c1.wav", type: "audio/x-wav", duration: 1.0 },
    960  { name: "sound.ogg", type: "audio/ogg" },
    961  { name: "owl.mp3", type: "audio/mpeg", duration: 3.343 },
    962  { name: "small-shot.m4a", type: "audio/mp4", duration: 0.29 },
    963  { name: "bogus.duh", type: "bogus/duh", duration: 123 },
    964  { name: "empty_size.mp3", type: "audio/mpeg", duration: 2.235 },
    965 ];
    966 
    967 // These files ensure our handling of 404 errors is consistent across the
    968 // various backends.
    969 var g404Tests = [
    970  { name: "404.wav", type: "audio/x-wav" },
    971  { name: "404.oga", type: "audio/ogg" },
    972  { name: "404.webm", type: "video/webm" },
    973  { name: "bogus.duh", type: "bogus/duh" },
    974 ];
    975 
    976 // These are files suitable for testing various decoder failures that are
    977 // expected to fire MEDIA_ERR_DECODE.  Used by test_decode_error, which expects
    978 // an error and emptied event, and no loadedmetadata or ended event.
    979 var gDecodeErrorTests = [
    980  // Valid files with unsupported codecs
    981  { name: "r11025_msadpcm_c1.wav", type: "audio/x-wav" },
    982  { name: "dirac.ogg", type: "video/ogg" },
    983  // Invalid files
    984  { name: "bogus.wav", type: "audio/x-wav" },
    985 
    986  { name: "bogus.duh", type: "bogus/duh" },
    987 ];
    988 
    989 // These are files that are used for media fragments tests
    990 var gFragmentTests = [
    991  { name: "big.wav", type: "audio/x-wav", duration: 9.278982, size: 102444 },
    992 ];
    993 
    994 // Used by test_chaining.html. The |links| attributes is the number of links in
    995 // this file that we should be able to play.
    996 var gChainingTests = [
    997  // Vorbis and Opus chained file. They have user comments |index=n| where `n`
    998  // is the index of this segment in the file, 0 indexed.
    999  { name: "chain.ogg", type: "audio/ogg", links: 4 },
   1000  { name: "chain.opus", type: "audio/ogg; codec=opus", links: 4 },
   1001  // Those files are chained files with a different number of channels in each
   1002  // part. This is not supported and should stop playing after the first part.
   1003  { name: "variable-channel.ogg", type: "audio/ogg", links: 1 },
   1004  { name: "variable-channel.opus", type: "audio/ogg; codec=opus", links: 1 },
   1005  // Those files are chained files with a different sample rate in each
   1006  // part. This is not supported and should stop playing after the first part.
   1007  { name: "variable-samplerate.ogg", type: "audio/ogg", links: 1 },
   1008  // Opus decoding in Firefox outputs 48 kHz PCM despite having a different
   1009  // original sample rate, so we can safely play Opus chained media that have
   1010  // different samplerate accross links.
   1011  { name: "variable-samplerate.opus", type: "audio/ogg; codec=opus", links: 2 },
   1012  // An opus file that has two links, with a different preskip value for each
   1013  // link. We should be able to play both links.
   1014  { name: "variable-preskip.opus", type: "audio/ogg; codec=opus", links: 2 },
   1015  { name: "bogus.duh", type: "bogus/duh" },
   1016 ];
   1017 
   1018 // Videos with an aspect ratio. Used for testing that displaying frames
   1019 // on a canvas works correctly in the case of non-standard aspect ratios.
   1020 // See bug 874897 for an example.
   1021 var gAspectRatioTests = [
   1022  { name: "VID_0001.ogg", type: "video/ogg", duration: 19.966 },
   1023 ];
   1024 
   1025 // These are files with non-trivial tag sets.
   1026 // Used by test_metadata.html.
   1027 var gMetadataTests = [
   1028  // Ogg Vorbis files
   1029  {
   1030    name: "detodos.opus",
   1031    tags: {
   1032      title: "De todos. Para todos.",
   1033      artist: "Mozilla.org",
   1034    },
   1035  },
   1036  { name: "sound.ogg", tags: {} },
   1037  {
   1038    name: "small-shot.ogg",
   1039    tags: {
   1040      title: "Pew SFX",
   1041    },
   1042  },
   1043  {
   1044    name: "badtags.ogg",
   1045    tags: {
   1046      // We list only the valid tags here, and verify
   1047      // the invalid ones are filtered out.
   1048      title: "Invalid comments test file",
   1049      empty: "",
   1050      "": "empty",
   1051      "{- [(`!@\"#$%^&')] -}": "valid tag name, surprisingly",
   1052      // The file also includes the following invalid tags.
   1053      // "A description with no separator is a common problem.",
   1054      // "雨":"Likely, but an invalid key (non-ascii).",
   1055      // "not\nval\x1fid":"invalid tag name",
   1056      // "not~valid":"this isn't a valid name either",
   1057      // "not-utf-8":"invalid sequences: \xff\xfe\xfa\xfb\0eol"
   1058    },
   1059  },
   1060  {
   1061    name: "wave_metadata.wav",
   1062    tags: {
   1063      name: "Track Title",
   1064      artist: "Artist Name",
   1065      comments: "Comments",
   1066    },
   1067  },
   1068  {
   1069    name: "wave_metadata_utf8.wav",
   1070    tags: {
   1071      name: "歌曲名稱",
   1072      artist: "作曲者",
   1073      comments: "註解",
   1074    },
   1075  },
   1076  {
   1077    name: "wave_metadata_unknown_tag.wav",
   1078    tags: {
   1079      name: "Track Title",
   1080      comments: "Comments",
   1081    },
   1082  },
   1083  {
   1084    name: "wave_metadata_bad_len.wav",
   1085    tags: {
   1086      name: "Track Title",
   1087      artist: "Artist Name",
   1088      comments: "Comments",
   1089    },
   1090  },
   1091  {
   1092    name: "wave_metadata_bad_no_null.wav",
   1093    tags: {
   1094      name: "Track Title",
   1095      artist: "Artist Name",
   1096      comments: "Comments!!",
   1097    },
   1098  },
   1099  {
   1100    name: "wave_metadata_bad_utf8.wav",
   1101    tags: {
   1102      name: "歌曲名稱",
   1103      comments: "註解",
   1104    },
   1105  },
   1106  { name: "wavedata_u8.wav", tags: {} },
   1107 ];
   1108 
   1109 // Now Fennec doesn't support flac, so only test it on non-android platforms.
   1110 if (getAndroidVersion() < 0) {
   1111  gMetadataTests = gMetadataTests.concat([
   1112    {
   1113      name: "flac-s24.flac",
   1114      tags: {
   1115        ALBUM: "Seascapes",
   1116        TITLE: "(La Mer) - II. Jeux de vagues. Allegro",
   1117        COMPOSER: "Debussy, Claude",
   1118        TRACKNUMBER: "2/9",
   1119        DISCNUMBER: "1/1",
   1120        encoder: "Lavf57.41.100",
   1121      },
   1122    },
   1123  ]);
   1124 }
   1125 
   1126 // Test files for Encrypted Media Extensions
   1127 var gEMETests = [
   1128  {
   1129    name: "vp9 in mp4",
   1130    tracks: [
   1131      {
   1132        name: "video",
   1133        type: 'video/mp4; codecs="vp9.0"',
   1134        fragments: ["short-vp9-encrypted-video.mp4"],
   1135      },
   1136      {
   1137        name: "audio",
   1138        type: 'audio/mp4; codecs="mp4a.40.2"',
   1139        fragments: ["short-aac-encrypted-audio.mp4"],
   1140      },
   1141    ],
   1142    keys: {
   1143      "2cdb0ed6119853e7850671c3e9906c3c": "808B9ADAC384DE1E4F56140F4AD76194",
   1144    },
   1145    sessionType: "temporary",
   1146    sessionCount: 2,
   1147    duration: 0.47,
   1148  },
   1149  {
   1150    name: "video-only with 2 keys",
   1151    tracks: [
   1152      {
   1153        name: "video",
   1154        type: 'video/mp4; codecs="avc1.4d4015"',
   1155        fragments: [
   1156          "bipbop-cenc-videoinit.mp4",
   1157          "bipbop-cenc-video1.m4s",
   1158          "bipbop-cenc-video2.m4s",
   1159        ],
   1160      },
   1161    ],
   1162    keys: {
   1163      // "keyid" : "key"
   1164      "7e571d037e571d037e571d037e571d03": "7e5733337e5733337e5733337e573333",
   1165      "7e571d047e571d047e571d047e571d04": "7e5744447e5744447e5744447e574444",
   1166    },
   1167    sessionType: "temporary",
   1168    sessionCount: 1,
   1169    duration: 1.6,
   1170  },
   1171  {
   1172    name: "video-only with 2 keys, CORS",
   1173    tracks: [
   1174      {
   1175        name: "video",
   1176        type: 'video/mp4; codecs="avc1.4d4015"',
   1177        fragments: [
   1178          "bipbop-cenc-videoinit.mp4",
   1179          "bipbop-cenc-video1.m4s",
   1180          "bipbop-cenc-video2.m4s",
   1181        ],
   1182      },
   1183    ],
   1184    keys: {
   1185      // "keyid" : "key"
   1186      "7e571d037e571d037e571d037e571d03": "7e5733337e5733337e5733337e573333",
   1187      "7e571d047e571d047e571d047e571d04": "7e5744447e5744447e5744447e574444",
   1188    },
   1189    sessionType: "temporary",
   1190    sessionCount: 1,
   1191    crossOrigin: true,
   1192    duration: 1.6,
   1193  },
   1194  {
   1195    name: "audio&video tracks, both with all keys",
   1196    tracks: [
   1197      {
   1198        name: "audio",
   1199        type: 'audio/mp4; codecs="mp4a.40.2"',
   1200        fragments: [
   1201          "bipbop-cenc-audioinit.mp4",
   1202          "bipbop-cenc-audio1.m4s",
   1203          "bipbop-cenc-audio2.m4s",
   1204          "bipbop-cenc-audio3.m4s",
   1205        ],
   1206      },
   1207      {
   1208        name: "video",
   1209        type: 'video/mp4; codecs="avc1.4d4015"',
   1210        fragments: [
   1211          "bipbop-cenc-videoinit.mp4",
   1212          "bipbop-cenc-video1.m4s",
   1213          "bipbop-cenc-video2.m4s",
   1214        ],
   1215      },
   1216    ],
   1217    keys: {
   1218      // "keyid" : "key"
   1219      "7e571d037e571d037e571d037e571d03": "7e5733337e5733337e5733337e573333",
   1220      "7e571d047e571d047e571d047e571d04": "7e5744447e5744447e5744447e574444",
   1221    },
   1222    sessionType: "temporary",
   1223    sessionCount: 2,
   1224    duration: 1.6,
   1225  },
   1226  {
   1227    name: "audio&video tracks, both with all keys, CORS",
   1228    tracks: [
   1229      {
   1230        name: "audio",
   1231        type: 'audio/mp4; codecs="mp4a.40.2"',
   1232        fragments: [
   1233          "bipbop-cenc-audioinit.mp4",
   1234          "bipbop-cenc-audio1.m4s",
   1235          "bipbop-cenc-audio2.m4s",
   1236          "bipbop-cenc-audio3.m4s",
   1237        ],
   1238      },
   1239      {
   1240        name: "video",
   1241        type: 'video/mp4; codecs="avc1.4d4015"',
   1242        fragments: [
   1243          "bipbop-cenc-videoinit.mp4",
   1244          "bipbop-cenc-video1.m4s",
   1245          "bipbop-cenc-video2.m4s",
   1246        ],
   1247      },
   1248    ],
   1249    keys: {
   1250      // "keyid" : "key"
   1251      "7e571d037e571d037e571d037e571d03": "7e5733337e5733337e5733337e573333",
   1252      "7e571d047e571d047e571d047e571d04": "7e5744447e5744447e5744447e574444",
   1253    },
   1254    sessionType: "temporary",
   1255    sessionCount: 2,
   1256    crossOrigin: true,
   1257    duration: 1.6,
   1258  },
   1259  {
   1260    name: "400x300 audio&video tracks, each with its key",
   1261    tracks: [
   1262      {
   1263        name: "audio",
   1264        type: 'audio/mp4; codecs="mp4a.40.2"',
   1265        fragments: [
   1266          "bipbop_300_215kbps-cenc-audio-key1-init.mp4",
   1267          "bipbop_300_215kbps-cenc-audio-key1-1.m4s",
   1268          "bipbop_300_215kbps-cenc-audio-key1-2.m4s",
   1269          "bipbop_300_215kbps-cenc-audio-key1-3.m4s",
   1270          "bipbop_300_215kbps-cenc-audio-key1-4.m4s",
   1271        ],
   1272      },
   1273      {
   1274        name: "video",
   1275        type: 'video/mp4; codecs="avc1.4d4015"',
   1276        fragments: [
   1277          "bipbop_300_215kbps-cenc-video-key1-init.mp4",
   1278          "bipbop_300_215kbps-cenc-video-key1-1.m4s",
   1279          "bipbop_300_215kbps-cenc-video-key1-2.m4s",
   1280        ],
   1281      },
   1282    ],
   1283    keys: {
   1284      // "keyid" : "key"
   1285      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1286      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1287    },
   1288    sessionType: "temporary",
   1289    sessionCount: 2,
   1290    duration: 1.6,
   1291  },
   1292  {
   1293    name: "640x480@624kbps audio&video tracks, each with its key",
   1294    tracks: [
   1295      {
   1296        name: "audio",
   1297        type: 'audio/mp4; codecs="mp4a.40.2"',
   1298        fragments: [
   1299          "bipbop_480_624kbps-cenc-audio-key1-init.mp4",
   1300          "bipbop_480_624kbps-cenc-audio-key1-1.m4s",
   1301          "bipbop_480_624kbps-cenc-audio-key1-2.m4s",
   1302          "bipbop_480_624kbps-cenc-audio-key1-3.m4s",
   1303          "bipbop_480_624kbps-cenc-audio-key1-4.m4s",
   1304        ],
   1305      },
   1306      {
   1307        name: "video",
   1308        type: 'video/mp4; codecs="avc1.4d401e"',
   1309        fragments: [
   1310          "bipbop_480_624kbps-cenc-video-key1-init.mp4",
   1311          "bipbop_480_624kbps-cenc-video-key1-1.m4s",
   1312          "bipbop_480_624kbps-cenc-video-key1-2.m4s",
   1313        ],
   1314      },
   1315    ],
   1316    keys: {
   1317      // "keyid" : "key"
   1318      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1319      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1320    },
   1321    sessionType: "temporary",
   1322    sessionCount: 2,
   1323    duration: 1.6,
   1324  },
   1325  {
   1326    name: "640x480@959kbps audio&video tracks, each with its key",
   1327    tracks: [
   1328      {
   1329        name: "audio",
   1330        type: 'audio/mp4; codecs="mp4a.40.2"',
   1331        fragments: [
   1332          "bipbop_480_959kbps-cenc-audio-key1-init.mp4",
   1333          "bipbop_480_959kbps-cenc-audio-key1-1.m4s",
   1334          "bipbop_480_959kbps-cenc-audio-key1-2.m4s",
   1335          "bipbop_480_959kbps-cenc-audio-key1-3.m4s",
   1336          "bipbop_480_959kbps-cenc-audio-key1-4.m4s",
   1337        ],
   1338      },
   1339      {
   1340        name: "video",
   1341        type: 'video/mp4; codecs="avc1.4d401e"',
   1342        fragments: [
   1343          "bipbop_480_959kbps-cenc-video-key1-init.mp4",
   1344          "bipbop_480_959kbps-cenc-video-key1-1.m4s",
   1345          "bipbop_480_959kbps-cenc-video-key1-2.m4s",
   1346        ],
   1347      },
   1348    ],
   1349    keys: {
   1350      // "keyid" : "key"
   1351      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1352      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1353    },
   1354    sessionType: "temporary",
   1355    sessionCount: 2,
   1356    duration: 1.6,
   1357  },
   1358  {
   1359    name: "640x480 then 400x300, same key (1st) per track",
   1360    tracks: [
   1361      {
   1362        name: "audio",
   1363        type: 'audio/mp4; codecs="mp4a.40.2"',
   1364        fragments: [
   1365          "bipbop_480_624kbps-cenc-audio-key1-init.mp4",
   1366          "bipbop_480_624kbps-cenc-audio-key1-1.m4s",
   1367          "bipbop_480_624kbps-cenc-audio-key1-2.m4s",
   1368          "bipbop_480_624kbps-cenc-audio-key1-3.m4s",
   1369          "bipbop_480_624kbps-cenc-audio-key1-4.m4s",
   1370        ],
   1371      },
   1372      {
   1373        name: "video",
   1374        type: 'video/mp4; codecs="avc1.4d401e,avc1.4d4015"',
   1375        fragments: [
   1376          "bipbop_480_624kbps-cenc-video-key1-init.mp4",
   1377          "bipbop_480_624kbps-cenc-video-key1-1.m4s",
   1378          "bipbop_300_215kbps-cenc-video-key1-init.mp4",
   1379          "bipbop_300_215kbps-cenc-video-key1-2.m4s",
   1380        ],
   1381      },
   1382    ],
   1383    keys: {
   1384      // "keyid" : "key"
   1385      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1386      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1387    },
   1388    sessionType: "temporary",
   1389    sessionCount: 3,
   1390    duration: 1.6,
   1391  },
   1392  {
   1393    name: "640x480 then 400x300, same key (2nd) per track",
   1394    tracks: [
   1395      {
   1396        name: "audio",
   1397        type: 'audio/mp4; codecs="mp4a.40.2"',
   1398        fragments: [
   1399          "bipbop_480_624kbps-cenc-audio-key2-init.mp4",
   1400          "bipbop_480_624kbps-cenc-audio-key2-1.m4s",
   1401          "bipbop_480_624kbps-cenc-audio-key2-2.m4s",
   1402          "bipbop_480_624kbps-cenc-audio-key2-3.m4s",
   1403          "bipbop_480_624kbps-cenc-audio-key2-4.m4s",
   1404        ],
   1405      },
   1406      {
   1407        name: "video",
   1408        type: 'video/mp4; codecs="avc1.4d401e,avc1.4d4015"',
   1409        fragments: [
   1410          "bipbop_480_624kbps-cenc-video-key2-init.mp4",
   1411          "bipbop_480_624kbps-cenc-video-key2-1.m4s",
   1412          "bipbop_300_215kbps-cenc-video-key2-init.mp4",
   1413          "bipbop_300_215kbps-cenc-video-key2-2.m4s",
   1414        ],
   1415      },
   1416    ],
   1417    keys: {
   1418      // "keyid" : "key"
   1419      "7e571d037e571d037e571d037e571d12": "7e5733337e5733337e5733337e573312",
   1420      "7e571d047e571d047e571d047e571d22": "7e5744447e5744447e5744447e574422",
   1421    },
   1422    sessionType: "temporary",
   1423    sessionCount: 3,
   1424    duration: 1.6,
   1425  },
   1426  {
   1427    name: "640x480 with 1st keys then 400x300 with 2nd keys",
   1428    tracks: [
   1429      {
   1430        name: "audio",
   1431        type: 'audio/mp4; codecs="mp4a.40.2"',
   1432        fragments: [
   1433          "bipbop_480_624kbps-cenc-audio-key1-init.mp4",
   1434          "bipbop_480_624kbps-cenc-audio-key1-1.m4s",
   1435          "bipbop_480_624kbps-cenc-audio-key1-2.m4s",
   1436          "bipbop_480_624kbps-cenc-audio-key1-3.m4s",
   1437          "bipbop_480_624kbps-cenc-audio-key1-4.m4s",
   1438        ],
   1439      },
   1440      {
   1441        name: "video",
   1442        type: 'video/mp4; codecs="avc1.4d401e,avc1.4d4015"',
   1443        fragments: [
   1444          "bipbop_480_624kbps-cenc-video-key1-init.mp4",
   1445          "bipbop_480_624kbps-cenc-video-key1-1.m4s",
   1446          "bipbop_300_215kbps-cenc-video-key2-init.mp4",
   1447          "bipbop_300_215kbps-cenc-video-key2-2.m4s",
   1448        ],
   1449      },
   1450    ],
   1451    keys: {
   1452      // "keyid" : "key"
   1453      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1454      "7e571d037e571d037e571d037e571d12": "7e5733337e5733337e5733337e573312",
   1455      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1456    },
   1457    sessionType: "temporary",
   1458    sessionCount: 3,
   1459    duration: 1.6,
   1460  },
   1461  {
   1462    name: "400x300 with 1st keys then 640x480 with 2nd keys",
   1463    tracks: [
   1464      {
   1465        name: "audio",
   1466        type: 'audio/mp4; codecs="mp4a.40.2"',
   1467        fragments: [
   1468          "bipbop_300_215kbps-cenc-audio-key1-init.mp4",
   1469          "bipbop_300_215kbps-cenc-audio-key1-1.m4s",
   1470          "bipbop_300_215kbps-cenc-audio-key1-2.m4s",
   1471          "bipbop_300_215kbps-cenc-audio-key1-3.m4s",
   1472          "bipbop_300_215kbps-cenc-audio-key1-4.m4s",
   1473        ],
   1474      },
   1475      {
   1476        name: "video",
   1477        type: 'video/mp4; codecs="avc1.4d4015,avc1.4d401e"',
   1478        fragments: [
   1479          "bipbop_300_215kbps-cenc-video-key1-init.mp4",
   1480          "bipbop_300_215kbps-cenc-video-key1-1.m4s",
   1481          "bipbop_480_624kbps-cenc-video-key2-init.mp4",
   1482          "bipbop_480_624kbps-cenc-video-key2-2.m4s",
   1483        ],
   1484      },
   1485    ],
   1486    keys: {
   1487      // "keyid" : "key"
   1488      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1489      "7e571d037e571d037e571d037e571d12": "7e5733337e5733337e5733337e573312",
   1490      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1491    },
   1492    sessionType: "temporary",
   1493    sessionCount: 3,
   1494    duration: 1.6,
   1495  },
   1496  {
   1497    name: "640x480@959kbps with 1st keys then 640x480@624kbps with 2nd keys",
   1498    tracks: [
   1499      {
   1500        name: "audio",
   1501        type: 'audio/mp4; codecs="mp4a.40.2"',
   1502        fragments: [
   1503          "bipbop_480_959kbps-cenc-audio-key1-init.mp4",
   1504          "bipbop_480_959kbps-cenc-audio-key1-1.m4s",
   1505          "bipbop_480_959kbps-cenc-audio-key1-2.m4s",
   1506          "bipbop_480_959kbps-cenc-audio-key1-3.m4s",
   1507          "bipbop_480_959kbps-cenc-audio-key1-4.m4s",
   1508        ],
   1509      },
   1510      {
   1511        name: "video",
   1512        type: 'video/mp4; codecs="avc1.4d401e"',
   1513        fragments: [
   1514          "bipbop_480_959kbps-cenc-video-key1-init.mp4",
   1515          "bipbop_480_959kbps-cenc-video-key1-1.m4s",
   1516          "bipbop_480_624kbps-cenc-video-key2-init.mp4",
   1517          "bipbop_480_624kbps-cenc-video-key2-2.m4s",
   1518        ],
   1519      },
   1520    ],
   1521    keys: {
   1522      // "keyid" : "key"
   1523      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1524      "7e571d037e571d037e571d037e571d12": "7e5733337e5733337e5733337e573312",
   1525      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1526    },
   1527    sessionType: "temporary",
   1528    sessionCount: 3,
   1529    duration: 1.6,
   1530  },
   1531  {
   1532    name: "640x480@624kbps with 1st keys then 640x480@959kbps with 2nd keys",
   1533    tracks: [
   1534      {
   1535        name: "audio",
   1536        type: 'audio/mp4; codecs="mp4a.40.2"',
   1537        fragments: [
   1538          "bipbop_480_624kbps-cenc-audio-key1-init.mp4",
   1539          "bipbop_480_624kbps-cenc-audio-key1-1.m4s",
   1540          "bipbop_480_624kbps-cenc-audio-key1-2.m4s",
   1541          "bipbop_480_624kbps-cenc-audio-key1-3.m4s",
   1542          "bipbop_480_624kbps-cenc-audio-key1-4.m4s",
   1543        ],
   1544      },
   1545      {
   1546        name: "video",
   1547        type: 'video/mp4; codecs="avc1.4d401e"',
   1548        fragments: [
   1549          "bipbop_480_624kbps-cenc-video-key1-init.mp4",
   1550          "bipbop_480_624kbps-cenc-video-key1-1.m4s",
   1551          "bipbop_480_959kbps-cenc-video-key2-init.mp4",
   1552          "bipbop_480_959kbps-cenc-video-key2-2.m4s",
   1553        ],
   1554      },
   1555    ],
   1556    keys: {
   1557      // "keyid" : "key"
   1558      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1559      "7e571d037e571d037e571d037e571d12": "7e5733337e5733337e5733337e573312",
   1560      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1561    },
   1562    sessionType: "temporary",
   1563    sessionCount: 3,
   1564    duration: 1.6,
   1565  },
   1566  {
   1567    name: "400x300 with presentation size 533x300",
   1568    tracks: [
   1569      {
   1570        name: "audio",
   1571        type: 'audio/mp4; codecs="mp4a.40.2"',
   1572        fragments: [
   1573          "bipbop_300wp_227kbps-cenc-audio-key1-init.mp4",
   1574          "bipbop_300wp_227kbps-cenc-audio-key1-1.m4s",
   1575          "bipbop_300wp_227kbps-cenc-audio-key1-2.m4s",
   1576          "bipbop_300wp_227kbps-cenc-audio-key1-3.m4s",
   1577          "bipbop_300wp_227kbps-cenc-audio-key1-4.m4s",
   1578        ],
   1579      },
   1580      {
   1581        name: "video",
   1582        type: 'video/mp4; codecs="avc1.4d4015"',
   1583        fragments: [
   1584          "bipbop_300wp_227kbps-cenc-video-key1-init.mp4",
   1585          "bipbop_300wp_227kbps-cenc-video-key1-1.m4s",
   1586          "bipbop_300wp_227kbps-cenc-video-key1-2.m4s",
   1587        ],
   1588      },
   1589    ],
   1590    keys: {
   1591      // "keyid" : "key"
   1592      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1593      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1594    },
   1595    sessionType: "temporary",
   1596    sessionCount: 2,
   1597    duration: 1.6,
   1598  },
   1599  {
   1600    name: "400x300 as-is then 400x300 presented as 533x300",
   1601    tracks: [
   1602      {
   1603        name: "audio",
   1604        type: 'audio/mp4; codecs="mp4a.40.2"',
   1605        fragments: [
   1606          "bipbop_300_215kbps-cenc-audio-key1-init.mp4",
   1607          "bipbop_300_215kbps-cenc-audio-key1-1.m4s",
   1608          "bipbop_300_215kbps-cenc-audio-key1-2.m4s",
   1609          "bipbop_300_215kbps-cenc-audio-key1-3.m4s",
   1610          "bipbop_300_215kbps-cenc-audio-key1-4.m4s",
   1611        ],
   1612      },
   1613      {
   1614        name: "video",
   1615        type: 'video/mp4; codecs="avc1.4d4015"',
   1616        fragments: [
   1617          "bipbop_300_215kbps-cenc-video-key1-init.mp4",
   1618          "bipbop_300_215kbps-cenc-video-key1-1.m4s",
   1619          "bipbop_300wp_227kbps-cenc-video-key1-init.mp4",
   1620          "bipbop_300wp_227kbps-cenc-video-key1-2.m4s",
   1621        ],
   1622      },
   1623    ],
   1624    keys: {
   1625      // "keyid" : "key"
   1626      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1627      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1628    },
   1629    sessionType: "temporary",
   1630    sessionCount: 3,
   1631    duration: 1.6,
   1632  },
   1633  {
   1634    name: "400x225",
   1635    tracks: [
   1636      {
   1637        name: "audio",
   1638        type: 'audio/mp4; codecs="mp4a.40.2"',
   1639        fragments: [
   1640          "bipbop_225w_175kbps-cenc-audio-key1-init.mp4",
   1641          "bipbop_225w_175kbps-cenc-audio-key1-1.m4s",
   1642          "bipbop_225w_175kbps-cenc-audio-key1-2.m4s",
   1643          "bipbop_225w_175kbps-cenc-audio-key1-3.m4s",
   1644          "bipbop_225w_175kbps-cenc-audio-key1-4.m4s",
   1645        ],
   1646      },
   1647      {
   1648        name: "video",
   1649        type: 'video/mp4; codecs="avc1.64000d"',
   1650        fragments: [
   1651          "bipbop_225w_175kbps-cenc-video-key1-init.mp4",
   1652          "bipbop_225w_175kbps-cenc-video-key1-1.m4s",
   1653        ],
   1654      },
   1655    ],
   1656    keys: {
   1657      // "keyid" : "key"
   1658      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1659      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1660    },
   1661    sessionType: "temporary",
   1662    sessionCount: 2,
   1663    duration: 1.6,
   1664  },
   1665  {
   1666    name: "640x360",
   1667    tracks: [
   1668      {
   1669        name: "audio",
   1670        type: 'audio/mp4; codecs="mp4a.40.2"',
   1671        fragments: [
   1672          "bipbop_360w_253kbps-cenc-audio-key1-init.mp4",
   1673          "bipbop_360w_253kbps-cenc-audio-key1-1.m4s",
   1674          "bipbop_360w_253kbps-cenc-audio-key1-2.m4s",
   1675          "bipbop_360w_253kbps-cenc-audio-key1-3.m4s",
   1676          "bipbop_360w_253kbps-cenc-audio-key1-4.m4s",
   1677        ],
   1678      },
   1679      {
   1680        name: "video",
   1681        type: 'video/mp4; codecs="avc1.64001e"',
   1682        fragments: [
   1683          "bipbop_360w_253kbps-cenc-video-key1-init.mp4",
   1684          "bipbop_360w_253kbps-cenc-video-key1-1.m4s",
   1685        ],
   1686      },
   1687    ],
   1688    keys: {
   1689      // "keyid" : "key"
   1690      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1691      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1692    },
   1693    sessionType: "temporary",
   1694    sessionCount: 2,
   1695    duration: 1.6,
   1696  },
   1697  {
   1698    name: "400x225 then 640x360",
   1699    tracks: [
   1700      {
   1701        name: "audio",
   1702        type: 'audio/mp4; codecs="mp4a.40.2"',
   1703        fragments: [
   1704          "bipbop_225w_175kbps-cenc-audio-key1-init.mp4",
   1705          "bipbop_225w_175kbps-cenc-audio-key1-1.m4s",
   1706          "bipbop_225w_175kbps-cenc-audio-key1-2.m4s",
   1707          "bipbop_225w_175kbps-cenc-audio-key1-3.m4s",
   1708          "bipbop_225w_175kbps-cenc-audio-key1-4.m4s",
   1709        ],
   1710      },
   1711      {
   1712        name: "video",
   1713        type: 'video/mp4; codecs="avc1.64000d,avc1.64001e"',
   1714        fragments: [
   1715          "bipbop_225w_175kbps-cenc-video-key1-init.mp4",
   1716          "bipbop_225w_175kbps-cenc-video-key1-1.m4s",
   1717          "bipbop_360w_253kbps-cenc-video-key2-init.mp4",
   1718          "bipbop_360w_253kbps-cenc-video-key2-1.m4s",
   1719        ],
   1720      },
   1721    ],
   1722    keys: {
   1723      // "keyid" : "key"
   1724      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1725      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1726      "7e571d037e571d037e571d037e571d12": "7e5733337e5733337e5733337e573312",
   1727    },
   1728    sessionType: "temporary",
   1729    sessionCount: 3,
   1730    duration: 1.6,
   1731  },
   1732  {
   1733    name: "640x360 then 640x480",
   1734    tracks: [
   1735      {
   1736        name: "audio",
   1737        type: 'audio/mp4; codecs="mp4a.40.2"',
   1738        fragments: [
   1739          "bipbop_360w_253kbps-cenc-audio-key1-init.mp4",
   1740          "bipbop_360w_253kbps-cenc-audio-key1-1.m4s",
   1741          "bipbop_360w_253kbps-cenc-audio-key1-2.m4s",
   1742          "bipbop_360w_253kbps-cenc-audio-key1-3.m4s",
   1743          "bipbop_360w_253kbps-cenc-audio-key1-4.m4s",
   1744        ],
   1745      },
   1746      {
   1747        name: "video",
   1748        type: 'video/mp4; codecs="avc1.64001e,avc1.4d401e"',
   1749        fragments: [
   1750          "bipbop_360w_253kbps-cenc-video-key1-init.mp4",
   1751          "bipbop_360w_253kbps-cenc-video-key1-1.m4s",
   1752          "bipbop_480_624kbps-cenc-video-key2-init.mp4",
   1753          "bipbop_480_624kbps-cenc-video-key2-2.m4s",
   1754        ],
   1755      },
   1756    ],
   1757    keys: {
   1758      // "keyid" : "key"
   1759      "7e571d037e571d037e571d037e571d11": "7e5733337e5733337e5733337e573311",
   1760      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1761      "7e571d037e571d037e571d037e571d12": "7e5733337e5733337e5733337e573312",
   1762    },
   1763    sessionType: "temporary",
   1764    sessionCount: 3,
   1765    duration: 1.6,
   1766  },
   1767  {
   1768    // File generated with shaka packager:
   1769    // packager-osx --enable_raw_key_encryption --keys label=:key_id=7e571d047e571d047e571d047e571d21:key=7e5744447e5744447e5744447e574421 --segment_duration 1 --clear_lead 0 in=test-flac.mp4,stream=audio,output=flac-sample-cenc.mp4
   1770    name: "flac in mp4 clearkey",
   1771    tracks: [
   1772      {
   1773        name: "audio",
   1774        type: 'audio/mp4; codecs="flac"',
   1775        fragments: ["flac-sample-cenc.mp4"],
   1776      },
   1777    ],
   1778    keys: {
   1779      // "keyid" : "key"
   1780      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1781    },
   1782    sessionType: "temporary",
   1783    sessionCount: 1,
   1784    duration: 2.05,
   1785  },
   1786  {
   1787    // File generated with shaka packager:
   1788    // packager-osx --enable_raw_key_encryption --keys label=:key_id=7e571d047e571d047e571d047e571d21:key=7e5744447e5744447e5744447e574421 --segment_duration 1 --clear_lead 0 in=test-opus.mp4,stream=audio,output=opus-sample-cenc.mp4
   1789    name: "opus in mp4 clearkey",
   1790    tracks: [
   1791      {
   1792        name: "audio",
   1793        type: 'audio/mp4; codecs="opus"',
   1794        fragments: ["opus-sample-cenc.mp4"],
   1795      },
   1796    ],
   1797    keys: {
   1798      // "keyid" : "key"
   1799      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1800    },
   1801    sessionType: "temporary",
   1802    sessionCount: 1,
   1803    duration: 1.98,
   1804  },
   1805  // ffmpeg -i bipbop.mp4 -t 00:00:02 -c:v libaom-av1 bipbop_av1.mp4
   1806  // packager-linux-x64 in=bipbop_av1.mp4,stream=video,out=bipbop-clearkey-video-av1.mp4 --enable_raw_key_encryption --keys label=:key_id=8b5df745ad84145b5617c33116e35a67:key=bddfd35dd9be033ee73bc18bc1885056 --clear_lead 0
   1807  {
   1808    name: "MP4 av1 video clearkey",
   1809    tracks: [
   1810      {
   1811        name: "video",
   1812        type: 'video/mp4; codecs="av1"',
   1813        fragments: ["bipbop-clearkey-video-av1.mp4"],
   1814      },
   1815    ],
   1816    keys: {
   1817      // "keyid" : "key"
   1818      "8b5df745ad84145b5617c33116e35a67": "bddfd35dd9be033ee73bc18bc1885056",
   1819    },
   1820    sessionType: "temporary",
   1821    sessionCount: 1,
   1822    duration: 2.0,
   1823    skipTests: ["waitingforkey"],
   1824  },
   1825  // ffmpeg -i bipbop.mp4 -t 00:00:02 -c:v libaom-av1 bipbop_av1.webm
   1826  // packager-linux-x64 in=bipbop_av1.webm,stream=video,out=bipbop-clearkey-video-av1.webm --enable_raw_key_encryption --keys label=:key_id=8b5df745ad84145b5617c33116e35a67:key=bddfd35dd9be033ee73bc18bc1885056 --clear_lead 0
   1827  {
   1828    name: "WebM av1 video clearkey",
   1829    tracks: [
   1830      {
   1831        name: "video",
   1832        type: 'video/webm; codecs="av1"',
   1833        fragments: ["bipbop-clearkey-video-av1.webm"],
   1834      },
   1835    ],
   1836    keys: {
   1837      // "keyid" : "key"
   1838      "8b5df745ad84145b5617c33116e35a67": "bddfd35dd9be033ee73bc18bc1885056",
   1839    },
   1840    sessionType: "temporary",
   1841    sessionCount: 1,
   1842    duration: 2.0,
   1843    skipTests: ["waitingforkey"],
   1844  },
   1845  {
   1846    name: "WebM vorbis audio & vp8 video clearkey",
   1847    tracks: [
   1848      {
   1849        name: "audio",
   1850        type: 'audio/webm; codecs="vorbis"',
   1851        fragments: ["bipbop_360w_253kbps-clearkey-audio.webm"],
   1852      },
   1853      {
   1854        name: "video",
   1855        type: 'video/webm; codecs="vp8"',
   1856        fragments: ["bipbop_360w_253kbps-clearkey-video-vp8.webm"],
   1857      },
   1858    ],
   1859    keys: {
   1860      // "keyid" : "key"
   1861      f1f3ee1790527e9de47217d43835f76a: "97b9ddc459c8d5ff23c1f2754c95abe8",
   1862      "8b5df745ad84145b5617c33116e35a67": "bddfd35dd9be033ee73bc18bc1885056",
   1863    },
   1864    sessionType: "temporary",
   1865    sessionCount: 2,
   1866    duration: 1.6,
   1867  },
   1868  {
   1869    name: "WebM vorbis audio & vp9 video clearkey",
   1870    tracks: [
   1871      {
   1872        name: "audio",
   1873        type: 'audio/webm; codecs="vorbis"',
   1874        fragments: ["bipbop_360w_253kbps-clearkey-audio.webm"],
   1875      },
   1876      {
   1877        name: "video",
   1878        type: 'video/webm; codecs="vp9"',
   1879        fragments: ["bipbop_360w_253kbps-clearkey-video-vp9.webm"],
   1880      },
   1881    ],
   1882    keys: {
   1883      // "keyid" : "key"
   1884      f1f3ee1790527e9de47217d43835f76a: "97b9ddc459c8d5ff23c1f2754c95abe8",
   1885      eedf63a94fa7c398ee094f123a4ee709: "973b679a746c82f3acdb856b30e9378e",
   1886    },
   1887    sessionType: "temporary",
   1888    sessionCount: 2,
   1889    duration: 1.6,
   1890  },
   1891  {
   1892    name: "WebM vorbis audio & vp9 video clearkey with subsample encryption",
   1893    tracks: [
   1894      {
   1895        name: "audio",
   1896        type: 'audio/webm; codecs="vorbis"',
   1897        fragments: ["sintel-short-clearkey-subsample-encrypted-audio.webm"],
   1898      },
   1899      {
   1900        name: "video",
   1901        type: 'video/webm; codecs="vp9"',
   1902        fragments: ["sintel-short-clearkey-subsample-encrypted-video.webm"],
   1903      },
   1904    ],
   1905    keys: {
   1906      // "keyid" : "key"
   1907      "2cdb0ed6119853e7850671c3e9906c3c": "808B9ADAC384DE1E4F56140F4AD76194",
   1908    },
   1909    sessionType: "temporary",
   1910    sessionCount: 2,
   1911    duration: 2.0,
   1912  },
   1913  {
   1914    // Files adapted from testcase for bug 1560092. See bug 1630381 for a
   1915    // detailed explanation on how they were adapted.
   1916    name: "avc3 h264 video in mp4 using clearkey cenc encryption",
   1917    tracks: [
   1918      {
   1919        name: "video",
   1920        type: 'video/mp4; codecs="avc3.640015"',
   1921        fragments: [
   1922          "big-buck-bunny-cenc-avc3-init.mp4",
   1923          "big-buck-bunny-cenc-avc3-1.m4s",
   1924        ],
   1925      },
   1926    ],
   1927    keys: {
   1928      // "keyid" : "key"
   1929      "10000000100010001000100000000001": "3A2A1B68DD2BD9B2EEB25E84C4776668",
   1930    },
   1931    sessionType: "temporary",
   1932    sessionCount: 1,
   1933    duration: 2.08,
   1934  },
   1935  // The following cbcs files are created using shaka-packager using commands like
   1936  // ./packager-win.exe 'in=bipbop_2s.mp4,stream=audio,init_segment=bipbop_cbcs_1_9_audio_init.mp4,segment_template=bipbop_cbcs_1_9_audio_$Number$.m4s' \
   1937  // 'in=bipbop_2s.mp4,stream=video,init_segment=bipbop_cbcs_1_9_video_init.mp4,segment_template=bipbop_cbcs_1_9_video_$Number$.m4s' --protection_scheme cbcs \
   1938  // --enable_raw_key_encryption --keys label=:key_id=7e571d047e571d047e571d047e571d21:key=7e5744447e5744447e5744447e574421 --iv 11223344556677889900112233445566 \
   1939  // --clear_lead 0 --crypt_byte_block 1 --skip_byte_block 9
   1940  // See bug 1726202 for more details on their creation.
   1941  {
   1942    name: "mp4 h264 + aac clearkey cbcs 1:9 pattern",
   1943    tracks: [
   1944      {
   1945        name: "video",
   1946        type: 'video/mp4; codecs="avc1.4d4015"',
   1947        fragments: [
   1948          "bipbop_cbcs_1_9_video_init.mp4",
   1949          "bipbop_cbcs_1_9_video_1.m4s",
   1950        ],
   1951      },
   1952      {
   1953        name: "audio",
   1954        type: 'audio/mp4; codecs="mp4a.40.2"',
   1955        fragments: [
   1956          "bipbop_cbcs_1_9_audio_init.mp4",
   1957          "bipbop_cbcs_1_9_audio_1.m4s",
   1958        ],
   1959      },
   1960    ],
   1961    keys: {
   1962      // "keyid" : "key"
   1963      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1964    },
   1965    sessionType: "temporary",
   1966    sessionCount: 2,
   1967    duration: 2.04,
   1968  },
   1969  {
   1970    name: "mp4 h264 + aac clearkey cbcs 5:5 pattern",
   1971    tracks: [
   1972      {
   1973        name: "video",
   1974        type: 'video/mp4; codecs="avc1.4d4015"',
   1975        fragments: [
   1976          "bipbop_cbcs_5_5_video_init.mp4",
   1977          "bipbop_cbcs_5_5_video_1.m4s",
   1978        ],
   1979      },
   1980      {
   1981        name: "audio",
   1982        type: 'audio/mp4; codecs="mp4a.40.2"',
   1983        fragments: [
   1984          "bipbop_cbcs_5_5_audio_init.mp4",
   1985          "bipbop_cbcs_5_5_audio_1.m4s",
   1986        ],
   1987      },
   1988    ],
   1989    keys: {
   1990      // "keyid" : "key"
   1991      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   1992    },
   1993    sessionType: "temporary",
   1994    sessionCount: 2,
   1995    duration: 2.04,
   1996  },
   1997  {
   1998    name: "mp4 h264 + aac clearkey cbcs 10:0 pattern",
   1999    tracks: [
   2000      {
   2001        name: "video",
   2002        type: 'video/mp4; codecs="avc1.4d4015"',
   2003        fragments: [
   2004          "bipbop_cbcs_10_0_video_init.mp4",
   2005          "bipbop_cbcs_10_0_video_1.m4s",
   2006        ],
   2007      },
   2008      {
   2009        name: "audio",
   2010        type: 'audio/mp4; codecs="mp4a.40.2"',
   2011        fragments: [
   2012          "bipbop_cbcs_10_0_audio_init.mp4",
   2013          "bipbop_cbcs_10_0_audio_1.m4s",
   2014        ],
   2015      },
   2016    ],
   2017    keys: {
   2018      // "keyid" : "key"
   2019      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   2020    },
   2021    sessionType: "temporary",
   2022    sessionCount: 2,
   2023    duration: 2.04,
   2024  },
   2025  {
   2026    name: "mp4 h264 + aac clearkey cbcs 7:7 pattern",
   2027    tracks: [
   2028      {
   2029        name: "video",
   2030        type: 'video/mp4; codecs="avc1.4d4015"',
   2031        fragments: [
   2032          "bipbop_cbcs_7_7_video_init.mp4",
   2033          "bipbop_cbcs_7_7_video_1.m4s",
   2034        ],
   2035      },
   2036      {
   2037        name: "audio",
   2038        type: 'audio/mp4; codecs="mp4a.40.2"',
   2039        fragments: [
   2040          "bipbop_cbcs_7_7_audio_init.mp4",
   2041          "bipbop_cbcs_7_7_audio_1.m4s",
   2042        ],
   2043      },
   2044    ],
   2045    keys: {
   2046      // "keyid" : "key"
   2047      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   2048    },
   2049    sessionType: "temporary",
   2050    sessionCount: 2,
   2051    duration: 2.04,
   2052  },
   2053  {
   2054    name: "mp4 h264 + aac clearkey cbcs 9:8 pattern",
   2055    tracks: [
   2056      {
   2057        name: "video",
   2058        type: 'video/mp4; codecs="avc1.4d4015"',
   2059        fragments: [
   2060          "bipbop_cbcs_9_8_video_init.mp4",
   2061          "bipbop_cbcs_9_8_video_1.m4s",
   2062        ],
   2063      },
   2064      {
   2065        name: "audio",
   2066        type: 'audio/mp4; codecs="mp4a.40.2"',
   2067        fragments: [
   2068          "bipbop_cbcs_9_8_audio_init.mp4",
   2069          "bipbop_cbcs_9_8_audio_1.m4s",
   2070        ],
   2071      },
   2072    ],
   2073    keys: {
   2074      // "keyid" : "key"
   2075      "7e571d047e571d047e571d047e571d21": "7e5744447e5744447e5744447e574421",
   2076    },
   2077    sessionType: "temporary",
   2078    sessionCount: 2,
   2079    duration: 2.04,
   2080  },
   2081 ];
   2082 
   2083 var gEMENonMSEFailTests = [
   2084  {
   2085    name: "short-cenc.mp4",
   2086    audioType: 'audio/mp4; codecs="mp4a.40.2"',
   2087    videoType: 'video/mp4; codecs="avc1.64000d"',
   2088    duration: 0.47,
   2089  },
   2090 ];
   2091 
   2092 // Test files that are supposed to loop seamlessly when played back.
   2093 var gSeamlessLoopingTests = [
   2094  // MP4 files dont't loop seamlessly yet, the seeking logic seeks to 0, not the
   2095  // actual first packet, resulting in incorrect decoding.
   2096  // See bug 1817989
   2097  // { name: "sin-441-1s-44100-fdk_aac.mp4", type: "audio/mp4" },
   2098  // { name: "sin-441-1s-44100-afconvert.mp4", type: "audio/mp4" },
   2099  // { name: "sin-441-1s-44100.ogg", type: "audio/vorbis" },
   2100  // { name: "sin-441-1s-44100.opus", type: "audio/opus" },
   2101  { name: "sin-441-1s-44100-lame.mp3", type: "audio/mpeg" },
   2102  { name: "sin-441-1s-44100.flac", type: "audio/flac" },
   2103 ];
   2104 
   2105 // These are files that are used for video decode suspend in
   2106 // background tabs tests.
   2107 var gDecodeSuspendTests = [
   2108  { name: "gizmo.mp4", type: "video/mp4", duration: 5.56 },
   2109  { name: "gizmo-noaudio.mp4", type: "video/mp4", duration: 5.56 },
   2110  { name: "gizmo.webm", type: 'video/webm; codecs="vp9,opus"', duration: 5.56 },
   2111  {
   2112    name: "gizmo-noaudio.webm",
   2113    type: 'video/webm; codecs="vp9"',
   2114    duration: 5.56,
   2115  },
   2116 ];
   2117 
   2118 // These are video files with hardware-decodable formats and longer
   2119 // durations that are looped while we check telemetry for macOS video
   2120 // low power mode.
   2121 var gVideoLowPowerTests = [
   2122  { name: "gizmo.mp4", type: "video/mp4", duration: 5.56 },
   2123 ];
   2124 
   2125 function checkMetadata(msg, e, test) {
   2126  if (test.width) {
   2127    is(e.videoWidth, test.width, msg + " video width");
   2128  }
   2129  if (test.height) {
   2130    is(e.videoHeight, test.height, msg + " video height");
   2131  }
   2132  if (test.duration) {
   2133    ok(
   2134      Math.abs(e.duration - test.duration) < 0.1,
   2135      msg + " duration (" + e.duration + ") should be around " + test.duration
   2136    );
   2137  }
   2138  is(
   2139    !!test.keys,
   2140    SpecialPowers.do_lookupGetter(e, "isEncrypted").apply(e),
   2141    msg + " isEncrypted should be true if we have decryption keys"
   2142  );
   2143 }
   2144 
   2145 // Returns the first test from candidates array which we can play with the
   2146 // installed video backends.
   2147 function getPlayableVideo(candidates) {
   2148  var resources = getPlayableVideos(candidates);
   2149  if (resources.length) {
   2150    return resources[0];
   2151  }
   2152  return null;
   2153 }
   2154 
   2155 function getPlayableVideos(candidates) {
   2156  var v = manifestVideo();
   2157  return candidates.filter(function (x) {
   2158    return /^video/.test(x.type) && v.canPlayType(x.type);
   2159  });
   2160 }
   2161 
   2162 function getPlayableAudio(candidates) {
   2163  var v = manifestVideo();
   2164  var resources = candidates.filter(function (x) {
   2165    return /^audio/.test(x.type) && v.canPlayType(x.type);
   2166  });
   2167  if (resources.length) {
   2168    return resources[0];
   2169  }
   2170  return null;
   2171 }
   2172 
   2173 // Returns the type of element that should be created for the given mimetype.
   2174 function getMajorMimeType(mimetype) {
   2175  if (/^video/.test(mimetype)) {
   2176    return "video";
   2177  }
   2178  return "audio";
   2179 }
   2180 
   2181 // Force releasing decoder to avoid timeout in waiting for decoding resource.
   2182 function removeNodeAndSource(n) {
   2183  n.remove();
   2184  // reset |srcObject| first since it takes precedence over |src|.
   2185  n.srcObject = null;
   2186  n.removeAttribute("src");
   2187  n.load();
   2188  while (n.firstChild) {
   2189    n.firstChild.remove();
   2190  }
   2191 }
   2192 
   2193 function once(target, name, cb) {
   2194  var p = new Promise(function (resolve) {
   2195    target.addEventListener(
   2196      name,
   2197      function () {
   2198        resolve();
   2199      },
   2200      { once: true }
   2201    );
   2202  });
   2203  if (cb) {
   2204    p.then(cb);
   2205  }
   2206  return p;
   2207 }
   2208 
   2209 /**
   2210 * @param {HTMLMediaElement} video target of interest.
   2211 * @param {string} eventName the event to wait on.
   2212 * @returns {Promise} A promise that is resolved when event happens.
   2213 */
   2214 function nextEvent(video, eventName) {
   2215  return new Promise(function (resolve) {
   2216    let f = function (event) {
   2217      video.removeEventListener(eventName, f);
   2218      resolve(event);
   2219    };
   2220    video.addEventListener(eventName, f);
   2221  });
   2222 }
   2223 
   2224 function TimeStamp(token) {
   2225  function pad(x) {
   2226    return x < 10 ? "0" + x : x;
   2227  }
   2228  var now = new Date();
   2229  var ms = now.getMilliseconds();
   2230  var time =
   2231    "[" +
   2232    pad(now.getHours()) +
   2233    ":" +
   2234    pad(now.getMinutes()) +
   2235    ":" +
   2236    pad(now.getSeconds()) +
   2237    "." +
   2238    ms +
   2239    "]" +
   2240    // eslint-disable-next-line no-nested-ternary
   2241    (ms < 10 ? "  " : ms < 100 ? " " : "");
   2242  return token ? time + " " + token : time;
   2243 }
   2244 
   2245 function Log(token, msg) {
   2246  info(TimeStamp(token) + " " + msg);
   2247 }
   2248 
   2249 // Number of tests to run in parallel.
   2250 var PARALLEL_TESTS = 2;
   2251 
   2252 // Disable parallel test for media engine tests, see more info in bug 1840914.
   2253 if (
   2254  SpecialPowers.Services.prefs.getIntPref("media.wmf.media-engine.enabled", 0)
   2255 ) {
   2256  PARALLEL_TESTS = 1;
   2257 }
   2258 
   2259 // Prefs to set before running tests.  Use this to improve coverage of
   2260 // conditions that might not otherwise be encountered on the test data.
   2261 var gTestPrefs = [
   2262  ["media.recorder.max_memory", 1024],
   2263  ["media.audio-max-decode-error", 0],
   2264  ["media.video-max-decode-error", 0],
   2265 ];
   2266 
   2267 // When true, we'll loop forever on whatever test we run. Use this to debug
   2268 // intermittent test failures.
   2269 const DEBUG_TEST_LOOP_FOREVER = false;
   2270 
   2271 // Manages a run of media tests. Runs them in chunks in order to limit
   2272 // the number of media elements/threads running in parallel. This limits peak
   2273 // memory use, particularly on Linux x86 where thread stacks use 10MB of
   2274 // virtual address space.
   2275 // Usage:
   2276 //   1. Create a new MediaTestManager object.
   2277 //   2. Create a test startTest function. This takes a test object and a token,
   2278 //      and performs anything necessary to start the test. The test object is an
   2279 //      element in one of the g*Tests above. Your startTest function must call
   2280 //      MediaTestManager.start(token) if it starts a test. The test object is
   2281 //      guaranteed to be playable by our supported decoders; you don't need to
   2282 //      check canPlayType.
   2283 //   3. When your tests finishes, call MediaTestManager.finished(), passing
   2284 //      the token back to the manager. The manager may either start the next run
   2285 //      or end the mochitest if all the tests are done.
   2286 function MediaTestManager() {
   2287  // Set a very large timeout to prevent Mochitest timeout.
   2288  // Instead MediaTestManager will manage timeout of each test.
   2289  SimpleTest.requestLongerTimeout(1000);
   2290 
   2291  // Return how many seconds elapsed since |begin|.
   2292  function elapsedTime(begin) {
   2293    var end = new Date();
   2294    return (end.getTime() - begin.getTime()) / 1000;
   2295  }
   2296  // Sets up a MediaTestManager to runs through the 'tests' array, which needs
   2297  // to be one of, or have the same fields as, the g*Test arrays of tests. Uses
   2298  // the user supplied 'startTest' function to initialize the test. This
   2299  // function must accept two arguments, the test entry from the 'tests' array,
   2300  // and a token. Call MediaTestManager.started(token) if you start the test,
   2301  // and MediaTestManager.finished(token) when the test finishes. You don't have
   2302  // to start every test, but if you call started() you *must* call finish()
   2303  // else you'll timeout.
   2304  this.runTests = function (tests, startTest) {
   2305    this.startTime = new Date();
   2306    SimpleTest.info(
   2307      "Started " +
   2308        this.startTime +
   2309        " (" +
   2310        this.startTime.getTime() / 1000 +
   2311        "s)"
   2312    );
   2313    this.testNum = 0;
   2314    this.tests = tests;
   2315    this.startTest = startTest;
   2316    this.tokens = [];
   2317    this.isShutdown = false;
   2318    this.numTestsRunning = 0;
   2319    this.handlers = {};
   2320    this.timers = {};
   2321 
   2322    // Always wait for explicit finish.
   2323    SimpleTest.waitForExplicitFinish();
   2324    SpecialPowers.pushPrefEnv({ set: gTestPrefs }, () => {
   2325      this.nextTest();
   2326    });
   2327 
   2328    SimpleTest.registerCleanupFunction(() => {
   2329      if (this.tokens.length) {
   2330        info("Test timed out. Remaining tests=" + this.tokens);
   2331      }
   2332      for (var token of this.tokens) {
   2333        var handler = this.handlers[token];
   2334        if (handler && handler.ontimeout) {
   2335          handler.ontimeout();
   2336        }
   2337      }
   2338    });
   2339  };
   2340 
   2341  // Registers that the test corresponding to 'token' has been started.
   2342  // Don't call more than once per token.
   2343  this.started = function (token, handler) {
   2344    this.tokens.push(token);
   2345    this.numTestsRunning++;
   2346    this.handlers[token] = handler;
   2347 
   2348    var onTimeout = async () => {
   2349      ok(false, "Test timed out!");
   2350      info(`${token} timed out!`);
   2351      await dumpDebugInfoForToken(token);
   2352      this.finished(token);
   2353    };
   2354    // Default timeout to 180s for each test.
   2355    // Call SimpleTest._originalSetTimeout() to bypass the flaky timeout checker.
   2356    this.timers[token] = SimpleTest._originalSetTimeout.call(
   2357      window,
   2358      onTimeout,
   2359      180000
   2360    );
   2361 
   2362    is(
   2363      this.numTestsRunning,
   2364      this.tokens.length,
   2365      "[started " +
   2366        token +
   2367        " t=" +
   2368        elapsedTime(this.startTime) +
   2369        "] Length of array should match number of running tests"
   2370    );
   2371  };
   2372 
   2373  // Registers that the test corresponding to 'token' has finished. Call when
   2374  // you've finished your test. If all tests are complete this will finish the
   2375  // run, otherwise it may start up the next run. It's ok to call multiple times
   2376  // per token.
   2377  this.finished = function (token) {
   2378    var i = this.tokens.indexOf(token);
   2379    if (i != -1) {
   2380      // Remove the element from the list of running tests.
   2381      this.tokens.splice(i, 1);
   2382    }
   2383 
   2384    if (this.timers[token]) {
   2385      // Cancel the timer when the test finishes.
   2386      clearTimeout(this.timers[token]);
   2387      this.timers[token] = null;
   2388    }
   2389 
   2390    info("[finished " + token + "] remaining= " + this.tokens);
   2391    this.numTestsRunning--;
   2392    is(
   2393      this.numTestsRunning,
   2394      this.tokens.length,
   2395      "[finished " +
   2396        token +
   2397        " t=" +
   2398        elapsedTime(this.startTime) +
   2399        "] Length of array should match number of running tests"
   2400    );
   2401    if (this.tokens.length < PARALLEL_TESTS) {
   2402      this.nextTest();
   2403    }
   2404  };
   2405 
   2406  // Starts the next batch of tests, or finishes if they're all done.
   2407  // Don't call this directly, call finished(token) when you're done.
   2408  this.nextTest = function () {
   2409    while (
   2410      this.testNum < this.tests.length &&
   2411      this.tokens.length < PARALLEL_TESTS
   2412    ) {
   2413      var test = this.tests[this.testNum];
   2414      var token = (test.name ? test.name + "-" : "") + this.testNum;
   2415      this.testNum++;
   2416 
   2417      if (DEBUG_TEST_LOOP_FOREVER && this.testNum == this.tests.length) {
   2418        this.testNum = 0;
   2419      }
   2420 
   2421      // Ensure we can play the resource type.
   2422      if (
   2423        test.type &&
   2424        !document.createElement("video").canPlayType(test.type)
   2425      ) {
   2426        SimpleTest.info(`Skipping ${token} type=${test.type}`);
   2427        continue;
   2428      }
   2429 
   2430      // Do the init. This should start the test.
   2431      this.startTest(test, token);
   2432    }
   2433 
   2434    if (
   2435      this.testNum == this.tests.length &&
   2436      !DEBUG_TEST_LOOP_FOREVER &&
   2437      !this.tokens.length &&
   2438      !this.isShutdown
   2439    ) {
   2440      this.isShutdown = true;
   2441      if (this.onFinished) {
   2442        this.onFinished();
   2443      }
   2444      var onCleanup = () => {
   2445        var end = new Date();
   2446        SimpleTest.info(
   2447          "Finished at " + end + " (" + end.getTime() / 1000 + "s)"
   2448        );
   2449        SimpleTest.info("Running time: " + elapsedTime(this.startTime) + "s");
   2450        SimpleTest.finish();
   2451      };
   2452      mediaTestCleanup(onCleanup);
   2453    }
   2454  };
   2455 }
   2456 
   2457 // Ensures we've got no active video or audio elements in the document, and
   2458 // forces a GC to release the address space reserved by the decoders' threads'
   2459 // stacks.
   2460 function mediaTestCleanup(callback) {
   2461  var V = document.getElementsByTagName("video");
   2462  for (let i = 0; i < V.length; i++) {
   2463    removeNodeAndSource(V[i]);
   2464    V[i] = null;
   2465  }
   2466  var A = document.getElementsByTagName("audio");
   2467  for (let i = 0; i < A.length; i++) {
   2468    removeNodeAndSource(A[i]);
   2469    A[i] = null;
   2470  }
   2471  SpecialPowers.exactGC(callback);
   2472 }
   2473 
   2474 async function dumpDebugInfoForToken(token) {
   2475  for (let v of document.getElementsByTagName("video")) {
   2476    if (token === v.token) {
   2477      info(JSON.stringify(await SpecialPowers.wrap(v).mozRequestDebugInfo()));
   2478      return;
   2479    }
   2480  }
   2481  for (let a of document.getElementsByTagName("audio")) {
   2482    if (token === a.token) {
   2483      info(JSON.stringify(await SpecialPowers.wrap(a).mozRequestDebugInfo()));
   2484      return;
   2485    }
   2486  }
   2487 }
   2488 
   2489 // Could be undefined in a page opened by the parent test page
   2490 // like file_access_controls.html.
   2491 if ("SimpleTest" in window) {
   2492  SimpleTest.requestFlakyTimeout("untriaged");
   2493 
   2494  // Register timeout function to dump debugging logs.
   2495  SimpleTest.registerTimeoutFunction(async function () {
   2496    for (const v of document.getElementsByTagName("video")) {
   2497      SimpleTest.info(
   2498        JSON.stringify(await SpecialPowers.wrap(v).mozRequestDebugInfo())
   2499      );
   2500    }
   2501    for (const a of document.getElementsByTagName("audio")) {
   2502      SimpleTest.info(
   2503        JSON.stringify(await SpecialPowers.wrap(a).mozRequestDebugInfo())
   2504      );
   2505    }
   2506  });
   2507 }