079d7092 by David LaPalomento

Merge pull request #165 from videojs/hotfix/src-change

Cleanup the current source when loading a new one
2 parents 667e96ef b3bf48b9
...@@ -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 });
......