63c605b7 by Brandon Bay

Solving the hang on transition issue

Addressing the issue where video playback would hang when transitioning
to a different quality stream with a large discontinuity in media
sequence.
1 parent c1f9ab02
...@@ -89,6 +89,18 @@ videojs.Hls.prototype.src = function(src) { ...@@ -89,6 +89,18 @@ videojs.Hls.prototype.src = function(src) {
89 }); 89 });
90 }; 90 };
91 91
92 videojs.Hls.setMediaIndexForLive = function(selectedPlaylist) {
93 var tailIterator = selectedPlaylist.segments.length,
94 tailDuration = 0;
95
96 while (tailDuration < 30 && tailIterator > 0) {
97 tailDuration += selectedPlaylist.segments[tailIterator - 1].duration;
98 tailIterator--;
99 }
100
101 return tailIterator;
102 }
103
92 videojs.Hls.prototype.handleSourceOpen = function() { 104 videojs.Hls.prototype.handleSourceOpen = function() {
93 // construct the video data buffer and set the appropriate MIME type 105 // construct the video data buffer and set the appropriate MIME type
94 var 106 var
...@@ -110,7 +122,7 @@ videojs.Hls.prototype.handleSourceOpen = function() { ...@@ -110,7 +122,7 @@ videojs.Hls.prototype.handleSourceOpen = function() {
110 122
111 this.playlists.on('loadedmetadata', videojs.bind(this, function() { 123 this.playlists.on('loadedmetadata', videojs.bind(this, function() {
112 var selectedPlaylist, loaderHandler, oldBitrate, newBitrate, segmentDuration, 124 var selectedPlaylist, loaderHandler, oldBitrate, newBitrate, segmentDuration,
113 segmentDlTime, setupEvents, threshold, tailIterator, tailDuration; 125 segmentDlTime, setupEvents, threshold;
114 126
115 setupEvents = function() { 127 setupEvents = function() {
116 this.fillBuffer(); 128 this.fillBuffer();
...@@ -143,13 +155,7 @@ videojs.Hls.prototype.handleSourceOpen = function() { ...@@ -143,13 +155,7 @@ videojs.Hls.prototype.handleSourceOpen = function() {
143 155
144 // start live playlists 30 seconds before the current time 156 // start live playlists 30 seconds before the current time
145 if (this.duration() === Infinity && this.mediaIndex === 0 && selectedPlaylist.segments) { 157 if (this.duration() === Infinity && this.mediaIndex === 0 && selectedPlaylist.segments) {
146 tailIterator = selectedPlaylist.segments.length; 158 this.mediaIndex = videojs.Hls.setMediaIndexForLive(selectedPlaylist);
147 tailDuration = 0;
148 while (tailDuration < 30 && tailIterator > 0) {
149 tailDuration += selectedPlaylist.segments[tailIterator - 1].duration;
150 tailIterator--;
151 }
152 this.mediaIndex = tailIterator;
153 } 159 }
154 160
155 // this threshold is to account for having a high latency on the manifest 161 // this threshold is to account for having a high latency on the manifest
...@@ -791,7 +797,8 @@ videojs.Hls.getPlaylistTotalDuration = function(playlist) { ...@@ -791,7 +797,8 @@ videojs.Hls.getPlaylistTotalDuration = function(playlist) {
791 videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) { 797 videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) {
792 var 798 var
793 i, 799 i,
794 originalSegment; 800 originalSegment,
801 translatedMediaIndex;
795 802
796 // no segments have been loaded from the original playlist 803 // no segments have been loaded from the original playlist
797 if (mediaIndex === 0) { 804 if (mediaIndex === 0) {
...@@ -802,17 +809,15 @@ videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) { ...@@ -802,17 +809,15 @@ videojs.Hls.translateMediaIndex = function(mediaIndex, original, update) {
802 return 0; 809 return 0;
803 } 810 }
804 811
805 // try to sync based on URI 812 translatedMediaIndex = (mediaIndex + (original.mediaSequence - update.mediaSequence))
806 i = update.segments.length; 813
807 originalSegment = original.segments[mediaIndex - 1]; 814 if (update.duration() === Infinity && translatedMediaIndex >= update.segments.length) {
808 while (i--) { 815 // recalculate the live point if the streams are too far out of sync
809 if (originalSegment.uri === update.segments[i].uri) { 816 return videojs.Hls.setMediaIndexForLive(update) + 1;
810 return i + 1;
811 }
812 } 817 }
813 818
814 // sync on media sequence 819 // sync on media sequence
815 return (update.mediaSequence + mediaIndex) - original.mediaSequence; 820 return translatedMediaIndex;
816 }; 821 };
817 822
818 /** 823 /**
......