05ab599aad01b4f6121a4c58424213534adcca0b
[WebKit-https.git] / LayoutTests / imported / w3c / web-platform-tests / media-source / mediasource-duration.html
1 <!DOCTYPE html>
2 <!--  Copyright © 2016 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang).  -->
3 <html>
4     <head>
5         <title>MediaSource.duration &amp; HTMLMediaElement.duration test cases.</title>
6         <script src="/resources/testharness.js"></script>
7         <script src="/resources/testharnessreport.js"></script>
8         <script src="mediasource-util.js"></script>
9     </head>
10     <body>
11         <div id="log"></div>
12         <script>
13           function mediasource_truncated_duration_seek_test(testFunction, description, options)
14           {
15               return mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
16               {
17                   assert_greater_than(segmentInfo.duration, 2, 'Sufficient test media duration');
18
19                   var fullDuration = segmentInfo.duration;
20                   var seekTo = fullDuration / 2.0;
21                   var truncatedDuration = seekTo / 2.0;
22
23                   mediaElement.play();
24
25                   // Append all the segments
26                   test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
27                   test.expectEvent(mediaElement, 'playing', 'Playing triggered');
28                   sourceBuffer.appendBuffer(mediaData);
29
30                   test.waitForExpectedEvents(function()
31                   {
32                       test.expectEvent(mediaElement, 'seeking', 'seeking to seekTo');
33                       test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while seeking to seekTo');
34                       test.expectEvent(mediaElement, 'seeked', 'seeked to seekTo');
35                       mediaElement.currentTime = seekTo;
36                       assert_true(mediaElement.seeking, 'mediaElement.seeking (to seekTo)');
37                   });
38
39                   test.waitForExpectedEvents(function()
40                   {
41                       assert_greater_than_equal(mediaElement.currentTime, seekTo, 'Playback time has reached seekTo');
42                       assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to seekTo');
43
44                       assert_false(sourceBuffer.updating, 'sourceBuffer.updating');
45
46                       sourceBuffer.remove(truncatedDuration, Infinity);
47
48                       assert_true(sourceBuffer.updating, 'sourceBuffer.updating');
49                       test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
50                       test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
51                       test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
52                   });
53
54                   test.waitForExpectedEvents(function()
55                   {
56                       // remove will not remove partial frames. The truncated duration is as such the highest end time.
57                       truncatedDuration = sourceBuffer.buffered.end(sourceBuffer.buffered.length-1);
58                       assert_greater_than_equal(mediaElement.currentTime, seekTo, 'Playback time has reached seekTo');
59                       test.expectEvent(mediaElement, 'seeking', 'Seeking to truncated duration');
60
61                       assert_false(sourceBuffer.updating, 'sourceBuffer.updating');
62
63                       mediaSource.duration = truncatedDuration;
64
65                       assert_true(mediaElement.seeking, 'Seeking after setting truncatedDuration');
66                   });
67
68                   test.waitForExpectedEvents(function()
69                   {
70                       assert_equals(mediaElement.currentTime, truncatedDuration,
71                                     'Playback time is truncatedDuration while seeking');
72                       assert_true(mediaElement.seeking, 'mediaElement.seeking while seeking to truncatedDuration');
73                       assert_equals(mediaElement.duration, truncatedDuration,
74                                     'mediaElement truncatedDuration during seek to it');
75                       assert_equals(mediaSource.duration, truncatedDuration,
76                                     'mediaSource truncatedDuration during seek to it');
77
78                       testFunction(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData,
79                                    truncatedDuration);
80                   });
81               }, description, options);
82           }
83
84           mediasource_truncated_duration_seek_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer,
85                                                             mediaData, truncatedDuration)
86           {
87               // Tests that duration truncation below current playback position
88               // starts seek to new duration.
89               test.done();
90           }, 'Test seek starts on duration truncation below currentTime');
91
92           mediasource_truncated_duration_seek_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer,
93                                                             mediaData, truncatedDuration)
94           {
95               // The duration has been truncated at this point, and there is an
96               // outstanding seek pending.
97               test.expectEvent(sourceBuffer, 'updateend', 'updateend after appending more data');
98
99               test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while finishing seek to truncatedDuration');
100               test.expectEvent(mediaElement, 'seeked', 'seeked to truncatedDuration');
101
102               // Allow seek to complete by appending more data beginning at the
103               // truncated duration timestamp.
104               sourceBuffer.timestampOffset = truncatedDuration;
105               sourceBuffer.appendBuffer(mediaData);
106
107               test.waitForExpectedEvents(function()
108               {
109                   assert_greater_than_equal(mediaElement.currentTime, truncatedDuration,
110                                             'Playback time has reached truncatedDuration');
111                   assert_approx_equals(mediaElement.duration, truncatedDuration + segmentInfo.duration, 0.05,
112                                        'mediaElement duration increased by new append');
113                   assert_equals(mediaSource.duration, mediaElement.duration,
114                                 'mediaSource duration increased by new append');
115                   assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to truncatedDuration');
116
117                   test.done();
118               });
119           }, 'Test appendBuffer completes previous seek to truncated duration');
120
121           mediasource_truncated_duration_seek_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer,
122                                                             mediaData, truncatedDuration)
123           {
124               // The duration has been truncated at this point, and there is an
125               // outstanding seek pending.
126               test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowledged');
127
128               test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while finishing seek to truncatedDuration');
129               test.expectEvent(mediaElement, 'seeked', 'seeked to truncatedDuration');
130
131               // Call endOfStream() to complete the pending seek.
132               mediaSource.endOfStream();
133
134               test.waitForExpectedEvents(function()
135               {
136                   assert_greater_than_equal(mediaElement.currentTime, truncatedDuration,
137                                 'Playback time has reached truncatedDuration');
138                   // The mediaSource.readyState is "ended". Buffered ranges have been adjusted to the longest track.
139                   truncatedDuration = sourceBuffer.buffered.end(sourceBuffer.buffered.length-1);
140                   assert_equals(mediaElement.duration, truncatedDuration,
141                                 'mediaElement truncatedDuration after seek to it');
142                   assert_equals(mediaSource.duration, truncatedDuration,
143                                 'mediaSource truncatedDuration after seek to it');
144                   assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to truncatedDuration');
145
146                   test.done();
147               });
148           }, 'Test endOfStream completes previous seek to truncated duration');
149
150           mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
151           {
152               assert_greater_than(segmentInfo.duration, 2, 'Sufficient test media duration');
153
154               var fullDuration = segmentInfo.duration;
155               var newDuration = 0.5;
156
157               var expectedDurationChangeEventCount = 1;
158               var durationchangeEventCounter = 0;
159               var durationchangeEventHandler = test.step_func(function(event)
160               {
161                   assert_equals(mediaElement.duration, mediaSource.duration, 'mediaElement newDuration');
162                   // Final duration may be greater than originally set as per MSE's 2.4.6 Duration change
163                   // Adjust newDuration accordingly.
164                   assert_less_than_equal(newDuration, mediaSource.duration, 'mediaSource newDuration');
165                   durationchangeEventCounter++;
166               });
167
168               mediaElement.play();
169
170               // Append all the segments
171               test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
172               test.expectEvent(mediaElement, 'playing', 'Playing triggered');
173               sourceBuffer.appendBuffer(mediaData);
174
175               test.waitForExpectedEvents(function()
176               {
177                   assert_less_than(mediaElement.currentTime, newDuration / 2, 'mediaElement currentTime');
178
179                   assert_false(sourceBuffer.updating, "updating");
180
181                   // Truncate duration. This should result in one 'durationchange' fired.
182                   sourceBuffer.remove(newDuration, Infinity);
183
184                   assert_true(sourceBuffer.updating, "updating");
185                   test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
186                   test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
187                   test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
188               });
189
190               test.waitForExpectedEvents(function()
191               {
192                   // Media load also fires 'durationchange' event, so only start counting them now.
193                   mediaElement.addEventListener('durationchange', durationchangeEventHandler);
194
195                   assert_false(sourceBuffer.updating, "updating");
196
197                   // Truncate duration. This should result in one 'durationchange' fired.
198                   mediaSource.duration = newDuration;
199
200                   // Final duration may be greater than originally set as per MSE's 2.4.6 Duration change
201                   // Adjust newDuration accordingly.
202                   assert_true(newDuration <= mediaSource.duration, 'adjusted duration');
203                   newDuration = mediaSource.duration;
204
205                   // Set duration again to make sure it does not trigger another 'durationchange' event.
206                   mediaSource.duration = newDuration;
207
208                   // Mark endOfStream so that playback can reach 'ended' at the new duration.
209                   test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowledged');
210                   mediaSource.endOfStream();
211
212                   // endOfStream can change duration slightly.
213                   // Allow for one more 'durationchange' event only in this case.
214                   var currentDuration = mediaSource.duration;
215                   if (currentDuration != newDuration) {
216                       newDuration = currentDuration;
217                       ++expectedDurationChangeEventCount;
218                   }
219
220                   // Allow media to play to end while counting 'durationchange' events.
221                   test.expectEvent(mediaElement, 'ended', 'Playback ended');
222                   test.waitForExpectedEvents(function()
223                   {
224                       mediaElement.removeEventListener('durationchange', durationchangeEventHandler);
225                       assert_equals(durationchangeEventCounter, expectedDurationChangeEventCount, 'durationchanges');
226                       test.done();
227                   });
228               });
229           }, 'Test setting same duration multiple times does not fire duplicate durationchange');
230
231           mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
232           {
233               assert_greater_than(segmentInfo.duration, 2, 'Sufficient test media duration');
234
235               var fullDuration = segmentInfo.duration;
236               var newDuration = fullDuration / 2;
237
238               // Append all the segments
239               test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
240               test.expectEvent(mediaElement, 'loadedmetadata', 'mediaElement');
241               sourceBuffer.appendBuffer(mediaData);
242
243               test.waitForExpectedEvents(function()
244               {
245                   assert_false(sourceBuffer.updating, "updating");
246
247                   assert_throws("InvalidStateError", function()
248                   {
249                       mediaSource.duration = newDuration;
250                   }, "duration");
251
252                   test.done();
253               });
254           }, 'Test setting the duration to less than the highest starting presentation timestamp will throw');
255
256         </script>
257     </body>
258 </html>