diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /dom/media/mediasource/test | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/media/mediasource/test')
168 files changed, 3893 insertions, 0 deletions
diff --git a/dom/media/mediasource/test/aac20-48000-64000-1.m4s b/dom/media/mediasource/test/aac20-48000-64000-1.m4s Binary files differnew file mode 100644 index 000000000..56506e1f2 --- /dev/null +++ b/dom/media/mediasource/test/aac20-48000-64000-1.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..3faff17eb --- /dev/null +++ b/dom/media/mediasource/test/aac20-48000-64000-2.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..b70e01651 --- /dev/null +++ b/dom/media/mediasource/test/aac20-48000-64000-init.mp4 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..3424acfec --- /dev/null +++ b/dom/media/mediasource/test/aac51-48000-128000-1.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..b02bfd043 --- /dev/null +++ b/dom/media/mediasource/test/aac51-48000-128000-2.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..7d62401f2 --- /dev/null +++ b/dom/media/mediasource/test/aac51-48000-128000-init.mp4 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 000000000..4030ea1d3 --- /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/bipbop/bipbop1.m4s b/dom/media/mediasource/test/bipbop/bipbop1.m4s Binary files differnew file mode 100644 index 000000000..a237f2e91 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop1.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..d1f5e6a0b --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop10.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..57232fb35 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop11.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..f9b18713e --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop12.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..f2a876946 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop13.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..baa0d8578 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop2.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..4fd8b9cb6 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop2s.mp4 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..ed313e668 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop3.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..7709ac08c --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop4.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..6d36788e4 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop5.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..64f475c70 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop6.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..c148918d6 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop7.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..707dd4848 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop8.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..538cf72a4 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop9.m4s 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 000000000..4030ea1d3 --- /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_480_624kbps-video1.m4s b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s Binary files differnew file mode 100755 index 000000000..3dad336e8 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100755 index 000000000..dd7491241 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100755 index 000000000..b1a2d4405 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..33da98b5a --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..36a98afd2 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..23d4aa8d8 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..96f4bcc34 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..7de4bd0ca --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..494c71eb9 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..b50496b6c --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..02cf4d363 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..bb2252889 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..04a6a7af9 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..cb94b529a --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..bbf272197 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4 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 000000000..4030ea1d3 --- /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 000000000..532cdc65d --- /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_video1.m4s b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s Binary files differnew file mode 100644 index 000000000..929118251 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..72c7afaca --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video10.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..e6109f5e7 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video11.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..5c54a510f --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video12.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..c64f38a33 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video13.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..cd34fae56 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video2.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..5a1334004 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video3.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..e8d96b6ed --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video4.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..ca6a82046 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video5.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..fe9824355 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video6.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..3351fa685 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video7.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..af26ae5f9 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video8.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..25be672c1 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_video9.m4s 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..7c9c533c3 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4 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 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..39f0575a7 --- /dev/null +++ b/dom/media/mediasource/test/bipbop/bipbopinit.mp4 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 000000000..4030ea1d3 --- /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/crashtests/1005366.html b/dom/media/mediasource/test/crashtests/1005366.html new file mode 100644 index 000000000..aa8b7f652 --- /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 000000000..9dfda34b8 --- /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 000000000..a8247b27e --- /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;version=1.7">
+
+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 000000000..cdb5bd9ad --- /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 000000000..e16ec261d --- /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/mediasource.js b/dom/media/mediasource/test/mediasource.js new file mode 100644 index 000000000..6a464096a --- /dev/null +++ b/dom/media/mediasource/test/mediasource.js @@ -0,0 +1,130 @@ +// Helpers for Media Source Extensions tests + +function runWithMSE(testFunction) { + function bootstrapTest() { + var ms = new MediaSource(); + + var el = document.createElement("video"); + el.src = URL.createObjectURL(ms); + el.preload = "auto"; + + document.body.appendChild(el); + SimpleTest.registerCleanupFunction(function () { + el.parentNode.removeChild(el); + }); + + testFunction(ms, el); + } + + addLoadEvent(function () { + SpecialPowers.pushPrefEnv({"set": [ + [ "media.mediasource.enabled", true ], + ]}, + bootstrapTest); + }); +} + +function fetchWithXHR(uri, onLoadFunction) { + var p = new Promise(function(resolve, reject) { + var 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(); + }); + + if (onLoadFunction) { + p.then(onLoadFunction); + } + + return p; +}; + +function range(start, end) { + var rv = []; + for (var i = start; i < end; ++i) { + rv.push(i); + } + return rv; +} + +function once(target, name, cb) { + var p = new Promise(function(resolve, reject) { + target.addEventListener(name, function onceEvent() { + target.removeEventListener(name, onceEvent); + resolve(); + }); + }); + if (cb) { + p.then(cb); + } + return p; +} + +function timeRangeToString(r) { + var str = "TimeRanges: "; + for (var i = 0; i < r.length; i++) { + str += "[" + r.start(i) + ", " + r.end(i) + ")"; + } + return str; +} + +function loadSegment(sb, typedArrayOrArrayBuffer) { + var typedArray = (typedArrayOrArrayBuffer instanceof ArrayBuffer) ? new Uint8Array(typedArrayOrArrayBuffer) + : typedArrayOrArrayBuffer; + info(`Loading buffer: [${typedArray.byteOffset}, ${typedArray.byteOffset + typedArray.byteLength})`); + var beforeBuffered = timeRangeToString(sb.buffered); + return new Promise(function(resolve, reject) { + once(sb, 'update').then(function() { + var afterBuffered = timeRangeToString(sb.buffered); + info(`SourceBuffer buffered ranges grew from ${beforeBuffered} to ${afterBuffered}`); + resolve(); + }); + sb.appendBuffer(typedArray); + }); +} + +function fetchAndLoad(sb, prefix, chunks, suffix) { + + // Fetch the buffers in parallel. + var buffers = {}; + var fetches = []; + for (var 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() { + var rv = Promise.resolve(); + for (var chunk of chunks) { + rv = rv.then(loadSegment.bind(null, sb, buffers[chunk])); + } + return rv; + }); +} + +//Register timeout function to dump debugging logs. +SimpleTest.registerTimeoutFunction(function() { + for (var v of document.getElementsByTagName("video")) { + v.mozDumpDebugInfo(); + } + for (var a of document.getElementsByTagName("audio")) { + a.mozDumpDebugInfo(); + } +}); + +function waitUntilTime(target, targetTime) { + return new Promise(function(resolve, reject) { + target.addEventListener("waiting", function onwaiting() { + info("Got a waiting event at " + target.currentTime); + if (target.currentTime >= targetTime) { + ok(true, "Reached target time of: " + targetTime); + target.removeEventListener("waiting", onwaiting); + resolve(); + } + }); + }); +} diff --git a/dom/media/mediasource/test/mochitest.ini b/dom/media/mediasource/test/mochitest.ini new file mode 100644 index 000000000..89ed35382 --- /dev/null +++ b/dom/media/mediasource/test/mochitest.ini @@ -0,0 +1,137 @@ +[DEFAULT] +subsuite = media +support-files = + mediasource.js + seek.webm seek.webm^headers^ + seek_lowres.webm seek_lowres.webm^headers^ + bipbop/bipbop2s.mp4 bipbop/bipbop2s.mp4^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^ + 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^ + +[test_AudioChange_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_AutoRevocation.html] +tags = firstpartyisolation +[test_BufferedSeek.html] +[test_BufferedSeek_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_BufferingWait.html] +skip-if = toolkit == 'android' #timeout android bug 1199531 +[test_BufferingWait_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_DrainOnMissingData_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_DurationChange.html] +[test_DurationUpdated.html] +[test_DurationUpdated_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_EndOfStream.html] +[test_EndOfStream_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_Eviction_mp4.html] +skip-if = (os == "win" && os_version == "5.1") # Not supported on xp. +[test_FrameSelection.html] +[test_FrameSelection_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_HaveMetadataUnbufferedSeek.html] +[test_HaveMetadataUnbufferedSeek_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_LiveSeekable.html] +[test_LoadedDataFired_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_LoadedMetadataFired.html] +[test_LoadedMetadataFired_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_MediaSource.html] +[test_MediaSource_memory_reporting.html] +[test_MediaSource_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_MediaSource_disabled.html] +[test_MultipleInitSegments.html] +[test_MultipleInitSegments_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_OnEvents.html] +[test_PlayEvents.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_ResumeAfterClearing_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekableAfterEndOfStream.html] +[test_SeekableAfterEndOfStream_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekableAfterEndOfStreamSplit.html] +[test_SeekableAfterEndOfStreamSplit_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekableBeforeEndOfStream.html] +[test_SeekableBeforeEndOfStream_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekableBeforeEndOfStreamSplit.html] +[test_SeekableBeforeEndOfStreamSplit_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekNoData_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekedEvent_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekToEnd_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SeekTwice_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_Sequence_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SetModeThrows.html] +[test_SplitAppendDelay.html] +[test_SplitAppendDelay_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_SplitAppend.html] +[test_SplitAppend_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_Threshold_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_TimestampOffset_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_TruncatedDuration.html] +[test_TruncatedDuration_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_WaitingOnMissingData.html] +skip-if = (toolkit == 'android') #timeout android only bug 1101187 +[test_WaitingOnMissingData_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_WaitingOnMissingDataEnded_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 +[test_WaitingToEndedTransition_mp4.html] +skip-if = ((os == "win" && os_version == "5.1") || (toolkit == 'android')) # Not supported on xp and android 2.3 + diff --git a/dom/media/mediasource/test/seek.webm b/dom/media/mediasource/test/seek.webm Binary files differnew file mode 100644 index 000000000..72b029723 --- /dev/null +++ b/dom/media/mediasource/test/seek.webm diff --git a/dom/media/mediasource/test/seek.webm^headers^ b/dom/media/mediasource/test/seek.webm^headers^ new file mode 100644 index 000000000..4030ea1d3 --- /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 Binary files differnew file mode 100644 index 000000000..8a76e0647 --- /dev/null +++ b/dom/media/mediasource/test/seek_lowres.webm 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 000000000..4030ea1d3 --- /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/test_AudioChange_mp4.html b/dom/media/mediasource/test/test_AudioChange_mp4.html new file mode 100644 index 000000000..95f48cadf --- /dev/null +++ b/dom/media/mediasource/test/test_AudioChange_mp4.html @@ -0,0 +1,72 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: basic functionality</title> + <script type="text/javascript" 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(function(ms, el) { + el.controls = true; + once(ms, 'sourceopen').then(function() { + // Log events for debugging. + var events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata", + "loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort", + "waiting", "pause", "durationchange", "seeking", "seeked"]; + function logEvent(e) { + var v = e.target; + info("got " + e.type + " event"); + } + events.forEach(function(e) { + el.addEventListener(e, logEvent, false); + }); + + ok(true, "Receive a sourceopen event"); + var audiosb = ms.addSourceBuffer("audio/mp4"); + el.addEventListener("error", function(e) { + ok(false, "should not fire '" + e.type + "' event"); + SimpleTest.finish(); + }); + is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING"); + fetchAndLoad(audiosb, 'aac20-48000-64000-', ['init'], '.mp4') + .then(once.bind(null, el, 'loadedmetadata')) + .then(function() { + ok(true, "got loadedmetadata event"); + var promises = []; + promises.push(once(el, 'loadeddata')); + promises.push(once(el, 'canplay')); + promises.push(fetchAndLoad(audiosb, 'aac20-48000-64000-', ['1'], '.m4s')); + return Promise.all(promises); + }) + .then(function() { + ok(true, "got canplay event"); + el.play(); + return fetchAndLoad(audiosb, 'aac51-48000-128000-', ['init'], '.mp4'); + }) + .then(fetchAndLoad.bind(null, audiosb, 'aac51-48000-128000-', ['2'], '.m4s')) + .then(function() { + var promises = []; + ms.endOfStream(); + promises.push(once(el, 'ended')); + promises.push(once(audiosb, 'updateend')); + return Promise.all(promises); + }) + .then(function() { + 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 000000000..15474367e --- /dev/null +++ b/dom/media/mediasource/test/test_AutoRevocation.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: auto-revocation</title> + <script type="text/javascript" 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 () { + var ms = new MediaSource(); + var o = URL.createObjectURL(ms); + var v = document.createElement("video"); + + v.addEventListener("error", function (e) { + ok(true, "ObjectURL should be auto-revoked"); + SimpleTest.finish(); + }); + + v.addEventListener("stalled", function (e) { + 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 000000000..949fee773 --- /dev/null +++ b/dom/media/mediasource/test/test_BufferedSeek.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seeking in buffered range</title> + <script type="text/javascript" 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(); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + sb.addEventListener("updateend", function () { + 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(); + }; + }); + }); + + var target = 2; + + v.addEventListener("loadedmetadata", function () { + if (v.currentTime != target && + v.buffered.length && + target >= v.buffered.start(0) && + target < v.buffered.end(0)) { + v.currentTime = target; + } + }); + + var wasSeeking = false; + + v.addEventListener("seeking", function () { + wasSeeking = true; + is(v.currentTime, target, "Video currentTime at target"); + }); + + v.addEventListener("seeked", function () { + 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 000000000..7c5d992f3 --- /dev/null +++ b/dom/media/mediasource/test/test_BufferedSeek_mp4.html @@ -0,0 +1,63 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seeking in buffered range</title> + <script type="text/javascript" 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(); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + sb.addEventListener("updateend", function () { + 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(); + }; + }); + }); + + var target = 1.3; + + v.addEventListener("loadedmetadata", function () { + if (v.currentTime != target && + v.buffered.length && + target >= v.buffered.start(0) && + target < v.buffered.end(0)) { + v.currentTime = target; + } + }); + + var wasSeeking = false; + + v.addEventListener("seeking", function () { + wasSeeking = true; + is(v.currentTime, target, "Video currentTime at target"); + }); + + v.addEventListener("seeked", function () { + 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 000000000..8d45132b4 --- /dev/null +++ b/dom/media/mediasource/test/test_BufferingWait.html @@ -0,0 +1,56 @@ +<!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 type="text/javascript" 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(); + +var receivedSourceOpen = false; +runWithMSE(function(ms, v) { + ms.addEventListener("sourceopen", function() { + ok(true, "Receive a sourceopen event"); + ok(!receivedSourceOpen, "Should only receive one sourceopen for this test"); + receivedSourceOpen = true; + var sb = ms.addSourceBuffer("video/webm"); + ok(sb, "Create a SourceBuffer"); + + fetchWithXHR("seek.webm", function(arrayBuffer) { + sb.addEventListener('error', (e) => { ok(false, "Got Error: " + e); SimpleTest.finish(); }); + loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 0, 318))().then( + loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 318, 25523-318))).then( + loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 25523, 46712-25523))).then( + /* 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] */ + loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 88966))).then(function() { + // 0.767 is the time of the last video sample +- 40ms. + var promise = waitUntilTime(v, .767-0.04); + info("Playing video. It should play for a bit, then fire 'waiting'"); + v.play(); + return promise; + }).then(function() { + window.firstStop = Date.now(); + loadSegment(sb, new Uint8Array(arrayBuffer, 46712, 67833 - 46712)); + return waitUntilTime(v, 1.167-0.04); + }).then(function() { + var waitDuration = (Date.now() - window.firstStop) / 1000; + ok(waitDuration < 15, "Should not spend an 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. + once(v, 'ended', SimpleTest.finish.bind(SimpleTest)); + return 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 000000000..cb262b525 --- /dev/null +++ b/dom/media/mediasource/test/test_BufferingWait_mp4.html @@ -0,0 +1,54 @@ +<!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 type="text/javascript" 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(); + +var receivedSourceOpen = false; +runWithMSE(function(ms, v) { + ms.addEventListener("sourceopen", function() { + ok(true, "Receive a sourceopen event"); + ok(!receivedSourceOpen, "Should only receive one sourceopen for this test"); + receivedSourceOpen = true; + var sb = ms.addSourceBuffer("video/mp4"); + ok(sb, "Create a SourceBuffer"); + + sb.addEventListener('error', (e) => { ok(false, "Got Error: " + e); SimpleTest.finish(); }); + fetchAndLoad(sb, 'bipbop/bipbop', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop', ['1'], '.m4s')) + .then(fetchAndLoad.bind(null, 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] */ + .then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop', ['5'], '.m4s')) + .then(function() { + // last audio sample has a start time of 1.578956s + var promise = waitUntilTime(v, 1.57895); + info("Playing video. It should play for a bit, then fire 'waiting'"); + v.play(); + return promise; + }).then(function() { + window.firstStop = Date.now(); + fetchAndLoad(sb, 'bipbop/bipbop', ['3'], '.m4s'); + // last audio sample has a start time of 2.368435 + return waitUntilTime(v, 2.36843); + }).then(function() { + var waitDuration = (Date.now() - window.firstStop) / 1000; + ok(waitDuration < 15, "Should not spend an inordinate amount of time buffering: " + waitDuration); + once(v, 'ended', SimpleTest.finish.bind(SimpleTest)); + return fetchAndLoad(sb, 'bipbop/bipbop', ['4'], '.m4s'); + }).then(function() { + ms.endOfStream(); + });; + }); +}); +</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 000000000..f2284377f --- /dev/null +++ b/dom/media/mediasource/test/test_DrainOnMissingData_mp4.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 type="text/javascript" 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() { + ok(true, "Receive a sourceopen event"); + var videosb = ms.addSourceBuffer("video/mp4"); + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(function() { + // 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; + return fetchAndLoad(videosb, 'bipbop/bipbop_video', ['1'], '.m4s'); + }) + .then(function() { + info("Invoking play()"); + var promises = []; + promises.push(once(el, 'playing')); + el.play(); + return Promise.all(promises); + }) + .then(function() { + info("got playing"); + return once(el, 'waiting'); + }).then(function() { + 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; + var p = once(el, 'ended'); + var loads = fetchAndLoad(videosb, 'bipbop/bipbop_video', [1], '.m4s'); + loads.then(() => ms.endOfStream()); + return p; + }).then(function() { + // 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 000000000..58c58be15 --- /dev/null +++ b/dom/media/mediasource/test/test_DurationChange.html @@ -0,0 +1,111 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: check that duration change behaves properly</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); + once(v, "loadedmetadata") + .then(function() { + is(v.duration, ms.duration, "video duration is mediasource one"); + try { + ms.duration = 0; + } catch (e) { ok(false, "must not throw as operation is valid"); } + is(v.duration, 0, "reducing duration with no data buffered is valid"); + sb.appendBuffer(new Uint8Array(arrayBuffer, 318)); + // Adding more data will fire durationchange. + once(sb, "updateend") + .then(function() { + 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"); + var error = false; + try { + ms.duration = 0; + } catch (e) { + ok(true, "must use remove for range removal"); + is(e.name, "InvalidStateError", "Error is InvalidStateError"); + error = true; + } + ok(error, "got an error"); + ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration"); + try { + ms.duration = 10; + } catch (e) { ok(false, "must not throw as 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). + try { + ms.duration = 3.967000; + } catch (e) { ok(false, "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 "); + try { + ms.duration = 3.97; + } catch (e) { ok(false, "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 "); + error = false; + try { + ms.duration = 3.96; + } catch (e) { + ok(true, "setting duration with < highest frame presentation time is not valid"); + is(e.name, "InvalidStateError", "Error is InvalidStateError"); + error = true; + } + ok(error, "got an error"); + is(v.duration, sb.buffered.end(0), "duration is the highest end time reported by the buffered attribute "); + error = false; + try { + ms.duration = -1; + } catch (e) { + ok(true, "can't set a negative duration"); + is(e.name, "TypeError", "Error is TypeError"); + error = true; + } + ok(error, "got an error"); + sb.remove(sb.buffered.end(0), Infinity); + is(sb.updating, true, "updating is true") + error = false; + try { + ms.duration = Infinity; + } catch (e) { + ok(true, "setting the duration while updating is not allowed"); + is(e.name, "InvalidStateError", "Error is InvalidStateError"); + error = true; + } + ok(error, "got an error"); + error = false; + try { + sb.abort(); + } catch (e) { + ok(true, "Can't use abort while range removal is in progress"); + is(e.name, "InvalidStateError", "Error is InvalidStateError"); + error = true; + } + ok(error, "got an error"); + is(v.duration, sb.buffered.end(0), "duration is the highest end time reported by the buffered attribute "); + once(sb, "updateend", () => ms.endOfStream()); + }); + }); + }); + }); + ms.addEventListener("sourceended", function () { + 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 000000000..0ee6a5459 --- /dev/null +++ b/dom/media/mediasource/test/test_DurationUpdated.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append data and check that mediasource duration got updated</title> + <script type="text/javascript" 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(); + +var durationChangeCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + v.addEventListener("durationchange", function () { + durationChangeCount++; + }); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); + // Adding the first init segment will fire a durationchange. + once(v, "loadedmetadata") + .then(function() { + 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. + once(sb, "updateend") + .then(function() { + ok(true, "got updateend"); + // this will not fire durationchange as new duration == old duration + ms.endOfStream(); + }); + }); + }); + }); + ms.addEventListener("sourceended", function () { + 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 000000000..da14267eb --- /dev/null +++ b/dom/media/mediasource/test/test_DurationUpdated_mp4.html @@ -0,0 +1,56 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append data and check that mediasource duration got updated</title> + <script type="text/javascript" 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(); + +var durationChangeCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + v.addEventListener("durationchange", function () { + durationChangeCount++; + }); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 1395)); + // Adding the first init segment will fire a durationchange. + once(v, "loadedmetadata") + .then(function() { + 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. + once(sb, "updateend") + .then(function() { + ok(true, "got updateend"); + // this will not fire durationchange as new duration == old duration + ms.endOfStream(); + }); + }); + }); + }); + ms.addEventListener("sourceended", function () { + 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 000000000..655d21cd3 --- /dev/null +++ b/dom/media/mediasource/test/test_EndOfStream.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: endOfStream call after an appendBuffer</title> + <script type="text/javascript" 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 () { + var ms = new MediaSource(); + + var v = document.createElement("video"); + v.src = URL.createObjectURL(ms); + document.body.appendChild(v); + + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 88966)); + var count = 0; + sb.addEventListener("updateend", function () { + ++count; + if (count == 1) { + setTimeout(function() { + var fail = false; + try { + ms.endOfStream(); + } catch (e) { + fail = true; + } + ok(!fail, "MediaSource.endOfStream succeeded"); + SimpleTest.finish(); + }, 0); + } + }); + }); + }); +}); + +</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 000000000..1f703f2b6 --- /dev/null +++ b/dom/media/mediasource/test/test_EndOfStream_mp4.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: endOfStream call after an appendBuffer</title> + <script type="text/javascript" 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 () { + var ms = new MediaSource(); + + var v = document.createElement("video"); + v.src = URL.createObjectURL(ms); + document.body.appendChild(v); + + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + var count = 0; + sb.addEventListener("updateend", function () { + ++count; + if (count == 1) { + setTimeout(function() { + var fail = false; + try { + ms.endOfStream(); + } catch (e) { + fail = true; + } + ok(!fail, "MediaSource.endOfStream succeeded"); + SimpleTest.finish(); + }, 0); + } + }); + }); + }); +}); + +</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 000000000..c702cc3bb --- /dev/null +++ b/dom/media/mediasource/test/test_Eviction_mp4.html @@ -0,0 +1,82 @@ +<!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 type="text/javascript" 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) + +// Fill up the SourceBuffer by appending data repeatedly via doAppendDataFunc until +// an exception is thrown. +function fillUpSourceBuffer(sourceBuffer, doAppendDataFunc, onCaughtExceptionCallback) { + // We are appending data repeatedly in sequence mode, there should be no gaps. + ok(sourceBuffer.buffered.length <= 1, "there should be no gap in buffered ranges."); + try { + doAppendDataFunc(); + } catch(ex) { + onCaughtExceptionCallback(ex); + return; + } + once(sourceBuffer, 'updateend', () => { + fillUpSourceBuffer(sourceBuffer, doAppendDataFunc, onCaughtExceptionCallback); + }); +} + +runWithMSE(function(ms, el) { + el.controls = true; + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + SpecialPowers.pushPrefEnv({ + "set": [ + ["media.mediasource.eviction_threshold.audio", 524288], + ] + }, function() { + let audiosb = ms.addSourceBuffer("audio/mp4"); + audiosb.mode = "sequence"; + fetchAndLoad(audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4') + .then(function() { + fetchWithXHR('bipbop/bipbop_audio1.m4s', function(audioBuffer) { + fillUpSourceBuffer(audiosb, + function() { // doAppendDataFunc + audiosb.appendBuffer(audioBuffer); + }, + function(ex) { // onCaughtExceptionCallback + is(ex.name, 'QuotaExceededError', "QuotaExceededError thrown"); + is(audiosb.buffered.end(0), el.duration, "Duration is end of buffered range"); + let seekTime = audiosb.buffered.end(0) / 2; + el.currentTime = seekTime; + once(el, 'seeked', () => { + is(el.currentTime, seekTime, "correctly seeked to " + seekTime); + try { + audiosb.appendBuffer(audioBuffer); + } catch(ex) { + ok(false, "Shouldn't throw another time when data can be evicted"); + el.mozDumpDebugInfo(); + SimpleTest.finish(); + return; + } + once(audiosb, 'update', () => { + ok(true, "appendBuffer succeeded"); + SimpleTest.finish(); + }); + }); + }); + }); + }); + }); + }); +}); + +</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 000000000..f9190af9c --- /dev/null +++ b/dom/media/mediasource/test/test_FrameSelection.html @@ -0,0 +1,78 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: verify correct frames selected for given position</title> + <script type="text/javascript" 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(); + +var updateCount = 0; + + var targets = [{ currentTime: 3, videoWidth: 160, videoHeight: 120 }, + { currentTime: 2, videoWidth: 160, videoHeight: 120 }, + { currentTime: 0, videoWidth: 320, videoHeight: 240 }]; + var target; + +var lowResBuffer; +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm") + .then(function (arrayBuffer) { + var p = once(v, 'loadedmetadata'); + // Append entire file covering range [0, 4]. + sb.appendBuffer(new Uint8Array(arrayBuffer)); + return p; + }).then(function() { + 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"); + return fetchWithXHR("seek_lowres.webm"); + }).then(function (arrayBuffer) { + // Append initialization segment. + var p = once(sb, 'updateend'); + info("Appending low-res init segment"); + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 438)); + lowResBuffer = arrayBuffer; + return p; + }).then(function() { + var p = once(sb, 'updateend'); + info("Appending low-res range [2,4]"); + // Append media segment covering range [2, 4]. + sb.appendBuffer(new Uint8Array(lowResBuffer, 51003)); + return p; + }).then(function() { + ms.endOfStream(); + var p = Promise.all([once(v, 'seeked'), once(v, 'resize')]); + info("Seeking to t=3"); + v.currentTime = 3; + return p; + }).then(function() { + 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"); + + var p = Promise.all([once(v, 'seeked'), once(v, 'resize')]); + info("Seeking to t=1"); + v.currentTime = 1; + return p; + }).then(function() { + 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 000000000..a5b8fa290 --- /dev/null +++ b/dom/media/mediasource/test/test_FrameSelection_mp4.html @@ -0,0 +1,73 @@ +<!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 type="text/javascript" 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. + +var receivedSourceOpen = false; +runWithMSE(function(ms, v) { + ms.addEventListener("sourceopen", function() { + ok(true, "Receive a sourceopen event"); + ok(!receivedSourceOpen, "Should only receive one sourceopen for this test"); + receivedSourceOpen = true; + var sb = ms.addSourceBuffer("video/mp4"); + ok(sb, "Create a SourceBuffer"); + + // Log events for debugging. + var events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata", + "loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort", + "waiting", "pause", "durationchange", "seeking", "seeked"]; + function logEvent(e) { + var v = e.target; + info("got " + e.type + " event"); + } + events.forEach(function(e) { + v.addEventListener(e, logEvent, false); + }); + + sb.addEventListener('error', (e) => { ok(false, "Got Error: " + e); SimpleTest.finish(); }); + fetchAndLoad(sb, 'bipbop/bipbop', ['init'], '.mp4') + .then(function() { + var promises = []; + promises.push(fetchAndLoad(sb, 'bipbop/bipbop', range(1,3), '.m4s')); + promises.push(once(v, "loadeddata")); + return Promise.all(promises); + }).then(function() { + is(sb.buffered.length, 1, "continuous range"); + v.play(); + // We have nothing to play, waiting will be fired. + return waitUntilTime(v, 1.5); + }).then(function() { + return fetchAndLoad(sb, 'bipbop/bipbop_480_624kbps-video', ['init'], '.mp4'); + }).then(function() { + 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). + return fetchAndLoad(sb, 'bipbop/bipbop_480_624kbps-video', ['1'], '.m4s'); + }).then(function() { + ms.endOfStream(); + var promises = []; + promises.push(once(ms, "sourceended")); + promises.push(once(v, "playing")); + promises.push(once(v, "ended")); + return Promise.all(promises); + }).then(function() { + if(v.width, 640, "has proper width"); + if(v.height, 480, "has proper height"); + 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 000000000..f6192074a --- /dev/null +++ b/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute before end of stream</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 67833)); + }); + + var target = 2; + + v.addEventListener("loadeddata", function onloadeddata() { + v.removeEventListener("loadeddata", onloadeddata); + ok(v.readyState >= v.HAVE_CURRENT_DATA, "readyState is >= CURRENT_DATA"); + v.currentTime = target; + }); + + v.addEventListener("seeking", function () { + is(v.readyState, v.HAVE_METADATA, "readyState is HAVE_METADATA"); + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 67833)); + }); + }); + + v.addEventListener("seeked", function () { + 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 000000000..fc3ef06eb --- /dev/null +++ b/dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek_mp4.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute before end of stream</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + // 25819 is the offset of the first media segment's end + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25819)); + }); + + var target = 1.3; + + v.addEventListener("loadeddata", function onloadeddata() { + v.removeEventListener("loadeddata", onloadeddata); + ok(v.readyState >= v.HAVE_CURRENT_DATA, "readyState is >= CURRENT_DATA"); + v.currentTime = target; + }); + + v.addEventListener("seeking", function () { + is(v.readyState, v.HAVE_METADATA, "readyState is HAVE_METADATA"); + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + // 25819 is the offset of the first media segment's end + sb.addEventListener("updateend", function () { + ms.endOfStream(); + }); + sb.appendBuffer(new Uint8Array(arrayBuffer, 25819)); + }); + }); + + v.addEventListener("seeked", function () { + 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 000000000..6abc42450 --- /dev/null +++ b/dom/media/mediasource/test/test_LiveSeekable.html @@ -0,0 +1,80 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: live seekable range</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var 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; + var promises = []; + promises.push(fetchAndLoad(sb, 'seek', [''], '.webm')); + promises.push(once(v, "loadedmetadata")); + Promise.all(promises) + .then(function() { + 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(); + ok(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"); + + try { + ms.setLiveSeekableRange(2, 0); + ok(false, "start > end"); + } catch (e) { ok(true, "must thow if start > end"); } + + 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 000000000..9b15c8063 --- /dev/null +++ b/dom/media/mediasource/test/test_LoadedDataFired_mp4.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: Check that playback only starts once we have data at time = 0</title> + <script type="text/javascript" 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; + el.addEventListener("loadeddata", function() { + ok(el.buffered.length > 0, "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", function() { + ok(el.buffered.length > 0, "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"); + }); + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var videosb = ms.addSourceBuffer("video/mp4"); + is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING"); + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(once.bind(null, el, "loadedmetadata")) + .then(function() { + 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. + return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 8), '.m4s'); + }) + .then(function() { + 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(); + return once(el, "play"); + }) + .then(function() { + videosb.appendWindowStart = 0; + var promises = []; + // Load [0, 3.971666). + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 8), '.m4s')); + // playback can only start now. + promises.push(once(el, "playing")); + return Promise.all(promises); + }) + .then(function() { + 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 000000000..a26590537 --- /dev/null +++ b/dom/media/mediasource/test/test_LoadedMetadataFired.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append initialization only</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + v.addEventListener("loadedmetadata", function () { + 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(); + }); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); + v.play(); + }); + }); + +}); + +</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 000000000..6d7547cf1 --- /dev/null +++ b/dom/media/mediasource/test/test_LoadedMetadataFired_mp4.html @@ -0,0 +1,37 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append initialization only</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + v.addEventListener("loadedmetadata", function () { + 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(); + }); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 1395)); + v.play(); + }); + }); + +}); + +</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 000000000..6acd243e1 --- /dev/null +++ b/dom/media/mediasource/test/test_MediaSource.html @@ -0,0 +1,107 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: basic functionality</title> + <script type="text/javascript" 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 () { + SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail"); + SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail"); + + var ms = new MediaSource(); + ok(ms, "Create a MediaSource object"); + 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; + + var o = URL.createObjectURL(ms); + ok(o, "Create an objectURL from the MediaSource"); + + var v = document.createElement("video"); + v.preload = "auto"; + v.src = o; + document.body.appendChild(v); + + var loadedmetadataCount = 0; + var updatestartCount = 0; + var updateendCount = 0; + var updateCount = 0; + + ms.addEventListener("sourceopen", function () { + ok(true, "Receive a sourceopen event"); + is(ms.readyState, "open", "MediaSource must be in open state after sourceopen"); + var 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"); + + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer"); + }); + + sb.addEventListener("update", function () { + 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", function () { + updatestartCount++; + }); + + sb.addEventListener("updateend", function () { + 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", function () { + ok(true, "Receive a sourceended event"); + is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended"); + }); + + v.addEventListener("loadedmetadata", function () { + loadedmetadataCount++; + }); + + v.addEventListener("ended", function () { + // 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"); + v.parentNode.removeChild(v); + SimpleTest.finish(); + }); +}); + +</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 000000000..ccf36914a --- /dev/null +++ b/dom/media/mediasource/test/test_MediaSource_disabled.html @@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: disabling via pref</title> + <script type="text/javascript" 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_memory_reporting.html b/dom/media/mediasource/test/test_MediaSource_memory_reporting.html new file mode 100644 index 000000000..278b8760d --- /dev/null +++ b/dom/media/mediasource/test/test_MediaSource_memory_reporting.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: memory reporting</title> + <script type="text/javascript" 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, v) { + // Test that memory reporting works once we've played a video. + once(v, "stalled", () => { + // Grab a memory report. + var mgr = SpecialPowers.Cc["@mozilla.org/memory-reporter-manager;1"] + .getService(SpecialPowers.Ci.nsIMemoryReporterManager); + + var amount = 0; + var resourcesPathSeen = false; + var handleReport = function(aProcess, aPath, aKind, aUnits, aAmount, aDesc) { + if (aPath == "explicit/media/resources") { + resourcePathSeen = true; + amount += aAmount; + } + } + + var finished = function () { + ok(true, "Yay didn't crash!"); + ok(resourcePathSeen, "Got media resources amount"); + ok(amount > 0, "Non-zero amount reported for media resources"); + SimpleTest.finish(); + } + + mgr.getReports(handleReport, null, finished, null, /* anonymized = */ false); + }); + + // Load a webm video and play it. + ms.addEventListener("sourceopen", () => { + var sb = ms.addSourceBuffer("video/webm"); + fetchAndLoad(sb, 'seek', [''], '.webm').then(() => v.play()); + }); +}); + +</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 000000000..fc5ac2895 --- /dev/null +++ b/dom/media/mediasource/test/test_MediaSource_mp4.html @@ -0,0 +1,108 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: basic functionality</title> + <script type="text/javascript" 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 () { + SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail"); + SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail"); + + var ms = new MediaSource(); + ok(ms, "Create a MediaSource object"); + 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; + + var o = URL.createObjectURL(ms); + ok(o, "Create an objectURL from the MediaSource"); + + var v = document.createElement("video"); + v.preload = "auto"; + v.src = o; + document.body.appendChild(v); + + var loadedmetadataCount = 0; + var updatestartCount = 0; + var updateendCount = 0; + var updateCount = 0; + + ms.addEventListener("sourceopen", function () { + ok(true, "Receive a sourceopen event"); + is(ms.readyState, "open", "MediaSource must be in open state after sourceopen"); + var 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"); + + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer"); + }); + + sb.addEventListener("update", function () { + 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", function () { + updatestartCount++; + }); + + sb.addEventListener("updateend", function () { + 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", function () { + ok(true, "Receive a sourceended event"); + is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended"); + }); + + v.addEventListener("loadedmetadata", function () { + loadedmetadataCount++; + }); + + v.addEventListener("ended", function () { + // 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"); + v.parentNode.removeChild(v); + 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 000000000..d97d72dae --- /dev/null +++ b/dom/media/mediasource/test/test_MultipleInitSegments.html @@ -0,0 +1,53 @@ +<!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 type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + fetchWithXHR("seek_lowres.webm", function (seek_lowres) { + fetchWithXHR("seek.webm", function (seek) { + var 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 + ]; + var length = data.map(d => d[2] - d[1]).reduce((a, b) => a + b); + var arrayBuffer = new Uint8Array(length); + var pos = 0; + data.forEach(function(d) { + var buffer = new Uint8Array(d[0], d[1], d[2]-d[1]); + arrayBuffer.set(buffer, pos); + pos += buffer.byteLength; + }); + loadSegment.bind(null, sb, arrayBuffer)().then(function() { + // Since we are passing multiple segments in one buffer, + // the first durationchange event from parsing the init + // segment will be fired before updateend. + v.addEventListener("durationchange", function () { + ok(v.duration, 1.201); + SimpleTest.finish(); + }); + ms.endOfStream(); + }); + }); + }); + }); +}); + +</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 000000000..8b1a8c7b7 --- /dev/null +++ b/dom/media/mediasource/test/test_MultipleInitSegments_mp4.html @@ -0,0 +1,52 @@ +<!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 type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + fetchWithXHR("bipbop/bipbop_videoinit.mp4", function (init) { + init = new Uint8Array(init); + fetchWithXHR("bipbop/bipbop_video1.m4s", function (segment1) { + segment1 = new Uint8Array(segment1); + fetchWithXHR("bipbop/bipbop_video2.m4s", function (segment2) { + segment2 = new Uint8Array(segment2); + var data = [init, segment1, init, segment2]; + var length = data.map(d => d.byteLength).reduce((a, b) => a + b); + var arrayBuffer = new Uint8Array(length); + var pos = 0; + data.forEach(function(buffer) { + arrayBuffer.set(buffer, pos); + pos += buffer.byteLength; + }); + loadSegment.bind(null, sb, arrayBuffer)().then(function() { + // Since we are passing multiple segments in one buffer, + // the first durationchange event from parsing the init + // segment will be fired before updateend. + v.addEventListener("durationchange", function () { + ok(v.duration, 1.601666); + SimpleTest.finish(); + }); + ms.endOfStream(); + }); + }); + }); + }); + }); +}); + +</script> +</pre> +</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 000000000..1290e33f1 --- /dev/null +++ b/dom/media/mediasource/test/test_OnEvents.html @@ -0,0 +1,65 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: live seekable range</title> + <script type="text/javascript" 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, v) { + function initEvent(e) { + v['got' + e] = false; + } + function receiveEvent(e) { + v['got' + e] = true; + } + var msevents = ["onsourceopen", "onsourceended"]; + msevents.forEach(function(e) { + initEvent(e); + ms[e] = function() { receiveEvent(e); }; + }); + + var sblistevents = ["onaddsourcebuffer", "onremovesourcebuffer"]; + sblistevents.forEach(function(e) { + initEvent(e); + ms.sourceBuffers[e] = function() { receiveEvent(e); }; + }); + + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + var sbevents = ["onupdatestart", "onupdate", "onupdateend", "onabort"]; + sbevents.forEach(function(e) { + initEvent(e); + sb[e] = function() { receiveEvent(e); }; + }); + + fetchAndLoad(sb, 'seek', [''], '.webm') + .then(function() { + fetchWithXHR('seek.webm') + .then(function(arrayBuffer) { + sb.appendBuffer(arrayBuffer); + ms.removeSourceBuffer(sb); // will fire abort and removesourcebuffer + ms.endOfStream(); // will fire sourceended + once(ms, "sourceended").then(function() { + var events = ["onsourceopen", "onsourceended", "onupdatestart", "onupdate", "onupdateend", "onabort", "onaddsourcebuffer", "onremovesourcebuffer"]; + events.forEach(function(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 000000000..a390ae247 --- /dev/null +++ b/dom/media/mediasource/test/test_PlayEvents.html @@ -0,0 +1,165 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: basic functionality</title> + <script type="text/javascript" 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(function(ms, el) { + el.controls = true; + once(ms, 'sourceopen').then(function() { + // Log events for debugging. + var events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata", + "loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort", + "waiting", "pause", "durationchange", "seeking", "seeked"]; + function logEvent(e) { + var v = e.target; + info("got " + e.type + " event"); + } + events.forEach(function(e) { + el.addEventListener(e, logEvent, false); + }); + + ok(true, "Receive a sourceopen event"); + var videosb = ms.addSourceBuffer("video/mp4"); + el.addEventListener("error", function(e) { + ok(false, "should not fire '" + e + "' event"); + }); + is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING"); + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(once.bind(null, el, 'loadedmetadata')) + .then(function() { + ok(true, "got loadedmetadata event"); + var promises = []; + promises.push(once(el, 'loadeddata')); + promises.push(once(el, 'canplay')); + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s')); + return Promise.all(promises); + }) + .then(function() { + 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; + return once(el, 'durationchange'); + }) + .then(function() { + ok(true, "got durationchange event"); + var promises = []; + promises.push(once(el, 'canplaythrough')); + // Load [0.801666, 3.203333] + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(3, 5), '.m4s')); + return Promise.all(promises); + }) + .then(function() { + 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; + return once(el, 'durationchange'); + }) + .then(function() { + 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"); + return once(el, 'seeking'); + }) + .then(function() { + ok(true, "got seeking event"); + is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA"); + var promises = []; + promises.push(once(el, 'seeked')); + promises.push(once(el, 'canplay')); + // Load [6+0, 6+1.601666) + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s')); + return Promise.all(promises); + }) + .then(function() { + 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"); + var promises = []; + promises.push(once(el, 'canplaythrough')); + // Load [6+1.60166, 6+3.203333] + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(3, 5), '.m4s')); + return Promise.all(promises); + }) + .then(function() { + 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; + return once(el, 'durationchange'); + }) + .then(function() { + ok(true, "got durationchange event"); + el.currentTime = 15; + videosb.timestampOffset = 15; + ok(el.seeking, "seeking started"); + return once(el, 'seeking'); + }) + .then(function() { + ok(true, "got seeking event"); + var promises = []; + promises.push(once(el, 'seeked')); + // Load [15+0, 15+1.601666) + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s')); + return Promise.all(promises); + }) + .then(function() { + ok(true, "got seeked event"); + // Load [15+1.60166, 15+3.203333] + return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(3, 5), '.m4s'); + }) + .then(function() { + ok(true, "data loaded"); + // Playback we play for a little while then stall. + var promises = []; + promises.push(once(el, 'playing')); + promises.push(once(el, 'waiting')); + el.play(); + return Promise.all(promises); + }) + .then(function() { + 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"); + var promises = []; + promises.push(once(el, 'playing')); + promises.push(once(el, 'canplay')); + promises.push(once(el, 'canplaythrough')); + // Load [15+3.203333, 15+4.805) + // Our final buffered range will now be [0, 3.203333)[6, 9.203333)[15, 19.805) + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(5, 7), '.m4s')); + return Promise.all(promises); + }) + .then(function() { + ok(true, "got playing, canplay and canplaythrough event"); + SimpleTest.finish(); + }) + }); +}); + +</script> +</pre> +</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 000000000..b6769cb1b --- /dev/null +++ b/dom/media/mediasource/test/test_ResumeAfterClearing_mp4.html @@ -0,0 +1,55 @@ +<!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 type="text/javascript" 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(); + +var receivedSourceOpen = false; +runWithMSE(function(ms, v) { + ms.addEventListener("sourceopen", function() { + ok(true, "Receive a sourceopen event"); + ok(!receivedSourceOpen, "Should only receive one sourceopen for this test"); + receivedSourceOpen = true; + var sb = ms.addSourceBuffer("video/mp4"); + ok(sb, "Create a SourceBuffer"); + + sb.addEventListener('error', (e) => { ok(false, "Got Error: " + e); SimpleTest.finish(); }); + fetchAndLoad(sb, 'bipbop/bipbop', ['init'], '.mp4') + .then(function() { + var promises = []; + promises.push(fetchAndLoad(sb, 'bipbop/bipbop', range(1,3), '.m4s')); + promises.push(once(v, "loadeddata")); + return Promise.all(promises); + }).then(function() { + // clear the entire sourcebuffer. + sb.remove(0, 5); + return once(sb, "updateend"); + }).then(function() { + v.play(); + // We have nothing to play, waiting will be fired. + return once(v, "waiting"); + }).then(function() { + var promises = []; + promises.push(once(v, "playing")); + promises.push(fetchAndLoad(sb, 'bipbop/bipbop', range(1,4), '.m4s')); + return Promise.all(promises); + }).then(function() { + ms.endOfStream(); + var promises = []; + promises.push(once(ms, "sourceended")); + promises.push(once(v, "ended")); + return Promise.all(promises); + }).then(SimpleTest.finish.bind(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 000000000..efebff954 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekNoData_mp4.html @@ -0,0 +1,69 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: basic functionality</title> + <script type="text/javascript" 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(); + +// Avoid making trouble for people who fix rounding bugs. +function fuzzyEquals(a, b) { + return Math.abs(a - b) < 0.01; +} + +runWithMSE(function(ms, el) { + el.controls = true; + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var audiosb = ms.addSourceBuffer("audio/mp4"); + var videosb = ms.addSourceBuffer("video/mp4"); + el.addEventListener("error", function(e) { + ok(false, "should not fire '" + e + "' event"); + }); + is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING"); + try { + el.currentTime = 3; + } catch (e) { + ok(false, "should not throw '" + e + "' exception"); + } + is(el.currentTime, 3, "currentTime is default playback start position"); + is(el.seeking, false, "seek not started with HAVE_NOTHING"); + fetchAndLoad(audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', ['init'], '.mp4')) + .then(once.bind(null, el, 'loadedmetadata')) + .then(function() { + var 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"); + return p; + }) + .then(function() { + ok(true, "Got seeking event"); + var promises = []; + promises.push(once(el, 'seeked')); + promises.push(fetchAndLoad(audiosb, 'bipbop/bipbop_audio', range(5, 9), '.m4s')); + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(6, 10), '.m4s')); + return Promise.all(promises); + }) + .then(function() { + ok(true, "Got seeked event"); + ok(el.currentTime >= 5, "Time >= 5"); + once(el, 'ended').then(SimpleTest.finish.bind(SimpleTest)); + ms.endOfStream(); + }); + }); +}); + +</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 000000000..2ffa53898 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekToEnd_mp4.html @@ -0,0 +1,57 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seeking to end of data with data gap.</title> + <script type="text/javascript" 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) { + + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var videosb = ms.addSourceBuffer("video/mp4"); + var audiosb = ms.addSourceBuffer("audio/mp4"); + + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 6), '.m4s')) + .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4')) + .then(function() { + 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; + return fetchAndLoad(audiosb, 'bipbop/bipbop_audio', range(1, 6), '.m4s'); + }).then(function() { + ms.endOfStream(); + return Promise.all([once(el, "durationchange"), once(ms, "sourceended")]); + }).then(function() { + 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"); + return once(el, 'seeked'); + }).then(function() { + 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(); + once(el, 'ended').then(SimpleTest.finish.bind(SimpleTest)); + }); + }); +}); + +</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 000000000..dd250185f --- /dev/null +++ b/dom/media/mediasource/test/test_SeekTwice_mp4.html @@ -0,0 +1,54 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: basic functionality</title> + <script type="text/javascript" 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(); + +// Avoid making trouble for people who fix rounding bugs. +function fuzzyEquals(a, b) { + return Math.abs(a - b) < 0.01; +} + +runWithMSE(function(ms, el) { + el.controls = true; + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var audiosb = ms.addSourceBuffer("audio/mp4"); + var videosb = ms.addSourceBuffer("video/mp4"); + fetchAndLoad(audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(1, 5), '.m4s')) + .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(6, 12), '.m4s')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', ['init'], '.mp4')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 6), '.m4s')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(7, 14), '.m4s')) + .then(function() { + var p = once(el, 'seeking'); + el.play(); + el.currentTime = 4.5; // Seek to a gap in the video + return p; + }).then(function() { + ok(true, "Got seeking event"); + var p = once(el, 'seeked'); + el.currentTime = 6; // Seek past the gap. + return p; + }).then(function() { + ok(true, "Got seeked event"); + ok(el.currentTime >= 6, "Time >= 6"); + once(el, 'ended').then(SimpleTest.finish.bind(SimpleTest)); + ms.endOfStream(); + }); + }); +}); + +</script> +</pre> +</body> +</html> diff --git a/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html new file mode 100644 index 000000000..850434429 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute after end of stream</title> + <script type="text/javascript" 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(); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + sb.addEventListener("updateend", function () { + 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(); + }; + }); + }); + + var target = 2; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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_SeekableAfterEndOfStreamSplit.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html new file mode 100644 index 000000000..3aad2a0af --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute after end of stream with split appendBuffer</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + // 25523 is the offset of the first media segment's end + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25523)); + var updateCount = 0; + sb.addEventListener("updateend", function () { + updateCount++; + if (updateCount == 1) { + // 25523 is the offset of the first media segment's end + sb.appendBuffer(new Uint8Array(arrayBuffer, 25523)); + } + else if (updateCount == 2) { + ms.endOfStream(); + } + }); + }); + + var target = 2; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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_SeekableAfterEndOfStreamSplit_mp4.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit_mp4.html new file mode 100644 index 000000000..0933087a7 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit_mp4.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute after end of stream with split appendBuffer</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + // 25819 is the offset of the first media segment's end + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25819)); + var updateCount = 0; + sb.addEventListener("updateend", function () { + updateCount++; + if (updateCount == 1) { + // 25819 is the offset of the first media segment's end + sb.appendBuffer(new Uint8Array(arrayBuffer, 25819)); + } + else if (updateCount == 2) { + ms.endOfStream(); + } + }); + }); + + var target = 1.3; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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_SeekableAfterEndOfStream_mp4.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStream_mp4.html new file mode 100644 index 000000000..7adadad85 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStream_mp4.html @@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute after end of stream</title> + <script type="text/javascript" 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(); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + sb.addEventListener("updateend", function () { + 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(); + }; + }); + }); + + var target = 1.3; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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_SeekableBeforeEndOfStream.html b/dom/media/mediasource/test/test_SeekableBeforeEndOfStream.html new file mode 100644 index 000000000..49401d213 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableBeforeEndOfStream.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute before end of stream</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + }); + + var target = 2; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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_SeekableBeforeEndOfStreamSplit.html b/dom/media/mediasource/test/test_SeekableBeforeEndOfStreamSplit.html new file mode 100644 index 000000000..2013fb4e6 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableBeforeEndOfStreamSplit.html @@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute before end of stream with split appendBuffer</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25523)); + sb.addEventListener("updateend", function () { + sb.removeEventListener('updateend', arguments.callee); + sb.appendBuffer(new Uint8Array(arrayBuffer, 25523)); + }); + }); + + var target = 2; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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_SeekableBeforeEndOfStreamSplit_mp4.html b/dom/media/mediasource/test/test_SeekableBeforeEndOfStreamSplit_mp4.html new file mode 100644 index 000000000..f14669665 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableBeforeEndOfStreamSplit_mp4.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute before end of stream with split appendBuffer</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + // 25819 is the offset of the first media segment's end + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 25819)); + sb.addEventListener("updateend", function () { + sb.removeEventListener('updateend', arguments.callee); + // 25819 is the offset of the first media segment's end + sb.appendBuffer(new Uint8Array(arrayBuffer, 25819)); + }); + }); + + var target = 1.3; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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_SeekableBeforeEndOfStream_mp4.html b/dom/media/mediasource/test/test_SeekableBeforeEndOfStream_mp4.html new file mode 100644 index 000000000..cc06ff00d --- /dev/null +++ b/dom/media/mediasource/test/test_SeekableBeforeEndOfStream_mp4.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: seekable attribute before end of stream</title> + <script type="text/javascript" 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, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + }); + + var target = 1.3; + + v.addEventListener("loadedmetadata", function () { + ok(v.seekable.length, "Resource is seekable"); + 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 000000000..f80ae86f5 --- /dev/null +++ b/dom/media/mediasource/test/test_SeekedEvent_mp4.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: Check that seeked event is fired prior loadeddata</title> + <script type="text/javascript" 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; + el._seeked = false; + el._loadeddata = false; + el._playing = false; + el.addEventListener("seeked", function() { + ok(true, "got seeked event"); + is(el._loadeddata, false, "can't have received loadeddata prior seeked"); + is(el._playing, false, "can't be playing prior seeked"); + el._seeked = true; + }); + el.addEventListener("loadeddata", function() { + ok(true, "got loadeddata event"); + is(el._seeked, true, "must have received seeked prior loadeddata"); + is(el._playing, false, "can't be playing prior playing"); + el._loadeddata = true; + }); + el.addEventListener("playing", function() { + ok(true, "got playing"); + is(el._seeked, true, "must have received seeked prior playing"); + is(el._loadeddata, true, "must have received loadeddata prior playing"); + el._playing = true; + }); + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var videosb = ms.addSourceBuffer("video/mp4"); + is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING"); + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(once.bind(null, el, "loadedmetadata")) + .then(function() { + el.play(); + videosb.timestampOffset = 2; + is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA"); + // Load [2, 3.606). + var promises = []; + promises.push(once(el, "play")); + promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', ['1'], '.m4s')); + return Promise.all(promises); + }) + .then(function() { + return fetchAndLoad(videosb, 'bipbop/bipbop_video', ['2'], '.m4s'); + }) + .then(function() { + is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA"); + el.currentTime = 2; + var promises = []; + promises.push(once(el, "seeked")); + promises.push(once(el, "playing")); + return Promise.all(promises); + }) + .then(function() { + ok(true, "completed seek"); + 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 000000000..a68393547 --- /dev/null +++ b/dom/media/mediasource/test/test_Sequence_mp4.html @@ -0,0 +1,39 @@ +<!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 type="text/javascript" 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(); + +var receivedSourceOpen = false; +runWithMSE(function(ms, v) { + ms.addEventListener("sourceopen", function() { + ok(true, "Receive a sourceopen event"); + ok(!receivedSourceOpen, "Should only receive one sourceopen for this test"); + receivedSourceOpen = true; + var sb = ms.addSourceBuffer("video/mp4"); + ok(sb, "Create a SourceBuffer"); + sb.addEventListener('error', (e) => { ok(false, "Got Error: " + e); SimpleTest.finish(); }); + sb.mode = 'sequence'; + + fetchAndLoad(sb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop_video', ['5'], '.m4s')) + .then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop_video', ['2'], '.m4s')) + .then(function() { + 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 000000000..ce8f955cd --- /dev/null +++ b/dom/media/mediasource/test/test_SetModeThrows.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append initialization</title> + <script type="text/javascript" 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", function () { + var 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 000000000..e87bd00ed --- /dev/null +++ b/dom/media/mediasource/test/test_SplitAppend.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append initialization and media segment separately</title> + <script type="text/javascript" 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(); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); + sb.addEventListener("updateend", function () { + updateCount++; + if (updateCount == 1) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 318)); + } + else if (updateCount == 2) { + ms.endOfStream(); + } + }); + v.play(); + }); + }); + + v.addEventListener("ended", function () { + // 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 000000000..c5d443e80 --- /dev/null +++ b/dom/media/mediasource/test/test_SplitAppendDelay.html @@ -0,0 +1,50 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append segments with delay</title> + <script type="text/javascript" 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"); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); + sb.addEventListener("updateend", function () { + updateCount++; + if (updateCount == 1) { + window.setTimeout(function () { + sb.appendBuffer(new Uint8Array(arrayBuffer, 318)); + }, 1000); + } + else if (updateCount == 2) { + ms.endOfStream(); + } + }); + v.play(); + }); + }); + + v.addEventListener("ended", function () { + // 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 000000000..d48e63324 --- /dev/null +++ b/dom/media/mediasource/test/test_SplitAppendDelay_mp4.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append segments with delay</title> + <script type="text/javascript" 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"); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 1395)); + sb.addEventListener("updateend", function () { + updateCount++; + if (updateCount == 1) { + window.setTimeout(function () { + sb.appendBuffer(new Uint8Array(arrayBuffer, 1395)); + }, 1000); + } + else if (updateCount == 2) { + ms.endOfStream(); + } + }); + v.play(); + }); + }); + + v.addEventListener("ended", function () { + // 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 000000000..9e006e699 --- /dev/null +++ b/dom/media/mediasource/test/test_SplitAppend_mp4.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: append initialization and media segment separately</title> + <script type="text/javascript" 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(); + +var updateCount = 0; + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 1395)); + sb.addEventListener("updateend", function () { + updateCount++; + if (updateCount == 1) { + sb.appendBuffer(new Uint8Array(arrayBuffer, 1395)); + } + else if (updateCount == 2) { + ms.endOfStream(); + } + }); + v.play(); + }); + }); + + v.addEventListener("ended", function () { + // 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 000000000..a33dc08ec --- /dev/null +++ b/dom/media/mediasource/test/test_Threshold_mp4.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: data gap detection</title> + <script type="text/javascript" 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) { + +var threshold = 0.5; // gap threshold in seconds. +var fuzz = 0.000001; // fuzz when comparing double. + + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var videosb = ms.addSourceBuffer("video/mp4"); + var vchunks = [ {start: 0, end: 3.203333}, { start: 3.203333, end: 6.406666}]; + + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 5), '.m4s')) + .then(function() { + // We will insert a gap of threshold + videosb.timestampOffset = threshold; + return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(5, 9), '.m4s'); + }).then(function() { + // 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()"); + var p = once(el, 'playing'); + el.play(); + return p; + }).then(function() { + return once(el, 'waiting'); + }).then(function() { + // 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); + return once(el, 'seeked'); + }).then(function() { + // 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(); + return once(videosb, "updateend"); + }).then(function() { + return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 5), '.m4s'); + }).then(function() { + // We will insert a gap of threshold + 1ms + videosb.timestampOffset = threshold + 1/1000; + return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(5, 9), '.m4s'); + }).then(function() { + info("Invoking play()"); + var p = once(el, 'playing'); + el.play(); + return p; + }).then(function() { + return once(el, 'waiting'); + }).then(function() { + // 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 000000000..2a80e3e5c --- /dev/null +++ b/dom/media/mediasource/test/test_TimestampOffset_mp4.html @@ -0,0 +1,86 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: basic functionality</title> + <script type="text/javascript" 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(); + +function range(start, end) { + var rv = []; + for (var i = start; i < end; ++i) { + rv.push(i); + } + return rv; +} + +var eps = 0.01; +runWithMSE(function(ms, el) { + + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var audiosb = ms.addSourceBuffer("audio/mp4"); + var 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. + var vchunks = [ {start: 0, end: 3.2033}, { start: 3.2033, end: 6.4066}, { start: 6.4066, end: 10.01} ]; + var firstvoffset = vchunks[2].end - vchunks[2].start; // Duration of chunk 2 + var secondvoffset = -(vchunks[1].end - vchunks[1].start); // -(Duration of chunk 1) + + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 5), '.m4s')) + .then(function() { + 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; + return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(5, 9), '.m4s'); + }) + .then(function(data) { + 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; + return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(9, 14), '.m4s'); + }) + .then(function() { + 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; + }).then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4')) + .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(1, 12), '.m4s')) + .then(function() { + 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); + return Promise.all([audiosb.updating ? once(audiosb, 'updateend') : Promise.resolve(), + videosb.updating ? once(videosb, 'updateend') : Promise.resolve()]); + }).then(function() { + info("waiting for play to complete"); + el.play(); + el.currentTime = el.buffered.start(0); + ms.endOfStream(); + Promise.all([once(el, 'ended'), once(el, 'seeked')]).then(SimpleTest.finish.bind(SimpleTest)); + }); + }); +}); + +</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 000000000..cf25de395 --- /dev/null +++ b/dom/media/mediasource/test/test_TruncatedDuration.html @@ -0,0 +1,78 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: truncating the media seeks to end of media and update buffered range</title> + <script type="text/javascript" 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(); + +function round(n) { + return Math.round(n * 1000) / 1000; +} + +function do_seeking(e) { + var v = e.target; + v.removeEventListener("seeking", do_seeking, false); + SimpleTest.finish(); +} + +function do_seeked(e) { + var v = e.target; + v.removeEventListener("seeked", do_seeked, false); + var duration = round(v.duration / 3); + is(v._sb.updating, false, "sourcebuffer isn't updating"); + v._sb.remove(duration, Infinity); + once(v._sb, "updateend", function() { + v._ms.duration = duration + // frames aren't truncated, so duration may be slightly more. + isfuzzy(v.duration, duration, 1/30, "element duration was updated"); + v._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(v._sb.buffered.length, 1, "One buffered range"); + // Truncated mediasource duration will cause the video element to seek. + v.addEventListener("seeking", do_seeking, false); + }); +} + +function do_loaded(e) { + var v = e.target; + v.removeEventListener("loadeddata", do_loaded, false); + v.currentTime = v.duration / 2; + is(v.currentTime, v.duration / 2, "current time was updated"); + ok(v.seeking, "seeking is true"); + v.addEventListener("seeked", do_seeked, false); +} + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/webm"); + v._sb = sb; + v._ms = ms; + + fetchWithXHR("seek.webm", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + v.addEventListener("loadeddata", do_loaded, false); + }); + }); +}); + +</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 000000000..f226093de --- /dev/null +++ b/dom/media/mediasource/test/test_TruncatedDuration_mp4.html @@ -0,0 +1,83 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>MSE: truncating the media seeks to end of media and update buffered range</title> + <script type="text/javascript" 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(); + +function round(n) { + return Math.round(n * 1000) / 1000; +} + +function do_seeking(e) { + var v = e.target; + v.removeEventListener("seeking", do_seeking, false); + SimpleTest.finish(); +} + +function do_seeked(e) { + var v = e.target; + v.removeEventListener("seeked", do_seeked, false); + var duration = round(v.duration / 3); + is(v._sb.updating, false, "sourcebuffer isn't updating"); + v._sb.remove(duration, Infinity); + once(v._sb, "updateend", function() { + v._ms.duration = duration + // frames aren't truncated, so duration may be slightly more. + isfuzzy(v.duration, duration, 1/30, "element duration was updated"); + v._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(v._sb.buffered.length, 1, "One buffered range"); + // Truncated mediasource duration will cause the video element to seek. + v.addEventListener("seeking", do_seeking, false); + }); +} + +function do_loaded(e) { + var v = e.target; + v.removeEventListener("loadeddata", do_loaded, false); + // mp4 metadata states 10s when we only have 1.6s worth of video. + v._sb.remove(v._sb.buffered.end(0), Infinity); + once(v._sb, "updateend", function() { + v._ms.duration = v._sb.buffered.end(0); + is(v.duration, v._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"); + v.addEventListener("seeked", do_seeked, false); + }); +} + +runWithMSE(function (ms, v) { + ms.addEventListener("sourceopen", function () { + var sb = ms.addSourceBuffer("video/mp4"); + v._sb = sb; + v._ms = ms; + + fetchWithXHR("bipbop/bipbop2s.mp4", function (arrayBuffer) { + sb.appendBuffer(new Uint8Array(arrayBuffer)); + v.addEventListener("loadeddata", do_loaded, false); + }); + }); +}); + +</script> +</pre> +</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 000000000..a67441045 --- /dev/null +++ b/dom/media/mediasource/test/test_WaitingOnMissingData.html @@ -0,0 +1,63 @@ +<!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 type="text/javascript" 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) { + once(ms, 'sourceopen').then(function() { + ok(true, "Receive a sourceopen event"); + var sb = ms.addSourceBuffer("video/webm"); + fetchWithXHR("seek.webm", function(arrayBuffer) { + sb.addEventListener('error', (e) => { ok(false, "Got Error: " + e); SimpleTest.finish(); }); + loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 0, 318))() + .then(loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 318, 25223-318))) + .then(loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 25223, 46712-25223))) + /* Note - Missing |46712, 67833 - 46712| segment here */ + .then(loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 67833, 88966 - 67833))) + .then(loadSegment.bind(null, sb, new Uint8Array(arrayBuffer, 88966))) + .then(function() { + // 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()"); + var p = once(el, 'playing'); + el.play(); + return p; + }).then(function() { + ok(true, "Video playing. It should play for a bit, then fire 'waiting'"); + var p = once(el, 'waiting'); + el.play(); + return p; + }).then(function() { + // 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"); + var p = once(el, 'ended'); + loadSegment(sb, new Uint8Array(arrayBuffer, 46712, 67833 - 46712)).then(() => ms.endOfStream()); + return p; + }).then(function() { + // 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 000000000..6e1560d01 --- /dev/null +++ b/dom/media/mediasource/test/test_WaitingOnMissingDataEnded_mp4.html @@ -0,0 +1,53 @@ +<!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 type="text/javascript" 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() { + ok(true, "Receive a sourceopen event"); + el.addEventListener("ended", function () { + ok(false, "ended should never fire"); + SimpleTest.finish(); + }); + var videosb = ms.addSourceBuffer("video/mp4"); + fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 5), '.m4s')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(6, 8), '.m4s')) + .then(function() { + is(el.buffered.length, 2, "discontinuous buffered range"); + ms.endOfStream(); + return Promise.all([once(el, "durationchange"), once(ms, "sourceended")]); + }).then(function() { + // 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(); + return once(el, 'playing'); + }).then(function() { + ok(true, "Video playing. It should play for a bit, then fire 'waiting'"); + return once(el, 'waiting'); + }).then(function() { + // 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 000000000..79344c772 --- /dev/null +++ b/dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html @@ -0,0 +1,65 @@ +<!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 type="text/javascript" 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() { + ok(true, "Receive a sourceopen event"); + var audiosb = ms.addSourceBuffer("audio/mp4"); + var videosb = ms.addSourceBuffer("video/mp4"); + fetchAndLoad(audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(1, 5), '.m4s')) + .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(6, 12), '.m4s')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', ['init'], '.mp4')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 6), '.m4s')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(7, 14), '.m4s')) + .then(function() { + // 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()"); + var p = once(el, 'playing'); + el.play(); + return p; + }).then(function() { + ok(true, "Video playing. It should play for a bit, then fire 'waiting'"); + var p = once(el, 'waiting'); + el.play(); + return p; + }).then(function() { + // 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"); + var p = once(el, 'ended'); + var loads = Promise.all([fetchAndLoad(audiosb, 'bipbop/bipbop_audio', [5], '.m4s'), + fetchAndLoad(videosb, 'bipbop/bipbop_video', [6], '.m4s')]); + loads.then(() => ms.endOfStream()); + return p; + }).then(function() { + // 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 000000000..f932b3d4e --- /dev/null +++ b/dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html @@ -0,0 +1,56 @@ +<!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 type="text/javascript" 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() { + ok(true, "Receive a sourceopen event"); + var audiosb = ms.addSourceBuffer("audio/mp4"); + var 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; + fetchAndLoad(audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4') + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', ['init'], '.mp4')) + .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(1, 5), '.m4s')) + .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 6), '.m4s')) + .then(function() { + // 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()"); + var p = once(el, 'playing'); + el.play(); + return p; + }).then(function() { + ok(true, "Video playing. It should play for a bit, then fire 'waiting'"); + var p = once(el, 'waiting'); + el.play(); + return p; + }).then(function() { + var p = once(el, 'ended'); + ms.endOfStream(); + return p; + }).then(function() { + is(el.duration, 3.854512, "Video has correct duration: " + el.duration); + is(el.currentTime, el.duration, "Video has correct currentTime."); + SimpleTest.finish(); + }); + }); +}); + +</script> +</pre> +</body> +</html> |