Merge pull request #165 from videojs/hotfix/src-change
Cleanup the current source when loading a new one
Showing
2 changed files
with
65 additions
and
37 deletions
... | @@ -54,31 +54,39 @@ videojs.Hls.prototype.src = function(src) { | ... | @@ -54,31 +54,39 @@ videojs.Hls.prototype.src = function(src) { |
54 | mediaSource, | 54 | mediaSource, |
55 | source; | 55 | source; |
56 | 56 | ||
57 | if (src) { | 57 | // do nothing if the src is falsey |
58 | this.src_ = src; | 58 | if (!src) { |
59 | 59 | return; | |
60 | mediaSource = new videojs.MediaSource(); | ||
61 | source = { | ||
62 | src: videojs.URL.createObjectURL(mediaSource), | ||
63 | type: "video/flv" | ||
64 | }; | ||
65 | this.mediaSource = mediaSource; | ||
66 | |||
67 | this.segmentBuffer_ = []; | ||
68 | this.segmentParser_ = new videojs.Hls.SegmentParser(); | ||
69 | |||
70 | // load the MediaSource into the player | ||
71 | this.mediaSource.addEventListener('sourceopen', videojs.bind(this, this.handleSourceOpen)); | ||
72 | |||
73 | this.player().ready(function() { | ||
74 | // do nothing if the tech has been disposed already | ||
75 | // this can occur if someone sets the src in player.ready(), for instance | ||
76 | if (!tech.el()) { | ||
77 | return; | ||
78 | } | ||
79 | tech.el().vjs_src(source.src); | ||
80 | }); | ||
81 | } | 60 | } |
61 | |||
62 | // if there is already a source loaded, clean it up | ||
63 | if (this.src_) { | ||
64 | this.resetSrc_(); | ||
65 | } | ||
66 | |||
67 | this.src_ = src; | ||
68 | |||
69 | mediaSource = new videojs.MediaSource(); | ||
70 | source = { | ||
71 | src: videojs.URL.createObjectURL(mediaSource), | ||
72 | type: "video/flv" | ||
73 | }; | ||
74 | this.mediaSource = mediaSource; | ||
75 | |||
76 | this.segmentBuffer_ = []; | ||
77 | this.segmentParser_ = new videojs.Hls.SegmentParser(); | ||
78 | |||
79 | // load the MediaSource into the player | ||
80 | this.mediaSource.addEventListener('sourceopen', videojs.bind(this, this.handleSourceOpen)); | ||
81 | |||
82 | this.player().ready(function() { | ||
83 | // do nothing if the tech has been disposed already | ||
84 | // this can occur if someone sets the src in player.ready(), for instance | ||
85 | if (!tech.el()) { | ||
86 | return; | ||
87 | } | ||
88 | tech.el().vjs_src(source.src); | ||
89 | }); | ||
82 | }; | 90 | }; |
83 | 91 | ||
84 | videojs.Hls.prototype.handleSourceOpen = function() { | 92 | videojs.Hls.prototype.handleSourceOpen = function() { |
... | @@ -231,16 +239,11 @@ videojs.Hls.prototype.updateDuration = function(playlist) { | ... | @@ -231,16 +239,11 @@ videojs.Hls.prototype.updateDuration = function(playlist) { |
231 | }; | 239 | }; |
232 | 240 | ||
233 | /** | 241 | /** |
234 | * Abort all outstanding work and cleanup. | 242 | * Clear all buffers and reset any state relevant to the current |
243 | * source. After this function is called, the tech should be in a | ||
244 | * state suitable for switching to a different video. | ||
235 | */ | 245 | */ |
236 | videojs.Hls.prototype.dispose = function() { | 246 | videojs.Hls.prototype.resetSrc_ = function() { |
237 | var player = this.player(); | ||
238 | |||
239 | // remove event handlers | ||
240 | player.off('timeupdate', this.fillBuffer); | ||
241 | player.off('timeupdate', this.drainBuffer); | ||
242 | player.off('waiting', this.drainBuffer); | ||
243 | |||
244 | if (this.segmentXhr_) { | 247 | if (this.segmentXhr_) { |
245 | this.segmentXhr_.onreadystatechange = null; | 248 | this.segmentXhr_.onreadystatechange = null; |
246 | this.segmentXhr_.abort(); | 249 | this.segmentXhr_.abort(); |
... | @@ -251,12 +254,28 @@ videojs.Hls.prototype.dispose = function() { | ... | @@ -251,12 +254,28 @@ videojs.Hls.prototype.dispose = function() { |
251 | keyXhr.abort(); | 254 | keyXhr.abort(); |
252 | keyXhr = null; | 255 | keyXhr = null; |
253 | } | 256 | } |
254 | if (this.playlists) { | ||
255 | this.playlists.dispose(); | ||
256 | } | ||
257 | if (this.sourceBuffer) { | 257 | if (this.sourceBuffer) { |
258 | this.sourceBuffer.abort(); | 258 | this.sourceBuffer.abort(); |
259 | } | 259 | } |
260 | }; | ||
261 | |||
262 | /** | ||
263 | * Abort all outstanding work and cleanup. | ||
264 | */ | ||
265 | videojs.Hls.prototype.dispose = function() { | ||
266 | var player = this.player(); | ||
267 | |||
268 | // remove event handlers | ||
269 | player.off('timeupdate', this.fillBuffer); | ||
270 | player.off('timeupdate', this.drainBuffer); | ||
271 | player.off('waiting', this.drainBuffer); | ||
272 | |||
273 | if (this.playlists) { | ||
274 | this.playlists.dispose(); | ||
275 | } | ||
276 | |||
277 | this.resetSrc_(); | ||
278 | |||
260 | videojs.Flash.prototype.dispose.call(this); | 279 | videojs.Flash.prototype.dispose.call(this); |
261 | }; | 280 | }; |
262 | 281 | ... | ... |
... | @@ -293,7 +293,9 @@ test('recognizes domain-relative URLs', function() { | ... | @@ -293,7 +293,9 @@ test('recognizes domain-relative URLs', function() { |
293 | }); | 293 | }); |
294 | 294 | ||
295 | test('re-initializes the tech for each source', function() { | 295 | test('re-initializes the tech for each source', function() { |
296 | var firstPlaylists, secondPlaylists, firstMSE, secondMSE; | 296 | var firstPlaylists, secondPlaylists, firstMSE, secondMSE, aborts; |
297 | |||
298 | aborts = 0; | ||
297 | 299 | ||
298 | player.src({ | 300 | player.src({ |
299 | src: 'manifest/master.m3u8', | 301 | src: 'manifest/master.m3u8', |
... | @@ -302,6 +304,11 @@ test('re-initializes the tech for each source', function() { | ... | @@ -302,6 +304,11 @@ test('re-initializes the tech for each source', function() { |
302 | openMediaSource(player); | 304 | openMediaSource(player); |
303 | firstPlaylists = player.hls.playlists; | 305 | firstPlaylists = player.hls.playlists; |
304 | firstMSE = player.hls.mediaSource; | 306 | firstMSE = player.hls.mediaSource; |
307 | player.hls.sourceBuffer.abort = function() { | ||
308 | aborts++; | ||
309 | }; | ||
310 | standardXHRResponse(requests.shift()); | ||
311 | standardXHRResponse(requests.shift()); | ||
305 | 312 | ||
306 | player.src({ | 313 | player.src({ |
307 | src: 'manifest/master.m3u8', | 314 | src: 'manifest/master.m3u8', |
... | @@ -311,6 +318,8 @@ test('re-initializes the tech for each source', function() { | ... | @@ -311,6 +318,8 @@ test('re-initializes the tech for each source', function() { |
311 | secondPlaylists = player.hls.playlists; | 318 | secondPlaylists = player.hls.playlists; |
312 | secondMSE = player.hls.mediaSource; | 319 | secondMSE = player.hls.mediaSource; |
313 | 320 | ||
321 | equal(1, aborts, 'aborted the old source buffer'); | ||
322 | ok(requests[0].aborted, 'aborted the old segment request'); | ||
314 | notStrictEqual(firstPlaylists, secondPlaylists, 'the playlist object is not reused'); | 323 | notStrictEqual(firstPlaylists, secondPlaylists, 'the playlist object is not reused'); |
315 | notStrictEqual(firstMSE, secondMSE, 'the media source object is not reused'); | 324 | notStrictEqual(firstMSE, secondMSE, 'the media source object is not reused'); |
316 | }); | 325 | }); | ... | ... |
-
Please register or sign in to post a comment