RESOLVED FIXED 165336
[MSE] MediaSource.endOfStream() triggers updateend event
https://bugs.webkit.org/show_bug.cgi?id=165336
Summary [MSE] MediaSource.endOfStream() triggers updateend event
Joey Parrish
Reported 2016-12-02 14:10:21 PST
Shaka Player (https://github.com/google/shaka-player) discovered that calling endOfStream() on Safari's MediaSource can trigger an unexpected 'updateend' event. In our test, we set a duration, append several segments, then call endOfStream(). endOfStream() should never result in an 'updateend' event according to the spec. Quoting the MSE spec: https://www.w3.org/TR/media-source/#end-of-stream-algorithm ===== 2.4.7 End of stream algorithm 1. Change the readyState attribute value to "ended". 2. Queue a task to fire a simple event named sourceended at the MediaSource. 3. If error is not set 1. Run the duration change algorithm with new duration set to the largest track buffer ranges end time across all the track buffers across all SourceBuffer objects in sourceBuffers. NOTE: This allows the duration to properly reflect the end of the appended media segments. For example, if the duration was explicitly set to 10 seconds and only media segments for 0 to 5 seconds were appended before endOfStream() was called, then the duration will get updated to 5 seconds. ===== 2.4.6 Duration change 1. If the current value of duration is equal to new duration, then return. 2. If new duration is less than the highest presentation timestamp of any buffered coded frames for all SourceBuffer objects in sourceBuffers, then throw an InvalidStateError exception and abort these steps. NOTE: Duration reductions that would truncate currently buffered media are disallowed. When truncation is necessary, use remove() to reduce the buffered range before updating duration. ===== In this repro, the duration reduction is triggered by endOfStream(), which sets the new duration to the largest end time. Therefore, the new duration cannot truncate currently buffered media, which would be disallowed anyway. There is no reason for 'updateend' to fire. The event only fires when endOfStream() causes a reduction in duration. Could this perhaps be caused by an inappropriate call to the "range removal" algorithm? This is a problem because 'updateend' must be used to carefully track SourceBuffer state. If I call endOfStream() (which should be synchronous), followed by some async operation, the 'updateend' event can cause the application to believe that the other operation is complete, even though it is not. This can, in turn, trick the app into starting other operations at a time when they will fail. To reproduce: 1. Visit http://storage.googleapis.com/shaka-demo-assets/_bugs/safari-mse-endofstream/index.html in Safari 10 2. Open the JavaScript console 3. Observe the error message "Unexpected updateend event!" Reproducible on macOS Sierra, Safari 10.0.1 (12602.2.14.0.7). *Not* reproducible in WebKit nightly r209234.
Attachments
johnsfreemusic
Comment 1 2016-12-20 10:42:39 PST
Was about to file a similar bug. Not only does endOfStream fire an additional updateend event but it also sets the updating property to true. The audioplayer I work on calls endOfStream before a remove to help avoid the audio drift problem found on many browsers (that is to say that what MSE reports as the end of the buffer is not accurate). However since endOfStream causes updating to be true remove will throw an exception (the spec does say that you cannot remove while updating is true). So endOfStream is triggering something to cause the source buffer to enter the updating state (and eventually leave which fires updateend).
Radar WebKit Bug Importer
Comment 2 2016-12-20 10:42:52 PST
Joey Parrish
Comment 3 2016-12-20 10:55:08 PST
Yes, and it's almost impossible to polyfill this behavior without a user-agent check to determine the Safari version. Safari 10 sets updating to true and fires 'updateend'. Safari 9 sets updating to true but *doesn't* fire 'updateend'. So if you use updating=true to decide whether or not to wait for the extra 'updateend', you will stall your MediaSource code on Safari 9.
Joey Parrish
Comment 4 2017-10-03 14:47:13 PDT
No longer reproducible on Safari 11.
Note You need to log in before you can comment on or make changes to this bug.