summaryrefslogtreecommitdiffstats
path: root/dom/media/mediasource/test
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/mediasource/test')
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-1.m4sbin0 -> 24328 bytes
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-2.m4sbin0 -> 24132 bytes
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-init.mp4bin0 -> 1246 bytes
-rw-r--r--dom/media/mediasource/test/aac20-48000-64000-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-1.m4sbin0 -> 48979 bytes
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-2.m4sbin0 -> 47727 bytes
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-init.mp4bin0 -> 634 bytes
-rw-r--r--dom/media/mediasource/test/aac51-48000-128000-init.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop1.m4sbin0 -> 24424 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop10.m4sbin0 -> 18279 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop10.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop11.m4sbin0 -> 24607 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop11.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop12.m4sbin0 -> 22676 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop12.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop13.m4sbin0 -> 9847 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop13.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2.m4sbin0 -> 22205 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2s.mp4bin0 -> 48024 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop2s.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop3.m4sbin0 -> 24013 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop3.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop4.m4sbin0 -> 23112 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop4.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop5.m4sbin0 -> 18367 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop5.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop6.m4sbin0 -> 24455 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop6.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop7.m4sbin0 -> 22442 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop7.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop8.m4sbin0 -> 24356 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop8.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop9.m4sbin0 -> 23252 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop9.m4s^headers^1
-rwxr-xr-xdom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4sbin0 -> 66806 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s^headers^1
-rwxr-xr-xdom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4sbin0 -> 65292 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s^headers^1
-rwxr-xr-xdom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4bin0 -> 1410 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio1.m4sbin0 -> 694 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio10.m4sbin0 -> 879 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio10.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio11.m4sbin0 -> 208 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio11.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio2.m4sbin0 -> 750 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio3.m4sbin0 -> 724 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio3.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio4.m4sbin0 -> 806 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio4.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio5.m4sbin0 -> 822 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio5.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio6.m4sbin0 -> 833 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio6.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio7.m4sbin0 -> 888 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio7.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio8.m4sbin0 -> 829 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio8.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio9.m4sbin0 -> 778 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audio9.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4bin0 -> 825 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_dash.mpd48
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video1.m4sbin0 -> 23860 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video1.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video10.m4sbin0 -> 18109 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video10.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video11.m4sbin0 -> 23969 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video11.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video12.m4sbin0 -> 21937 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video12.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video13.m4sbin0 -> 16265 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video13.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video2.m4sbin0 -> 21595 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video2.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video3.m4sbin0 -> 23429 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video3.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video4.m4sbin0 -> 22446 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video4.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video5.m4sbin0 -> 18191 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video5.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video6.m4sbin0 -> 23773 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video6.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video7.m4sbin0 -> 21749 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video7.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video8.m4sbin0 -> 23608 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video8.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video9.m4sbin0 -> 22553 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_video9.m4s^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4bin0 -> 887 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/bipbop/bipbopinit.mp4bin0 -> 1395 bytes
-rw-r--r--dom/media/mediasource/test/bipbop/bipbopinit.mp4^headers^1
-rw-r--r--dom/media/mediasource/test/crashtests/1005366.html27
-rw-r--r--dom/media/mediasource/test/crashtests/1059035.html26
-rw-r--r--dom/media/mediasource/test/crashtests/926665.html26
-rw-r--r--dom/media/mediasource/test/crashtests/931388.html17
-rw-r--r--dom/media/mediasource/test/crashtests/crashtests.list4
-rw-r--r--dom/media/mediasource/test/mediasource.js130
-rw-r--r--dom/media/mediasource/test/mochitest.ini137
-rw-r--r--dom/media/mediasource/test/seek.webmbin0 -> 215529 bytes
-rw-r--r--dom/media/mediasource/test/seek.webm^headers^1
-rw-r--r--dom/media/mediasource/test/seek_lowres.webmbin0 -> 100749 bytes
-rw-r--r--dom/media/mediasource/test/seek_lowres.webm^headers^1
-rw-r--r--dom/media/mediasource/test/test_AudioChange_mp4.html72
-rw-r--r--dom/media/mediasource/test/test_AutoRevocation.html40
-rw-r--r--dom/media/mediasource/test/test_BufferedSeek.html63
-rw-r--r--dom/media/mediasource/test/test_BufferedSeek_mp4.html63
-rw-r--r--dom/media/mediasource/test/test_BufferingWait.html56
-rw-r--r--dom/media/mediasource/test/test_BufferingWait_mp4.html54
-rw-r--r--dom/media/mediasource/test/test_DrainOnMissingData_mp4.html60
-rw-r--r--dom/media/mediasource/test/test_DurationChange.html111
-rw-r--r--dom/media/mediasource/test/test_DurationUpdated.html57
-rw-r--r--dom/media/mediasource/test/test_DurationUpdated_mp4.html56
-rw-r--r--dom/media/mediasource/test/test_EndOfStream.html50
-rw-r--r--dom/media/mediasource/test/test_EndOfStream_mp4.html50
-rw-r--r--dom/media/mediasource/test/test_Eviction_mp4.html82
-rw-r--r--dom/media/mediasource/test/test_FrameSelection.html78
-rw-r--r--dom/media/mediasource/test/test_FrameSelection_mp4.html73
-rw-r--r--dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek.html47
-rw-r--r--dom/media/mediasource/test/test_HaveMetadataUnbufferedSeek_mp4.html52
-rw-r--r--dom/media/mediasource/test/test_LiveSeekable.html80
-rw-r--r--dom/media/mediasource/test/test_LoadedDataFired_mp4.html68
-rw-r--r--dom/media/mediasource/test/test_LoadedMetadataFired.html37
-rw-r--r--dom/media/mediasource/test/test_LoadedMetadataFired_mp4.html37
-rw-r--r--dom/media/mediasource/test/test_MediaSource.html107
-rw-r--r--dom/media/mediasource/test/test_MediaSource_disabled.html32
-rw-r--r--dom/media/mediasource/test/test_MediaSource_memory_reporting.html51
-rw-r--r--dom/media/mediasource/test/test_MediaSource_mp4.html108
-rw-r--r--dom/media/mediasource/test/test_MultipleInitSegments.html53
-rw-r--r--dom/media/mediasource/test/test_MultipleInitSegments_mp4.html52
-rw-r--r--dom/media/mediasource/test/test_OnEvents.html65
-rw-r--r--dom/media/mediasource/test/test_PlayEvents.html165
-rw-r--r--dom/media/mediasource/test/test_ResumeAfterClearing_mp4.html55
-rw-r--r--dom/media/mediasource/test/test_SeekNoData_mp4.html69
-rw-r--r--dom/media/mediasource/test/test_SeekToEnd_mp4.html57
-rw-r--r--dom/media/mediasource/test/test_SeekTwice_mp4.html54
-rw-r--r--dom/media/mediasource/test/test_SeekableAfterEndOfStream.html49
-rw-r--r--dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html50
-rw-r--r--dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit_mp4.html50
-rw-r--r--dom/media/mediasource/test/test_SeekableAfterEndOfStream_mp4.html49
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeEndOfStream.html38
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeEndOfStreamSplit.html42
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeEndOfStreamSplit_mp4.html44
-rw-r--r--dom/media/mediasource/test/test_SeekableBeforeEndOfStream_mp4.html38
-rw-r--r--dom/media/mediasource/test/test_SeekedEvent_mp4.html75
-rw-r--r--dom/media/mediasource/test/test_Sequence_mp4.html39
-rw-r--r--dom/media/mediasource/test/test_SetModeThrows.html34
-rw-r--r--dom/media/mediasource/test/test_SplitAppend.html47
-rw-r--r--dom/media/mediasource/test/test_SplitAppendDelay.html50
-rw-r--r--dom/media/mediasource/test/test_SplitAppendDelay_mp4.html51
-rw-r--r--dom/media/mediasource/test/test_SplitAppend_mp4.html48
-rw-r--r--dom/media/mediasource/test/test_Threshold_mp4.html84
-rw-r--r--dom/media/mediasource/test/test_TimestampOffset_mp4.html86
-rw-r--r--dom/media/mediasource/test/test_TruncatedDuration.html78
-rw-r--r--dom/media/mediasource/test/test_TruncatedDuration_mp4.html83
-rw-r--r--dom/media/mediasource/test/test_WaitingOnMissingData.html63
-rw-r--r--dom/media/mediasource/test/test_WaitingOnMissingDataEnded_mp4.html53
-rw-r--r--dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html65
-rw-r--r--dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html56
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
new file mode 100644
index 000000000..56506e1f2
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac20-48000-64000-1.m4s^headers^ b/dom/media/mediasource/test/aac20-48000-64000-1.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..3faff17eb
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac20-48000-64000-2.m4s^headers^ b/dom/media/mediasource/test/aac20-48000-64000-2.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..b70e01651
--- /dev/null
+++ b/dom/media/mediasource/test/aac20-48000-64000-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/aac20-48000-64000-init.mp4^headers^ b/dom/media/mediasource/test/aac20-48000-64000-init.mp4^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..3424acfec
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac51-48000-128000-1.m4s^headers^ b/dom/media/mediasource/test/aac51-48000-128000-1.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..b02bfd043
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/aac51-48000-128000-2.m4s^headers^ b/dom/media/mediasource/test/aac51-48000-128000-2.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..7d62401f2
--- /dev/null
+++ b/dom/media/mediasource/test/aac51-48000-128000-init.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/aac51-48000-128000-init.mp4^headers^ b/dom/media/mediasource/test/aac51-48000-128000-init.mp4^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..a237f2e91
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop1.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..d1f5e6a0b
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop10.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop10.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop10.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..57232fb35
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop11.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop11.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop11.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..f9b18713e
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop12.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop12.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop12.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..f2a876946
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop13.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop13.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop13.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..baa0d8578
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop2.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..4fd8b9cb6
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop2s.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop2s.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop2s.mp4^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..ed313e668
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop3.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop3.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop3.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..7709ac08c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop4.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop4.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop4.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..6d36788e4
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop5.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop5.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop5.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..64f475c70
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop6.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop6.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop6.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..c148918d6
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop7.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop7.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop7.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..707dd4848
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop8.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop8.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop8.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..538cf72a4
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop9.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop9.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop9.m4s^headers^
new file mode 100644
index 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
new file mode 100755
index 000000000..3dad336e8
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video1.m4s^headers^
new file mode 100644
index 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
new file mode 100755
index 000000000..dd7491241
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-video2.m4s^headers^
new file mode 100644
index 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
new file mode 100755
index 000000000..b1a2d4405
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_480_624kbps-videoinit.mp4^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..33da98b5a
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio1.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..36a98afd2
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio10.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..23d4aa8d8
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio11.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..96f4bcc34
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio2.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..7de4bd0ca
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio3.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..494c71eb9
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio4.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..b50496b6c
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio5.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..02cf4d363
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio6.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..bb2252889
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio7.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..04a6a7af9
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio8.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..cb94b529a
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audio9.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..bbf272197
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_audioinit.mp4^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..929118251
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video1.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video1.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..72c7afaca
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video10.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video10.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video10.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..e6109f5e7
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video11.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video11.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video11.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..5c54a510f
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video12.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video12.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video12.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..c64f38a33
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video13.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video13.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video13.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..cd34fae56
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video2.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video2.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video2.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..5a1334004
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video3.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video3.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video3.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..e8d96b6ed
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video4.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video4.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video4.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..ca6a82046
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video5.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video5.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video5.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..fe9824355
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video6.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video6.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video6.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..3351fa685
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video7.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video7.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video7.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..af26ae5f9
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video8.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video8.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video8.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..25be672c1
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_video9.m4s
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_video9.m4s^headers^ b/dom/media/mediasource/test/bipbop/bipbop_video9.m4s^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..7c9c533c3
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbop_videoinit.mp4^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..39f0575a7
--- /dev/null
+++ b/dom/media/mediasource/test/bipbop/bipbopinit.mp4
Binary files differ
diff --git a/dom/media/mediasource/test/bipbop/bipbopinit.mp4^headers^ b/dom/media/mediasource/test/bipbop/bipbopinit.mp4^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..72b029723
--- /dev/null
+++ b/dom/media/mediasource/test/seek.webm
Binary files differ
diff --git a/dom/media/mediasource/test/seek.webm^headers^ b/dom/media/mediasource/test/seek.webm^headers^
new file mode 100644
index 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
new file mode 100644
index 000000000..8a76e0647
--- /dev/null
+++ b/dom/media/mediasource/test/seek_lowres.webm
Binary files differ
diff --git a/dom/media/mediasource/test/seek_lowres.webm^headers^ b/dom/media/mediasource/test/seek_lowres.webm^headers^
new file mode 100644
index 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>