summaryrefslogtreecommitdiffstats
path: root/dom/media/mediasource/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/media/mediasource/test
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--dom/media/mediasource/test/.eslintrc.js28
-rw-r--r--dom/media/mediasource/test/1516754.webmbin0 -> 1081344 bytes
-rw-r--r--dom/media/mediasource/test/1516754.webm^headers^1
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-1.m4sbin0 -> 24328 bytes
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-2.m4sbin0 -> 24132 bytes
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-init.mp4bin0 -> 1246 bytes
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-1.m4sbin0 -> 48979 bytes
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-2.m4sbin0 -> 47727 bytes
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-init.mp4bin0 -> 634 bytes
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/avc3/init.mp4bin0 -> 687 bytes
-rw-r--r--dom/media/mediasource/test/avc3/init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/avc3/segment1.m4sbin0 -> 696869 bytes
-rw-r--r--dom/media/mediasource/test/avc3/segment1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop1.m4sbin0 -> 24424 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop10.m4sbin0 -> 18279 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop10.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop11.m4sbin0 -> 24607 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop11.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop12.m4sbin0 -> 22676 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop12.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop13.m4sbin0 -> 9847 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop13.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2.m4sbin0 -> 22205 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2s.mp4bin0 -> 48024 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2s.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop3.m4sbin0 -> 24013 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop3.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop4.m4sbin0 -> 23112 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop4.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop5.m4sbin0 -> 18367 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop5.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop6.m4sbin0 -> 24455 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop6.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop7.m4sbin0 -> 22442 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop7.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop8.m4sbin0 -> 24356 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop8.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop9.m4sbin0 -> 23252 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop9.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_300-3s.webmbin0 -> 79429 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_300-3s.webm^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4sbin0 -> 66806 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4sbin0 -> 65292 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4bin0 -> 1410 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio1.m4sbin0 -> 694 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio10.m4sbin0 -> 879 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio10.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio11.m4sbin0 -> 208 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio11.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio2.m4sbin0 -> 750 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio3.m4sbin0 -> 724 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio3.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio4.m4sbin0 -> 806 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio4.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio5.m4sbin0 -> 822 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio5.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio6.m4sbin0 -> 833 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio6.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio7.m4sbin0 -> 888 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio7.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio8.m4sbin0 -> 829 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio8.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio9.m4sbin0 -> 778 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio9.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4bin0 -> 825 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_dash.mpd48
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4bin0 -> 1441 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4sbin0 -> 110108 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4sbin0 -> 116079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4bin0 -> 1453 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4sbin0 -> 143079 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4sbin0 -> 137858 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4bin0 -> 1336 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4sbin0 -> 1023860 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video1.m4sbin0 -> 23860 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video10.m4sbin0 -> 18109 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video10.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video11.m4sbin0 -> 23969 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video11.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video12.m4sbin0 -> 21937 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video12.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video13.m4sbin0 -> 16265 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video13.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video2.m4sbin0 -> 21595 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video3.m4sbin0 -> 23429 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video3.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video4.m4sbin0 -> 22446 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video4.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video5.m4sbin0 -> 18191 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video5.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video6.m4sbin0 -> 23773 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video6.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video7.m4sbin0 -> 21749 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video7.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video8.m4sbin0 -> 23608 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video8.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video9.m4sbin0 -> 22553 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video9.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4bin0 -> 887 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbopinit.mp4bin0 -> 1395 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbopinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bug1718709_high_res.mp4bin0 -> 1038283 bytes
-rw-r--r--dom/media/mediasource/test/bug1718709_low_res.mp4bin0 -> 245318 bytes
-rw-r--r--dom/media/mediasource/test/crashtests/1005366.html27
-rw-r--r--dom/media/mediasource/test/crashtests/1059035.html26
-rw-r--r--dom/media/mediasource/test/crashtests/926665.html26
-rw-r--r--dom/media/mediasource/test/crashtests/931388.html17
-rw-r--r--dom/media/mediasource/test/crashtests/crashtests.list4
-rw-r--r--dom/media/mediasource/test/flac/00001.m4sbin0 -> 658125 bytes
-rw-r--r--dom/media/mediasource/test/flac/00001.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/flac/00002.m4sbin0 -> 685567 bytes
-rw-r--r--dom/media/mediasource/test/flac/00002.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/flac/00003.m4sbin0 -> 747868 bytes
-rw-r--r--dom/media/mediasource/test/flac/00003.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/flac/IS.mp4bin0 -> 608 bytes
-rw-r--r--dom/media/mediasource/test/flac/IS.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/init-trackid2.mp4bin0 -> 9108 bytes
-rw-r--r--dom/media/mediasource/test/init-trackid2.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/init-trackid3.mp4bin0 -> 9108 bytes
-rw-r--r--dom/media/mediasource/test/init-trackid3.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/mediasource.js235
-rw-r--r--dom/media/mediasource/test/mochitest.ini213
-rw-r--r--dom/media/mediasource/test/seek.webmbin0 -> 215529 bytes
-rw-r--r--dom/media/mediasource/test/seek.webm^headers^1
-rw-r--r--dom/media/mediasource/test/seek_lowres.webmbin0 -> 100749 bytes
-rw-r--r--dom/media/mediasource/test/seek_lowres.webm^headers^1
-rw-r--r--dom/media/mediasource/test/segment-2.0001.m4sbin0 -> 34778 bytes
-rw-r--r--dom/media/mediasource/test/segment-2.0001.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/segment-2.0002.m4sbin0 -> 34653 bytes
-rw-r--r--dom/media/mediasource/test/segment-2.0002.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/segment-3.0001.m4sbin0 -> 34787 bytes
-rw-r--r--dom/media/mediasource/test/segment-3.0001.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/segment-3.0002.m4sbin0 -> 34640 bytes
-rw-r--r--dom/media/mediasource/test/segment-3.0002.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/tags_before_cluster.webmbin0 -> 111714 bytes
-rw-r--r--dom/media/mediasource/test/tags_before_cluster.webm^header^1
-rw-r--r--dom/media/mediasource/test/test_AVC3_mp4.html38
-rw-r--r--dom/media/mediasource/test/test_AbortAfterPartialMediaSegment.html62
-rw-r--r--dom/media/mediasource/test/test_AppendPartialInitSegment.html43
-rw-r--r--dom/media/mediasource/test/test_AudioChange_mp4.html49
-rw-r--r--dom/media/mediasource/test/test_AudioChange_mp4_WebAudio.html55
-rw-r--r--dom/media/mediasource/test/test_AutoRevocation.html40
-rw-r--r--dom/media/mediasource/test/test_BufferedSeek.html44
-rw-r--r--dom/media/mediasource/test/test_BufferedSeek_mp4.html43
-rw-r--r--dom/media/mediasource/test/test_BufferingWait.html52
-rw-r--r--dom/media/mediasource/test/test_BufferingWait_mp4.html49
-rw-r--r--dom/media/mediasource/test/test_ChangeType.html84
-rw-r--r--dom/media/mediasource/test/test_ChangeWhileWaitingOnMissingData_mp4.html37
-rw-r--r--dom/media/mediasource/test/test_DifferentStreamStartTimes.html54
-rw-r--r--dom/media/mediasource/test/test_DrainOnMissingData_mp4.html49
-rw-r--r--dom/media/mediasource/test/test_DurationChange.html71
-rw-r--r--dom/media/mediasource/test/test_DurationUpdated.html48
-rw-r--r--dom/media/mediasource/test/test_DurationUpdated_mp4.html47
-rw-r--r--dom/media/mediasource/test/test_EndOfStream.html29
-rw-r--r--dom/media/mediasource/test/test_EndOfStream_mp4.html29
-rw-r--r--dom/media/mediasource/test/test_EndedEvent.html31
-rw-r--r--dom/media/mediasource/test/test_Eviction_mp4.html63
-rw-r--r--dom/media/mediasource/test/test_ExperimentalAsync.html102
-rw-r--r--dom/media/mediasource/test/test_FrameSelection.html64
-rw-r--r--dom/media/mediasource/test/test_FrameSelection_mp4.html49
-rw-r--r--dom/media/mediasource/test/test_HEAAC_extradata.html89
-rw-r--r--dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek.html38
-rw-r--r--dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek_mp4.html42
-rw-r--r--dom/media/mediasource/test/test_InputBufferIsCleared.html58
-rw-r--r--dom/media/mediasource/test/test_LiveSeekable.html84
-rw-r--r--dom/media/mediasource/test/test_LoadedDataFired_mp4.html57
-rw-r--r--dom/media/mediasource/test/test_LoadedMetadataFired.html31
-rw-r--r--dom/media/mediasource/test/test_LoadedMetadataFired_mp4.html31
-rw-r--r--dom/media/mediasource/test/test_MediaSource.html92
-rw-r--r--dom/media/mediasource/test/test_MediaSource_capture_gc.html72
-rw-r--r--dom/media/mediasource/test/test_MediaSource_disabled.html31
-rw-r--r--dom/media/mediasource/test/test_MediaSource_flac_mp4.html33
-rw-r--r--dom/media/mediasource/test/test_MediaSource_memory_reporting.html47
-rw-r--r--dom/media/mediasource/test/test_MediaSource_mp4.html90
-rw-r--r--dom/media/mediasource/test/test_MultipleInitSegments.html49
-rw-r--r--dom/media/mediasource/test/test_MultipleInitSegments_mp4.html44
-rw-r--r--dom/media/mediasource/test/test_NoAudioLoopBackData.html78
-rw-r--r--dom/media/mediasource/test/test_NoAudioLoopBackData_Muted.html79
-rw-r--r--dom/media/mediasource/test/test_NoVideoLoopBackData.html81
-rw-r--r--dom/media/mediasource/test/test_OnEvents.html42
-rw-r--r--dom/media/mediasource/test/test_PlayEvents.html115
-rw-r--r--dom/media/mediasource/test/test_PlayEventsAutoPlaying.html58
-rw-r--r--dom/media/mediasource/test/test_PlayEventsAutoPlaying2.html58
-rw-r--r--dom/media/mediasource/test/test_RemoveSourceBuffer.html52
-rw-r--r--dom/media/mediasource/test/test_Resolution_change_should_not_cause_video_freeze.html49
-rw-r--r--dom/media/mediasource/test/test_ResumeAfterClearing_mp4.html44
-rw-r--r--dom/media/mediasource/test/test_SeekNoData_mp4.html57
-rw-r--r--dom/media/mediasource/test/test_SeekToEnd_mp4.html54
-rw-r--r--dom/media/mediasource/test/test_SeekToLastFrame_mp4.html34
-rw-r--r--dom/media/mediasource/test/test_SeekTwice_mp4.html45
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream.html54
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit.html60
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit_mp4.html60
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream_mp4.html55
-rw-r--r--dom/media/mediasource/test/test_SeekedEvent_mp4.html48
-rw-r--r--dom/media/mediasource/test/test_Sequence_mp4.html37
-rw-r--r--dom/media/mediasource/test/test_SetModeThrows.html34
-rw-r--r--dom/media/mediasource/test/test_SplitAppend.html36
-rw-r--r--dom/media/mediasource/test/test_SplitAppendDelay.html38
-rw-r--r--dom/media/mediasource/test/test_SplitAppendDelay_mp4.html39
-rw-r--r--dom/media/mediasource/test/test_SplitAppend_mp4.html38
-rw-r--r--dom/media/mediasource/test/test_Threshold_mp4.html73
-rw-r--r--dom/media/mediasource/test/test_TimestampOffset_mp4.html76
-rw-r--r--dom/media/mediasource/test/test_TruncatedDuration.html55
-rw-r--r--dom/media/mediasource/test/test_TruncatedDuration_mp4.html59
-rw-r--r--dom/media/mediasource/test/test_WMFUnmatchedAudioDataTime.html32
-rw-r--r--dom/media/mediasource/test/test_WaitingOnMissingData.html60
-rw-r--r--dom/media/mediasource/test/test_WaitingOnMissingDataEnded_mp4.html47
-rw-r--r--dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html61
-rw-r--r--dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html52
-rw-r--r--dom/media/mediasource/test/test_WebMTagsBeforeCluster.html47
-rw-r--r--dom/media/mediasource/test/test_trackidchange_mp4.html32
-rw-r--r--dom/media/mediasource/test/whitenoise-he-aac-5s.mp4bin0 -> 27078 bytes
-rw-r--r--dom/media/mediasource/test/wmf_mismatchedaudiotime.mp4bin0 -> 48906 bytes
297 files changed, 4787 insertions, 0 deletions
diff --git a/dom/media/mediasource/test/.eslintrc.js b/dom/media/mediasource/test/.eslintrc.js
new file mode 100644
index 0000000000..e283e384ba
--- /dev/null
+++ b/dom/media/mediasource/test/.eslintrc.js
@@ -0,0 +1,28 @@
+"use strict";
+
+module.exports = {
+ // Globals from mediasource.js. We use false to indicate they should not
+ // be overwritten in scripts.
+ globals: {
+ addMSEPrefs: false,
+ fetchAndLoad: false,
+ fetchAndLoadAsync: false,
+ fetchWithXHR: false,
+ logEvents: false,
+ loadSegment: false,
+ must_not_reject: false,
+ must_not_throw: false,
+ must_reject: false,
+ must_throw: false,
+ once: false,
+ range: false,
+ runWithMSE: false,
+ wait: false,
+ waitUntilTime: false,
+ },
+ // Use const/let instead of var for tighter scoping, avoiding redeclaration
+ rules: {
+ "no-var": "error",
+ "prefer-const": "error",
+ },
+};
diff --git a/dom/media/mediasource/test/1516754.webm b/dom/media/mediasource/test/1516754.webm
new file mode 100644
index 0000000000..05a008d906
--- /dev/null
+++ b/dom/media/mediasource/test/1516754.webm
Binary files differ
diff --git a/dom/media/mediasource/test/1516754.webm^headers^ b/dom/media/mediasource/test/1516754.webm^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/1516754.webm^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/aac20-48000-64000-1.m4s b/dom/media/mediasource/test/aac20-48000-64000-1.m4s
new file mode 100644
index 0000000000..56506e1f2d
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac20-48000-64000-1.m4s^headers^ b/dom/media/mediasource/test/aac20-48000-64000-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/aac20-48000-64000-2.m4s b/dom/media/mediasource/test/aac20-48000-64000-2.m4s
new file mode 100644
index 0000000000..3faff17ebf
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac20-48000-64000-2.m4s^headers^ b/dom/media/mediasource/test/aac20-48000-64000-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/aac20-48000-64000-init.mp4 b/dom/media/mediasource/test/aac20-48000-64000-init.mp4
new file mode 100644
index 0000000000..b70e016512
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/aac20-48000-64000-init.mp4^headers^ b/dom/media/mediasource/test/aac20-48000-64000-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/aac51-48000-128000-1.m4s b/dom/media/mediasource/test/aac51-48000-128000-1.m4s
new file mode 100644
index 0000000000..3424acfecc
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac51-48000-128000-1.m4s^headers^ b/dom/media/mediasource/test/aac51-48000-128000-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/aac51-48000-128000-2.m4s b/dom/media/mediasource/test/aac51-48000-128000-2.m4s
new file mode 100644
index 0000000000..b02bfd043d
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac51-48000-128000-2.m4s^headers^ b/dom/media/mediasource/test/aac51-48000-128000-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/aac51-48000-128000-init.mp4 b/dom/media/mediasource/test/aac51-48000-128000-init.mp4
new file mode 100644
index 0000000000..7d62401f28
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/aac51-48000-128000-init.mp4^headers^ b/dom/media/mediasource/test/aac51-48000-128000-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/avc3/init.mp4 b/dom/media/mediasource/test/avc3/init.mp4
new file mode 100644
index 0000000000..12fc38bd20
--- /dev/null
+++ b/dom/media/mediasource/test/avc3/init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/avc3/init.mp4^headers^ b/dom/media/mediasource/test/avc3/init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/avc3/init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/avc3/segment1.m4s b/dom/media/mediasource/test/avc3/segment1.m4s
new file mode 100644
index 0000000000..d95a6adf02
--- /dev/null
+++ b/dom/media/mediasource/test/avc3/segment1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/avc3/segment1.m4s^headers^ b/dom/media/mediasource/test/avc3/segment1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/avc3/segment1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop1.m4s b/dom/media/mediasource/test/bipbop/bipbop1.m4s
new file mode 100644
index 0000000000..a237f2e91e
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop10.m4s b/dom/media/mediasource/test/bipbop/bipbop10.m4s
new file mode 100644
index 0000000000..d1f5e6a0b0
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop10.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop10.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop10.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop10.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop11.m4s b/dom/media/mediasource/test/bipbop/bipbop11.m4s
new file mode 100644
index 0000000000..57232fb359
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop11.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop11.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop11.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop11.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop12.m4s b/dom/media/mediasource/test/bipbop/bipbop12.m4s
new file mode 100644
index 0000000000..f9b18713ee
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop12.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop12.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop12.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop12.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop13.m4s b/dom/media/mediasource/test/bipbop/bipbop13.m4s
new file mode 100644
index 0000000000..f2a876946c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop13.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop13.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop13.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop13.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop2.m4s b/dom/media/mediasource/test/bipbop/bipbop2.m4s
new file mode 100644
index 0000000000..baa0d8578c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop2s.mp4 b/dom/media/mediasource/test/bipbop/bipbop2s.mp4
new file mode 100644
index 0000000000..4fd8b9cb6e
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop2s.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop2s.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop2s.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop2s.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop3.m4s b/dom/media/mediasource/test/bipbop/bipbop3.m4s
new file mode 100644
index 0000000000..ed313e668c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop3.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop3.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop3.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop3.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop4.m4s b/dom/media/mediasource/test/bipbop/bipbop4.m4s
new file mode 100644
index 0000000000..7709ac08c5
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop4.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop4.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop4.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop4.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop5.m4s b/dom/media/mediasource/test/bipbop/bipbop5.m4s
new file mode 100644
index 0000000000..6d36788e44
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop5.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop5.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop5.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop5.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop6.m4s b/dom/media/mediasource/test/bipbop/bipbop6.m4s
new file mode 100644
index 0000000000..64f475c700
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop6.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop6.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop6.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop6.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop7.m4s b/dom/media/mediasource/test/bipbop/bipbop7.m4s
new file mode 100644
index 0000000000..c148918d6d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop7.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop7.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop7.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop7.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop8.m4s b/dom/media/mediasource/test/bipbop/bipbop8.m4s
new file mode 100644
index 0000000000..707dd48485
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop8.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop8.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop8.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop8.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop9.m4s b/dom/media/mediasource/test/bipbop/bipbop9.m4s
new file mode 100644
index 0000000000..538cf72a4d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop9.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop9.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop9.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop9.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_300-3s.webm b/dom/media/mediasource/test/bipbop/bipbop_300-3s.webm
new file mode 100644
index 0000000000..db578dc96c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_300-3s.webm
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_300-3s.webm^headers^ b/dom/media/mediasource/test/bipbop/bipbop_300-3s.webm^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_300-3s.webm^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s
new file mode 100644
index 0000000000..3dad336e8e
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s
new file mode 100644
index 0000000000..dd7491241f
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4 b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4
new file mode 100644
index 0000000000..b1a2d44058
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s
new file mode 100644
index 0000000000..33da98b5a9
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s
new file mode 100644
index 0000000000..36a98afd29
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s
new file mode 100644
index 0000000000..23d4aa8d86
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s
new file mode 100644
index 0000000000..96f4bcc344
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s
new file mode 100644
index 0000000000..7de4bd0ca1
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s
new file mode 100644
index 0000000000..494c71eb92
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s
new file mode 100644
index 0000000000..b50496b6ce
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s
new file mode 100644
index 0000000000..02cf4d363c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s
new file mode 100644
index 0000000000..bb2252889f
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s
new file mode 100644
index 0000000000..04a6a7af91
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s b/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s
new file mode 100644
index 0000000000..cb94b529a7
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4 b/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4
new file mode 100644
index 0000000000..bbf272197d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_dash.mpd b/dom/media/mediasource/test/bipbop/bipbop_dash.mpd
new file mode 100644
index 0000000000..532cdc65d5
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_dash.mpd
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H0M9.98S" profiles="urn:mpeg:dash:profile:full:2011">
+ <ProgramInformation moreInformationURL="http://gpac.sourceforge.net">
+ <Title>bipbop_dash.mpd handcrafted by JYA</Title>
+ </ProgramInformation>
+
+ <Period duration="PT0H0M9.98S">
+ <AdaptationSet segmentAlignment="true" maxWidth="400" maxHeight="300" maxFrameRate="90000" par="4:3" lang="und">
+ <Representation id="1" mimeType="video/mp4" codecs="avc1.4d4015" width="400" height="300" frameRate="90000" sar="1:1" startWithSAP="1" bandwidth="226425">
+ <SegmentList timescale="90000" duration="69043">
+ <Initialization sourceURL="bipbop_videoinit.mp4"/>
+ <SegmentURL media="bipbop_video1.m4s"/>
+ <SegmentURL media="bipbop_video2.m4s"/>
+ <SegmentURL media="bipbop_video3.m4s"/>
+ <SegmentURL media="bipbop_video4.m4s"/>
+ <SegmentURL media="bipbop_video5.m4s"/>
+ <SegmentURL media="bipbop_video6.m4s"/>
+ <SegmentURL media="bipbop_video7.m4s"/>
+ <SegmentURL media="bipbop_video8.m4s"/>
+ <SegmentURL media="bipbop_video9.m4s"/>
+ <SegmentURL media="bipbop_video10.m4s"/>
+ <SegmentURL media="bipbop_video11.m4s"/>
+ <SegmentURL media="bipbop_video12.m4s"/>
+ <SegmentURL media="bipbop_video13.m4s"/>
+ </SegmentList>
+ </Representation>
+ </AdaptationSet>
+ <AdaptationSet segmentAlignment="true" lang="und">
+ <Representation id="1" mimeType="audio/mp4" codecs="mp4a.40.2" audioSamplingRate="22050" startWithSAP="1" bandwidth="7206">
+ <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
+ <SegmentList timescale="22050" duration="20101">
+ <Initialization sourceURL="bipbop_audioinit.mp4"/>
+ <SegmentURL media="bipbop_audio1.m4s"/>
+ <SegmentURL media="bipbop_audio2.m4s"/>
+ <SegmentURL media="bipbop_audio3.m4s"/>
+ <SegmentURL media="bipbop_audio4.m4s"/>
+ <SegmentURL media="bipbop_audio5.m4s"/>
+ <SegmentURL media="bipbop_audio6.m4s"/>
+ <SegmentURL media="bipbop_audio7.m4s"/>
+ <SegmentURL media="bipbop_audio8.m4s"/>
+ <SegmentURL media="bipbop_audio9.m4s"/>
+ <SegmentURL media="bipbop_audio10.m4s"/>
+ <SegmentURL media="bipbop_audio11.m4s"/>
+ </SegmentList>
+ </Representation>
+ </AdaptationSet>
+ </Period>
+</MPD>
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4s
new file mode 100644
index 0000000000..2b95d49de9
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4s
new file mode 100644
index 0000000000..3d95e7e2bf
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4
new file mode 100644
index 0000000000..cc7a48b5ce
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.0-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4s
new file mode 100644
index 0000000000..d67c4ef4cc
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4s
new file mode 100644
index 0000000000..be155dbb9c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4
new file mode 100644
index 0000000000..b67beb9548
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.1-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4s
new file mode 100644
index 0000000000..2056aaec7f
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4s
new file mode 100644
index 0000000000..ccdad15c39
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4
new file mode 100644
index 0000000000..5b618c64d8
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.2-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4s
new file mode 100644
index 0000000000..c834ea6ae8
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4s
new file mode 100644
index 0000000000..aad6b355ae
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4
new file mode 100644
index 0000000000..1f878bc84b
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.3-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4s
new file mode 100644
index 0000000000..88f05ee8bb
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4s
new file mode 100644
index 0000000000..23ecab42e2
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4
new file mode 100644
index 0000000000..3e5ad8ad3b
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.4-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4s
new file mode 100644
index 0000000000..df05700d87
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4s
new file mode 100644
index 0000000000..14daa425c7
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4
new file mode 100644
index 0000000000..2101dd876c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.5-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4s
new file mode 100644
index 0000000000..ef0a4614fc
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4s
new file mode 100644
index 0000000000..8f7c819867
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4
new file mode 100644
index 0000000000..91f48ab6a1
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.6-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4s
new file mode 100644
index 0000000000..dded8a37af
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4s
new file mode 100644
index 0000000000..2a3c10859c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4
new file mode 100644
index 0000000000..cf45610f7b
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.7-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4s
new file mode 100644
index 0000000000..74f0addd4f
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4s
new file mode 100644
index 0000000000..f062c85333
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4
new file mode 100644
index 0000000000..30a0ab0fed
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.8-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4s
new file mode 100644
index 0000000000..b74ebf1f64
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4s
new file mode 100644
index 0000000000..eabd8a3411
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4
new file mode 100644
index 0000000000..449722b0fd
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_0.9-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4s
new file mode 100644
index 0000000000..e032afcc4f
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4s
new file mode 100644
index 0000000000..6542c8d3d3
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4
new file mode 100644
index 0000000000..0a9da048f0
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.0-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4s
new file mode 100644
index 0000000000..1b8b22be4a
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4s b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4s
new file mode 100644
index 0000000000..3de855982f
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4 b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4
new file mode 100644
index 0000000000..80b3814f7c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_offset_1.1-init.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4s b/dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4s
new file mode 100644
index 0000000000..fa5d454277
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_trailing_skip_box_video1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video1.m4s b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s
new file mode 100644
index 0000000000..9291182516
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video10.m4s b/dom/media/mediasource/test/bipbop/bipbop_video10.m4s
new file mode 100644
index 0000000000..72c7afaca7
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video10.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video10.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video10.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video10.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video11.m4s b/dom/media/mediasource/test/bipbop/bipbop_video11.m4s
new file mode 100644
index 0000000000..e6109f5e71
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video11.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video11.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video11.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video11.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video12.m4s b/dom/media/mediasource/test/bipbop/bipbop_video12.m4s
new file mode 100644
index 0000000000..5c54a510f7
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video12.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video12.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video12.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video12.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video13.m4s b/dom/media/mediasource/test/bipbop/bipbop_video13.m4s
new file mode 100644
index 0000000000..c64f38a337
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video13.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video13.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video13.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video13.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video2.m4s b/dom/media/mediasource/test/bipbop/bipbop_video2.m4s
new file mode 100644
index 0000000000..cd34fae561
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video2.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video2.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video3.m4s b/dom/media/mediasource/test/bipbop/bipbop_video3.m4s
new file mode 100644
index 0000000000..5a13340043
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video3.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video3.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video3.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video3.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video4.m4s b/dom/media/mediasource/test/bipbop/bipbop_video4.m4s
new file mode 100644
index 0000000000..e8d96b6ed1
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video4.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video4.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video4.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video4.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video5.m4s b/dom/media/mediasource/test/bipbop/bipbop_video5.m4s
new file mode 100644
index 0000000000..ca6a820468
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video5.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video5.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video5.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video5.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video6.m4s b/dom/media/mediasource/test/bipbop/bipbop_video6.m4s
new file mode 100644
index 0000000000..fe9824355b
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video6.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video6.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video6.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video6.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video7.m4s b/dom/media/mediasource/test/bipbop/bipbop_video7.m4s
new file mode 100644
index 0000000000..3351fa6859
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video7.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video7.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video7.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video7.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video8.m4s b/dom/media/mediasource/test/bipbop/bipbop_video8.m4s
new file mode 100644
index 0000000000..af26ae5f9e
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video8.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video8.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video8.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video8.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video9.m4s b/dom/media/mediasource/test/bipbop/bipbop_video9.m4s
new file mode 100644
index 0000000000..25be672c15
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video9.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video9.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video9.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video9.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4 b/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4
new file mode 100644
index 0000000000..7c9c533c36
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bipbop/bipbopinit.mp4 b/dom/media/mediasource/test/bipbop/bipbopinit.mp4
new file mode 100644
index 0000000000..39f0575a71
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbopinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbopinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbopinit.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbopinit.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/bug1718709_high_res.mp4 b/dom/media/mediasource/test/bug1718709_high_res.mp4
new file mode 100644
index 0000000000..3f211d2370
--- /dev/null
+++ b/dom/media/mediasource/test/bug1718709_high_res.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bug1718709_low_res.mp4 b/dom/media/mediasource/test/bug1718709_low_res.mp4
new file mode 100644
index 0000000000..dc5cd6b7f1
--- /dev/null
+++ b/dom/media/mediasource/test/bug1718709_low_res.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/crashtests/1005366.html b/dom/media/mediasource/test/crashtests/1005366.html
new file mode 100644
index 0000000000..aa8b7f652e
--- /dev/null
+++ b/dom/media/mediasource/test/crashtests/1005366.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+
+/*
+user_pref("media.mediasource.enabled", true);
+*/
+
+function boom()
+{
+ var source = new window.MediaSource();
+ var videoElement = document.createElementNS('http://www.w3.org/1999/xhtml', 'video');
+ videoElement.src = URL.createObjectURL(source);
+
+ setTimeout(function() {
+ var buf = source.addSourceBuffer("video/webm");
+ buf.abort();
+ buf.appendBuffer(new Float32Array(203));
+ }, 0);
+}
+
+</script>
+</head>
+<body onload="boom();"></body>
+</html>
diff --git a/dom/media/mediasource/test/crashtests/1059035.html b/dom/media/mediasource/test/crashtests/1059035.html
new file mode 100644
index 0000000000..9dfda34b82
--- /dev/null
+++ b/dom/media/mediasource/test/crashtests/1059035.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+/*
+user_pref("media.mediasource.enabled", true);
+*/
+
+function boom()
+{
+ var mediaSource = new MediaSource();
+ var htmlAudio = document.createElement("audio");
+ htmlAudio.src = URL.createObjectURL(mediaSource);
+
+ setTimeout(function() {
+ var sourceBuffer = mediaSource.addSourceBuffer("video/webm");
+ mediaSource.removeSourceBuffer(sourceBuffer);
+ sourceBuffer.remove(0, 0);
+ }, 0);
+}
+
+</script>
+</head>
+<body onload="boom();"></body>
+</html>
diff --git a/dom/media/mediasource/test/crashtests/926665.html b/dom/media/mediasource/test/crashtests/926665.html
new file mode 100644
index 0000000000..ccac5a7644
--- /dev/null
+++ b/dom/media/mediasource/test/crashtests/926665.html
@@ -0,0 +1,26 @@
+<html>
+<head>
+<meta charset="UTF-8">
+<script style="display: none;" id="fuzz1" type="text/javascript">
+
+function boom()
+{
+ var mediaSource = new window.MediaSource();
+ var mediaSourceURL = URL.createObjectURL(mediaSource);
+ var v1 = document.createElement('video');
+ v1.src = mediaSourceURL;
+ mediaSource.addEventListener("sourceopen", function (e) {
+ var v2 = document.createElement('video');
+ v2.src = mediaSourceURL;
+ setTimeout(function () {
+ v2.src = "data:text/plain,1";
+ v1.src = "data:text/plain,2";
+ }, 0);
+ });
+}
+
+</script>
+</head>
+
+<body onload="boom();"></body>
+</html>
diff --git a/dom/media/mediasource/test/crashtests/931388.html b/dom/media/mediasource/test/crashtests/931388.html
new file mode 100644
index 0000000000..cdb5bd9add
--- /dev/null
+++ b/dom/media/mediasource/test/crashtests/931388.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+
+function boom()
+{
+ var v = document.createElement('video');
+ v.src = URL.createObjectURL(new MediaSource());
+ v.play();
+}
+
+</script>
+</head>
+<body onload="boom();"></body>
+</html>
diff --git a/dom/media/mediasource/test/crashtests/crashtests.list b/dom/media/mediasource/test/crashtests/crashtests.list
new file mode 100644
index 0000000000..e16ec261d2
--- /dev/null
+++ b/dom/media/mediasource/test/crashtests/crashtests.list
@@ -0,0 +1,4 @@
+test-pref(media.mediasource.enabled,true) load 926665.html
+test-pref(media.mediasource.enabled,true) load 931388.html
+test-pref(media.mediasource.enabled,true) load 1005366.html
+test-pref(media.mediasource.enabled,true) load 1059035.html
diff --git a/dom/media/mediasource/test/flac/00001.m4s b/dom/media/mediasource/test/flac/00001.m4s
new file mode 100644
index 0000000000..02745ba2f8
--- /dev/null
+++ b/dom/media/mediasource/test/flac/00001.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/flac/00001.m4s^headers^ b/dom/media/mediasource/test/flac/00001.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/flac/00001.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/flac/00002.m4s b/dom/media/mediasource/test/flac/00002.m4s
new file mode 100644
index 0000000000..cd6b1f5949
--- /dev/null
+++ b/dom/media/mediasource/test/flac/00002.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/flac/00002.m4s^headers^ b/dom/media/mediasource/test/flac/00002.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/flac/00002.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/flac/00003.m4s b/dom/media/mediasource/test/flac/00003.m4s
new file mode 100644
index 0000000000..c5b78e1ce0
--- /dev/null
+++ b/dom/media/mediasource/test/flac/00003.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/flac/00003.m4s^headers^ b/dom/media/mediasource/test/flac/00003.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/flac/00003.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/flac/IS.mp4 b/dom/media/mediasource/test/flac/IS.mp4
new file mode 100644
index 0000000000..7f108602fd
--- /dev/null
+++ b/dom/media/mediasource/test/flac/IS.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/flac/IS.mp4^headers^ b/dom/media/mediasource/test/flac/IS.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/flac/IS.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/init-trackid2.mp4 b/dom/media/mediasource/test/init-trackid2.mp4
new file mode 100644
index 0000000000..c96da9d4df
--- /dev/null
+++ b/dom/media/mediasource/test/init-trackid2.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/init-trackid2.mp4^headers^ b/dom/media/mediasource/test/init-trackid2.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/init-trackid2.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/init-trackid3.mp4 b/dom/media/mediasource/test/init-trackid3.mp4
new file mode 100644
index 0000000000..e37d8ea098
--- /dev/null
+++ b/dom/media/mediasource/test/init-trackid3.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/init-trackid3.mp4^headers^ b/dom/media/mediasource/test/init-trackid3.mp4^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/init-trackid3.mp4^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/mediasource.js b/dom/media/mediasource/test/mediasource.js
new file mode 100644
index 0000000000..71d8d4ef9f
--- /dev/null
+++ b/dom/media/mediasource/test/mediasource.js
@@ -0,0 +1,235 @@
+// Helpers for Media Source Extensions tests
+
+let gMSETestPrefs = [
+ ["media.mediasource.enabled", true],
+ ["media.audio-max-decode-error", 0],
+ ["media.video-max-decode-error", 0],
+];
+
+// Called before runWithMSE() to set the prefs before running MSE tests.
+function addMSEPrefs(...prefs) {
+ gMSETestPrefs = gMSETestPrefs.concat(prefs);
+}
+
+async function runWithMSE(testFunction) {
+ await once(window, "load");
+ await SpecialPowers.pushPrefEnv({ set: gMSETestPrefs });
+
+ const ms = new MediaSource();
+
+ const el = document.createElement("video");
+ el.src = URL.createObjectURL(ms);
+ el.preload = "auto";
+
+ document.body.appendChild(el);
+ SimpleTest.registerCleanupFunction(() => {
+ el.remove();
+ el.removeAttribute("src");
+ el.load();
+ });
+ try {
+ await testFunction(ms, el);
+ } catch (e) {
+ ok(false, `${testFunction.name} failed with error ${e.name}`);
+ throw e;
+ }
+}
+
+async function fetchWithXHR(uri) {
+ return new Promise(resolve => {
+ const xhr = new XMLHttpRequest();
+ xhr.open("GET", uri, true);
+ xhr.responseType = "arraybuffer";
+ xhr.addEventListener("load", function () {
+ is(
+ xhr.status,
+ 200,
+ "fetchWithXHR load uri='" + uri + "' status=" + xhr.status
+ );
+ resolve(xhr.response);
+ });
+ xhr.send();
+ });
+}
+
+function range(start, end) {
+ const rv = [];
+ for (let i = start; i < end; ++i) {
+ rv.push(i);
+ }
+ return rv;
+}
+
+function must_throw(f, msg, error = true) {
+ try {
+ f();
+ ok(!error, msg);
+ } catch (e) {
+ ok(error, msg);
+ if (error === true) {
+ ok(
+ false,
+ `Please provide name of expected error! Got ${e.name}: ${e.message}.`
+ );
+ } else if (e.name != error) {
+ throw e;
+ }
+ }
+}
+
+async function must_reject(f, msg, error = true) {
+ try {
+ await f();
+ ok(!error, msg);
+ } catch (e) {
+ ok(error, msg);
+ if (error === true) {
+ ok(
+ false,
+ `Please provide name of expected error! Got ${e.name}: ${e.message}.`
+ );
+ } else if (e.name != error) {
+ throw e;
+ }
+ }
+}
+
+const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+const must_not_throw = (f, msg) => must_throw(f, msg, false);
+const must_not_reject = (f, msg) => must_reject(f, msg, false);
+
+async function once(target, name) {
+ return new Promise(r => target.addEventListener(name, r, { once: true }));
+}
+
+function timeRangeToString(r) {
+ let str = "TimeRanges: ";
+ for (let i = 0; i < r.length; i++) {
+ str += "[" + r.start(i) + ", " + r.end(i) + ")";
+ }
+ return str;
+}
+
+async function loadSegment(sb, typedArrayOrArrayBuffer) {
+ const typedArray =
+ typedArrayOrArrayBuffer instanceof ArrayBuffer
+ ? new Uint8Array(typedArrayOrArrayBuffer)
+ : typedArrayOrArrayBuffer;
+ info(
+ `Loading buffer: [${typedArray.byteOffset}, ${
+ typedArray.byteOffset + typedArray.byteLength
+ })`
+ );
+ const beforeBuffered = timeRangeToString(sb.buffered);
+ const p = once(sb, "update");
+ sb.appendBuffer(typedArray);
+ await p;
+ const afterBuffered = timeRangeToString(sb.buffered);
+ info(
+ `SourceBuffer buffered ranges grew from ${beforeBuffered} to ${afterBuffered}`
+ );
+}
+
+async function fetchAndLoad(sb, prefix, chunks, suffix) {
+ // Fetch the buffers in parallel.
+ const buffers = await Promise.all(
+ chunks.map(c => fetchWithXHR(prefix + c + suffix))
+ );
+
+ // Load them in series, as required per spec.
+ for (const buffer of buffers) {
+ await loadSegment(sb, buffer);
+ }
+}
+
+function loadSegmentAsync(sb, typedArrayOrArrayBuffer) {
+ const typedArray =
+ typedArrayOrArrayBuffer instanceof ArrayBuffer
+ ? new Uint8Array(typedArrayOrArrayBuffer)
+ : typedArrayOrArrayBuffer;
+ info(
+ `Loading buffer2: [${typedArray.byteOffset}, ${
+ typedArray.byteOffset + typedArray.byteLength
+ })`
+ );
+ const beforeBuffered = timeRangeToString(sb.buffered);
+ return sb.appendBufferAsync(typedArray).then(() => {
+ const afterBuffered = timeRangeToString(sb.buffered);
+ info(
+ `SourceBuffer buffered ranges grew from ${beforeBuffered} to ${afterBuffered}`
+ );
+ });
+}
+
+function fetchAndLoadAsync(sb, prefix, chunks, suffix) {
+ // Fetch the buffers in parallel.
+ const buffers = {};
+ const fetches = [];
+ for (const chunk of chunks) {
+ fetches.push(
+ fetchWithXHR(prefix + chunk + suffix).then(
+ ((c, x) => (buffers[c] = x)).bind(null, chunk)
+ )
+ );
+ }
+
+ // Load them in series, as required per spec.
+ return Promise.all(fetches).then(function () {
+ let rv = Promise.resolve();
+ for (const chunk of chunks) {
+ rv = rv.then(loadSegmentAsync.bind(null, sb, buffers[chunk]));
+ }
+ return rv;
+ });
+}
+
+// Register timeout function to dump debugging logs.
+SimpleTest.registerTimeoutFunction(async function () {
+ for (const v of document.getElementsByTagName("video")) {
+ console.log(await SpecialPowers.wrap(v).mozRequestDebugInfo());
+ }
+ for (const a of document.getElementsByTagName("audio")) {
+ console.log(await SpecialPowers.wrap(a).mozRequestDebugInfo());
+ }
+});
+
+async function waitUntilTime(target, targetTime) {
+ await new Promise(resolve => {
+ target.addEventListener("waiting", function onwaiting() {
+ info("Got a waiting event at " + target.currentTime);
+ if (target.currentTime >= targetTime) {
+ target.removeEventListener("waiting", onwaiting);
+ resolve();
+ }
+ });
+ });
+ ok(true, "Reached target time of: " + targetTime);
+}
+
+// Log events for debugging.
+
+function logEvents(el) {
+ [
+ "suspend",
+ "play",
+ "canplay",
+ "canplaythrough",
+ "loadstart",
+ "loadedmetadata",
+ "loadeddata",
+ "playing",
+ "ended",
+ "error",
+ "stalled",
+ "emptied",
+ "abort",
+ "waiting",
+ "pause",
+ "durationchange",
+ "seeking",
+ "seeked",
+ ].forEach(type =>
+ el.addEventListener(type, e => info(`got ${e.type} event`))
+ );
+}
diff --git a/dom/media/mediasource/test/mochitest.ini b/dom/media/mediasource/test/mochitest.ini
new file mode 100644
index 0000000000..f231255c1e
--- /dev/null
+++ b/dom/media/mediasource/test/mochitest.ini
@@ -0,0 +1,213 @@
+[DEFAULT]
+subsuite = media
+support-files =
+ mediasource.js
+ seek.webm seek.webm^headers^
+ seek_lowres.webm seek_lowres.webm^headers^
+ bipbop/bipbop_300-3s.webm bipbop/bipbop_300-3s.webm^headers^
+ bipbop/bipbop2s.mp4 bipbop/bipbop2s.mp4^headers^
+ bipbop/bipbop_trailing_skip_box_video1.m4s
+ bipbop/bipbop_trailing_skip_box_video1.m4s^headers^
+ bipbop/bipbopinit.mp4 bipbop/bipbop_audioinit.mp4 bipbop/bipbop_videoinit.mp4
+ bipbop/bipbop1.m4s bipbop/bipbop_audio1.m4s bipbop/bipbop_video1.m4s
+ bipbop/bipbop2.m4s bipbop/bipbop_audio2.m4s bipbop/bipbop_video2.m4s
+ bipbop/bipbop3.m4s bipbop/bipbop_audio3.m4s bipbop/bipbop_video3.m4s
+ bipbop/bipbop4.m4s bipbop/bipbop_audio4.m4s bipbop/bipbop_video4.m4s
+ bipbop/bipbop5.m4s bipbop/bipbop_audio5.m4s bipbop/bipbop_video5.m4s
+ bipbop/bipbop6.m4s bipbop/bipbop_audio6.m4s bipbop/bipbop_video6.m4s
+ bipbop/bipbop7.m4s bipbop/bipbop_audio7.m4s bipbop/bipbop_video7.m4s
+ bipbop/bipbop8.m4s bipbop/bipbop_audio8.m4s bipbop/bipbop_video8.m4s
+ bipbop/bipbop9.m4s bipbop/bipbop_audio9.m4s bipbop/bipbop_video9.m4s
+ bipbop/bipbop10.m4s bipbop/bipbop_audio10.m4s bipbop/bipbop_video10.m4s
+ bipbop/bipbop11.m4s bipbop/bipbop_audio11.m4s bipbop/bipbop_video11.m4s
+ bipbop/bipbop12.m4s bipbop/bipbop_video12.m4s
+ bipbop/bipbop13.m4s bipbop/bipbop_video13.m4s
+ bipbop/bipbopinit.mp4^headers^ bipbop/bipbop_audioinit.mp4^headers^ bipbop/bipbop_videoinit.mp4^headers^
+ bipbop/bipbop1.m4s^headers^ bipbop/bipbop_audio1.m4s^headers^ bipbop/bipbop_video1.m4s^headers^
+ bipbop/bipbop2.m4s^headers^ bipbop/bipbop_audio2.m4s^headers^ bipbop/bipbop_video2.m4s^headers^
+ bipbop/bipbop3.m4s^headers^ bipbop/bipbop_audio3.m4s^headers^ bipbop/bipbop_video3.m4s^headers^
+ bipbop/bipbop4.m4s^headers^ bipbop/bipbop_audio4.m4s^headers^ bipbop/bipbop_video4.m4s^headers^
+ bipbop/bipbop5.m4s^headers^ bipbop/bipbop_audio5.m4s^headers^ bipbop/bipbop_video5.m4s^headers^
+ bipbop/bipbop6.m4s^headers^ bipbop/bipbop_audio6.m4s^headers^ bipbop/bipbop_video6.m4s^headers^
+ bipbop/bipbop7.m4s^headers^ bipbop/bipbop_audio7.m4s^headers^ bipbop/bipbop_video7.m4s^headers^
+ bipbop/bipbop8.m4s^headers^ bipbop/bipbop_audio8.m4s^headers^ bipbop/bipbop_video8.m4s^headers^
+ bipbop/bipbop9.m4s^headers^ bipbop/bipbop_audio9.m4s^headers^ bipbop/bipbop_video9.m4s^headers^
+ bipbop/bipbop10.m4s^headers^ bipbop/bipbop_audio10.m4s^headers^ bipbop/bipbop_video10.m4s^headers^
+ bipbop/bipbop11.m4s^headers^ bipbop/bipbop_audio11.m4s^headers^ bipbop/bipbop_video11.m4s^headers^
+ bipbop/bipbop12.m4s^headers^ bipbop/bipbop_video12.m4s^headers^
+ bipbop/bipbop13.m4s^headers^ bipbop/bipbop_video13.m4s^headers^
+ bipbop/bipbop_offset_0.0-1.m4s
+ bipbop/bipbop_offset_0.0-1.m4s^headers^
+ bipbop/bipbop_offset_0.0-2.m4s
+ bipbop/bipbop_offset_0.0-2.m4s^headers^
+ bipbop/bipbop_offset_0.0-init.mp4
+ bipbop/bipbop_offset_0.0-init.mp4^headers^
+ bipbop/bipbop_offset_0.1-1.m4s
+ bipbop/bipbop_offset_0.1-1.m4s^headers^
+ bipbop/bipbop_offset_0.1-2.m4s
+ bipbop/bipbop_offset_0.1-2.m4s^headers^
+ bipbop/bipbop_offset_0.1-init.mp4
+ bipbop/bipbop_offset_0.1-init.mp4^headers^
+ bipbop/bipbop_offset_0.2-1.m4s
+ bipbop/bipbop_offset_0.2-1.m4s^headers^
+ bipbop/bipbop_offset_0.2-2.m4s
+ bipbop/bipbop_offset_0.2-2.m4s^headers^
+ bipbop/bipbop_offset_0.2-init.mp4
+ bipbop/bipbop_offset_0.2-init.mp4^headers^
+ bipbop/bipbop_offset_0.3-1.m4s
+ bipbop/bipbop_offset_0.3-1.m4s^headers^
+ bipbop/bipbop_offset_0.3-2.m4s
+ bipbop/bipbop_offset_0.3-2.m4s^headers^
+ bipbop/bipbop_offset_0.3-init.mp4
+ bipbop/bipbop_offset_0.3-init.mp4^headers^
+ bipbop/bipbop_offset_0.4-1.m4s
+ bipbop/bipbop_offset_0.4-1.m4s^headers^
+ bipbop/bipbop_offset_0.4-2.m4s
+ bipbop/bipbop_offset_0.4-2.m4s^headers^
+ bipbop/bipbop_offset_0.4-init.mp4
+ bipbop/bipbop_offset_0.4-init.mp4^headers^
+ bipbop/bipbop_offset_0.5-1.m4s
+ bipbop/bipbop_offset_0.5-1.m4s^headers^
+ bipbop/bipbop_offset_0.5-2.m4s
+ bipbop/bipbop_offset_0.5-2.m4s^headers^
+ bipbop/bipbop_offset_0.5-init.mp4
+ bipbop/bipbop_offset_0.5-init.mp4^headers^
+ bipbop/bipbop_offset_0.6-1.m4s
+ bipbop/bipbop_offset_0.6-1.m4s^headers^
+ bipbop/bipbop_offset_0.6-2.m4s
+ bipbop/bipbop_offset_0.6-2.m4s^headers^
+ bipbop/bipbop_offset_0.6-init.mp4
+ bipbop/bipbop_offset_0.6-init.mp4^headers^
+ bipbop/bipbop_offset_0.7-1.m4s
+ bipbop/bipbop_offset_0.7-1.m4s^headers^
+ bipbop/bipbop_offset_0.7-2.m4s
+ bipbop/bipbop_offset_0.7-2.m4s^headers^
+ bipbop/bipbop_offset_0.7-init.mp4
+ bipbop/bipbop_offset_0.7-init.mp4^headers^
+ bipbop/bipbop_offset_0.8-1.m4s
+ bipbop/bipbop_offset_0.8-1.m4s^headers^
+ bipbop/bipbop_offset_0.8-2.m4s
+ bipbop/bipbop_offset_0.8-2.m4s^headers^
+ bipbop/bipbop_offset_0.8-init.mp4
+ bipbop/bipbop_offset_0.8-init.mp4^headers^
+ bipbop/bipbop_offset_0.9-1.m4s
+ bipbop/bipbop_offset_0.9-1.m4s^headers^
+ bipbop/bipbop_offset_0.9-2.m4s
+ bipbop/bipbop_offset_0.9-2.m4s^headers^
+ bipbop/bipbop_offset_0.9-init.mp4
+ bipbop/bipbop_offset_0.9-init.mp4^headers^
+ bipbop/bipbop_offset_1.0-1.m4s
+ bipbop/bipbop_offset_1.0-1.m4s^headers^
+ bipbop/bipbop_offset_1.0-2.m4s
+ bipbop/bipbop_offset_1.0-2.m4s^headers^
+ bipbop/bipbop_offset_1.0-init.mp4
+ bipbop/bipbop_offset_1.0-init.mp4^headers^
+ bipbop/bipbop_offset_1.1-1.m4s
+ bipbop/bipbop_offset_1.1-1.m4s^headers^
+ bipbop/bipbop_offset_1.1-2.m4s
+ bipbop/bipbop_offset_1.1-2.m4s^headers^
+ bipbop/bipbop_offset_1.1-init.mp4
+ bipbop/bipbop_offset_1.1-init.mp4^headers^
+ aac20-48000-64000-init.mp4 aac20-48000-64000-init.mp4^headers^
+ aac20-48000-64000-1.m4s aac20-48000-64000-1.m4s^headers^
+ aac20-48000-64000-2.m4s aac20-48000-64000-2.m4s^headers^
+ aac51-48000-128000-init.mp4 aac51-48000-128000-init.mp4^headers^
+ aac51-48000-128000-1.m4s aac51-48000-128000-1.m4s^headers^
+ aac51-48000-128000-2.m4s aac51-48000-128000-2.m4s^headers^
+ bipbop/bipbop_480_624kbps-videoinit.mp4 bipbop/bipbop_480_624kbps-videoinit.mp4^headers^
+ bipbop/bipbop_480_624kbps-video1.m4s bipbop/bipbop_480_624kbps-video1.m4s^headers^
+ bipbop/bipbop_480_624kbps-video2.m4s bipbop/bipbop_480_624kbps-video2.m4s^headers^
+ flac/IS.mp4 flac/IS.mp4^headers^ flac/00001.m4s flac/00001.m4s^headers^
+ flac/00002.m4s flac/00002.m4s^headers^ flac/00003.m4s flac/00003.m4s^headers^
+ avc3/init.mp4 avc3/init.mp4^headers^ avc3/segment1.m4s avc3/segment1.m4s^headers^
+ tags_before_cluster.webm
+ tags_before_cluster.webm^header^
+ 1516754.webm 1516754.webm^headers^
+ init-trackid2.mp4 init-trackid3.mp4 segment-2.0001.m4s segment-2.0002.m4s segment-3.0001.m4s segment-3.0002.m4s
+ init-trackid2.mp4^headers^ init-trackid3.mp4^headers^ segment-2.0001.m4s^headers^ segment-2.0002.m4s^headers^
+ segment-3.0001.m4s^headers^ segment-3.0002.m4s^headers^
+ wmf_mismatchedaudiotime.mp4
+ bug1718709_low_res.mp4
+ bug1718709_high_res.mp4
+ whitenoise-he-aac-5s.mp4
+
+[test_AbortAfterPartialMediaSegment.html]
+[test_AppendPartialInitSegment.html]
+[test_AVC3_mp4.html]
+[test_AudioChange_mp4.html]
+[test_AudioChange_mp4_WebAudio.html]
+[test_AutoRevocation.html]
+tags = firstpartyisolation
+[test_BufferedSeek.html]
+[test_BufferedSeek_mp4.html]
+[test_BufferingWait.html]
+[test_BufferingWait_mp4.html]
+[test_ChangeType.html]
+[test_ChangeWhileWaitingOnMissingData_mp4.html]
+[test_DifferentStreamStartTimes.html]
+[test_DrainOnMissingData_mp4.html]
+[test_DurationChange.html]
+[test_DurationUpdated.html]
+[test_DurationUpdated_mp4.html]
+[test_EndedEvent.html]
+[test_EndOfStream.html]
+[test_EndOfStream_mp4.html]
+[test_Eviction_mp4.html]
+[test_ExperimentalAsync.html]
+[test_FrameSelection.html]
+skip-if = toolkit == 'android' # bug 1341519, bug 1401090
+[test_FrameSelection_mp4.html]
+skip-if = os == 'win' # bug 1487973,
+ (os == 'mac') # mac due to bug 1487973
+[test_HaveMetadataUnbufferedSeek.html]
+[test_HaveMetadataUnbufferedSeek_mp4.html]
+[test_HEAAC_extradata.html]
+[test_InputBufferIsCleared.html]
+[test_LiveSeekable.html]
+[test_LoadedDataFired_mp4.html]
+[test_LoadedMetadataFired.html]
+[test_LoadedMetadataFired_mp4.html]
+[test_MediaSource.html]
+[test_MediaSource_capture_gc.html]
+[test_MediaSource_memory_reporting.html]
+[test_MediaSource_mp4.html]
+[test_MediaSource_flac_mp4.html]
+[test_MediaSource_disabled.html]
+[test_MultipleInitSegments.html]
+[test_MultipleInitSegments_mp4.html]
+[test_NoAudioLoopBackData.html]
+[test_NoAudioLoopBackData_Muted.html]
+[test_NoVideoLoopBackData.html]
+[test_OnEvents.html]
+[test_PlayEvents.html]
+[test_PlayEventsAutoPlaying.html]
+[test_PlayEventsAutoPlaying2.html]
+[test_RemoveSourceBuffer.html]
+[test_Resolution_change_should_not_cause_video_freeze.html]
+[test_ResumeAfterClearing_mp4.html]
+[test_SeekableBeforeAndAfterEndOfStream.html]
+[test_SeekableBeforeAndAfterEndOfStream_mp4.html]
+[test_SeekableBeforeAndAfterEndOfStreamSplit.html]
+[test_SeekableBeforeAndAfterEndOfStreamSplit_mp4.html]
+[test_SeekNoData_mp4.html]
+[test_SeekedEvent_mp4.html]
+[test_SeekToEnd_mp4.html]
+[test_SeekToLastFrame_mp4.html]
+[test_SeekTwice_mp4.html]
+[test_Sequence_mp4.html]
+[test_SetModeThrows.html]
+[test_SplitAppendDelay.html]
+[test_SplitAppendDelay_mp4.html]
+[test_SplitAppend.html]
+[test_SplitAppend_mp4.html]
+[test_Threshold_mp4.html]
+[test_TimestampOffset_mp4.html]
+[test_trackidchange_mp4.html]
+[test_TruncatedDuration.html]
+[test_TruncatedDuration_mp4.html]
+[test_WaitingOnMissingData.html]
+[test_WaitingOnMissingData_mp4.html]
+[test_WaitingOnMissingDataEnded_mp4.html]
+[test_WaitingToEndedTransition_mp4.html]
+[test_WebMTagsBeforeCluster.html]
+[test_WMFUnmatchedAudioDataTime.html]
diff --git a/dom/media/mediasource/test/seek.webm b/dom/media/mediasource/test/seek.webm
new file mode 100644
index 0000000000..72b0297233
--- /dev/null
+++ b/dom/media/mediasource/test/seek.webm
Binary files differ
diff --git a/dom/media/mediasource/test/seek.webm^headers^ b/dom/media/mediasource/test/seek.webm^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/seek.webm^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/seek_lowres.webm b/dom/media/mediasource/test/seek_lowres.webm
new file mode 100644
index 0000000000..8a76e06470
--- /dev/null
+++ b/dom/media/mediasource/test/seek_lowres.webm
Binary files differ
diff --git a/dom/media/mediasource/test/seek_lowres.webm^headers^ b/dom/media/mediasource/test/seek_lowres.webm^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/seek_lowres.webm^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/segment-2.0001.m4s b/dom/media/mediasource/test/segment-2.0001.m4s
new file mode 100644
index 0000000000..b63fd6aaa6
--- /dev/null
+++ b/dom/media/mediasource/test/segment-2.0001.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/segment-2.0001.m4s^headers^ b/dom/media/mediasource/test/segment-2.0001.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/segment-2.0001.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/segment-2.0002.m4s b/dom/media/mediasource/test/segment-2.0002.m4s
new file mode 100644
index 0000000000..3a0051f10e
--- /dev/null
+++ b/dom/media/mediasource/test/segment-2.0002.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/segment-2.0002.m4s^headers^ b/dom/media/mediasource/test/segment-2.0002.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/segment-2.0002.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/segment-3.0001.m4s b/dom/media/mediasource/test/segment-3.0001.m4s
new file mode 100644
index 0000000000..71e33f0e8f
--- /dev/null
+++ b/dom/media/mediasource/test/segment-3.0001.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/segment-3.0001.m4s^headers^ b/dom/media/mediasource/test/segment-3.0001.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/segment-3.0001.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/segment-3.0002.m4s b/dom/media/mediasource/test/segment-3.0002.m4s
new file mode 100644
index 0000000000..10a3ce695d
--- /dev/null
+++ b/dom/media/mediasource/test/segment-3.0002.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/segment-3.0002.m4s^headers^ b/dom/media/mediasource/test/segment-3.0002.m4s^headers^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/segment-3.0002.m4s^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/tags_before_cluster.webm b/dom/media/mediasource/test/tags_before_cluster.webm
new file mode 100644
index 0000000000..cf7d596b0e
--- /dev/null
+++ b/dom/media/mediasource/test/tags_before_cluster.webm
Binary files differ
diff --git a/dom/media/mediasource/test/tags_before_cluster.webm^header^ b/dom/media/mediasource/test/tags_before_cluster.webm^header^
new file mode 100644
index 0000000000..4030ea1d3d
--- /dev/null
+++ b/dom/media/mediasource/test/tags_before_cluster.webm^header^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/media/mediasource/test/test_AVC3_mp4.html b/dom/media/mediasource/test/test_AVC3_mp4.html
new file mode 100644
index 0000000000..dd20feed06
--- /dev/null
+++ b/dom/media/mediasource/test/test_AVC3_mp4.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: AVC3 content playback.</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+
+ await fetchAndLoad(videosb, "avc3/init", [""], ".mp4");
+ const p = once(el, "loadeddata");
+ await fetchAndLoad(videosb, "avc3/segment", range(1, 2), ".m4s");
+ await p;
+ is(videosb.buffered.length, 1, "continuous buffered range");
+ ok(true, "got loadeddata");
+ ms.endOfStream();
+ await once(ms, "sourceended");
+ ok(true, "endOfStream completed");
+ // Now ensure that we can play to the end.
+ el.play();
+ await once(el, "ended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_AbortAfterPartialMediaSegment.html b/dom/media/mediasource/test/test_AbortAfterPartialMediaSegment.html
new file mode 100644
index 0000000000..4c695f48c7
--- /dev/null
+++ b/dom/media/mediasource/test/test_AbortAfterPartialMediaSegment.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: can properly resume after a partial media segment header followed by abort </title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+const VIDEO_CODEC_STRING = 'video/webm; codecs="vp09.00.51.08.01.01.01.01"';
+
+const logError = (error) => {
+ console.error(error, error.message);
+ ok(false, "should not reach here");
+};
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+
+ const supported = MediaSource.isTypeSupported(VIDEO_CODEC_STRING);
+ if (!supported) {
+ ok(true, "vp9 isn't supported on this platform, abort");
+ SimpleTest.finish();
+ return;
+ }
+ const sb = ms.addSourceBuffer(VIDEO_CODEC_STRING);
+
+ const arrayBuffer = await fetchWithXHR("1516754.webm");
+ info("- append init segment, a media segment and a partial media segment header -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 87355 + 3000));
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+
+ // start seeking.
+ v.currentTime = 11;
+ v.addEventListener("seeked", () => {
+ info("- seek completed -");
+ SimpleTest.finish();
+ });
+
+ sb.abort();
+
+ info("- append init segment -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 3150));
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+ info("- append media segment 10-15s -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 159968, 72931));
+
+ // We now wait for seek to complete
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_AppendPartialInitSegment.html b/dom/media/mediasource/test/test_AppendPartialInitSegment.html
new file mode 100644
index 0000000000..408c073bd6
--- /dev/null
+++ b/dom/media/mediasource/test/test_AppendPartialInitSegment.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: split init segment and append them separately </title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ // init segment is total 236 bytes.
+ info("- append partial init segment -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 100));
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+
+ info("- append remaining init segment -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 100, 136));
+
+ info("- wait for metadata -");
+ await once(v, "loadedmetadata");
+ is(v.videoWidth, 320, "videoWidth has correct initial value");
+ is(v.videoHeight, 240, "videoHeight has correct initial value");
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_AudioChange_mp4.html b/dom/media/mediasource/test/test_AudioChange_mp4.html
new file mode 100644
index 0000000000..9051af05a1
--- /dev/null
+++ b/dom/media/mediasource/test/test_AudioChange_mp4.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// This test checks loading a stereo segment, followed by a 5.1 segment plays without error.
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ logEvents(el);
+
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ el.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(audiosb, "aac20-48000-64000-", ["init"], ".mp4");
+ await p;
+ ok(true, "got loadedmetadata event");
+ p = Promise.all([once(el, "loadeddata"), once(el, "canplay")]);
+ await fetchAndLoad(audiosb, "aac20-48000-64000-", ["1"], ".m4s");
+ await p;
+ ok(true, "got canplay event");
+ el.play();
+ await fetchAndLoad(audiosb, "aac51-48000-128000-", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "aac51-48000-128000-", ["2"], ".m4s");
+ ms.endOfStream();
+ await once(el, "ended");
+ ok(el.currentTime >= 6, "played to the end");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_AudioChange_mp4_WebAudio.html b/dom/media/mediasource/test/test_AudioChange_mp4_WebAudio.html
new file mode 100644
index 0000000000..c76342f793
--- /dev/null
+++ b/dom/media/mediasource/test/test_AudioChange_mp4_WebAudio.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// This test checks loading a stereo segment, followed by a 5.1 segment plays
+// without error, when the audio is being routed to an AudioContext.
+
+const ac = new AudioContext();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ const source = ac.createMediaElementSource(el);
+ source.connect(ac.destination);
+
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ logEvents(el);
+
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ el.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(audiosb, "aac20-48000-64000-", ["init"], ".mp4");
+ await p;
+ ok(true, "got loadedmetadata event");
+ p = Promise.all([once(el, "loadeddata"), once(el, "canplay")]);
+ await fetchAndLoad(audiosb, "aac20-48000-64000-", ["1"], ".m4s");
+ await p;
+ ok(true, "got canplay event");
+ el.play();
+ await fetchAndLoad(audiosb, "aac51-48000-128000-", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "aac51-48000-128000-", ["2"], ".m4s");
+ ms.endOfStream();
+ await once(el, "ended");
+ ok(el.currentTime >= 6, "played to the end");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_AutoRevocation.html b/dom/media/mediasource/test/test_AutoRevocation.html
new file mode 100644
index 0000000000..42e9b0e6a5
--- /dev/null
+++ b/dom/media/mediasource/test/test_AutoRevocation.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: auto-revocation</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(function() {
+ const ms = new MediaSource();
+ const o = URL.createObjectURL(ms);
+ const v = document.createElement("video");
+
+ v.addEventListener("error", () => {
+ ok(true, "ObjectURL should be auto-revoked");
+ SimpleTest.finish();
+ });
+
+ v.addEventListener("stalled", () => {
+ ok(false, "If auto-revocation is gone, please turn on TODOs in browser_mediaSourceURL.js");
+ SimpleTest.finish();
+ });
+
+ setTimeout(function() {
+ v.src = o;
+ v.preload = "auto";
+ document.body.appendChild(v);
+ }, 0);
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_BufferedSeek.html b/dom/media/mediasource/test/test_BufferedSeek.html
new file mode 100644
index 0000000000..039f56bc16
--- /dev/null
+++ b/dom/media/mediasource/test/test_BufferedSeek.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seeking in buffered range</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("seek.webm")));
+
+ const target = 2;
+
+ v.addEventListener("loadedmetadata", () => {
+ ok(true, "received loadedmetadata");
+ v.currentTime = target;
+ });
+
+ let wasSeeking = false;
+
+ v.addEventListener("seeking", () => {
+ wasSeeking = true;
+ is(v.currentTime, target, "Video currentTime at target");
+ });
+
+ await once(v, "seeked");
+ ok(wasSeeking, "Received expected seeking and seeked events");
+ is(v.currentTime, target, "Video currentTime at target");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_BufferedSeek_mp4.html b/dom/media/mediasource/test/test_BufferedSeek_mp4.html
new file mode 100644
index 0000000000..e89e972c91
--- /dev/null
+++ b/dom/media/mediasource/test/test_BufferedSeek_mp4.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seeking in buffered range</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("bipbop/bipbop2s.mp4")));
+
+ const target = 1.3;
+
+ await once(v, "loadedmetadata");
+ ok(true, "received loadedmetadata");
+ v.currentTime = target;
+
+ let wasSeeking = false;
+
+ v.addEventListener("seeking", () => {
+ wasSeeking = true;
+ is(v.currentTime, target, "Video currentTime at target");
+ });
+
+ await once(v, "seeked");
+ ok(wasSeeking, "Received expected seeking and seeked events");
+ is(v.currentTime, target, "Video currentTime at target");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_BufferingWait.html b/dom/media/mediasource/test/test_BufferingWait.html
new file mode 100644
index 0000000000..289ddfe4d2
--- /dev/null
+++ b/dom/media/mediasource/test/test_BufferingWait.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Don't get stuck buffering for too long when we have frames to show</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ ms.addEventListener("sourceopen", () => ok(false, "No more sourceopen"));
+ const sb = ms.addSourceBuffer("video/webm");
+ ok(sb, "Create a SourceBuffer");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ sb.addEventListener("error", e => {
+ ok(false, "Got Error: " + e);
+ SimpleTest.finish();
+ });
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 0, 318));
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 318, 25523 - 318));
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 25523, 46712 - 25523));
+ /* Note - Missing |46712, 67833 - 46712| segment here corresponding to (0.8, 1.2] */
+ /* Note - Missing |67833, 88966 - 67833| segment here corresponding to (1.2, 1.6] */
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 88966));
+ // 0.767 is the time of the last video sample +- 40ms.
+ info("Playing video. It should play for a bit, then fire 'waiting'");
+ v.play();
+ await waitUntilTime(v, .767 - 0.04);
+ const firstStop = Date.now();
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 46712, 67833 - 46712));
+ await waitUntilTime(v, 1.167 - 0.04);
+ const waitDuration = (Date.now() - firstStop) / 1000;
+ ok(waitDuration < 15, `Should not spend inordinate amount of time buffering: ${waitDuration}`);
+ SimpleTest.finish();
+ /* If we allow the rest of the stream to be played, we get stuck at
+ around 2s. See bug 1093133.
+ await once(v, "ended");
+ SimpleTest.finish();
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 67833, 88966 - 67833));
+ */
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_BufferingWait_mp4.html b/dom/media/mediasource/test/test_BufferingWait_mp4.html
new file mode 100644
index 0000000000..04e094a852
--- /dev/null
+++ b/dom/media/mediasource/test/test_BufferingWait_mp4.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Don't get stuck buffering for too long when we have frames to show</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ ms.addEventListener("sourceopen", () => ok(false, "No more sourceopen"));
+ const sb = ms.addSourceBuffer("video/mp4");
+ ok(sb, "Create a SourceBuffer");
+
+ sb.addEventListener("error", e => {
+ ok(false, "Got Error: " + e);
+ SimpleTest.finish();
+ });
+ await fetchAndLoad(sb, "bipbop/bipbop", ["init"], ".mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop", ["1"], ".m4s");
+ await fetchAndLoad(sb, "bipbop/bipbop", ["2"], ".m4s");
+ /* Note - Missing |bipbop3| segment here corresponding to (1.62, 2.41] */
+ /* Note - Missing |bipbop4| segment here corresponding to (2.41, 3.20] */
+ await fetchAndLoad(sb, "bipbop/bipbop", ["5"], ".m4s");
+ // last audio sample has a start time of 1.578956s
+ info("Playing video. It should play for a bit, then fire 'waiting'");
+ v.play();
+ await waitUntilTime(v, 1.57895);
+ const firstStop = Date.now();
+ await fetchAndLoad(sb, "bipbop/bipbop", ["3"], ".m4s");
+ // last audio sample has a start time of 2.368435
+ await waitUntilTime(v, 2.36843);
+ const waitDuration = (Date.now() - firstStop) / 1000;
+ ok(waitDuration < 15, `Should not spend inordinate amount of time buffering: ${waitDuration}`);
+ await fetchAndLoad(sb, "bipbop/bipbop", ["4"], ".m4s");
+ ms.endOfStream();
+ await once(v, "ended");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_ChangeType.html b/dom/media/mediasource/test/test_ChangeType.html
new file mode 100644
index 0000000000..690b9f61c4
--- /dev/null
+++ b/dom/media/mediasource/test/test_ChangeType.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: changeType allow to change container and codec type</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(function(ms, el) {
+ el.controls = true;
+ once(ms, "sourceopen").then(function() {
+ // Log events for debugging.
+ const events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
+ "loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort",
+ "waiting", "pause", "durationchange", "seeking", "seeked"];
+ function logEvent(e) {
+ info("got " + e.type + " event");
+ }
+ events.forEach(function(e) {
+ el.addEventListener(e, logEvent);
+ });
+
+ ok(true, "Receive a sourceopen event");
+
+ const videosb = ms.addSourceBuffer("video/mp4");
+ if (typeof videosb.changeType === "undefined") {
+ info("changeType API is not available");
+ }
+
+ el.addEventListener("error", e => {
+ ok(false, "should not fire '" + e.type + "' event");
+ SimpleTest.finish();
+ });
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ const loadedmetadataPromises = [];
+ loadedmetadataPromises.push(fetchAndLoad(videosb, "bipbop/bipbop", ["init"], ".mp4"));
+ loadedmetadataPromises.push(once(el, "loadedmetadata"));
+ Promise.all(loadedmetadataPromises)
+ .then(function() {
+ ok(true, "got loadedmetadata event");
+ const canplayPromises = [];
+ canplayPromises.push(once(el, "loadeddata"));
+ canplayPromises.push(once(el, "canplay"));
+ canplayPromises.push(fetchAndLoad(videosb, "bipbop/bipbop", range(1, 3), ".m4s"));
+ return Promise.all(canplayPromises);
+ })
+ .then(function() {
+ ok(true, "got canplay event");
+ el.play();
+ videosb.timestampOffset = el.buffered.end(0);
+ return fetchAndLoad(videosb, "bipbop/bipbop_480_624kbps-video", ["init"], ".mp4");
+ })
+ .then(fetchAndLoad.bind(null, videosb, "bipbop/bipbop_480_624kbps-video", range(1, 3), ".m4s"))
+ .then(function() {
+ videosb.timestampOffset = el.buffered.end(0);
+ try {
+ videosb.changeType("video/webm");
+ } catch (e) {
+ ok(false, "shouldn't throw an exception");
+ SimpleTest.finish();
+ throw e;
+ }
+ return fetchAndLoad(videosb, "bipbop/bipbop_300-3s", [""], ".webm");
+ })
+ .then(function() {
+ ms.endOfStream();
+ return once(el, "ended");
+ })
+ .then(function() {
+ ok(el.currentTime >= el.buffered.end(0), "played to the end");
+ SimpleTest.finish();
+ });
+ });
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_ChangeWhileWaitingOnMissingData_mp4.html b/dom/media/mediasource/test/test_ChangeWhileWaitingOnMissingData_mp4.html
new file mode 100644
index 0000000000..b5889da560
--- /dev/null
+++ b/dom/media/mediasource/test/test_ChangeWhileWaitingOnMissingData_mp4.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: resume from waiting even after format change occurred</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const sb = ms.addSourceBuffer("video/mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop_480_624kbps-video", ["init"], ".mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop_480_624kbps-video", range(1, 3), ".m4s");
+ el.play();
+ // let seek to the last audio frame.
+ // The seek will complete and then playback will stall.
+ el.currentTime = 1.532517;
+ await Promise.all([once(el, "seeked"), once(el, "waiting")]);
+ info("seek completed");
+ await fetchAndLoad(sb, "bipbop/bipbop", ["init"], ".mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop", range(1, 4), ".m4s");
+ ms.endOfStream();
+ await once(el, "ended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_DifferentStreamStartTimes.html b/dom/media/mediasource/test/test_DifferentStreamStartTimes.html
new file mode 100644
index 0000000000..197e809e4f
--- /dev/null
+++ b/dom/media/mediasource/test/test_DifferentStreamStartTimes.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: Mismatched stream start time playback test</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ el.autoplay = true;
+ for (let i = 0; i <= 0.5; i += 0.1) {
+ const offset = i.toFixed(1);
+
+ info("----------------------");
+ info("Running test for mismatched stream start times with offset of: " + offset);
+ info("----------------------");
+
+ ms = new MediaSource();
+ el.removeAttribute("src");
+ el.src = URL.createObjectURL(ms);
+
+ await once(ms, "sourceopen");
+ logEvents(el);
+ const videosb = ms.addSourceBuffer("video/mp4");
+ ok(true, "Receive a sourceopen event");
+
+ el.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(videosb, "bipbop/bipbop_offset_" + offset + "-", ["init"], ".mp4");
+ await p;
+ ok(true, "got loadedmetadata event");
+
+ p = Promise.all(["loadeddata", "canplay", "play", "playing"].map(e => once(el, e)));
+ await fetchAndLoad(videosb, "bipbop/bipbop_offset_" + offset + "-", range(1, 2), ".m4s");
+ el.play();
+ await p;
+ }
+ ok(true, "got all required event");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_DrainOnMissingData_mp4.html b/dom/media/mediasource/test/test_DrainOnMissingData_mp4.html
new file mode 100644
index 0000000000..ddc503aebf
--- /dev/null
+++ b/dom/media/mediasource/test/test_DrainOnMissingData_mp4.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: |waiting| event when source data is missing</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ // Set appendWindowEnd to ensure we only have about 6 frames worth.
+ // We must feed at least 6 frames to pass the MDSM pre-roll.
+ videosb.appendWindowEnd = .4;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["1"], ".m4s");
+ info("Invoking play()");
+ const p = once(el, "playing");
+ await el.play();
+ await p;
+ info("got playing");
+ await once(el, "waiting");
+ info("got waiting");
+ info("Loading more data");
+ // Waiting will be fired on the last frame +- 40ms.
+ isfuzzy(el.currentTime, videosb.buffered.end(0) - 1 / 30,
+ 0.04, `Got a waiting event at ${el.currentTime}`);
+ videosb.appendWindowEnd = 1;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", [1], ".m4s");
+ ms.endOfStream();
+ await once(el, "ended");
+ // These fuzz factors are bigger than they should be. We should investigate
+ // and fix them in bug 1137574.
+ is(el.duration, 0.801666, "Video has correct duration: " + el.duration);
+ is(el.currentTime, el.duration, "Video has correct currentTime.");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_DurationChange.html b/dom/media/mediasource/test/test_DurationChange.html
new file mode 100644
index 0000000000..3c83e83fa4
--- /dev/null
+++ b/dom/media/mediasource/test/test_DurationChange.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: check that duration change behaves properly</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
+ await Promise.all([once(v, "loadedmetadata"), once(sb, "updateend")]);
+ is(v.duration, ms.duration, "video duration is mediasource one");
+ must_not_throw(() => ms.duration = 0, "duration = 0 is valid initially");
+ is(v.duration, 0, "reducing duration with no data buffered is valid");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
+ // Adding more data will fire durationchange.
+ await once(sb, "updateend");
+ ok(true, "got updateend");
+ // XXX: Duration should be exactly 4.0, see bug 1065207.
+ ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
+ must_throw(() => ms.duration = 0,
+ "Must use remove for range removal",
+ "InvalidStateError");
+ ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
+ must_not_throw(() => ms.duration = 10, "setting duration past data is valid");
+ is(v.duration, 10, "extending duration is always valid");
+ // The last sample has a start time of 3.967000s and a end time of 4.001 (see bug 1065207).
+ must_not_throw(() => ms.duration = 3.967000,
+ "setting duration with >= highest frame presentation time is valid");
+ is(v.duration, sb.buffered.end(0),
+ "duration is the highest end time reported by the buffered attribute ");
+ must_not_throw(() => ms.duration = 3.97,
+ "setting duration with >= highest frame presentation time is valid");
+ is(v.duration, sb.buffered.end(0),
+ "duration is the highest end time reported by the buffered attribute ");
+ must_throw(() => ms.duration = 3.96,
+ "setting duration with < highest frame presentation time is not valid",
+ "InvalidStateError");
+ is(v.duration, sb.buffered.end(0),
+ "duration is the highest end time reported by the buffered attribute ");
+ must_throw(() => ms.duration = -1, "can't set a negative duration", "TypeError");
+ sb.remove(sb.buffered.end(0), Infinity);
+ is(sb.updating, true, "updating is true");
+ must_throw(() => ms.duration = Infinity,
+ "setting the duration while updating is not allowed",
+ "InvalidStateError");
+ must_throw(() => sb.abort(),
+ "Can't use abort while range removal is in progress",
+ "InvalidStateError");
+ is(v.duration, sb.buffered.end(0),
+ "duration is the highest end time reported by the buffered attribute ");
+ await once(sb, "updateend");
+ ms.endOfStream();
+ await once(ms, "sourceended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_DurationUpdated.html b/dom/media/mediasource/test/test_DurationUpdated.html
new file mode 100644
index 0000000000..eb54e76c90
--- /dev/null
+++ b/dom/media/mediasource/test/test_DurationUpdated.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append data and check that mediasource duration got updated</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ let durationChangeCount = 0;
+ v.addEventListener("durationchange", () => durationChangeCount++);
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
+
+ // Adding the first init segment will fire a durationchange.
+ await Promise.all([once(sb, "updateend"), once(v, "loadedmetadata")]);
+ ok(true, "got loadedmetadata");
+ // Set mediasource duration to 0, so future appendBuffer
+ // will update the mediasource duration.
+ // Changing the duration will fire a durationchange.
+ ms.duration = 0;
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
+ // Adding more data will fire durationchange.
+ await once(sb, "updateend");
+ ok(true, "got updateend");
+ // this will not fire durationchange as new duration == old duration
+ ms.endOfStream();
+ await once(ms, "sourceended");
+ is(durationChangeCount, 3, "durationchange not fired as many times as expected");
+ // XXX: Duration should be exactly 4.0, see bug 1065207.
+ ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_DurationUpdated_mp4.html b/dom/media/mediasource/test/test_DurationUpdated_mp4.html
new file mode 100644
index 0000000000..f263264b09
--- /dev/null
+++ b/dom/media/mediasource/test/test_DurationUpdated_mp4.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append data and check that mediasource duration got updated</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ let durationChangeCount = 0;
+ v.addEventListener("durationchange", () => durationChangeCount++);
+
+ const arrayBuffer = await fetchWithXHR("bipbop/bipbop2s.mp4");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 1395));
+
+ // Adding the first init segment will fire a durationchange.
+ await Promise.all([once(sb, "updateend"), once(v, "loadedmetadata")]);
+ ok(true, "got loadedmetadata");
+ // Set mediasource duration to 0, so future appendBuffer
+ // will update the mediasource duration.
+ // Changing the duration will fire a durationchange.
+ ms.duration = 0;
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 1395));
+ // Adding more data will fire durationchange.
+ await once(sb, "updateend");
+ ok(true, "got updateend");
+ // this will not fire durationchange as new duration == old duration
+ ms.endOfStream();
+ await once(ms, "sourceended");
+ is(durationChangeCount, 3, "durationchange not fired as many times as expected");
+ is(v.duration, 1.696666, "Video has correct duration");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_EndOfStream.html b/dom/media/mediasource/test/test_EndOfStream.html
new file mode 100644
index 0000000000..b926869f1f
--- /dev/null
+++ b/dom/media/mediasource/test/test_EndOfStream.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: endOfStream call after an appendBuffer</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("seek.webm"), 0, 88966));
+ await once(sb, "updateend");
+ await wait(0);
+ must_not_throw(() => ms.endOfStream(), "MediaSource.endOfStream succeeded");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_EndOfStream_mp4.html b/dom/media/mediasource/test/test_EndOfStream_mp4.html
new file mode 100644
index 0000000000..9319b80390
--- /dev/null
+++ b/dom/media/mediasource/test/test_EndOfStream_mp4.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: endOfStream call after an appendBuffer</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("bipbop/bipbop2s.mp4")));
+ await once(sb, "updateend");
+ await wait(0);
+ must_not_throw(() => ms.endOfStream(), "MediaSource.endOfStream succeeded");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_EndedEvent.html b/dom/media/mediasource/test/test_EndedEvent.html
new file mode 100644
index 0000000000..ee43fa8cf5
--- /dev/null
+++ b/dom/media/mediasource/test/test_EndedEvent.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("seek.webm")));
+ sb.addEventListener("updateend", () => ms.endOfStream());
+
+ // Test "ended" is fired when seeking to the end of the media
+ // once the duration is known.
+ ms.onsourceended = () => el.currentTime = el.duration;
+ await once(el, "ended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_Eviction_mp4.html b/dom/media/mediasource/test/test_Eviction_mp4.html
new file mode 100644
index 0000000000..e336fae4c7
--- /dev/null
+++ b/dom/media/mediasource/test/test_Eviction_mp4.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: QuotaExceededError when source buffer is full</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+// We fill up the source buffer with audio data until the buffer is full.
+// We ensure that QuotaExceededError is thrown once the buffer is full.
+// We then seek to half the content. By that time, another appendBuffer must succeed
+// as the auto-eviction would succeed (removing all data prior currentTime)
+
+addMSEPrefs(
+ ["media.mediasource.eviction_threshold.audio", 524288],
+ ["media.dormant-on-pause-timeout-ms", -1] // FIXME: bug 1319292
+);
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ audiosb.mode = "sequence";
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ const audioBuffer = await fetchWithXHR("bipbop/bipbop_audio1.m4s");
+
+ await must_reject(async () => {
+ // We are appending data repeatedly in sequence mode, there should be no gaps.
+ while (true) {
+ ok(audiosb.buffered.length <= 1, "there should be no gap in buffered ranges.");
+ audiosb.appendBuffer(audioBuffer);
+ await once(audiosb, "updateend");
+ }
+ },
+ "Fill up SourceBuffer by appending data until an exception is thrown.",
+ "QuotaExceededError");
+
+ is(audiosb.buffered.end(0), el.duration, "Duration is end of buffered range");
+ const seekTime = audiosb.buffered.end(0) / 2;
+ el.currentTime = seekTime;
+ await once(el, "seeked");
+ dump("dump: seeked to " + seekTime);
+ is(el.currentTime, seekTime, "correctly seeked to " + seekTime);
+ try {
+ audiosb.appendBuffer(audioBuffer);
+ await once(audiosb, "update");
+ ok(true, "appendBuffer succeeded");
+ } catch (ex) {
+ ok(false, "Shouldn't throw another time when data can be evicted");
+ dump(JSON.stringify(await SpecialPowers.wrap(el).mozRequestDebugInfo()));
+ }
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_ExperimentalAsync.html b/dom/media/mediasource/test/test_ExperimentalAsync.html
new file mode 100644
index 0000000000..6617716f26
--- /dev/null
+++ b/dom/media/mediasource/test/test_ExperimentalAsync.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: testing removeAsync and appendBufferAsync</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+addMSEPrefs(
+ ["media.mediasource.eviction_threshold.audio", 524288],
+ ["media.dormant-on-pause-timeout-ms", -1], // FIXME: bug 1319292
+ ["media.mediasource.experimental.enabled", true]
+);
+
+// We fill up the source buffer with audio data until the buffer is full.
+// We ensure that QuotaExceededError is thrown once the buffer is full.
+// We then seek to half the content. By that time, another appendBuffer must succeed
+// as the auto-eviction would succeed (removing all data prior currentTime)
+// The test then fills the audio buffer and plays until the end.
+
+// Fill up the SourceBuffer by appending data repeatedly via doAppendDataFunc until
+// an exception is thrown.
+async function fillUpSourceBuffer(sourceBuffer, doAppendDataFunc, onCaughtExceptionCallback) {
+ try {
+ // We are appending data repeatedly in sequence mode, there should be no gaps.
+ while (true) {
+ ok(sourceBuffer.buffered.length <= 1, "there should be no gap in buffered ranges.");
+ await doAppendDataFunc();
+ }
+ } catch (ex) {
+ ok(true, "appendBuffer promise got rejected");
+ onCaughtExceptionCallback(ex);
+ }
+}
+
+runWithMSE(async function(ms, el) {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+
+ // Test removeAsync
+ audiosb.mode = "sequence";
+ const audioInitBuffer = await fetchWithXHR("bipbop/bipbop_audioinit.mp4");
+ await audiosb.appendBufferAsync(audioInitBuffer);
+ const audioBuffer = await fetchWithXHR("bipbop/bipbop_audio1.m4s");
+ fillUpSourceBuffer(audiosb,
+ function() { // doAppendDataFunc
+ return audiosb.appendBufferAsync(audioBuffer);
+ },
+ async function(ex1) { // onCaughtExceptionCallback
+ is(ex1.name, "QuotaExceededError", "QuotaExceededError thrown");
+ is(audiosb.buffered.end(0), el.duration, "Duration is end of buffered range");
+ const seekTime = audiosb.buffered.end(0) / 2;
+ el.currentTime = seekTime;
+ await once(el, "seeked");
+ dump("dump: seeked to " + seekTime);
+ is(el.currentTime, seekTime, "correctly seeked to " + seekTime);
+ await audiosb.appendBufferAsync(audioBuffer).catch(async function(ex2) {
+ ok(false, "Shouldn't throw another time when data can be evicted");
+ dump(JSON.stringify(await SpecialPowers.wrap(el).mozRequestDebugInfo()));
+ SimpleTest.finish();
+ });
+ // Test that an error in remove return a rejected promise
+ await audiosb.removeAsync(5, 0).catch(async function(ex3) {
+ ok(true, "remove promise got rejected with end <= start");
+ is(ex3.name, "TypeError");
+ await audiosb.removeAsync(ms.duration + 1, Infinity).catch(async function(ex4) {
+ ok(true, "remove promise got rejected with start > duration");
+ is(ex4.name, "TypeError");
+ await audiosb.removeAsync(0, Infinity).catch(function(ex5) {
+ ok(false, "shouldn't throw");
+ });
+ ok(true, "remove succeeded");
+ is(audiosb.buffered.length, 0, "buffered should be empty");
+ audiosb.mode = "segment";
+ audiosb.timestampOffset = 0;
+ el.currentTime = 0;
+ await fetchAndLoadAsync(audiosb, "bipbop/bipbop_audio", range(1, 4), ".m4s");
+ ms.endOfStream();
+ el.play();
+ await once(el, "ended");
+ is(el.currentTime, el.duration, "played to the end");
+ SimpleTest.finish();
+ throw ex4; // ensure we don't fallback on lines below.
+ });
+ ok(false, "should have returned an error");
+ });
+ ok(false, "should have returned an error");
+ }
+ );
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_FrameSelection.html b/dom/media/mediasource/test/test_FrameSelection.html
new file mode 100644
index 0000000000..3e696841c2
--- /dev/null
+++ b/dom/media/mediasource/test/test_FrameSelection.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: verify correct frames selected for given position</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ let arrayBuffer = await fetchWithXHR("seek.webm");
+ let p = once(v, "loadedmetadata");
+ // Append entire file covering range [0, 4].
+ sb.appendBuffer(new Uint8Array(arrayBuffer));
+ await p;
+ is(v.currentTime, 0, "currentTime has correct initial value");
+ is(v.videoWidth, 320, "videoWidth has correct initial value");
+ is(v.videoHeight, 240, "videoHeight has correct initial value");
+
+ arrayBuffer = await fetchWithXHR("seek_lowres.webm");
+ // Append initialization segment.
+ info("Appending low-res init segment");
+ p = once(sb, "updateend");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 438));
+ await p;
+
+ info("Appending low-res range [2,4]");
+ // Append media segment covering range [2, 4].
+ p = once(sb, "updateend");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 51003));
+ await p;
+
+ ms.endOfStream();
+
+ info("Seeking to t=3");
+ p = Promise.all([once(v, "seeked"), once(v, "resize")]);
+ v.currentTime = 3;
+ await p;
+ is(v.currentTime, 3, "Video currentTime at target");
+ is(v.videoWidth, 160, "videoWidth has correct low-res value");
+ is(v.videoHeight, 120, "videoHeight has correct low-res value");
+
+ info("Seeking to t=1");
+ p = Promise.all([once(v, "seeked"), once(v, "resize")]);
+ v.currentTime = 1;
+ await p;
+ is(v.currentTime, 1, "Video currentTime at target");
+ is(v.videoWidth, 320, "videoWidth has correct high-res value");
+ is(v.videoHeight, 240, "videoHeight has correct high-res value");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_FrameSelection_mp4.html b/dom/media/mediasource/test/test_FrameSelection_mp4.html
new file mode 100644
index 0000000000..628b4bf0e9
--- /dev/null
+++ b/dom/media/mediasource/test/test_FrameSelection_mp4.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Don't get stuck buffering for too long when we have frames to show</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// This test loads partial video, plays and waits until playback stalls.
+// It then loads only 3 frames of a video at higher resolution.
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ ms.addEventListener("sourceopen", () => ok(false, "No more sourceopen"));
+ const sb = ms.addSourceBuffer("video/mp4");
+ ok(sb, "Create a SourceBuffer");
+ logEvents(v);
+ sb.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+ await fetchAndLoad(sb, "bipbop/bipbop", ["init"], ".mp4");
+ const p = once(v, "loadeddata");
+ await fetchAndLoad(sb, "bipbop/bipbop", range(1, 3), ".m4s");
+ await p;
+ is(sb.buffered.length, 1, "continuous range");
+ v.play();
+ // We have nothing to play, waiting will be fired.
+ await waitUntilTime(v, 1.5);
+ await fetchAndLoad(sb, "bipbop/bipbop_480_624kbps-video", ["init"], ".mp4");
+ sb.timestampOffset = 1.601666; // End of the video track buffered - time of first video sample (0.095).
+ sb.appendWindowEnd = 1.796677; // Only allow room for three extra video frames (we need 3 as this video has b-frames).
+ await fetchAndLoad(sb, "bipbop/bipbop_480_624kbps-video", ["1"], ".m4s");
+ ms.endOfStream();
+ await Promise.all([once(ms, "sourceended"), once(v, "playing"), once(v, "ended")]);
+ is(v.videoWidth, 640, "has proper width");
+ is(v.videoHeight, 480, "has proper height");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_HEAAC_extradata.html b/dom/media/mediasource/test/test_HEAAC_extradata.html
new file mode 100644
index 0000000000..9fbbec8d72
--- /dev/null
+++ b/dom/media/mediasource/test/test_HEAAC_extradata.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HE-AAC decoding test</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+
+SimpleTest.waitForExplicitFinish();
+
+const SOURCE_FILE = "whitenoise-he-aac-5s.mp4";
+
+// This test checks when decoding HE-AAC using MediaSource or HTTP playback, the
+// audio is decoded correctly (in particular with the SBR part). This means
+// that the extradata describing the encoded AAC stream have been communicated
+// correctly to the audio decoder. For this, we check that there is energy
+// above 10kHz using the Web Audio API when playing white noise, which has
+// maximum energy accross the audible spectrum.
+
+// Return the index corresponding for a particular frequency in an array
+// containing frequency data from a FFT.
+function binIndexForFrequency(frequency, fftSize, sampleRate) {
+ return (1 + Math.round((frequency * fftSize) / sampleRate));
+}
+
+async function checkHighFrequencyContent(element) {
+ const ac = new AudioContext();
+ await ac.resume();
+ const mediaElementSource = ac.createMediaElementSource(element);
+ const analyser = new AnalyserNode(ac);
+
+ // Undo the volume scaling applied globally during test. This is fine because
+ // the audio isn't routed to an actual audio output device in this test, it's
+ // just analyzed with the Web Audio API.
+ const gain = new GainNode(ac);
+ const testVolumeScaling =
+ parseFloat(SpecialPowers.getCharPref("media.volume_scale"));
+ gain.gain.value = 1 / parseFloat(testVolumeScaling);
+ mediaElementSource.connect(gain).connect(analyser)
+
+ const spectrum = new Float32Array(analyser.frequencyBinCount);
+ const indexFor15kHz =
+ binIndexForFrequency(15000, analyser.fftSize, ac.sampleRate);
+ // Wait a few hundreds of milliseconds
+ while (!element.ended) {
+ await once(element, "timeupdate");
+ analyser.getFloatFrequencyData(spectrum);
+ if (spectrum[indexFor15kHz] > -50) {
+ ok(spectrum[indexFor15kHz] > -50,
+ `Energy present at 15kHz (bin index: ${indexFor15kHz}) when playing white noise encoded in HE-AAC ${spectrum[indexFor15kHz]}`);
+ return;
+ }
+ }
+ ok(false,
+ `No energy present at 15kHz (bin index: ${indexFor15kHz}) when playing white noise encoded in HE-AAC (last value ${spectrum[indexFor15kHz]})`);
+}
+
+runWithMSE(async (ms, el) => {
+ // First check with MSE playback
+ el.controls = true;
+ await once(ms, "sourceopen");
+
+ const audiosb = ms.addSourceBuffer('audio/mp4; codecs="mp4a.40.5"');
+ await fetchAndLoad(audiosb, SOURCE_FILE, [""], "");
+ ms.endOfStream();
+ el.play();
+ once(el, "playing");
+
+ await checkHighFrequencyContent(el);
+
+ // Redo the same test, with HTTP playback
+ el.src = SOURCE_FILE;
+ el.play();
+ once(el, "playing");
+
+ await checkHighFrequencyContent(el);
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek.html b/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek.html
new file mode 100644
index 0000000000..dd1b252f01
--- /dev/null
+++ b/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seekable attribute before end of stream</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 67833));
+
+ const target = 2;
+
+ await once(v, "loadeddata");
+ ok(v.readyState >= v.HAVE_CURRENT_DATA, "readyState is >= CURRENT_DATA");
+ v.currentTime = target;
+
+ await once(v, "seeking");
+ is(v.readyState, v.HAVE_METADATA, "readyState is HAVE_METADATA");
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("seek.webm"), 67833));
+ await once(v, "seeked");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek_mp4.html b/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek_mp4.html
new file mode 100644
index 0000000000..9b8e885cda
--- /dev/null
+++ b/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek_mp4.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seekable attribute before end of stream</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ const arrayBuffer = await fetchWithXHR("bipbop/bipbop2s.mp4");
+ // 25819 is the offset of the first media segment's end
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25819));
+
+ const target = 1.3;
+
+ await once(v, "loadeddata");
+ ok(v.readyState >= v.HAVE_CURRENT_DATA, "readyState is >= CURRENT_DATA");
+ v.currentTime = target;
+
+ await once(v, "seeking");
+ is(v.readyState, v.HAVE_METADATA);
+ // 25819 is the offset of the first media segment's end
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 25819));
+ await once(sb, "updateend");
+ ms.endOfStream();
+ await once(v, "seeked");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_InputBufferIsCleared.html b/dom/media/mediasource/test/test_InputBufferIsCleared.html
new file mode 100644
index 0000000000..bad9a0c558
--- /dev/null
+++ b/dom/media/mediasource/test/test_InputBufferIsCleared.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: input buffer is cleared as expected (bug 1697476)</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// Test bug 1697476 is fixed. We do this by appending a number of segments with
+// trailing `skip` boxes. If the bug is fixed, then the data from these appends
+// will eventually be cleared from memory. If not fixed, we leak that memory.
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop_video", ["init"], ".mp4");
+ // Load ~1mb of media.
+ await fetchAndLoad(sb, "bipbop/bipbop_trailing_skip_box_video", ["1"], ".m4s");
+ // Load ~1mb more media several more times.
+ const numberOfAppends = 5;
+ for (let i = 1; i < numberOfAppends; ++i) {
+ sb.timestampOffset = v.buffered.end(0);
+ await fetchAndLoad(sb, "bipbop/bipbop_trailing_skip_box_video", ["1"], ".m4s");
+ }
+
+ // Grab a memory report. We'll use this to make sure we're not accumulating
+ // too much data in our buffers.
+ const mgr = SpecialPowers.Cc["@mozilla.org/memory-reporter-manager;1"]
+ .getService(SpecialPowers.Ci.nsIMemoryReporterManager);
+
+ let amount = 0;
+ const handleReport = (aProcess, aPath, aKind, aUnits, aAmount) => {
+ if (aPath == "explicit/media/resources") {
+ amount += aAmount;
+ }
+ };
+
+ await new Promise(r => mgr.getReports(handleReport, null, r, null, /* anonymized = */ false));
+ ok(true, "Yay didn't crash!");
+ ok(amount !== undefined, "Got media resources amount");
+ const sgementSize = 1023860;
+ // Set the limit to be equal to the total data we appended. If we're not
+ // clearing buffers, we'll have all the data from the appends + some other
+ // data, so will fail.
+ const limit = sgementSize * numberOfAppends - 1;
+ ok(amount < limit, `Should have less than ${limit} bytes of media usage. Got ${amount} bytes.`);
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_LiveSeekable.html b/dom/media/mediasource/test/test_LiveSeekable.html
new file mode 100644
index 0000000000..f48852f6af
--- /dev/null
+++ b/dom/media/mediasource/test/test_LiveSeekable.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: live seekable range</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ // Load data with a +2 offset so that we can distinguish buffered range start
+ // and seekable range start.
+ sb.timestampOffset = 2;
+ const p = once(v, "loadedmetadata");
+ await fetchAndLoad(sb, "seek", [""], ".webm");
+ await p;
+ ms.duration = Infinity;
+ sb.abort();
+ is(sb.buffered.length, 1, "continuous buffered range");
+ is(sb.buffered.start(0), 2, "buffered range start at timestamp offset");
+ is(sb.buffered.end(0), 6.001, "buffered range end at original duration + timestamp offset");
+ is(v.seekable.length, 1, "continuous seekable range");
+ is(v.seekable.start(0), 0, "seekable range start at 0");
+ is(v.seekable.end(0), sb.buffered.end(0), "seekable range end at buffered end");
+
+ // LiveSeekableRange.start < buffered.start
+ ms.setLiveSeekableRange(1, 5);
+ is(v.seekable.length, 1, "continuous seekable range");
+ is(v.seekable.start(0), 1, "seekable range start at live range start");
+ is(v.seekable.end(0), sb.buffered.end(0), "seekable range end at buffered end");
+
+ ms.clearLiveSeekableRange();
+ is(v.seekable.length, 1, "continuous seekable range");
+ is(v.seekable.start(0), 0, "seekable range start at 0");
+ is(v.seekable.end(0), sb.buffered.end(0), "seekable range end at buffered end");
+
+ // LiveSeekableRange.end > buffered.end
+ ms.setLiveSeekableRange(1, 8);
+ is(v.seekable.start(0), 1, "seekable range start at live range start");
+ is(v.seekable.end(0), 8, "seekable range end at live range end");
+
+ // LiveSeekableRange.start > buffered.start
+ // LiveSeekableRange.end < buffered.end
+ ms.setLiveSeekableRange(3, 5);
+ is(v.seekable.start(0), sb.buffered.start(0), "seekable range start at buffered start");
+ is(v.seekable.end(0), sb.buffered.end(0), "seekable range end at live range end");
+
+ // LiveSeekableRange.start > buffered.end
+ ms.setLiveSeekableRange(8, 10);
+ is(v.seekable.start(0), sb.buffered.start(0), "seekable range start at buffered start");
+ is(v.seekable.end(0), 10, "seekable range end at live range end");
+
+ // LiveSeekableRange.end < buffered.start
+ ms.setLiveSeekableRange(0, 2);
+ is(v.seekable.start(0), 0, "seekable range start at live range start");
+ is(v.seekable.end(0), sb.buffered.end(0), "seekable range end at buffered end");
+
+ must_throw(() => ms.setLiveSeekableRange(2, 0),
+ "must thow if start > end",
+ "TypeError");
+
+ must_throw(() => ms.setLiveSeekableRange(2, 0),
+ "must thow if start > end",
+ "TypeError");
+
+ ms.setLiveSeekableRange(0, 1e300);
+ is(v.seekable.start(0), 0, "seekable range start at live range start");
+ is(v.seekable.end(0), 1e300, "seekable range end at specified time");
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_LoadedDataFired_mp4.html b/dom/media/mediasource/test/test_LoadedDataFired_mp4.html
new file mode 100644
index 0000000000..476303d4fd
--- /dev/null
+++ b/dom/media/mediasource/test/test_LoadedDataFired_mp4.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: Check that playback only starts once we have data at time = 0</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ el.addEventListener("loadeddata", () => {
+ ok(el.buffered.length, "data is buffered");
+ is(el.buffered.start(0), 0, "must fire loadeddata when data has been loaded");
+ is(el.currentTime, 0, "must fire loadeddata at start");
+ });
+ el.addEventListener("playing", () => {
+ ok(el.buffered.length, "data is buffered");
+ is(el.buffered.start(0), 0, "must fire playing when data has been loaded");
+ ok(el.currentTime >= 0, "must have started playback");
+ });
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await p;
+ videosb.appendWindowStart = 2;
+ videosb.appendWindowEnd = 4;
+ is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
+ // Load [2.4, 3.968344). 2.4 as it's the first keyframe after 2s and
+ // 3.968344 as the last frame ends after 4s.
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 8), ".m4s");
+ is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
+ // test that appendWindowEnd did its job.
+ ok(el.buffered.start(0) >= 2, "no data can be found prior appendWindowStart");
+ ok(el.buffered.end(el.buffered.length - 1) <= 4, "no data can be found beyond appendWindowEnd");
+ el.play();
+ await once(el, "play");
+ videosb.appendWindowStart = 0;
+ p = once(el, "playing");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 8), ".m4s");
+ await p;
+ ok(true, "playing");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_LoadedMetadataFired.html b/dom/media/mediasource/test/test_LoadedMetadataFired.html
new file mode 100644
index 0000000000..68030dbe2f
--- /dev/null
+++ b/dom/media/mediasource/test/test_LoadedMetadataFired.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append initialization only</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("seek.webm"), 0, 318));
+ v.play();
+ await once(v, "loadedmetadata");
+ ok(true, "Got loadedmetadata event");
+ is(v.videoWidth, 320, "videoWidth has correct initial value");
+ is(v.videoHeight, 240, "videoHeight has correct initial value");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_LoadedMetadataFired_mp4.html b/dom/media/mediasource/test/test_LoadedMetadataFired_mp4.html
new file mode 100644
index 0000000000..0934907578
--- /dev/null
+++ b/dom/media/mediasource/test/test_LoadedMetadataFired_mp4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append initialization only</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("bipbop/bipbop2s.mp4"), 0, 1395));
+ v.play();
+ await once(v, "loadedmetadata");
+ ok(true, "Got loadedmetadata event");
+ is(v.videoWidth, 400, "videoWidth has correct initial value");
+ is(v.videoHeight, 300, "videoHeight has correct initial value");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MediaSource.html b/dom/media/mediasource/test/test_MediaSource.html
new file mode 100644
index 0000000000..9bdaa0d30b
--- /dev/null
+++ b/dom/media/mediasource/test/test_MediaSource.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail");
+ SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail");
+
+ ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
+ is(ms.readyState, "closed", "New MediaSource must be in closed state");
+
+ // Wrapper creation, tests for leaks.
+ SpecialPowers.wrap(ms);
+
+ // Set an expando to force wrapper creation, tests for leaks.
+ ms.foo = null;
+
+ ok(URL.createObjectURL(ms), "Create an objectURL from the MediaSource");
+
+ let loadedmetadataCount = 0;
+ let updatestartCount = 0;
+ let updateendCount = 0;
+ let updateCount = 0;
+
+ ok(MediaSource.isTypeSupported("video/webm; codecs=vp8"), "VP8 MSE is always supported");
+ ok(MediaSource.isTypeSupported("audio/webm"), "Audio MSE is always supported");
+
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+ ok(sb, "Create a SourceBuffer");
+ is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
+ is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
+ is(ms.activeSourceBuffers.length, 0, "MediaSource.activeSourceBuffers is expected length");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("seek.webm")));
+ is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer");
+
+ sb.addEventListener("update", () => {
+ is(sb.updating, false, "SourceBuffer.updating is expected value in update event");
+ updateCount++;
+ /* Ensure that we endOfStream on the first update event only as endOfStream can
+ raise more if the duration of the last buffered range and the intial duration
+ differ. See bug 1065207 */
+ if (updateCount == 1) {
+ ms.endOfStream();
+ }
+ });
+
+ sb.addEventListener("updatestart", () => updatestartCount++);
+
+ sb.addEventListener("updateend", () => {
+ is(ms.activeSourceBuffers[0], sb, "SourceBuffer in active list matches our SourceBuffer");
+ is(sb.updating, false, "SourceBuffer.updating is expected value in updateend event");
+ updateendCount++;
+ v.play();
+ });
+
+ ms.addEventListener("sourceended", () => {
+ ok(true, "Receive a sourceended event");
+ is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
+ });
+
+ v.addEventListener("loadedmetadata", () => loadedmetadataCount++);
+
+ await once(v, "ended");
+ // XXX: Duration should be exactly 4.0, see bug 1065207.
+ ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
+ ok(Math.abs(v.currentTime - 4) <= 0.002, "Video has played to end");
+ // XXX: 2 update events can be received dueto duration differences, see bug 1065207.
+ ok(updateCount == 1 || updateCount == 2, "update event received");
+ ok(updateendCount == 1 || updateendCount == 2, "updateend event received");
+ ok(updatestartCount == 1 || updatestartCount == 2, "updatestart event received");
+ is(loadedmetadataCount, 1, "loadedmetadata event received");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MediaSource_capture_gc.html b/dom/media/mediasource/test/test_MediaSource_capture_gc.html
new file mode 100644
index 0000000000..d986a6f9ac
--- /dev/null
+++ b/dom/media/mediasource/test/test_MediaSource_capture_gc.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test garbage collection of captured stream, when playing a MediaSource</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script type="text/javascript" src="mediasource.js"></script>
+</head>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+function forceGC() {
+ SpecialPowers.gc();
+ SpecialPowers.forceGC();
+ SpecialPowers.forceCC();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+window.onload = async function() {
+// Create an infinite source using a MediaSource
+let el = document.createElement("audio");
+const ms = new MediaSource();
+el.src = URL.createObjectURL(ms);
+await once(ms, "sourceopen");
+const sb = ms.addSourceBuffer("video/mp4");
+await fetchAndLoad(sb, "bipbop/bipbop_audio", ["init"], ".mp4");
+await fetchAndLoad(sb, "bipbop/bipbop_audio", range(1, 11), ".m4s");
+setInterval(async function() {
+ sb.timestampOffset = sb.buffered.end(sb.buffered.length - 1);
+ await fetchAndLoad(sb, "bipbop/bipbop_audio", range(1, 11), ".m4s");
+}, 8000);
+el.play();
+
+// Analyze the media element output.
+const ac = new AudioContext;
+const analyzer = ac.createAnalyser();
+
+// bug 1703603
+const stream = el.mozCaptureStreamUntilEnded();
+const mss = ac.createMediaStreamSource(stream);
+const gain = ac.createGain();
+// compensate mochitest volume scaling, but don't connect to the AudioContext's
+// destination to avoid noise during the test
+gain.gain.value = 90;
+mss.connect(gain).connect(analyzer);
+
+
+// Drop the media element reference: it is supposed to be kept alive by the
+// AudioContext via the `MediaStream`.
+el = null;
+
+// check whether the media element is still playing using the analyzer, spam the
+// GC to ensure all refs are kept.
+const buf = new Float32Array(analyzer.frequencyBinCount);
+const startTime = Date.now();
+function checkNonSilent() {
+ analyzer.getFloatFrequencyData(buf);
+ forceGC();
+ // Wait a good 20 seconds.
+ if (Date.now() - startTime < 2000) {
+ requestAnimationFrame(checkNonSilent);
+ } else {
+ ok(true, "All objects were kept alive.");
+ SimpleTest.finish();
+ }
+}
+checkNonSilent();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MediaSource_disabled.html b/dom/media/mediasource/test/test_MediaSource_disabled.html
new file mode 100644
index 0000000000..e14f493e0f
--- /dev/null
+++ b/dom/media/mediasource/test/test_MediaSource_disabled.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: disabling via pref</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function test() {
+ ok(!window.MediaSource && !window.SourceBuffer && !window.SourceBufferList,
+ "MediaSource should be hidden behind a pref");
+ SimpleTest.doesThrow(() => new MediaSource,
+ "MediaSource should be hidden behind a pref");
+ SimpleTest.finish();
+}
+
+SpecialPowers.pushPrefEnv({"set":
+ [
+ ["media.mediasource.enabled", false],
+ ],
+}, test);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MediaSource_flac_mp4.html b/dom/media/mediasource/test/test_MediaSource_flac_mp4.html
new file mode 100644
index 0000000000..9cc159e467
--- /dev/null
+++ b/dom/media/mediasource/test/test_MediaSource_flac_mp4.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Can seek to last frame</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
+ const sb = ms.addSourceBuffer("audio/mp4; codecs=\"flac\"");
+ ok(sb, "Create a SourceBuffer");
+
+ await fetchAndLoad(sb, "flac/IS", [""], ".mp4");
+ await fetchAndLoad(sb, "flac/0000", range(1, 3), ".m4s");
+ el.play();
+ ms.endOfStream();
+ await once(el, "ended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MediaSource_memory_reporting.html b/dom/media/mediasource/test/test_MediaSource_memory_reporting.html
new file mode 100644
index 0000000000..70c720effd
--- /dev/null
+++ b/dom/media/mediasource/test/test_MediaSource_memory_reporting.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: memory reporting</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ // Load a webm video and play it.
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+ await fetchAndLoad(sb, "seek", [""], ".webm");
+ const p = once(v, "ended");
+ ms.endOfStream();
+ v.play();
+ await p;
+
+ // Test that memory reporting works once we've played a video.
+ // Grab a memory report.
+ const mgr = SpecialPowers.Cc["@mozilla.org/memory-reporter-manager;1"]
+ .getService(SpecialPowers.Ci.nsIMemoryReporterManager);
+
+ let amount;
+ const handleReport = (aProcess, aPath, aKind, aUnits, aAmount) => {
+ if (aPath == "explicit/media/resources") {
+ amount = (amount || 0) + aAmount;
+ }
+ };
+
+ await new Promise(r => mgr.getReports(handleReport, null, r, null, /* anonymized = */ false));
+ ok(true, "Yay didn't crash!");
+ ok(amount !== undefined, "Got media resources amount");
+ ok(amount > 0, "Non-zero amount reported for media resources");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MediaSource_mp4.html b/dom/media/mediasource/test/test_MediaSource_mp4.html
new file mode 100644
index 0000000000..2ab79f37f3
--- /dev/null
+++ b/dom/media/mediasource/test/test_MediaSource_mp4.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail");
+ SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail");
+
+ ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
+ is(ms.readyState, "closed", "New MediaSource must be in closed state");
+
+ // Wrapper creation, tests for leaks.
+ SpecialPowers.wrap(ms);
+
+ // Set an expando to force wrapper creation, tests for leaks.
+ ms.foo = null;
+
+ ok(URL.createObjectURL(ms), "Create an objectURL from the MediaSource");
+
+ let loadedmetadataCount = 0;
+ let updatestartCount = 0;
+ let updateendCount = 0;
+ let updateCount = 0;
+
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+ ok(sb, "Create a SourceBuffer");
+ is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
+ is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
+ is(ms.activeSourceBuffers.length, 0, "MediaSource.activeSourceBuffers is expected length");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("bipbop/bipbop2s.mp4")));
+ is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer");
+
+ sb.addEventListener("update", () => {
+ is(sb.updating, false, "SourceBuffer.updating is expected value in update event");
+ updateCount++;
+ /* Ensure that we endOfStream on the first update event only as endOfStream can
+ raise more if the duration of the last buffered range and the intial duration
+ differ. See bug 1065207 */
+ if (updateCount == 1) {
+ ms.endOfStream();
+ }
+ });
+
+ sb.addEventListener("updatestart", () => updatestartCount++);
+
+ sb.addEventListener("updateend", () => {
+ is(ms.activeSourceBuffers[0], sb, "SourceBuffer in active list matches our SourceBuffer");
+ is(sb.updating, false, "SourceBuffer.updating is expected value in updateend event");
+ updateendCount++;
+ v.play();
+ });
+
+ ms.addEventListener("sourceended", () => {
+ ok(true, "Receive a sourceended event");
+ is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
+ });
+
+ v.addEventListener("loadedmetadata", () => loadedmetadataCount++);
+
+ await once(v, "ended");
+ // The bipbop video doesn't start at 0. The old MSE code adjust the
+ // timestamps and ignore the audio track. The new one doesn't.
+ isfuzzy(v.duration, 1.696, 0.166, "Video has correct duration");
+ isfuzzy(v.currentTime, 1.696, 0.166, "Video has correct duration");
+ // XXX: 2 update events can be received dueto duration differences, see bug 1065207.
+ ok(updateCount == 1 || updateCount == 2, "update event received");
+ ok(updateendCount == 1 || updateendCount == 2, "updateend event received");
+ ok(updatestartCount == 1 || updatestartCount == 2, "updatestart event received");
+ is(loadedmetadataCount, 1, "loadedmetadata event received");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MultipleInitSegments.html b/dom/media/mediasource/test/test_MultipleInitSegments.html
new file mode 100644
index 0000000000..f4c91c08c5
--- /dev/null
+++ b/dom/media/mediasource/test/test_MultipleInitSegments.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Append buffer with multiple init segments</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+ const seek_lowres = await fetchWithXHR("seek_lowres.webm");
+ const seek = await fetchWithXHR("seek.webm");
+ const data = [
+ [seek_lowres, 0, 438], // lowres init segment
+ [seek_lowres, 438, 25950], // lowres media segment 0-1
+ [seek, 0, 318], // init segment
+ [seek, 46712, 67833], // media segment 0.8-1.201
+ ];
+ const length = data.map(d => d[2] - d[1]).reduce((a, b) => a + b, 0);
+ const arrayBuffer = new Uint8Array(length);
+ let pos = 0;
+ for (const d of data) {
+ const buffer = new Uint8Array(d[0], d[1], d[2] - d[1]);
+ arrayBuffer.set(buffer, pos);
+ pos += buffer.byteLength;
+ }
+ await loadSegment(sb, arrayBuffer);
+ // Since we are passing multiple segments in one buffer,
+ // the first durationchange event from parsing the init
+ // segment will be fired before updateend.
+ const p = once(v, "durationchange");
+ ms.endOfStream();
+ await p;
+ ok(v.duration, 1.201);
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_MultipleInitSegments_mp4.html b/dom/media/mediasource/test/test_MultipleInitSegments_mp4.html
new file mode 100644
index 0000000000..47c115677d
--- /dev/null
+++ b/dom/media/mediasource/test/test_MultipleInitSegments_mp4.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Append buffer with multiple init segments</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+ const init = new Uint8Array(await fetchWithXHR("bipbop/bipbop_videoinit.mp4"));
+ const segment1 = new Uint8Array(await fetchWithXHR("bipbop/bipbop_video1.m4s"));
+ const segment2 = new Uint8Array(await fetchWithXHR("bipbop/bipbop_video2.m4s"));
+ const data = [init, segment1, init, segment2];
+ const length = data.map(d => d.byteLength).reduce((a, b) => a + b, 0);
+ const arrayBuffer = new Uint8Array(length);
+ let pos = 0;
+ for (const buffer of data) {
+ arrayBuffer.set(buffer, pos);
+ pos += buffer.byteLength;
+ }
+ await loadSegment(sb, arrayBuffer);
+ // Since we are passing multiple segments in one buffer,
+ // the first durationchange event from parsing the init
+ // segment will be fired before updateend.
+ const p = once(v, "durationchange");
+ ms.endOfStream();
+ await p;
+ ok(v.duration, 1.601666);
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_NoAudioLoopBackData.html b/dom/media/mediasource/test/test_NoAudioLoopBackData.html
new file mode 100644
index 0000000000..7de7209b74
--- /dev/null
+++ b/dom/media/mediasource/test/test_NoAudioLoopBackData.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: loop-back data not available yet (shorter audio)</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+/**
+ * This test is used to check whether a looping video can loop back successfully
+ * when it has a shorter audio track than its video track. When reaching EOS for
+ * the shorter track, there is no loop-back data at the start position (they are
+ * not appended yet) Even that, we should still be able to loop back but the
+ * looping would become non-seamless in this situation.
+ */
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+
+ // Here we create a shorter audio than video.
+ info(`create different length source buffers`);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(5, 8), ".m4s");
+ audiosb.appendWindowEnd = videosb.buffered.end(0) - 0.2;
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(5, 8), ".m4s");
+ ms.endOfStream();
+ await Promise.all([once(el, "durationchange"), once(ms, "sourceended")]);
+ info(`audio=[${audiosb.buffered.start(0)}-${audiosb.buffered.end(0)}], video=[${videosb.buffered.start(0)}-${videosb.buffered.end(0)}]`);
+ ok(true, `endOfStream completed, buffer=[${el.buffered.start(0)}, ${el.buffered.end(0)}]`);
+ ok(videosb.buffered.end(0) > audiosb.buffered.end(0), `video should be longer than audio`);
+
+ info(`seek to the position where buffered data exists`);
+ el.loop = true;
+ el.controls = true;
+ el.currentTime = el.buffered.start(0);
+ await el.play();
+
+ info(`video should trigger seeking when reaching to the end`);
+ let seekingCount = 0, seekedCount = 0;
+ el.addEventListener("seeking", () => {
+ is(++seekingCount, 1, "should only receive seeking once!");
+ });
+ el.addEventListener("seeked", () => {
+ is(++seekedCount, 1, "should only receive seeked once!");
+ });
+ await once(el, "seeking");
+
+ info(`trim old data before append new data`);
+ let p = Promise.all([once(videosb, "updateend"), once(audiosb, "updateend")]);
+ videosb.remove(videosb.buffered.start(0), videosb.buffered.end(0));
+ audiosb.remove(audiosb.buffered.start(0), audiosb.buffered.end(0));
+ await p;
+
+ info(`append new data`);
+ const seekedPromise = once(el, "seeked");
+ p = Promise.all([once(videosb, "updateend"), once(audiosb, "updateend")]);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 2), ".m4s");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 2), ".m4s");
+ await p;
+ info(`audio=[${audiosb.buffered.start(0)}-${audiosb.buffered.end(0)}], video=[${videosb.buffered.start(0)}-${videosb.buffered.end(0)}]`);
+
+ info(`now we should be able to finish seeking to the start position`);
+ await seekedPromise;
+
+ SimpleTest.finish(SimpleTest);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_NoAudioLoopBackData_Muted.html b/dom/media/mediasource/test/test_NoAudioLoopBackData_Muted.html
new file mode 100644
index 0000000000..14cdf34bc6
--- /dev/null
+++ b/dom/media/mediasource/test/test_NoAudioLoopBackData_Muted.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: loop-back data not available yet (shorter MUTED audio)</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+/**
+ * This test is used to check whether a looping video can loop back successfully
+ * when it has a shorter MUTED audio track than its video track. When reaching
+ * EOS for the shorter track, there is no loop-back data at the start position
+ * (they are not appended yet) Even that, we should still be able to loop back
+ * but the looping would become non-seamless in this situation.
+ */
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+
+ // Here we create a shorter audio than video.
+ info(`create different length source buffers`);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(5, 8), ".m4s");
+ audiosb.appendWindowEnd = videosb.buffered.end(0) - 0.2;
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(5, 8), ".m4s");
+ ms.endOfStream();
+ await Promise.all([once(el, "durationchange"), once(ms, "sourceended")]);
+ info(`audio=[${audiosb.buffered.start(0)}-${audiosb.buffered.end(0)}], video=[${videosb.buffered.start(0)}-${videosb.buffered.end(0)}]`);
+ ok(true, `endOfStream completed, buffer=[${el.buffered.start(0)}, ${el.buffered.end(0)}]`);
+ ok(videosb.buffered.end(0) > audiosb.buffered.end(0), `video should be longer than audio`);
+
+ info(`seek to the position where buffered data exists`);
+ el.muted = true;
+ el.loop = true;
+ el.controls = true;
+ el.currentTime = el.buffered.start(0);
+ await el.play();
+
+ info(`video should trigger seeking when reaching to the end`);
+ let seekingCount = 0, seekedCount = 0;
+ el.addEventListener("seeking", () => {
+ is(++seekingCount, 1, "should only receive seeking once!");
+ });
+ el.addEventListener("seeked", () => {
+ is(++seekedCount, 1, "should only receive seeked once!");
+ });
+ await once(el, "seeking");
+
+ info(`trim old data before append new data`);
+ let p = Promise.all([once(videosb, "updateend"), once(audiosb, "updateend")]);
+ videosb.remove(videosb.buffered.start(0), videosb.buffered.end(0));
+ audiosb.remove(audiosb.buffered.start(0), audiosb.buffered.end(0));
+ await p;
+
+ info(`append new data`);
+ const seekedPromise = once(el, "seeked");
+ p = Promise.all([once(videosb, "updateend"), once(audiosb, "updateend")]);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 2), ".m4s");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 2), ".m4s");
+ await p;
+ info(`audio=[${audiosb.buffered.start(0)}-${audiosb.buffered.end(0)}], video=[${videosb.buffered.start(0)}-${videosb.buffered.end(0)}]`);
+
+ info(`now we should be able to finish seeking to the start position`);
+ await seekedPromise;
+
+ SimpleTest.finish(SimpleTest);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_NoVideoLoopBackData.html b/dom/media/mediasource/test/test_NoVideoLoopBackData.html
new file mode 100644
index 0000000000..407b2ecb42
--- /dev/null
+++ b/dom/media/mediasource/test/test_NoVideoLoopBackData.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: loop-back data not available yet (shorter video)</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+/**
+ * This test is used to check whether a looping video can loop back successfully
+ * when it has a shorter video track than its audio track. When reaching EOS for
+ * the shorter track, there is no loop-back data at the start position (they are
+ * not appended yet) Even that, we should still be able to loop back but the
+ * looping would become non-seamless in this situation.
+ */
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+
+ // Here we create a way shorter video than audio because audio decoding is
+ // very fast. If two track only have small diffence in length, audio track
+ // would still reach to the end first. But in this test, we want to test
+ // reaching video EOS first.
+ info(`create different length source buffers`);
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(5, 8), ".m4s");
+ videosb.appendWindowEnd = audiosb.buffered.end(0) - 2.5;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(5, 8), ".m4s");
+ ms.endOfStream();
+ await Promise.all([once(el, "durationchange"), once(ms, "sourceended")]);
+ info(`audio=[${audiosb.buffered.start(0)}-${audiosb.buffered.end(0)}], video=[${videosb.buffered.start(0)}-${videosb.buffered.end(0)}]`);
+ ok(true, `endOfStream completed, buffer=[${el.buffered.start(0)}, ${el.buffered.end(0)}]`);
+ ok(audiosb.buffered.end(0) > videosb.buffered.end(0), `audio should be longer than video`);
+
+ info(`seek to the position where buffered data exists`);
+ el.loop = true;
+ el.controls = true;
+ el.currentTime = el.buffered.start(0);
+ await el.play();
+
+ info(`video should trigger seeking when reaching to the end`);
+ let seekingCount = 0, seekedCount = 0;
+ el.addEventListener("seeking", () => {
+ is(++seekingCount, 1, "should only receive seeking once!");
+ });
+ el.addEventListener("seeked", () => {
+ is(++seekedCount, 1, "should only receive seeked once!");
+ });
+ await once(el, "seeking");
+
+ info(`trim old data before append new data`);
+ let p = Promise.all([once(videosb, "updateend"), once(audiosb, "updateend")]);
+ videosb.remove(videosb.buffered.start(0), videosb.buffered.end(0));
+ audiosb.remove(audiosb.buffered.start(0), audiosb.buffered.end(0));
+ await p;
+
+ info(`append new data`);
+ const seekedPromise = once(el, "seeked");
+ p = Promise.all([once(videosb, "updateend"), once(audiosb, "updateend")]);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 2), ".m4s");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 2), ".m4s");
+ await p;
+ info(`audio=[${audiosb.buffered.start(0)}-${audiosb.buffered.end(0)}], video=[${videosb.buffered.start(0)}-${videosb.buffered.end(0)}]`);
+
+ info(`now we should be able to finish seeking to the start position`);
+ await seekedPromise;
+
+ SimpleTest.finish(SimpleTest);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_OnEvents.html b/dom/media/mediasource/test/test_OnEvents.html
new file mode 100644
index 0000000000..ae0f348ebe
--- /dev/null
+++ b/dom/media/mediasource/test/test_OnEvents.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: live seekable range</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ const receiveEvent = e => v["got" + e] = true;
+
+ const msevents = ["onsourceopen", "onsourceended"];
+ msevents.forEach(e => ms[e] = () => receiveEvent(e));
+
+ const sblistevents = ["onaddsourcebuffer", "onremovesourcebuffer"];
+ sblistevents.forEach(e => ms.sourceBuffers[e] = () => receiveEvent(e));
+
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const sbevents = ["onupdatestart", "onupdate", "onupdateend", "onabort"];
+ sbevents.forEach(e => sb[e] = () => receiveEvent(e));
+
+ await fetchAndLoad(sb, "seek", [""], ".webm");
+ sb.appendBuffer(await fetchWithXHR("seek.webm"));
+ ms.removeSourceBuffer(sb); // will fire abort and removesourcebuffer
+ ms.endOfStream(); // will fire sourceended
+ await once(ms, "sourceended");
+ [...msevents, ...sbevents, ...sblistevents].forEach(e => ok(v["got" + e], "got " + e));
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_PlayEvents.html b/dom/media/mediasource/test/test_PlayEvents.html
new file mode 100644
index 0000000000..82ccaa42b5
--- /dev/null
+++ b/dom/media/mediasource/test/test_PlayEvents.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// This test checks that readyState is properly set and the appropriate events are being fired accordingly:
+// 1. Load 1.6s of data and ensure that canplay event is fired.
+// 2. Load data to have a complete buffered range from 0 to duration and ensure that canplaythrough is fired.
+// 3. Seek to an area with no buffered data, and ensure that readyState goes back to HAVE_METADATA
+// 4. Load 1.6s of data at the seek position and ensure that canplay is fired and that readyState is now HAVE_FUTURE_DATA
+// 5. Start playing video and check that once it reaches a position with no data, readyState goes back to HAVE_CURRENT_DATA and waiting event is fired.
+// 6. Add 1.6s of data once video element fired waiting, that canplay is fired once readyState is HAVE_FUTURE_DATA.
+// 7. Finally load data to the end and ensure that canplaythrough is fired and that readyState is now HAVE_ENOUGH_DATA
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ logEvents(el);
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ el.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await p;
+ ok(true, "got loadedmetadata event");
+ p = Promise.all([once(el, "loadeddata"), once(el, "canplay")]);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 3), ".m4s");
+ await p;
+ ok(true, "got canplay event");
+ // set element duration to 3.203333s. We do so in order to guarantee that
+ // the end of the buffered range will be equal to duration, causing
+ // canplaythrough to be fired later.
+ ms.duration = 3.203333;
+ await once(el, "durationchange");
+ ok(true, "got durationchange event");
+ // Load [0.801666, 3.203333]
+ p = once(el, "canplaythrough");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(3, 5), ".m4s");
+ await p;
+ ok(true, "got canplaythrough event");
+ // set element duration to 9.203333s, this value is set to coincide with
+ // data added later (we now have an empty range from 6s to 9.203333s).
+ ms.duration = 9.203333;
+ await once(el, "durationchange");
+ ok(true, "got durationchange event");
+ // An arbitrary value, so we are guaranteed to be in a range with no data.
+ el.currentTime = 6;
+ videosb.timestampOffset = 6;
+ ok(el.seeking, "seeking started");
+ await once(el, "seeking");
+ ok(true, "got seeking event");
+ is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
+ // Load [6+0, 6+1.601666)
+ p = Promise.all([once(el, "seeked"), once(el, "canplay")]);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 3), ".m4s");
+ await p;
+ ok(true, "got seeked and canplay event");
+ is(el.currentTime, 6, "seeked to 6s");
+ is(el.readyState, el.HAVE_FUTURE_DATA, "readyState is HAVE_FUTURE_DATA");
+ // Load [6+1.60166, 6+3.203333]
+ p = once(el, "canplaythrough");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(3, 5), ".m4s");
+ await p;
+ ok(true, "got canplaythrough event");
+ // set element duration to 19.805s, this value is set to coincide with
+ // data added later (we now have an empty range from 15 to 19.805).
+ ms.duration = 19.805;
+ await once(el, "durationchange");
+ ok(true, "got durationchange event");
+ el.currentTime = 15;
+ videosb.timestampOffset = 15;
+ ok(el.seeking, "seeking started");
+ await once(el, "seeking");
+ ok(true, "got seeking event");
+ // Load [15+0, 15+1.601666)
+ p = once(el, "seeked");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 3), ".m4s");
+ await p;
+ ok(true, "got seeked event");
+ // Load [15+1.60166, 15+3.203333]
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(3, 5), ".m4s");
+ ok(true, "data loaded");
+ // Playback we play for a little while then stall.
+ p = Promise.all([once(el, "playing"), once(el, "waiting")]);
+ el.play();
+ await p;
+ ok(true, "got playing and waiting event");
+ // Playback has stalled, readyState is back to HAVE_CURRENT_DATA.
+ is(el.readyState, el.HAVE_CURRENT_DATA, "readyState is HAVE_CURRENT_DATA");
+ // Load [15+3.203333, 15+4.805)
+ // Our final buffered range will now be [0, 3.203333)[6, 9.203333)[15, 19.805)
+ p = Promise.all([once(el, "playing"), once(el, "canplay"), once(el, "canplaythrough")]);
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(5, 7), ".m4s");
+ await p;
+ ok(true, "got playing, canplay and canplaythrough event");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_PlayEventsAutoPlaying.html b/dom/media/mediasource/test/test_PlayEventsAutoPlaying.html
new file mode 100644
index 0000000000..3e395c799d
--- /dev/null
+++ b/dom/media/mediasource/test/test_PlayEventsAutoPlaying.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// This test checks that readyState is properly set and the appropriate events are being fired accordingly:
+// 1. Ensure that play/playing aren't fired before any media data been added.
+// 2. Load 1.6s of data and ensure that canplay, play and playing events are fired.
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ el.autoplay = true;
+ const eventCounts = { play: 0, playing: 0 };
+ await once(ms, "sourceopen");
+ logEvents(el);
+ ok(true, "Receive a sourceopen event");
+
+ const forbiddenEvents = e => {
+ ok(el.readyState >= el.HAVE_FUTURE_DATA, "Must not have received event too early");
+ is(eventCounts[e.type], 0, "event should have only be fired once");
+ eventCounts[e.type]++;
+ };
+ el.addEventListener("play", forbiddenEvents);
+ el.addEventListener("playing", forbiddenEvents);
+
+ const videosb = ms.addSourceBuffer("video/mp4");
+ el.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await p;
+ ok(true, "got loadedmetadata event");
+ // We're only adding 1.6s worth of data, not enough for readyState to change to HAVE_ENOUGH_DATA
+ // So we end the media source so that all the playable data is available.
+ p = Promise.all(["loadeddata", "canplay", "play", "playing", "ended"].map(e => once(el, e)));
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 3), ".m4s");
+ ms.endOfStream();
+ await p;
+ ok(true, "got all required event");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_PlayEventsAutoPlaying2.html b/dom/media/mediasource/test/test_PlayEventsAutoPlaying2.html
new file mode 100644
index 0000000000..8845a26ac4
--- /dev/null
+++ b/dom/media/mediasource/test/test_PlayEventsAutoPlaying2.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// This test checks that readyState is properly set and the appropriate events are being fired accordingly:
+// 1. Ensure that play/playing aren't fired before any media data been added.
+// 2. Load more than 10s of data and ensure that canplay, play and playing events are fired.
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ el.autoplay = true;
+ const eventCounts = { play: 0, playing: 0 };
+ await once(ms, "sourceopen");
+ logEvents(el);
+ ok(true, "Receive a sourceopen event");
+
+ const forbiddenEvents = e => {
+ ok(el.readyState >= el.HAVE_FUTURE_DATA, "Must not have received event too early");
+ is(eventCounts[e.type], 0, "event should have only be fired once");
+ eventCounts[e.type]++;
+ };
+ el.addEventListener("play", forbiddenEvents);
+ el.addEventListener("playing", forbiddenEvents);
+
+ const videosb = ms.addSourceBuffer("video/mp4");
+ el.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await p;
+ ok(true, "got loadedmetadata event");
+ // We shift the timestamps slightly to create a small gaps at the start.
+ // one that should normally be ignored.
+ videosb.timestampOffset = 0.1;
+ p = Promise.all(["loadeddata", "canplay", "play", "playing"].map(e => once(el, e)));
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 14), ".m4s");
+ await p;
+ ok(true, "got all required event");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_RemoveSourceBuffer.html b/dom/media/mediasource/test/test_RemoveSourceBuffer.html
new file mode 100644
index 0000000000..11c6a51deb
--- /dev/null
+++ b/dom/media/mediasource/test/test_RemoveSourceBuffer.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: check buffered status after removed all source buffer</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+const videoURL = "seek.webm";
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async function(ms, el) {
+ info("- wait for sourceopen -");
+ await once(ms, "sourceopen");
+
+ info("- wait for fetching data -");
+ const arrayBuffer = await fetchWithXHR(videoURL);
+
+ info("- create source buffer and append data -");
+ const sourceBuffer = ms.addSourceBuffer("video/webm");
+ sourceBuffer.appendBuffer(arrayBuffer);
+ await once(sourceBuffer, "updateend");
+ is(ms.sourceBuffers.length, 1,
+ "the length of source buffers list is 1.");
+ is(ms.activeSourceBuffers.length, 1,
+ "the length of active source buffers list is 1.");
+ ok(ms.duration != 0, "duration is not 0.");
+ is(el.buffered.length, 1, "buffered range is 1.");
+
+ info("- remove source buffer from media source -");
+ ms.removeSourceBuffer(sourceBuffer);
+ await once(ms.sourceBuffers, "removesourcebuffer");
+ is(ms.sourceBuffers.length, 0, "source buffers list is empty.");
+ is(ms.activeSourceBuffers.length, 0, "active source buffers list is empty.");
+ ok(ms.duration != 0, "duration is not 0.");
+ is(el.buffered.length, 0,
+ "buffered range is empty since we don't have any source buffer.");
+
+ info("- call endOfStream -");
+ ms.endOfStream();
+ is(ms.duration, 0, "duraton is 0 since we don't have any source buffer.");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_Resolution_change_should_not_cause_video_freeze.html b/dom/media/mediasource/test/test_Resolution_change_should_not_cause_video_freeze.html
new file mode 100644
index 0000000000..640b53441e
--- /dev/null
+++ b/dom/media/mediasource/test/test_Resolution_change_should_not_cause_video_freeze.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: video resolution changes during playback should not cause video freeze (Bug 1718709)</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer('video/mp4');
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("bug1718709_low_res.mp4")));
+ ok(true, "appended low resolution video");
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("bug1718709_high_res.mp4")));
+ ok(true, "appended high resolution video");
+
+ info(`start from the position which is near to the place where resolution changes`);
+ v.currentTime = 13;
+ ok(await v.play().then(_=>true,_=>false), "video started playing");
+
+ // When video resolution changes, it should not cause video freeze so we check
+ // its painted frame amount regularly to see if we stop updating video frames.
+ let lastPaintedFramesAmount = v.mozPaintedFrames;
+ const intervalHandle = setInterval(_=>{
+ ok(lastPaintedFramesAmount < v.mozPaintedFrames,
+ `painted frames keeps growing from ${lastPaintedFramesAmount} to ${v.mozPaintedFrames}`);
+ lastPaintedFramesAmount = v.mozPaintedFrames;
+ }, 1000);
+
+ // As we didn't append full video, so we will receive `waiting` event later
+ // which indicates that we can stop testing because we've finished playing
+ // the high resolution part.
+ await new Promise(r => {
+ v.onwaiting = _ => {
+ clearInterval(intervalHandle);
+ r();
+ }
+ });
+ SimpleTest.finish();
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_ResumeAfterClearing_mp4.html b/dom/media/mediasource/test/test_ResumeAfterClearing_mp4.html
new file mode 100644
index 0000000000..40e512ba12
--- /dev/null
+++ b/dom/media/mediasource/test/test_ResumeAfterClearing_mp4.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Don't get stuck buffering for too long when we have frames to show</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ ms.addEventListener("sourceopen", () => ok(false, "No more sourceopen"));
+ const sb = ms.addSourceBuffer("video/mp4");
+ ok(sb, "Create a SourceBuffer");
+ sb.addEventListener("error", e => {
+ ok(false, "Got Error: " + e);
+ SimpleTest.finish();
+ });
+ await fetchAndLoad(sb, "bipbop/bipbop", ["init"], ".mp4");
+ let p = once(v, "loadeddata");
+ await fetchAndLoad(sb, "bipbop/bipbop", range(1, 3), ".m4s");
+ await p;
+ // clear the entire sourcebuffer.
+ sb.remove(0, 5);
+ await once(sb, "updateend");
+ v.play();
+ // We have nothing to play, waiting will be fired.
+ await once(v, "waiting");
+ p = once(v, "playing");
+ await fetchAndLoad(sb, "bipbop/bipbop", range(1, 4), ".m4s");
+ await p;
+ ms.endOfStream();
+ await Promise.all([once(ms, "sourceended"), once(v, "ended")]);
+ SimpleTest.finish(SimpleTest);
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekNoData_mp4.html b/dom/media/mediasource/test/test_SeekNoData_mp4.html
new file mode 100644
index 0000000000..1ea64f3fa4
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekNoData_mp4.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ el.addEventListener("error", e => {
+ ok(false, `should not fire ${e.type} event`);
+ SimpleTest.finish();
+ });
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ must_not_throw(() => el.currentTime = 3, "setting currentTime is valid");
+ is(el.currentTime, 3, "currentTime is default playback start position");
+ is(el.seeking, false, "seek not started with HAVE_NOTHING");
+ await Promise.all([
+ fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4"),
+ fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4"),
+ once(el, "loadedmetadata"),
+ ]);
+ const p = once(el, "seeking");
+ el.play();
+ el.currentTime = 5;
+ is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
+ is(el.seeking, true, "seek not started with HAVE_METADATA");
+ is(el.currentTime, 5, "currentTime is seek position");
+ await p;
+ ok(true, "Got seeking event");
+ await Promise.all([
+ once(el, "seeked"),
+ fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(5, 9), ".m4s"),
+ fetchAndLoad(videosb, "bipbop/bipbop_video", range(6, 10), ".m4s"),
+ ]);
+ ok(true, "Got seeked event");
+ ok(el.currentTime >= 5, "Time >= 5");
+ ms.endOfStream();
+ await once(el, "ended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekToEnd_mp4.html b/dom/media/mediasource/test/test_SeekToEnd_mp4.html
new file mode 100644
index 0000000000..0405cb875f
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekToEnd_mp4.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seeking to end of data with data gap.</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 6), ".m4s");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ is(videosb.buffered.length, 1, "continuous buffered range");
+ // Ensure we have at least 2s less audio than video.
+ audiosb.appendWindowEnd = videosb.buffered.end(0) - 2;
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 6), ".m4s");
+ ms.endOfStream();
+ await Promise.all([once(el, "durationchange"), once(ms, "sourceended")]);
+ ok(true, "endOfStream completed");
+ // Seek to the middle of the gap where audio is missing. As we are in readyState = ended
+ // seeking must complete.
+ el.currentTime = videosb.buffered.end(0) / 2 + audiosb.buffered.end(0) / 2;
+ ok(el.currentTime - audiosb.buffered.end(0) >= 1, "gap is big enough");
+ is(el.buffered.length, 1, "continuous buffered range");
+ is(el.buffered.end(0), videosb.buffered.end(0),
+ "buffered range end is aligned with longest track");
+ ok(el.seeking, "element is now seeking");
+ ok(el.currentTime >= el.buffered.start(0) && el.currentTime <= el.buffered.end(0),
+ "seeking time is in buffered range");
+ ok(el.currentTime > audiosb.buffered.end(0),
+ "seeking point is not buffered in audio track");
+ await once(el, "seeked");
+ ok(true, "we have successfully seeked");
+ // Now ensure that we can play to the end, even though we are missing data in one track.
+ el.play();
+ await once(el, "ended");
+ SimpleTest.finish(SimpleTest);
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekToLastFrame_mp4.html b/dom/media/mediasource/test/test_SeekToLastFrame_mp4.html
new file mode 100644
index 0000000000..edbfdff0a0
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekToLastFrame_mp4.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Can seek to last frame</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const sb = ms.addSourceBuffer("video/mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop_480_624kbps-video", ["init"], ".mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop_480_624kbps-video", range(1, 3), ".m4s");
+ el.play();
+ // let seek to the last audio frame.
+ el.currentTime = 1.532517;
+ await once(el, "seeked");
+ ok(true, "seek completed");
+ ms.endOfStream();
+ await once(el, "ended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekTwice_mp4.html b/dom/media/mediasource/test/test_SeekTwice_mp4.html
new file mode 100644
index 0000000000..50ff32b1cd
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekTwice_mp4.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 5), ".m4s");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(6, 12), ".m4s");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 6), ".m4s");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(7, 14), ".m4s");
+ let p = once(el, "seeking");
+ el.play();
+ el.currentTime = 4.5; // Seek to a gap in the video
+ await p;
+ ok(true, "Got seeking event");
+ p = once(el, "seeked");
+ el.currentTime = 6; // Seek past the gap.
+ await p;
+ ok(true, "Got seeked event");
+ ok(el.currentTime >= 6, "Time >= 6");
+ ms.endOfStream();
+ await once(el, "ended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream.html b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream.html
new file mode 100644
index 0000000000..c65a4aff7e
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seekable attribute after end of stream</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ info("- append first buffer -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer));
+
+ info("- wait for metadata -");
+ await once(v, "loadedmetadata");
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+
+ info("- check seekable -");
+ const target = 2;
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+
+ info("- call end of stream -");
+ ms.endOfStream();
+ await once(ms, "sourceended");
+
+ info("- check seekable -");
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit.html b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit.html
new file mode 100644
index 0000000000..bed2af8d48
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seekable attribute after end of stream with split appendBuffer</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ info("- append first buffer -");
+ // 25523 is the offset of the first media segment's end
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25523));
+
+ info("- wait for metadata -");
+ await once(v, "loadedmetadata");
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+
+ info("- append second buffer -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 25523));
+ await once(sb, "updateend");
+
+ info("- check seekable -");
+ const target = 2;
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+
+ info("- call end of stream -");
+ ms.endOfStream();
+ await once(ms, "sourceended");
+
+ info("- check seekable -");
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit_mp4.html b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit_mp4.html
new file mode 100644
index 0000000000..00b5f9a832
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStreamSplit_mp4.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seekable attribute after end of stream with split appendBuffer</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ const arrayBuffer = await fetchWithXHR("bipbop/bipbop2s.mp4");
+ info("- append first buffer -");
+ // 25819 is the offset of the first media segment's end
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25819));
+
+ info("- wait for metadata -");
+ await once(v, "loadedmetadata");
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+
+ info("- append second buffer -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 25819));
+ await once(sb, "updateend");
+
+ info("- check seekable -");
+ const target = 1.3;
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+
+ info("- call end of stream -");
+ ms.endOfStream();
+ await once(ms, "sourceended");
+
+ info("- check seekable -");
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream_mp4.html b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream_mp4.html
new file mode 100644
index 0000000000..c8e53833fb
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekableBeforeAndAfterEndOfStream_mp4.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: seekable attribute after end of stream</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ const arrayBuffer = await fetchWithXHR("bipbop/bipbop2s.mp4");
+ info("- append buffer -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer));
+
+ info("- wait for metadata -");
+ await once(v, "loadedmetadata");
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+
+ info("- check seekable -");
+ const target = 1.3;
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+
+ info("- call end of stream -");
+ ms.endOfStream();
+ await once(ms, "sourceended");
+
+ info("- check seekable -");
+ ok(v.seekable.length, "Resource is seekable");
+ is(v.seekable.start(0), 0, "Seekable's start point is correct");
+ is(v.seekable.end(0), ms.duration, "Seekable's end point is correct");
+ ok(v.seekable.length &&
+ target >= v.seekable.start(0) &&
+ target < v.seekable.end(0), "Target is within seekable range");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SeekedEvent_mp4.html b/dom/media/mediasource/test/test_SeekedEvent_mp4.html
new file mode 100644
index 0000000000..70401f1eb1
--- /dev/null
+++ b/dom/media/mediasource/test/test_SeekedEvent_mp4.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: Check that seeked event is fired prior loadeddata</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ const events = ["seeked", "loadeddata", "playing"];
+ let eventCount = 0;
+ events.forEach(type => el.addEventListener(type,
+ () => is(events[eventCount++], type, "events must come in order")));
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+ let p = once(el, "loadedmetadata");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await p;
+ el.play();
+ videosb.timestampOffset = 2;
+ is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
+ // Load [2, 3.606).
+ p = once(el, "play");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["1"], ".m4s");
+ await p;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["2"], ".m4s");
+ // TODO: readyState should be at least HAVE_CURRENTDATA, see bug 1367993.
+ ok(el.readyState >= el.HAVE_METADATA, "readyState is HAVE_METADATA");
+ el.currentTime = 2;
+ await Promise.all([once(el, "seeked"), once(el, "playing")]);
+ ok(true, "completed seek");
+ is(eventCount, events.length, "Received expected number of events");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_Sequence_mp4.html b/dom/media/mediasource/test/test_Sequence_mp4.html
new file mode 100644
index 0000000000..5af7fe5a0b
--- /dev/null
+++ b/dom/media/mediasource/test/test_Sequence_mp4.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: Don't get stuck buffering for too long when we have frames to show</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ ms.addEventListener("sourceopen", () => ok(false, "No more sourceopen"));
+ const sb = ms.addSourceBuffer("video/mp4");
+ ok(sb, "Create a SourceBuffer");
+ sb.addEventListener("error", e => {
+ ok(false, "Got Error: " + e);
+ SimpleTest.finish();
+ });
+ sb.mode = "sequence";
+
+ await fetchAndLoad(sb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(sb, "bipbop/bipbop_video", ["5"], ".m4s");
+ await fetchAndLoad(sb, "bipbop/bipbop_video", ["2"], ".m4s");
+ is(v.buffered.length, 1, "Continuous buffered range");
+ is(v.buffered.start(0), 0, "Buffered range starts at 0");
+ ok(sb.timestampOffset >= 0, "SourceBuffer.timestampOffset set to allow continuous range");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SetModeThrows.html b/dom/media/mediasource/test/test_SetModeThrows.html
new file mode 100644
index 0000000000..c715854b41
--- /dev/null
+++ b/dom/media/mediasource/test/test_SetModeThrows.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append initialization</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// MSE supports setting mode now. make sure it does not throw.
+runWithMSE(function(ms, v) {
+ ms.addEventListener("sourceopen", () => {
+ const sb = ms.addSourceBuffer("video/webm");
+
+ sb.mode = "segments";
+ ok("true", "Setting to segments does not throw");
+ try {
+ sb.mode = "sequence";
+ ok("true", "Setting to sequence does not throw");
+ } catch (e) { ok(false, "Should not throw setting mode to sequence: " + e); }
+
+ SimpleTest.finish();
+ });
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SplitAppend.html b/dom/media/mediasource/test/test_SplitAppend.html
new file mode 100644
index 0000000000..a4be5de282
--- /dev/null
+++ b/dom/media/mediasource/test/test_SplitAppend.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append initialization and media segment separately</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
+ v.play();
+ await once(sb, "updateend");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
+ await once(sb, "updateend");
+ ms.endOfStream();
+ await once(v, "ended");
+ // XXX: Duration should be exactly 4.0, see bug 1065207.
+ ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
+ ok(Math.abs(v.currentTime - 4) <= 0.002, "Video has played to end");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SplitAppendDelay.html b/dom/media/mediasource/test/test_SplitAppendDelay.html
new file mode 100644
index 0000000000..40183c3db0
--- /dev/null
+++ b/dom/media/mediasource/test/test_SplitAppendDelay.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append segments with delay</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
+ v.play();
+ await once(sb, "updateend");
+ await wait(1000);
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
+ await once(sb, "updateend");
+ ms.endOfStream();
+ await once(v, "ended");
+ // XXX: Duration should be exactly 4.0, see bug 1065207.
+ ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
+ ok(Math.abs(v.currentTime - 4) <= 0.002, "Video has played to end");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SplitAppendDelay_mp4.html b/dom/media/mediasource/test/test_SplitAppendDelay_mp4.html
new file mode 100644
index 0000000000..c072a526cf
--- /dev/null
+++ b/dom/media/mediasource/test/test_SplitAppendDelay_mp4.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append segments with delay</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ const arrayBuffer = await fetchWithXHR("bipbop/bipbop2s.mp4");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 1395));
+ v.play();
+ await once(sb, "updateend");
+ await wait(1000);
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 1395));
+ await once(sb, "updateend");
+ ms.endOfStream();
+ await once(v, "ended");
+ // The bipbop video doesn't start at 0. The old MSE code adjust the
+ // timestamps and ignore the audio track. The new one doesn't.
+ isfuzzy(v.duration, 1.696, 0.166, "Video has correct duration");
+ isfuzzy(v.currentTime, 1.696, 0.166, "Video has played to end");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_SplitAppend_mp4.html b/dom/media/mediasource/test/test_SplitAppend_mp4.html
new file mode 100644
index 0000000000..308fa9837d
--- /dev/null
+++ b/dom/media/mediasource/test/test_SplitAppend_mp4.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: append initialization and media segment separately</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ const arrayBuffer = await fetchWithXHR("bipbop/bipbop2s.mp4");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 1395));
+ v.play();
+ await once(sb, "updateend");
+ sb.appendBuffer(new Uint8Array(arrayBuffer, 1395));
+ await once(sb, "updateend");
+ ms.endOfStream();
+
+ await once(v, "ended");
+ // The bipbop video doesn't start at 0. The old MSE code adjust the
+ // timestamps and ignore the audio track. The new one doesn't.
+ isfuzzy(v.duration, 1.696, 0.166, "Video has correct duration");
+ isfuzzy(v.currentTime, 1.696, 0.166, "Video has played to end");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_Threshold_mp4.html b/dom/media/mediasource/test/test_Threshold_mp4.html
new file mode 100644
index 0000000000..c46883c93d
--- /dev/null
+++ b/dom/media/mediasource/test/test_Threshold_mp4.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: data gap detection</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ const threshold = 0.5; // gap threshold in seconds.
+ const fuzz = 0.000001; // fuzz when comparing double.
+
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ const vchunks = [{start: 0, end: 3.203333}, { start: 3.203333, end: 6.406666}];
+
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 5), ".m4s");
+ // We will insert a gap of threshold
+ videosb.timestampOffset = threshold;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(5, 9), ".m4s");
+ // HTMLMediaElement fires 'waiting' if somebody invokes |play()| before the MDSM
+ // has notified it of available data. Make sure that we get 'playing' before
+ // we starting waiting for 'waiting'.
+ info("Invoking play()");
+ let p = once(el, "playing");
+ el.play();
+ await p;
+ await once(el, "waiting");
+ // We're waiting for data after the start of the last frame.
+ // 0.033333 is the duration of the last frame.
+ ok((el.currentTime >= vchunks[1].end - 0.033333 + threshold - fuzz &&
+ el.currentTime <= vchunks[1].end + threshold + fuzz),
+ `skipped the gap properly: ${el.currentTime} ${vchunks[1].end + threshold}`);
+ is(el.buffered.length, 2, "buffered range has right length");
+ // Now we test that seeking will succeed despite the gap.
+ el.currentTime = el.buffered.end(0) + (threshold / 2);
+ await once(el, "seeked");
+ // Now we test that we don't pass the gap.
+ // Clean up our sourcebuffer by removing all data.
+ videosb.timestampOffset = 0;
+ videosb.remove(0, Infinity);
+ el.currentTime = 0;
+ el.pause();
+ await once(videosb, "updateend");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 5), ".m4s");
+ // We will insert a gap of threshold + 1ms
+ videosb.timestampOffset = threshold + 1 / 1000;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(5, 9), ".m4s");
+ info("Invoking play()");
+ p = once(el, "playing");
+ el.play();
+ await p;
+ await once(el, "waiting");
+ // We're waiting for data after the start of the last frame.
+ // 0.033333 is the duration of the last frame.
+ ok((el.currentTime >= vchunks[0].end - 0.033333 - fuzz &&
+ el.currentTime <= vchunks[0].end + fuzz),
+ `stopped at the gap properly: ${el.currentTime} ${vchunks[0].end}`);
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_TimestampOffset_mp4.html b/dom/media/mediasource/test/test_TimestampOffset_mp4.html
new file mode 100644
index 0000000000..bd08e0f36e
--- /dev/null
+++ b/dom/media/mediasource/test/test_TimestampOffset_mp4.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: basic functionality</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ const eps = 0.01;
+
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ // We divide the video into 3 chunks:
+ // chunk 0: segments 1-4
+ // chunk 1: segments 5-8
+ // chunk 2: segments 9-13
+ // We then fill the timeline so that it seamlessly plays the chunks in order 0, 2, 1.
+ const vchunks = [{start: 0, end: 3.2033},
+ { start: 3.2033, end: 6.4066},
+ { start: 6.4066, end: 10.01}];
+ const firstvoffset = vchunks[2].end - vchunks[2].start; // Duration of chunk 2
+ const secondvoffset = -(vchunks[1].end - vchunks[1].start); // -(Duration of chunk 1)
+
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 5), ".m4s");
+ is(videosb.buffered.length, 1, "No discontinuity");
+ isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "Chunk start");
+ isfuzzy(videosb.buffered.end(0), vchunks[0].end, eps, "Chunk end");
+ videosb.timestampOffset = firstvoffset;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(5, 9), ".m4s");
+ is(videosb.buffered.length, 2, "One discontinuity");
+ isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "First Chunk start");
+ isfuzzy(videosb.buffered.end(0), vchunks[0].end, eps, "First chunk end");
+ isfuzzy(videosb.buffered.start(1), vchunks[1].start + firstvoffset, eps, "Second chunk start");
+ isfuzzy(videosb.buffered.end(1), vchunks[1].end + firstvoffset, eps, "Second chunk end");
+ videosb.timestampOffset = secondvoffset;
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(9, 14), ".m4s");
+ is(videosb.buffered.length, 1, "No discontinuity (end)");
+ isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "Chunk start");
+ isfuzzy(videosb.buffered.end(0), vchunks[2].end, eps, "Chunk end");
+ audiosb.timestampOffset = 3;
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 12), ".m4s");
+ is(audiosb.buffered.length, 1, "No audio discontinuity");
+ isfuzzy(audiosb.buffered.start(0), 3, eps, "Audio starts at 3");
+
+ // Trim the rest of the audio.
+ audiosb.remove(videosb.buffered.end(0), Infinity);
+ videosb.remove(videosb.buffered.end(0), Infinity);
+ if (audiosb.updating) {
+ await once(audiosb, "updateend");
+ }
+ if (videosb.updating) {
+ await once(videosb, "updateend");
+ }
+ info("waiting for play to complete");
+ el.play();
+ el.currentTime = el.buffered.start(0);
+ ms.endOfStream();
+ await Promise.all([once(el, "ended"), once(el, "seeked")]);
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_TruncatedDuration.html b/dom/media/mediasource/test/test_TruncatedDuration.html
new file mode 100644
index 0000000000..c80e40ac98
--- /dev/null
+++ b/dom/media/mediasource/test/test_TruncatedDuration.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: truncating the media seeks to end of media and update buffered range</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+// This test append data to a mediasource and then seek to half the duration
+// of the video.
+// We then shorten the video to 1/3rd of its original size by modifying the
+// mediasource.duration attribute.
+// We ensure that the buffered range immediately reflect the truncation
+// and that we've seeked to the new end of the media as per W3C spec and
+// video.currentTime got updated.
+
+SimpleTest.waitForExplicitFinish();
+
+const round = n => Math.round(n * 1000) / 1000;
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("seek.webm")));
+ await once(sb, "updateend");
+ v.currentTime = v.duration / 2;
+ is(v.currentTime, v.duration / 2, "current time was updated");
+ ok(v.seeking, "seeking is true");
+ await once(v, "seeked");
+ const duration = round(v.duration / 3);
+ is(sb.updating, false, "sourcebuffer isn't updating");
+ sb.remove(duration, Infinity);
+ await once(sb, "updateend");
+ ms.duration = duration;
+ // frames aren't truncated, so duration may be slightly more.
+ isfuzzy(v.duration, duration, 1 / 30, "element duration was updated");
+ sb.abort(); // this shouldn't abort updating the duration (bug 1130826).
+ ok(v.seeking, "seeking is true");
+ // test playback position was updated (bug 1130839).
+ is(v.currentTime, v.duration, "current time was updated");
+ is(sb.buffered.length, 1, "One buffered range");
+ // Truncated mediasource duration will cause the video element to seek.
+ await once(v, "seeking");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_TruncatedDuration_mp4.html b/dom/media/mediasource/test/test_TruncatedDuration_mp4.html
new file mode 100644
index 0000000000..2f37150fd3
--- /dev/null
+++ b/dom/media/mediasource/test/test_TruncatedDuration_mp4.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: truncating the media seeks to end of media and update buffered range</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+// This test append data to a mediasource and then seek to half the duration
+// of the video.
+// We then shorten the video to 1/3rd of its original size.
+// We ensure that the buffered range immediately reflect the truncation
+// and that we've seeked to the new end of the media as per W3C spec and
+// video.currentTime got updated.
+
+SimpleTest.waitForExplicitFinish();
+
+const round = n => Math.round(n * 1000) / 1000;
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/mp4");
+
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("bipbop/bipbop2s.mp4")));
+ await once(sb, "updateend");
+ // mp4 metadata states 10s when we only have 1.6s worth of video.
+ sb.remove(sb.buffered.end(0), Infinity);
+ await once(sb, "updateend");
+ ms.duration = sb.buffered.end(0);
+ is(v.duration, ms.duration, "current time updated with mediasource duration");
+ v.currentTime = v.duration / 2;
+ is(v.currentTime, v.duration / 2, "current time was updated");
+ ok(v.seeking, "seeking is true");
+ await once(v, "seeked");
+ const duration = round(v.duration / 3);
+ is(sb.updating, false, "sourcebuffer isn't updating");
+ sb.remove(duration, Infinity);
+ await once(sb, "updateend");
+ ms.duration = duration;
+ // frames aren't truncated, so duration may be slightly more.
+ isfuzzy(v.duration, duration, 1 / 30, "element duration was updated");
+ sb.abort(); // this shouldn't abort updating the duration (bug 1130826).
+ ok(v.seeking, "seeking is true");
+ // test playback position was updated (bug 1130839).
+ is(v.currentTime, v.duration, "current time was updated");
+ is(sb.buffered.length, 1, "One buffered range");
+ // Truncated mediasource duration will cause the video element to seek.
+ await once(v, "seeking");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_WMFUnmatchedAudioDataTime.html b/dom/media/mediasource/test/test_WMFUnmatchedAudioDataTime.html
new file mode 100644
index 0000000000..7c03214c7b
--- /dev/null
+++ b/dom/media/mediasource/test/test_WMFUnmatchedAudioDataTime.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: audio output time doesn't match the input time on WMF</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer('audio/mp4;codecs=" mp4a.40.2"');
+ sb.appendBuffer(new Uint8Array(await fetchWithXHR("wmf_mismatchedaudiotime.mp4")));
+ ok(true, "appended data");
+
+ info(`if error doesn't occur, we should be able to receive 'seeked', otherwise 'error' would be dispatched`);
+ v.currentTime = 22.05;
+ ok(await Promise.race([
+ once(v, "seeked").then(_ => true),
+ once(v, "error").then(_ => false),
+ ]), "finished seeking without any error");
+ ok(!v.error, "should not get any error");
+ SimpleTest.finish();
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_WaitingOnMissingData.html b/dom/media/mediasource/test/test_WaitingOnMissingData.html
new file mode 100644
index 0000000000..b1ad41bb37
--- /dev/null
+++ b/dom/media/mediasource/test/test_WaitingOnMissingData.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: |waiting| event when source data is missing</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const sb = ms.addSourceBuffer("video/webm");
+ sb.addEventListener("error", e => {
+ ok(false, "Got Error: " + e);
+ SimpleTest.finish();
+ });
+ const arrayBuffer = await fetchWithXHR("seek.webm");
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 0, 318));
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 318, 25223 - 318));
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 25223, 46712 - 25223));
+ /* Note - Missing |46712, 67833 - 46712| segment here */
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 67833, 88966 - 67833));
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 88966));
+ // HTMLMediaElement fires "waiting" if somebody invokes |play()| before the MDSM
+ // has notified it of available data. Make sure that we get "playing" before
+ // we starting waiting for "waiting".
+ info("Invoking play()");
+ let p = once(el, "playing");
+ el.play();
+ await p;
+ ok(true, "Video playing. It should play for a bit, then fire 'waiting'");
+ p = once(el, "waiting");
+ el.play();
+ await p;
+ // currentTime is based on the current video frame, so if the audio ends just before
+ // the next video frame, currentTime can be up to 1 frame's worth earlier than
+ // min(audioEnd, videoEnd).
+ // 0.0465 is the length of the last audio frame.
+ ok(el.currentTime >= (sb.buffered.end(0) - 0.0465),
+ `Got a waiting event at ${el.currentTime}`);
+ info("Loading more data");
+ p = once(el, "ended");
+ await loadSegment(sb, new Uint8Array(arrayBuffer, 46712, 67833 - 46712));
+ ms.endOfStream();
+ await p;
+ // These fuzz factors are bigger than they should be. We should investigate
+ // and fix them in bug 1137574.
+ isfuzzy(el.duration, 4.001, 0.1, "Video has correct duration: " + el.duration);
+ isfuzzy(el.currentTime, el.duration, 0.1, "Video has correct currentTime.");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_WaitingOnMissingDataEnded_mp4.html b/dom/media/mediasource/test/test_WaitingOnMissingDataEnded_mp4.html
new file mode 100644
index 0000000000..8ca61eae7e
--- /dev/null
+++ b/dom/media/mediasource/test/test_WaitingOnMissingDataEnded_mp4.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: |waiting| event when source data is missing</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ el.addEventListener("ended", () => {
+ ok(false, "ended should never fire");
+ SimpleTest.finish();
+ });
+ const videosb = ms.addSourceBuffer("video/mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 5), ".m4s");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(6, 8), ".m4s");
+ is(el.buffered.length, 2, "discontinuous buffered range");
+ ms.endOfStream();
+ await Promise.all([once(el, "durationchange"), once(ms, "sourceended")]);
+ // HTMLMediaElement fires "waiting" if somebody invokes |play()| before the MDSM
+ // has notified it of available data. Make sure that we get "playing" before
+ // we starting waiting for "waiting".
+ info("Invoking play()");
+ el.play();
+ await once(el, "playing");
+ ok(true, "Video playing. It should play for a bit, then fire 'waiting'");
+ await once(el, "waiting");
+ // waiting is fired when we start to play the last frame.
+ // 0.033334 is the duration of the last frame, + 0.000001 of fuzz.
+ // the next video frame, currentTime can be up to 1 frame's worth earlier than end of video.
+ isfuzzy(el.currentTime, videosb.buffered.end(0), 0.033334, "waiting was fired on gap");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html b/dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html
new file mode 100644
index 0000000000..f6768754e7
--- /dev/null
+++ b/dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: |waiting| event when source data is missing</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 5), ".m4s");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(6, 12), ".m4s");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 6), ".m4s");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(7, 14), ".m4s");
+ // HTMLMediaElement fires "waiting" if somebody invokes |play()| before the MDSM
+ // has notified it of available data. Make sure that we get "playing" before
+ // we starting waiting for "waiting".
+ info("Invoking play()");
+ let p = once(el, "playing");
+ el.play();
+ await p;
+ ok(true, "Video playing. It should play for a bit, then fire 'waiting'");
+ p = once(el, "waiting");
+ el.play();
+ await p;
+ // currentTime is based on the current video frame, so if the audio ends just before
+ // the next video frame, currentTime can be up to 1 frame's worth earlier than
+ // min(audioEnd, videoEnd).
+ // 0.0465 is the length of the last audio frame.
+ ok(el.currentTime >= (Math.min(audiosb.buffered.end(0), videosb.buffered.end(0)) - 0.0465),
+ `Got a waiting event at ${el.currentTime}`);
+ info("Loading more data");
+ p = once(el, "ended");
+ await Promise.all([
+ fetchAndLoad(audiosb, "bipbop/bipbop_audio", [5], ".m4s"),
+ fetchAndLoad(videosb, "bipbop/bipbop_video", [6], ".m4s"),
+ ]);
+ ms.endOfStream();
+ await p;
+ // These fuzz factors are bigger than they should be. We should investigate
+ // and fix them in bug 1137574.
+ isfuzzy(el.duration, 10.1, 0.1, "Video has correct duration: " + el.duration);
+ isfuzzy(el.currentTime, el.duration, 0.1, "Video has correct currentTime.");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html b/dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html
new file mode 100644
index 0000000000..9c3fc73161
--- /dev/null
+++ b/dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+ <title>MSE: |waiting| event when source data is missing</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test"><script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ const videosb = ms.addSourceBuffer("video/mp4");
+ // ensure tracks end at approximately the same time to ensure ended event is
+ // always fired (bug 1233639).
+ audiosb.appendWindowEnd = 3.9;
+ videosb.appendWindowEnd = 3.9;
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", ["init"], ".mp4");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", ["init"], ".mp4");
+ await fetchAndLoad(audiosb, "bipbop/bipbop_audio", range(1, 5), ".m4s");
+ await fetchAndLoad(videosb, "bipbop/bipbop_video", range(1, 6), ".m4s");
+ // HTMLMediaElement fires "waiting" if somebody invokes |play()| before the MDSM
+ // has notified it of available data. Make sure that we get "playing" before
+ // we starting waiting for "waiting".
+ info("Invoking play()");
+ let p = once(el, "playing");
+ el.play();
+ await p;
+ ok(true, "Video playing. It should play for a bit, then fire 'waiting'");
+ await once(el, "waiting");
+ p = once(el, "ended");
+ ms.endOfStream();
+ await p;
+ // Following bug 1524890, we now implement fully step 8 of the coded frame
+ // processing algorithm
+ // http://w3c.github.io/media-source/index.html#sourcebuffer-coded-frame-processing
+ // As such, duration is exactly the value of videosb.appendWindowEnd
+ is(el.duration, videosb.appendWindowEnd, "Video has correct duration: " + el.duration);
+ is(el.currentTime, el.duration, "Video has correct currentTime.");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_WebMTagsBeforeCluster.html b/dom/media/mediasource/test/test_WebMTagsBeforeCluster.html
new file mode 100644
index 0000000000..d1d45173cd
--- /dev/null
+++ b/dom/media/mediasource/test/test_WebMTagsBeforeCluster.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: WebM tags element before cluster element</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+addMSEPrefs(["media.mediasource.webm.enabled", true]);
+
+runWithMSE(async (ms, v) => {
+ await once(ms, "sourceopen");
+ const sb = ms.addSourceBuffer("video/webm");
+
+ const arrayBuffer = await fetchWithXHR("tags_before_cluster.webm");
+ info("- append buffer -");
+ sb.appendBuffer(new Uint8Array(arrayBuffer));
+
+ info("- wait for metadata -");
+ await once(v, "loadedmetadata");
+
+ info("- wait for updateend -");
+ await once(sb, "updateend");
+
+ info("- call end of stream -");
+ ms.endOfStream();
+ await once(ms, "sourceended");
+
+ info("- check buffered range -");
+ is(sb.buffered.length, 1, "buffered range is not empty.");
+
+ info("- video is playing -");
+ v.play();
+ await once(v, "timeupdate");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/test_trackidchange_mp4.html b/dom/media/mediasource/test/test_trackidchange_mp4.html
new file mode 100644
index 0000000000..fdbeece3cd
--- /dev/null
+++ b/dom/media/mediasource/test/test_trackidchange_mp4.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>MSE: test append of audio with similar init segments that have different track ids</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="mediasource.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+runWithMSE(async (ms, el) => {
+ el.controls = true;
+ await once(ms, "sourceopen");
+ ok(true, "Receive a sourceopen event");
+ const audiosb = ms.addSourceBuffer("audio/mp4");
+ await fetchAndLoad(audiosb, "init-trackid2", [''], ".mp4");
+ await fetchAndLoad(audiosb, "segment-2.0001", [''], ".m4s");
+ await fetchAndLoad(audiosb, "init-trackid3", [''], ".mp4");
+ await fetchAndLoad(audiosb, "segment-3.0002", [''], ".m4s");
+ is(el.buffered.length, 1, "data is buffered");
+ is(el.buffered.end(0), 8, "all data got appended");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/mediasource/test/whitenoise-he-aac-5s.mp4 b/dom/media/mediasource/test/whitenoise-he-aac-5s.mp4
new file mode 100644
index 0000000000..db648b8229
--- /dev/null
+++ b/dom/media/mediasource/test/whitenoise-he-aac-5s.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/wmf_mismatchedaudiotime.mp4 b/dom/media/mediasource/test/wmf_mismatchedaudiotime.mp4
new file mode 100644
index 0000000000..9e179bd326
--- /dev/null
+++ b/dom/media/mediasource/test/wmf_mismatchedaudiotime.mp4
Binary files differ