OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <html> | 2 <html> |
3 <head> | 3 <head> |
4 <script src="/w3c/resources/testharness.js"></script> | 4 <script src="/w3c/resources/testharness.js"></script> |
5 <script src="/w3c/resources/testharnessreport.js"></script> | 5 <script src="/w3c/resources/testharnessreport.js"></script> |
6 <script src="mediasource-util.js"></script> | 6 <script src="mediasource-util.js"></script> |
7 <link rel='stylesheet' href='/w3c/resources/testharness.css'> | 7 <link rel='stylesheet' href='/w3c/resources/testharness.css'> |
8 </head> | 8 </head> |
9 <body> | 9 <body> |
10 <div id="log"></div> | 10 <div id="log"></div> |
11 <script> | 11 <script> |
12 function mediasource_truncated_duration_seek_test(testFunction, descri
ption, options) | 12 function mediasource_duration_below_currentTime_seek_test(testFunction
, description, options) |
13 { | 13 { |
14 return mediasource_testafterdataloaded(function(test, mediaElement
, mediaSource, segmentInfo, sourceBuffer, mediaData) | 14 return mediasource_testafterdataloaded(function(test, mediaElement
, mediaSource, segmentInfo, sourceBuffer, mediaData) |
15 { | 15 { |
16 assert_greater_than(segmentInfo.duration, 2, 'Sufficient test
media duration'); | 16 assert_greater_than(segmentInfo.duration, 2, 'Sufficient test
media duration'); |
17 | 17 |
18 var fullDuration = segmentInfo.duration; | 18 var fullDuration = segmentInfo.duration; |
19 var seekTo = fullDuration / 2.0; | 19 var seekTo = fullDuration / 2.0; |
20 var truncatedDuration = seekTo / 2.0; | 20 var reducedDuration = seekTo / 2.0; |
21 | 21 |
22 mediaElement.play(); | 22 mediaElement.play(); |
23 | 23 |
24 // Append all the segments | 24 // Append all the segments |
25 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer'); | 25 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer appe
nd completed'); |
26 test.expectEvent(mediaElement, 'playing', 'Playing triggered')
; | 26 test.expectEvent(mediaElement, 'playing', 'Playing triggered')
; |
27 sourceBuffer.appendBuffer(mediaData); | 27 sourceBuffer.appendBuffer(mediaData); |
28 | 28 |
29 test.waitForExpectedEvents(function() | 29 test.waitForExpectedEvents(function() |
30 { | 30 { |
31 assert_equals(mediaElement.duration, fullDuration, 'mediaE
lement fullDuration'); | 31 assert_equals(mediaElement.duration, fullDuration, 'mediaE
lement duration matches fullDuration'); |
32 assert_equals(mediaSource.duration, fullDuration, 'mediaSo
urce fullDuration'); | 32 assert_equals(mediaSource.duration, fullDuration, 'mediaSo
urce duration matches fullDuration'); |
33 | 33 |
34 test.expectEvent(mediaElement, 'seeking', 'seeking to seek
To'); | 34 test.expectEvent(mediaElement, 'seeking', 'seeking to seek
To'); |
35 test.expectEvent(mediaElement, 'timeupdate', 'timeupdate w
hile seeking to seekTo'); | 35 test.expectEvent(mediaElement, 'timeupdate', 'timeupdate w
hile seeking to seekTo'); |
36 test.expectEvent(mediaElement, 'seeked', 'seeked to seekTo
'); | 36 test.expectEvent(mediaElement, 'seeked', 'seeked to seekTo
'); |
37 mediaElement.currentTime = seekTo; | 37 mediaElement.currentTime = seekTo; |
38 assert_true(mediaElement.seeking, 'mediaElement.seeking (t
o seekTo)'); | 38 assert_true(mediaElement.seeking, 'mediaElement.seeking (t
o seekTo)'); |
39 }); | 39 }); |
40 | 40 |
41 test.waitForExpectedEvents(function() | 41 test.waitForExpectedEvents(function() |
42 { | 42 { |
43 assert_greater_than_equal(mediaElement.currentTime, seekTo
, 'Playback time has reached seekTo'); | 43 assert_greater_than_equal(mediaElement.currentTime, seekTo
, 'Playback time has reached seekTo'); |
44 assert_equals(mediaElement.duration, fullDuration, 'mediaE
lement fullDuration after seekTo'); | 44 assert_equals(mediaElement.duration, fullDuration, 'mediaE
lement duration matches fullDuration after seekTo'); |
45 assert_equals(mediaSource.duration, fullDuration, 'mediaSo
urce fullDuration after seekTo'); | 45 assert_equals(mediaSource.duration, fullDuration, 'mediaSo
urce duration matches fullDuration after seekTo'); |
46 assert_false(mediaElement.seeking, 'mediaElement.seeking a
fter seeked to seekTo'); | 46 assert_false(mediaElement.seeking, 'mediaElement.seeking a
fter seeked to seekTo'); |
47 | 47 |
48 test.expectEvent(mediaElement, 'seeking', 'Seeking to trun
cated duration'); | 48 // Explicitly remove buffered media beyond the new reduced
duration prior to reducing duration. |
49 mediaSource.duration = truncatedDuration; | 49 // Implicit removal of buffered media as part of duration
reduction is disallowed as of |
50 assert_true(mediaElement.seeking, 'Seeking after setting t
runcatedDuration'); | 50 // https://github.com/w3c/media-source/pull/65/ |
| 51 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer
range removal completed'); |
| 52 sourceBuffer.remove(reducedDuration, fullDuration); |
| 53 assert_true(sourceBuffer.updating, 'sourceBuffer.updating
during range removal'); |
51 }); | 54 }); |
52 | 55 |
53 test.waitForExpectedEvents(function() | 56 test.waitForExpectedEvents(function() |
54 { | 57 { |
55 assert_equals(mediaElement.currentTime, truncatedDuration, | 58 assert_false(sourceBuffer.updating, 'sourceBuffer.updating
after range removal'); |
56 'Playback time is truncatedDuration while se
eking'); | 59 assert_greater_than_equal(mediaElement.currentTime, seekTo
, |
57 assert_true(mediaElement.seeking, 'mediaElement.seeking wh
ile seeking to truncatedDuration'); | 60 'Playback time is still at least
seekTo after range removal'); |
58 assert_equals(mediaElement.duration, truncatedDuration, | 61 |
59 'mediaElement truncatedDuration during seek
to it'); | 62 test.expectEvent(mediaElement, 'seeking', 'Seeking to redu
ced duration'); |
60 assert_equals(mediaSource.duration, truncatedDuration, | 63 mediaSource.duration = reducedDuration; |
61 'mediaSource truncatedDuration during seek t
o it'); | 64 assert_true(mediaElement.seeking, 'Seeking after setting r
educedDuration'); |
| 65 }); |
| 66 |
| 67 test.waitForExpectedEvents(function() |
| 68 { |
| 69 assert_equals(mediaElement.currentTime, reducedDuration, |
| 70 'Playback time is reducedDuration while seek
ing'); |
| 71 assert_true(mediaElement.seeking, 'mediaElement.seeking wh
ile seeking to reducedDuration'); |
| 72 assert_equals(mediaElement.duration, reducedDuration, |
| 73 'mediaElement duration matches reducedDurati
on during seek to it'); |
| 74 assert_equals(mediaSource.duration, reducedDuration, |
| 75 'mediaSource duration matches reducedDuratio
n during seek to it'); |
62 | 76 |
63 // FIXME: Confirm 'waiting' and then 'stalled' fire here.
See http://crbug.com/266592. | 77 // FIXME: Confirm 'waiting' and then 'stalled' fire here.
See http://crbug.com/266592. |
64 | 78 |
65 testFunction(test, mediaElement, mediaSource, segmentInfo,
sourceBuffer, mediaData, | 79 testFunction(test, mediaElement, mediaSource, segmentInfo,
sourceBuffer, mediaData, |
66 truncatedDuration); | 80 reducedDuration); |
67 }); | 81 }); |
68 }, description, options); | 82 }, description, options); |
69 } | 83 } |
70 | 84 |
71 mediasource_truncated_duration_seek_test(function(test, mediaElement,
mediaSource, segmentInfo, sourceBuffer, | 85 mediasource_duration_below_currentTime_seek_test(function(test, mediaE
lement, mediaSource, segmentInfo, |
72 mediaData, truncated
Duration) | 86 sourceBuffer, mediaDa
ta, reducedDuration) |
73 { | 87 { |
74 // Tests that duration truncation below current playback position | 88 // Tests that duration reduction below current playback position |
75 // starts seek to new duration. | 89 // starts seek to new duration. |
76 test.done(); | 90 test.done(); |
77 }, 'Test seek starts on duration truncation below currentTime'); | 91 }, 'Test seek starts on duration reduction below currentTime'); |
78 | 92 |
79 mediasource_truncated_duration_seek_test(function(test, mediaElement,
mediaSource, segmentInfo, sourceBuffer, | 93 mediasource_duration_below_currentTime_seek_test(function(test, mediaE
lement, mediaSource, segmentInfo, |
80 mediaData, truncated
Duration) | 94 sourceBuffer, mediaDa
ta, reducedDuration) |
81 { | 95 { |
82 // The duration has been truncated at this point, and there is an | 96 // The duration has been reduced at this point, and there is an |
83 // outstanding seek pending. | 97 // outstanding seek pending. |
84 test.expectEvent(sourceBuffer, 'updateend', 'updateend after appen
ding more data'); | 98 test.expectEvent(sourceBuffer, 'updateend', 'updateend after appen
ding more data'); |
85 | 99 |
86 // FIXME: Confirm 'playing' fires here. See http://crbug.com/26659
2. | 100 // FIXME: Confirm 'playing' fires here. See http://crbug.com/26659
2. |
87 | 101 |
88 test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while fin
ishing seek to truncatedDuration'); | 102 test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while fin
ishing seek to reducedDuration'); |
89 test.expectEvent(mediaElement, 'seeked', 'seeked to truncatedDurat
ion'); | 103 test.expectEvent(mediaElement, 'seeked', 'seeked to reducedDuratio
n'); |
90 | 104 |
91 // Allow seek to complete by appending more data beginning at the | 105 // Allow seek to complete by appending more data beginning at the |
92 // truncated duration timestamp. | 106 // reduced duration timestamp. |
93 sourceBuffer.timestampOffset = truncatedDuration; | 107 sourceBuffer.timestampOffset = reducedDuration; |
94 sourceBuffer.appendBuffer(mediaData); | 108 sourceBuffer.appendBuffer(mediaData); |
95 | 109 |
96 test.waitForExpectedEvents(function() | 110 test.waitForExpectedEvents(function() |
97 { | 111 { |
98 assert_greater_than_equal(mediaElement.currentTime, truncatedD
uration, | 112 assert_greater_than_equal(mediaElement.currentTime, reducedDur
ation, |
99 'Playback time has reached truncated
Duration'); | 113 'Playback time has reached reducedDu
ration'); |
100 assert_approx_equals(mediaElement.duration, truncatedDuration
+ segmentInfo.duration, 0.05, | 114 assert_approx_equals(mediaElement.duration, reducedDuration +
segmentInfo.duration, 0.05, |
101 'mediaElement duration increased by new a
ppend'); | 115 'mediaElement duration increased by new a
ppend'); |
102 assert_equals(mediaSource.duration, mediaElement.duration, | 116 assert_equals(mediaSource.duration, mediaElement.duration, |
103 'mediaSource duration increased by new append'); | 117 'mediaSource duration increased by new append'); |
104 assert_false(mediaElement.seeking, 'mediaElement.seeking after
seeked to truncatedDuration'); | 118 assert_false(mediaElement.seeking, 'mediaElement.seeking after
seeked to reducedDuration'); |
105 | 119 |
106 test.done(); | 120 test.done(); |
107 }); | 121 }); |
108 }, 'Test appendBuffer completes previous seek to truncated duration'); | 122 }, 'Test appendBuffer completes previous seek to reduced duration'); |
109 | 123 |
110 mediasource_truncated_duration_seek_test(function(test, mediaElement,
mediaSource, segmentInfo, sourceBuffer, | 124 mediasource_duration_below_currentTime_seek_test(function(test, mediaE
lement, mediaSource, segmentInfo, |
111 mediaData, truncated
Duration) | 125 sourceBuffer, mediaDa
ta, reducedDuration) |
112 { | 126 { |
113 // The duration has been truncated at this point, and there is an | 127 // The duration has been reduced at this point, and there is an |
114 // outstanding seek pending. | 128 // outstanding seek pending. |
115 test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowle
dged'); | 129 test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowle
dged'); |
116 | 130 |
117 // FIXME: Investigate if 'playing' should fire here. See http://cr
bug.com/266592. | 131 // FIXME: Investigate if 'playing' should fire here. See http://cr
bug.com/266592. |
118 | 132 |
119 test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while fin
ishing seek to truncatedDuration'); | 133 test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while fin
ishing seek to reducedDuration'); |
120 test.expectEvent(mediaElement, 'seeked', 'seeked to truncatedDurat
ion'); | 134 test.expectEvent(mediaElement, 'seeked', 'seeked to reducedDuratio
n'); |
121 | 135 |
122 // Call endOfStream() to complete the pending seek. | 136 // Call endOfStream() to complete the pending seek. |
123 mediaSource.endOfStream(); | 137 mediaSource.endOfStream(); |
124 | 138 |
125 test.waitForExpectedEvents(function() | 139 test.waitForExpectedEvents(function() |
126 { | 140 { |
127 assert_equals(mediaElement.currentTime, truncatedDuration, | 141 assert_equals(mediaElement.currentTime, reducedDuration, |
128 'Playback time has reached truncatedDuration'); | 142 'Playback time has reached reducedDuration'); |
129 assert_equals(mediaElement.duration, truncatedDuration, | 143 assert_equals(mediaElement.duration, reducedDuration, |
130 'mediaElement truncatedDuration after seek to it
'); | 144 'mediaElement duration matches reducedDuration a
fter seek to it'); |
131 assert_equals(mediaSource.duration, truncatedDuration, | 145 assert_equals(mediaSource.duration, reducedDuration, |
132 'mediaSource truncatedDuration after seek to it'
); | 146 'mediaSource duration matches reducedDuration af
ter seek to it'); |
133 assert_false(mediaElement.seeking, 'mediaElement.seeking after
seeked to truncatedDuration'); | 147 assert_false(mediaElement.seeking, 'mediaElement.seeking after
seeked to reducedDuration'); |
134 | 148 |
135 test.done(); | 149 test.done(); |
136 }); | 150 }); |
137 }, 'Test endOfStream completes previous seek to truncated duration'); | 151 }, 'Test endOfStream completes previous seek to reduced duration'); |
138 | 152 |
139 mediasource_testafterdataloaded(function(test, mediaElement, mediaSour
ce, segmentInfo, sourceBuffer, mediaData) | 153 mediasource_testafterdataloaded(function(test, mediaElement, mediaSour
ce, segmentInfo, sourceBuffer, mediaData) |
140 { | 154 { |
141 assert_greater_than(segmentInfo.duration, 2, 'Sufficient test medi
a duration'); | 155 assert_greater_than(segmentInfo.duration, 2, 'Sufficient test medi
a duration'); |
142 | 156 |
143 var fullDuration = segmentInfo.duration; | 157 var fullDuration = segmentInfo.duration; |
144 var newDuration = 0.5; | 158 var newDuration = fullDuration * 2; |
145 | 159 |
146 var durationchangeEventCounter = 0; | 160 var durationchangeEventCounter = 0; |
147 var expectedDurationChangeEventCount = 1; | 161 var expectedDurationChangeEventCount = 1; |
148 var durationchangeEventHandler = test.step_func(function(event) | 162 var durationchangeEventHandler = test.step_func(function(event) |
149 { | 163 { |
150 assert_equals(mediaElement.duration, newDuration, 'mediaElemen
t newDuration'); | 164 assert_equals(mediaElement.duration, newDuration, 'mediaElemen
t duration matches newDuration'); |
151 assert_equals(mediaSource.duration, newDuration, 'mediaSource
newDuration'); | 165 assert_equals(mediaSource.duration, newDuration, 'mediaSource
duration matches newDuration'); |
152 durationchangeEventCounter++; | 166 durationchangeEventCounter++; |
153 }); | 167 }); |
154 | 168 |
155 mediaElement.play(); | 169 mediaElement.play(); |
156 | 170 |
157 // Append all the segments | 171 // Append all the segments |
158 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer'); | 172 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer append c
ompleted'); |
159 test.expectEvent(mediaElement, 'playing', 'Playing triggered'); | 173 test.expectEvent(mediaElement, 'playing', 'Playing triggered'); |
160 sourceBuffer.appendBuffer(mediaData); | 174 sourceBuffer.appendBuffer(mediaData); |
161 | 175 |
162 test.waitForExpectedEvents(function() | 176 test.waitForExpectedEvents(function() |
163 { | 177 { |
164 assert_equals(mediaElement.duration, fullDuration, 'mediaEleme
nt fullDuration'); | 178 assert_equals(mediaElement.duration, fullDuration, 'mediaEleme
nt duration matches fullDuration'); |
165 assert_equals(mediaSource.duration, fullDuration, 'mediaSource
fullDuration'); | 179 assert_equals(mediaSource.duration, fullDuration, 'mediaSource
duration matches fullDuration'); |
166 assert_less_than(mediaElement.currentTime, newDuration / 2, 'm
ediaElement currentTime'); | 180 assert_less_than(mediaElement.currentTime, newDuration / 2, 'm
ediaElement currentTime check'); |
167 | 181 |
168 // Media load also fires 'durationchange' event, so only start
counting them now. | 182 // Media load also fires 'durationchange' event, so only start
counting them now. |
169 mediaElement.addEventListener('durationchange', durationchange
EventHandler); | 183 mediaElement.addEventListener('durationchange', durationchange
EventHandler); |
170 | 184 |
171 // Truncate duration. This should result in one 'durationchang
e' fired. | 185 // Increase duration. This should result in one 'durationchang
e' fired. |
172 mediaSource.duration = newDuration; | 186 mediaSource.duration = newDuration; |
| 187 assert_false(sourceBuffer.updating, "sourceBuffer.updating aft
er duration set to newDuration"); |
173 | 188 |
174 assert_true(sourceBuffer.updating, "sourceBuffer.updating"); | |
175 test.expectEvent(sourceBuffer, "updateend"); | |
176 }); | |
177 | |
178 test.waitForExpectedEvents(function() | |
179 { | |
180 // Set duration again to make sure it does not trigger another
'durationchange' event. | 189 // Set duration again to make sure it does not trigger another
'durationchange' event. |
181 mediaSource.duration = newDuration; | 190 mediaSource.duration = newDuration; |
182 | 191 |
183 assert_false(sourceBuffer.updating, "sourceBuffer.updating"); | 192 assert_false(sourceBuffer.updating, "sourceBuffer.updating aft
er duration set again to newDuration"); |
184 | 193 |
185 // Mark endOfStream so that playback can reach 'ended' at the
new duration. | 194 // Mark endOfStream so that playback can reach 'ended' at the
new duration. |
186 test.expectEvent(mediaSource, 'sourceended', 'endOfStream ackn
owledged'); | 195 test.expectEvent(mediaSource, 'sourceended', 'endOfStream ackn
owledged'); |
187 mediaSource.endOfStream(); | 196 mediaSource.endOfStream(); |
188 | 197 |
189 // endOfStream can change duration downwards slightly. | 198 // endOfStream can change duration downwards slightly. |
190 // Allow for one more 'durationchange' event only in this case
. | 199 // Allow for one more 'durationchange' event only in this case
. |
191 var currentDuration = mediaSource.duration; | 200 var currentDuration = mediaSource.duration; |
192 if (currentDuration != newDuration) { | 201 if (currentDuration != newDuration) { |
193 assert_true(currentDuration > 0 && currentDuration < newDu
ration, 'adjusted duration'); | 202 assert_true(currentDuration > 0 && currentDuration < newDu
ration, 'adjusted duration check'); |
194 newDuration = currentDuration; | 203 newDuration = currentDuration; |
195 ++expectedDurationChangeEventCount; | 204 ++expectedDurationChangeEventCount; |
196 } | 205 } |
| 206 }); |
197 | 207 |
198 // Allow media to play to end while counting 'durationchange'
events. | 208 test.waitForExpectedEvents(function() |
199 test.expectEvent(mediaElement, 'ended', 'Playback ended'); | 209 { |
200 test.waitForExpectedEvents(function() | 210 // Allow any remaining queued durationchange to fire, while co
unting 'durationchange' them. |
| 211 test.step_timeout(test.step_func(function() |
201 { | 212 { |
202 mediaElement.removeEventListener('durationchange', duratio
nchangeEventHandler); | 213 mediaElement.removeEventListener('durationchange', duratio
nchangeEventHandler); |
203 assert_equals(durationchangeEventCounter, expectedDuration
ChangeEventCount, 'durationchanges'); | 214 assert_equals(durationchangeEventCounter, expectedDuration
ChangeEventCount, 'durationchange count check'); |
204 test.done(); | 215 test.done(); |
205 }); | 216 }), 0); |
206 }); | 217 }); |
207 }, 'Test setting same duration multiple times does not fire duplicate
durationchange', {timeout: 2500}); | 218 }, 'Test setting same duration multiple times does not fire duplicate
durationchange', {timeout: 2500}); |
208 | 219 |
| 220 mediasource_testafterdataloaded(function(test, mediaElement, mediaSour
ce, segmentInfo, sourceBuffer, mediaData) |
| 221 { |
| 222 assert_greater_than(segmentInfo.duration, 2, 'Sufficient test medi
a duration'); |
| 223 |
| 224 var fullDuration = segmentInfo.duration; |
| 225 |
| 226 // Append all the segments |
| 227 test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer'); |
| 228 sourceBuffer.appendBuffer(mediaData); |
| 229 |
| 230 test.waitForExpectedEvents(function() |
| 231 { |
| 232 assert_equals(mediaElement.duration, fullDuration, 'mediaEleme
nt duration matches fullDuration'); |
| 233 assert_equals(mediaSource.duration, fullDuration, 'mediaSource
duration matches fullDuration'); |
| 234 |
| 235 // TODO(wolenetz): Fine-tune this test to use the buffered att
ribute's highest end time |
| 236 // instead of fullDuration once Chrome correctly reports buffe
red PTS, not DTS. |
| 237 // See https://crbug.com/398130. |
| 238 |
| 239 // Setting duration to same as current, or increasing it, shou
ld not trigger exception. |
| 240 mediaSource.duration = fullDuration; |
| 241 mediaSource.duration = fullDuration + 1; |
| 242 |
| 243 // Reducing duration to below the highest buffered PTS should
trigger exception. |
| 244 assert_throws('InvalidStateError', |
| 245 function() { mediaSource.duration = fullDuration - 0.05; }
, |
| 246 'Duration reduction that truncates at least one whole code
d frame throws an exception.'); |
| 247 |
| 248 assert_equals(mediaSource.duration, fullDuration + 1, 'mediaSo
urce duration matches fullDuration+1'); |
| 249 |
| 250 // Reducing duration without truncating any buffered media sho
uld not trigger exception. |
| 251 mediaSource.duration = fullDuration; |
| 252 |
| 253 // Reducing duration by less then the minimum of the last test
audio and video frame |
| 254 // durations should not trigger exception. |
| 255 mediaSource.duration = fullDuration - 0.001; |
| 256 test.done(); |
| 257 }); |
| 258 }, 'Test duration reduction below highest buffered presentation time i
s disallowed'); |
| 259 |
209 </script> | 260 </script> |
210 </body> | 261 </body> |
211 </html> | 262 </html> |
OLD | NEW |