Addressed bug where playback doesn't initiate after a playlist 404s
Showing
2 changed files
with
48 additions
and
13 deletions
... | @@ -90,6 +90,7 @@ | ... | @@ -90,6 +90,7 @@ |
90 | dispose, | 90 | dispose, |
91 | mediaUpdateTimeout, | 91 | mediaUpdateTimeout, |
92 | request, | 92 | request, |
93 | playlistRequestError, | ||
93 | haveMetadata; | 94 | haveMetadata; |
94 | 95 | ||
95 | PlaylistLoader.prototype.init.call(this); | 96 | PlaylistLoader.prototype.init.call(this); |
... | @@ -102,17 +103,16 @@ | ... | @@ -102,17 +103,16 @@ |
102 | throw new Error('A non-empty playlist URL is required'); | 103 | throw new Error('A non-empty playlist URL is required'); |
103 | } | 104 | } |
104 | 105 | ||
105 | // update the playlist loader's state in response to a new or | 106 | playlistRequestError = function(xhr, url, startingState) { |
106 | // updated playlist. | ||
107 | haveMetadata = function(error, xhr, url) { | ||
108 | var parser, refreshDelay, update; | ||
109 | |||
110 | loader.setBandwidth(request || xhr); | 107 | loader.setBandwidth(request || xhr); |
111 | 108 | ||
112 | // any in-flight request is now finished | 109 | // any in-flight request is now finished |
113 | request = null; | 110 | request = null; |
114 | 111 | ||
115 | if (error) { | 112 | if (startingState) { |
113 | loader.state = startingState; | ||
114 | } | ||
115 | |||
116 | loader.error = { | 116 | loader.error = { |
117 | playlist: loader.master.playlists[url], | 117 | playlist: loader.master.playlists[url], |
118 | status: xhr.status, | 118 | status: xhr.status, |
... | @@ -120,9 +120,19 @@ | ... | @@ -120,9 +120,19 @@ |
120 | responseText: xhr.responseText, | 120 | responseText: xhr.responseText, |
121 | code: (xhr.status >= 500) ? 4 : 2 | 121 | code: (xhr.status >= 500) ? 4 : 2 |
122 | }; | 122 | }; |
123 | return loader.trigger('error'); | 123 | loader.trigger('error'); |
124 | } | 124 | }; |
125 | |||
126 | // update the playlist loader's state in response to a new or | ||
127 | // updated playlist. | ||
128 | |||
129 | haveMetadata = function(xhr, url) { | ||
130 | var parser, refreshDelay, update; | ||
125 | 131 | ||
132 | loader.setBandwidth(request || xhr); | ||
133 | |||
134 | // any in-flight request is now finished | ||
135 | request = null; | ||
126 | loader.state = 'HAVE_METADATA'; | 136 | loader.state = 'HAVE_METADATA'; |
127 | 137 | ||
128 | parser = new videojs.m3u8.Parser(); | 138 | parser = new videojs.m3u8.Parser(); |
... | @@ -252,12 +262,12 @@ | ... | @@ -252,12 +262,12 @@ |
252 | uri: resolveUrl(loader.master.uri, playlist.uri), | 262 | uri: resolveUrl(loader.master.uri, playlist.uri), |
253 | withCredentials: withCredentials | 263 | withCredentials: withCredentials |
254 | }, function(error, request) { | 264 | }, function(error, request) { |
255 | haveMetadata(error, request, playlist.uri); | ||
256 | |||
257 | if (error) { | 265 | if (error) { |
258 | return; | 266 | return playlistRequestError(request, playlist.uri, startingState); |
259 | } | 267 | } |
260 | 268 | ||
269 | haveMetadata(request, playlist.uri); | ||
270 | |||
261 | // fire loadedmetadata the first time a media playlist is loaded | 271 | // fire loadedmetadata the first time a media playlist is loaded |
262 | if (startingState === 'HAVE_MASTER') { | 272 | if (startingState === 'HAVE_MASTER') { |
263 | loader.trigger('loadedmetadata'); | 273 | loader.trigger('loadedmetadata'); |
... | @@ -289,7 +299,10 @@ | ... | @@ -289,7 +299,10 @@ |
289 | uri: resolveUrl(loader.master.uri, loader.media().uri), | 299 | uri: resolveUrl(loader.master.uri, loader.media().uri), |
290 | withCredentials: withCredentials | 300 | withCredentials: withCredentials |
291 | }, function(error, request) { | 301 | }, function(error, request) { |
292 | haveMetadata(error, request, loader.media().uri); | 302 | if (error) { |
303 | return playlistRequestError(request, loader.media().uri); | ||
304 | } | ||
305 | haveMetadata(request, loader.media().uri); | ||
293 | }); | 306 | }); |
294 | }); | 307 | }); |
295 | 308 | ||
... | @@ -349,7 +362,7 @@ | ... | @@ -349,7 +362,7 @@ |
349 | }] | 362 | }] |
350 | }; | 363 | }; |
351 | loader.master.playlists[srcUrl] = loader.master.playlists[0]; | 364 | loader.master.playlists[srcUrl] = loader.master.playlists[0]; |
352 | haveMetadata(null, req, srcUrl); | 365 | haveMetadata(req, srcUrl); |
353 | return loader.trigger('loadedmetadata'); | 366 | return loader.trigger('loadedmetadata'); |
354 | }); | 367 | }); |
355 | }; | 368 | }; | ... | ... |
... | @@ -1296,6 +1296,28 @@ test('blacklists switching from video-only playlists to video+audio', function() | ... | @@ -1296,6 +1296,28 @@ test('blacklists switching from video-only playlists to video+audio', function() |
1296 | equal(videoAudioPlaylist.excludeUntil, Infinity, 'excluded incompatible playlist'); | 1296 | equal(videoAudioPlaylist.excludeUntil, Infinity, 'excluded incompatible playlist'); |
1297 | }); | 1297 | }); |
1298 | 1298 | ||
1299 | test('After an initial media playlist 404s, we fire loadedmetadata once we successfully load a playlist', function() { | ||
1300 | var count = 0; | ||
1301 | player.src({ | ||
1302 | src: 'manifest/master.m3u8', | ||
1303 | type: 'application/vnd.apple.mpegurl' | ||
1304 | }); | ||
1305 | openMediaSource(player); | ||
1306 | player.tech_.hls.bandwidth = 20000; | ||
1307 | player.on('loadedmetadata', function() { | ||
1308 | count += 1; | ||
1309 | }); | ||
1310 | standardXHRResponse(requests.shift()); //master | ||
1311 | equal(count, 0, | ||
1312 | 'loadedMedia not triggered before requesting playlist'); | ||
1313 | requests.shift().respond(404); //media | ||
1314 | equal(count, 0, | ||
1315 | 'loadedMedia not triggered after playlist 404'); | ||
1316 | standardXHRResponse(requests.shift()); //media | ||
1317 | equal(count, 1, | ||
1318 | 'loadedMedia triggered after successful recovery from 404'); | ||
1319 | }); | ||
1320 | |||
1299 | test('does not blacklist compatible H.264 codec strings', function() { | 1321 | test('does not blacklist compatible H.264 codec strings', function() { |
1300 | var master; | 1322 | var master; |
1301 | player.src({ | 1323 | player.src({ | ... | ... |
-
Please register or sign in to post a comment