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.
Showing
1 changed file
with
22 additions
and
17 deletions
... | @@ -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 | /** | ... | ... |
-
Please register or sign in to post a comment