update missing season creator

This commit is contained in:
Luke Pulverenti 2016-05-20 15:45:04 -04:00
parent a981c0eb8b
commit 5fa9e9637b
22 changed files with 190 additions and 83 deletions

View File

@ -16,12 +16,12 @@
}, },
"devDependencies": {}, "devDependencies": {},
"ignore": [], "ignore": [],
"version": "1.3.51", "version": "1.3.52",
"_release": "1.3.51", "_release": "1.3.52",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "1.3.51", "tag": "1.3.52",
"commit": "0c56ace6eb1ffd23624d7721b3fa8902022e4cc3" "commit": "c00f1f1e92a8572cd01145ad02137e3eb74442fd"
}, },
"_source": "https://github.com/MediaBrowser/emby-webcomponents.git", "_source": "https://github.com/MediaBrowser/emby-webcomponents.git",
"_target": "^1.2.0", "_target": "^1.2.0",

View File

@ -18,6 +18,12 @@ define(['loading', 'viewManager', 'skinManager', 'pluginManager', 'backdrop', 'b
}, },
showSearch: function () { showSearch: function () {
skinManager.getCurrentSkin().search(); skinManager.getCurrentSkin().search();
},
showGuide: function () {
skinManager.getCurrentSkin().showGuide();
},
showLiveTV: function () {
skinManager.getCurrentSkin().showLiveTV();
} }
}; };

View File

@ -1,4 +1,7 @@
{ {
"Delete": "Delete",
"HeaderDeleteItem": "Delete Item",
"ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Special - {0}",
"Share": "Del", "Share": "Del",
"ServerUpdateNeeded": "Denne Emby server b\u00f8r opdateres. For at downloade den nyeste version bes\u00f8g venligst {0}", "ServerUpdateNeeded": "Denne Emby server b\u00f8r opdateres. For at downloade den nyeste version bes\u00f8g venligst {0}",

View File

@ -1,4 +1,7 @@
{ {
"Delete": "Delete",
"HeaderDeleteItem": "Delete Item",
"ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"ValueSpecialEpisodeName": "Especial - {0}", "ValueSpecialEpisodeName": "Especial - {0}",
"Share": "Compartir", "Share": "Compartir",
"ServerUpdateNeeded": "Este Servidor Emby necesita ser actualizado. Para descargar la ultima versi\u00f3n, por favor visite {0}", "ServerUpdateNeeded": "Este Servidor Emby necesita ser actualizado. Para descargar la ultima versi\u00f3n, por favor visite {0}",

View File

@ -1,4 +1,7 @@
{ {
"Delete": "Delete",
"HeaderDeleteItem": "Delete Item",
"ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"ValueSpecialEpisodeName": "\u0410\u0440\u043d\u0430\u0439\u044b - {0}", "ValueSpecialEpisodeName": "\u0410\u0440\u043d\u0430\u0439\u044b - {0}",
"Share": "\u041e\u0440\u0442\u0430\u049b\u0442\u0430\u0441\u0443", "Share": "\u041e\u0440\u0442\u0430\u049b\u0442\u0430\u0441\u0443",
"ServerUpdateNeeded": "\u041e\u0441\u044b Emby Server \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442. \u0421\u043e\u04a3\u0493\u044b \u043d\u04b1\u0441\u049b\u0430\u0441\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d, {0} \u043a\u0456\u0440\u0456\u04a3\u0456\u0437", "ServerUpdateNeeded": "\u041e\u0441\u044b Emby Server \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442. \u0421\u043e\u04a3\u0493\u044b \u043d\u04b1\u0441\u049b\u0430\u0441\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d, {0} \u043a\u0456\u0440\u0456\u04a3\u0456\u0437",

View File

@ -1,4 +1,7 @@
{ {
"Delete": "Slett",
"HeaderDeleteItem": "Slett element",
"ConfirmDeleteItem": "Ved \u00e5 slette dette element vil du b\u00e5de slette det fra statement og mediebiblioteket. Er du sikker p\u00e5 at du vil forsette?",
"ValueSpecialEpisodeName": "Spesial - {0}", "ValueSpecialEpisodeName": "Spesial - {0}",
"Share": "Del", "Share": "Del",
"ServerUpdateNeeded": "Denne Emby serveren trenger en oppdatering. For \u00e5 laste ned nyeste versjon, vennligst bes\u00f8k: {0}", "ServerUpdateNeeded": "Denne Emby serveren trenger en oppdatering. For \u00e5 laste ned nyeste versjon, vennligst bes\u00f8k: {0}",

View File

@ -1,4 +1,7 @@
{ {
"Delete": "Verwijder",
"HeaderDeleteItem": "Item verwijderen",
"ConfirmDeleteItem": "Verwijderen van dit item zal het verwijderen uit zowel het bestandssysteem als de Media Bibliotheek. Weet u zeker dat u wilt doorgaan?",
"ValueSpecialEpisodeName": "Speciaal - {0}", "ValueSpecialEpisodeName": "Speciaal - {0}",
"Share": "Delen", "Share": "Delen",
"ServerUpdateNeeded": "Deze Emby Server moet worden bijgewerkt. Om de laatste versie te downloaden, gaat u naar {0}", "ServerUpdateNeeded": "Deze Emby Server moet worden bijgewerkt. Om de laatste versie te downloaden, gaat u naar {0}",

View File

@ -1,4 +1,7 @@
{ {
"Delete": "Delete",
"HeaderDeleteItem": "Delete Item",
"ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434 - {0}", "ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434 - {0}",
"Share": "\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f", "Share": "\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f",
"ServerUpdateNeeded": "\u0414\u0430\u043d\u043d\u044b\u0439 Emby \u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438. \u0427\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0432\u0435\u0440\u0441\u0438\u044e, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 {0}", "ServerUpdateNeeded": "\u0414\u0430\u043d\u043d\u044b\u0439 Emby \u0421\u0435\u0440\u0432\u0435\u0440 \u043d\u0443\u0436\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438. \u0427\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0432\u0435\u0440\u0441\u0438\u044e, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 {0}",

View File

@ -1,6 +1,6 @@
{ {
"name": "hls.js", "name": "hls.js",
"version": "0.5.30", "version": "0.5.32",
"license": "Apache-2.0", "license": "Apache-2.0",
"description": "Media Source Extension - HLS library, by/for Dailymotion", "description": "Media Source Extension - HLS library, by/for Dailymotion",
"homepage": "https://github.com/dailymotion/hls.js", "homepage": "https://github.com/dailymotion/hls.js",
@ -16,11 +16,11 @@
"test", "test",
"tests" "tests"
], ],
"_release": "0.5.30", "_release": "0.5.32",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v0.5.30", "tag": "v0.5.32",
"commit": "c8eab206bbd77040cbe9f35f64303775c2065608" "commit": "bceb5b05fb906e6877e48778828378c05353d2b8"
}, },
"_source": "git://github.com/dailymotion/hls.js.git", "_source": "git://github.com/dailymotion/hls.js.git",
"_target": "~0.5.7", "_target": "~0.5.7",

View File

@ -1,6 +1,6 @@
{ {
"name": "hls.js", "name": "hls.js",
"version": "0.5.30", "version": "0.5.32",
"license": "Apache-2.0", "license": "Apache-2.0",
"description": "Media Source Extension - HLS library, by/for Dailymotion", "description": "Media Source Extension - HLS library, by/for Dailymotion",
"homepage": "https://github.com/dailymotion/hls.js", "homepage": "https://github.com/dailymotion/hls.js",

View File

@ -1329,8 +1329,9 @@ var LevelController = function (_EventHandler) {
var details = data.details, var details = data.details,
hls = this.hls, hls = this.hls,
levelId, levelId = void 0,
level; level = void 0,
levelError = false;
// try to recover not fatal errors // try to recover not fatal errors
switch (details) { switch (details) {
case _errors.ErrorDetails.FRAG_LOAD_ERROR: case _errors.ErrorDetails.FRAG_LOAD_ERROR:
@ -1343,6 +1344,7 @@ var LevelController = function (_EventHandler) {
case _errors.ErrorDetails.LEVEL_LOAD_ERROR: case _errors.ErrorDetails.LEVEL_LOAD_ERROR:
case _errors.ErrorDetails.LEVEL_LOAD_TIMEOUT: case _errors.ErrorDetails.LEVEL_LOAD_TIMEOUT:
levelId = data.level; levelId = data.level;
levelError = true;
break; break;
default: default:
break; break;
@ -1366,6 +1368,10 @@ var LevelController = function (_EventHandler) {
hls.abrController.nextAutoLevel = 0; hls.abrController.nextAutoLevel = 0;
} else if (level && level.details && level.details.live) { } else if (level && level.details && level.details.live) {
_logger.logger.warn('level controller,' + details + ' on live stream, discard'); _logger.logger.warn('level controller,' + details + ' on live stream, discard');
if (levelError) {
// reset this._level so that another call to set level() will retrigger a frag load
this._level = undefined;
}
// FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT are handled by mediaController // FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT are handled by mediaController
} else if (details !== _errors.ErrorDetails.FRAG_LOAD_ERROR && details !== _errors.ErrorDetails.FRAG_LOAD_TIMEOUT) { } else if (details !== _errors.ErrorDetails.FRAG_LOAD_ERROR && details !== _errors.ErrorDetails.FRAG_LOAD_TIMEOUT) {
_logger.logger.error('cannot recover ' + details + ' error'); _logger.logger.error('cannot recover ' + details + ' error');
@ -1664,14 +1670,15 @@ var StreamController = function (_EventHandler) {
break; break;
case State.STARTING: case State.STARTING:
// determine load level // determine load level
this.startLevel = hls.startLevel; var startLevel = hls.startLevel;
if (this.startLevel === -1) { if (startLevel === -1) {
// -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level
this.startLevel = 0; startLevel = 0;
this.fragBitrateTest = true; this.fragBitrateTest = true;
} }
// set new level to playlist loader : this will trigger start level load // set new level to playlist loader : this will trigger start level load
this.level = hls.nextLoadLevel = this.startLevel; // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded
this.level = hls.nextLoadLevel = startLevel;
this.state = State.WAITING_LEVEL; this.state = State.WAITING_LEVEL;
this.loadedmetadata = false; this.loadedmetadata = false;
break; break;
@ -1692,13 +1699,7 @@ var StreamController = function (_EventHandler) {
} else { } else {
pos = this.nextLoadPosition; pos = this.nextLoadPosition;
} }
// determine next load level level = hls.nextLoadLevel;
if (this.startFragRequested === false) {
level = this.startLevel;
} else {
// we are not at playback start, get next load level from level Controller
level = hls.nextLoadLevel;
}
var bufferInfo = _bufferHelper2.default.bufferInfo(this.media, pos, config.maxBufferHole), var bufferInfo = _bufferHelper2.default.bufferInfo(this.media, pos, config.maxBufferHole),
bufferLen = bufferInfo.len, bufferLen = bufferInfo.len,
bufferEnd = bufferInfo.end, bufferEnd = bufferInfo.end,
@ -1827,8 +1828,14 @@ var StreamController = function (_EventHandler) {
} else { } else {
// have we reached end of VOD playlist ? // have we reached end of VOD playlist ?
if (!levelDetails.live) { if (!levelDetails.live) {
// Finalize the media stream
_this2.hls.trigger(_events2.default.BUFFER_EOS); _this2.hls.trigger(_events2.default.BUFFER_EOS);
_this2.state = State.ENDED; // We might be loading the last fragment but actually the media
// is currently processing a seek command and waiting for new data to resume at another point.
// Going to ended state while media is seeking can spawn an infinite buffering broken state.
if (!_this2.media.seeking) {
_this2.state = State.ENDED;
}
} }
frag = null; frag = null;
} }
@ -2278,10 +2285,13 @@ var StreamController = function (_EventHandler) {
value: function onFragLoaded(data) { value: function onFragLoaded(data) {
var fragCurrent = this.fragCurrent; var fragCurrent = this.fragCurrent;
if (this.state === State.FRAG_LOADING && fragCurrent && data.frag.level === fragCurrent.level && data.frag.sn === fragCurrent.sn) { if (this.state === State.FRAG_LOADING && fragCurrent && data.frag.level === fragCurrent.level && data.frag.sn === fragCurrent.sn) {
_logger.logger.log('Loaded ' + fragCurrent.sn + ' of level ' + fragCurrent.level);
if (this.fragBitrateTest === true) { if (this.fragBitrateTest === true) {
// switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo // switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo
this.state = State.IDLE; this.state = State.IDLE;
this.fragBitrateTest = false; this.fragBitrateTest = false;
this.startFragRequested = false;
data.stats.tparsed = data.stats.tbuffered = performance.now(); data.stats.tparsed = data.stats.tbuffered = performance.now();
this.hls.trigger(_events2.default.FRAG_BUFFERED, { stats: data.stats, frag: fragCurrent }); this.hls.trigger(_events2.default.FRAG_BUFFERED, { stats: data.stats, frag: fragCurrent });
} else { } else {
@ -2606,8 +2616,16 @@ var StreamController = function (_EventHandler) {
} }
} }
} else { } else {
if (targetSeekPosition && media.currentTime !== targetSeekPosition) { var _currentTime = media.currentTime;
_logger.logger.log('adjust currentTime from ' + media.currentTime + ' to ' + targetSeekPosition); if (targetSeekPosition && _currentTime !== targetSeekPosition) {
if (bufferInfo.len === 0) {
var nextStart = bufferInfo.nextStart;
if (nextStart !== undefined && nextStart - targetSeekPosition < this.config.maxSeekHole) {
targetSeekPosition = nextStart;
_logger.logger.log('target seek position not buffered, seek to next buffered ' + targetSeekPosition);
}
}
_logger.logger.log('adjust currentTime from ' + _currentTime + ' to ' + targetSeekPosition);
media.currentTime = targetSeekPosition; media.currentTime = targetSeekPosition;
} }
} }
@ -4520,7 +4538,8 @@ var TSDemuxer = function () {
pid, pid,
atf, atf,
offset, offset,
codecsOnly = this.remuxer.passthrough; codecsOnly = this.remuxer.passthrough,
unknownPIDs = false;
this.audioCodec = audioCodec; this.audioCodec = audioCodec;
this.videoCodec = videoCodec; this.videoCodec = videoCodec;
@ -4634,6 +4653,15 @@ var TSDemuxer = function () {
avcId = this._avcTrack.id; avcId = this._avcTrack.id;
aacId = this._aacTrack.id; aacId = this._aacTrack.id;
id3Id = this._id3Track.id; id3Id = this._id3Track.id;
if (unknownPIDs) {
_logger.logger.log('reparse from beginning');
unknownPIDs = false;
// we set it to -188, the += 188 in the for loop will reset start to 0
start = -188;
}
} else {
_logger.logger.log('unknown PID found before PAT/PMT');
unknownPIDs = true;
} }
} }
} else { } else {
@ -4948,8 +4976,10 @@ var TSDemuxer = function () {
//build sample from PES //build sample from PES
// Annex B to MP4 conversion to be done // Annex B to MP4 conversion to be done
if (units2.length) { if (units2.length) {
// only push AVC sample if keyframe already found. browsers expect a keyframe at first to start decoding // only push AVC sample if keyframe already found in this fragment OR
if (key === true || track.sps) { // keyframe found in last fragment (track.sps) AND
// samples already appended (we already found a keyframe in this fragment) OR fragment is contiguous
if (key === true || track.sps && (samples.length || this.contiguous)) {
avcSample = { units: { units: units2, length: length }, pts: pes.pts, dts: pes.dts, key: key }; avcSample = { units: { units: units2, length: length }, pts: pes.pts, dts: pes.dts, key: key };
samples.push(avcSample); samples.push(avcSample);
track.len += length; track.len += length;
@ -8420,7 +8450,6 @@ var logger = exports.logger = exportedLogger;
'use strict'; 'use strict';
var URLHelper = { var URLHelper = {
// build an absolute URL from a relative one using the provided baseURL // build an absolute URL from a relative one using the provided baseURL
// if relativeURL is an absolute URL it will be returned as is. // if relativeURL is an absolute URL it will be returned as is.
buildAbsoluteURL: function buildAbsoluteURL(baseURL, relativeURL) { buildAbsoluteURL: function buildAbsoluteURL(baseURL, relativeURL) {
@ -8454,18 +8483,27 @@ var URLHelper = {
baseURL = baseURLQuerySplit[1]; baseURL = baseURLQuerySplit[1];
} }
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL); var baseURLDomainSplit = /^(([a-z]+:)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?)?(\/.*)$/i.exec(baseURL);
var baseURLProtocol = baseURLDomainSplit[3]; if (!baseURLDomainSplit) {
var baseURLDomain = baseURLDomainSplit[1]; throw new Error('Error trying to parse base URL.');
var baseURLPath = baseURLDomainSplit[5]; }
// e.g. 'http:', 'https:', ''
var baseURLProtocol = baseURLDomainSplit[2] || '';
// e.g. 'http://example.com', '//example.com', ''
var baseURLProtocolDomain = baseURLDomainSplit[1] || '';
// e.g. '/a/b/c/playlist.m3u8'
var baseURLPath = baseURLDomainSplit[4];
var builtURL = null; var builtURL = null;
if (/^\/\//.test(relativeURL)) { if (/^\/\//.test(relativeURL)) {
builtURL = baseURLProtocol + '://' + URLHelper.buildAbsolutePath('', relativeURL.substring(2)); // relative url starts wth '//' so copy protocol (which may be '' if baseUrl didn't provide one)
builtURL = baseURLProtocol + '//' + URLHelper.buildAbsolutePath('', relativeURL.substring(2));
} else if (/^\//.test(relativeURL)) { } else if (/^\//.test(relativeURL)) {
builtURL = baseURLDomain + URLHelper.buildAbsolutePath('', relativeURL.substring(1)); // relative url starts with '/' so start from root of domain
builtURL = baseURLProtocolDomain + '/' + URLHelper.buildAbsolutePath('', relativeURL.substring(1));
} else { } else {
builtURL = URLHelper.buildAbsolutePath(baseURLDomain + baseURLPath, relativeURL); builtURL = URLHelper.buildAbsolutePath(baseURLProtocolDomain + baseURLPath, relativeURL);
} }
// put the query and hash parts back // put the query and hash parts back

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{ {
"name": "hls.js", "name": "hls.js",
"version": "0.5.30", "version": "0.5.32",
"license": "Apache-2.0", "license": "Apache-2.0",
"description": "Media Source Extension - HLS library, by/for Dailymotion", "description": "Media Source Extension - HLS library, by/for Dailymotion",
"homepage": "https://github.com/dailymotion/hls.js", "homepage": "https://github.com/dailymotion/hls.js",

View File

@ -186,7 +186,7 @@ class LevelController extends EventHandler {
return; return;
} }
var details = data.details, hls = this.hls, levelId, level; let details = data.details, hls = this.hls, levelId, level, levelError = false;
// try to recover not fatal errors // try to recover not fatal errors
switch(details) { switch(details) {
case ErrorDetails.FRAG_LOAD_ERROR: case ErrorDetails.FRAG_LOAD_ERROR:
@ -199,6 +199,7 @@ class LevelController extends EventHandler {
case ErrorDetails.LEVEL_LOAD_ERROR: case ErrorDetails.LEVEL_LOAD_ERROR:
case ErrorDetails.LEVEL_LOAD_TIMEOUT: case ErrorDetails.LEVEL_LOAD_TIMEOUT:
levelId = data.level; levelId = data.level;
levelError = true;
break; break;
default: default:
break; break;
@ -222,6 +223,10 @@ class LevelController extends EventHandler {
hls.abrController.nextAutoLevel = 0; hls.abrController.nextAutoLevel = 0;
} else if(level && level.details && level.details.live) { } else if(level && level.details && level.details.live) {
logger.warn(`level controller,${details} on live stream, discard`); logger.warn(`level controller,${details} on live stream, discard`);
if (levelError) {
// reset this._level so that another call to set level() will retrigger a frag load
this._level = undefined;
}
// FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT are handled by mediaController // FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT are handled by mediaController
} else if (details !== ErrorDetails.FRAG_LOAD_ERROR && details !== ErrorDetails.FRAG_LOAD_TIMEOUT) { } else if (details !== ErrorDetails.FRAG_LOAD_ERROR && details !== ErrorDetails.FRAG_LOAD_TIMEOUT) {
logger.error(`cannot recover ${details} error`); logger.error(`cannot recover ${details} error`);

View File

@ -128,14 +128,15 @@ class StreamController extends EventHandler {
break; break;
case State.STARTING: case State.STARTING:
// determine load level // determine load level
this.startLevel = hls.startLevel; let startLevel = hls.startLevel;
if (this.startLevel === -1) { if (startLevel === -1) {
// -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level
this.startLevel = 0; startLevel = 0;
this.fragBitrateTest = true; this.fragBitrateTest = true;
} }
// set new level to playlist loader : this will trigger start level load // set new level to playlist loader : this will trigger start level load
this.level = hls.nextLoadLevel = this.startLevel; // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded
this.level = hls.nextLoadLevel = startLevel;
this.state = State.WAITING_LEVEL; this.state = State.WAITING_LEVEL;
this.loadedmetadata = false; this.loadedmetadata = false;
break; break;
@ -157,13 +158,7 @@ class StreamController extends EventHandler {
} else { } else {
pos = this.nextLoadPosition; pos = this.nextLoadPosition;
} }
// determine next load level level = hls.nextLoadLevel;
if (this.startFragRequested === false) {
level = this.startLevel;
} else {
// we are not at playback start, get next load level from level Controller
level = hls.nextLoadLevel;
}
var bufferInfo = BufferHelper.bufferInfo(this.media,pos,config.maxBufferHole), var bufferInfo = BufferHelper.bufferInfo(this.media,pos,config.maxBufferHole),
bufferLen = bufferInfo.len, bufferLen = bufferInfo.len,
bufferEnd = bufferInfo.end, bufferEnd = bufferInfo.end,
@ -292,8 +287,14 @@ class StreamController extends EventHandler {
} else { } else {
// have we reached end of VOD playlist ? // have we reached end of VOD playlist ?
if (!levelDetails.live) { if (!levelDetails.live) {
// Finalize the media stream
this.hls.trigger(Event.BUFFER_EOS); this.hls.trigger(Event.BUFFER_EOS);
this.state = State.ENDED; // We might be loading the last fragment but actually the media
// is currently processing a seek command and waiting for new data to resume at another point.
// Going to ended state while media is seeking can spawn an infinite buffering broken state.
if (!this.media.seeking) {
this.state = State.ENDED;
}
} }
frag = null; frag = null;
} }
@ -747,10 +748,13 @@ class StreamController extends EventHandler {
fragCurrent && fragCurrent &&
data.frag.level === fragCurrent.level && data.frag.level === fragCurrent.level &&
data.frag.sn === fragCurrent.sn) { data.frag.sn === fragCurrent.sn) {
logger.log(`Loaded ${fragCurrent.sn} of level ${fragCurrent.level}`);
if (this.fragBitrateTest === true) { if (this.fragBitrateTest === true) {
// switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo // switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo
this.state = State.IDLE; this.state = State.IDLE;
this.fragBitrateTest = false; this.fragBitrateTest = false;
this.startFragRequested = false;
data.stats.tparsed = data.stats.tbuffered = performance.now(); data.stats.tparsed = data.stats.tbuffered = performance.now();
this.hls.trigger(Event.FRAG_BUFFERED, {stats: data.stats, frag: fragCurrent}); this.hls.trigger(Event.FRAG_BUFFERED, {stats: data.stats, frag: fragCurrent});
} else { } else {
@ -1064,8 +1068,17 @@ _checkBuffer() {
} }
} }
} else { } else {
if (targetSeekPosition && media.currentTime !== targetSeekPosition) { let currentTime = media.currentTime;
logger.log(`adjust currentTime from ${media.currentTime} to ${targetSeekPosition}`); if (targetSeekPosition && currentTime !== targetSeekPosition) {
if(bufferInfo.len === 0) {
let nextStart = bufferInfo.nextStart;
if (nextStart !== undefined &&
(nextStart - targetSeekPosition) < this.config.maxSeekHole) {
targetSeekPosition = nextStart;
logger.log(`target seek position not buffered, seek to next buffered ${targetSeekPosition}`);
}
}
logger.log(`adjust currentTime from ${currentTime} to ${targetSeekPosition}`);
media.currentTime = targetSeekPosition; media.currentTime = targetSeekPosition;
} }
} }

View File

@ -55,7 +55,8 @@
push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) {
var avcData, aacData, id3Data, var avcData, aacData, id3Data,
start, len = data.length, stt, pid, atf, offset, start, len = data.length, stt, pid, atf, offset,
codecsOnly = this.remuxer.passthrough; codecsOnly = this.remuxer.passthrough,
unknownPIDs = false;
this.audioCodec = audioCodec; this.audioCodec = audioCodec;
this.videoCodec = videoCodec; this.videoCodec = videoCodec;
@ -169,6 +170,15 @@
avcId = this._avcTrack.id; avcId = this._avcTrack.id;
aacId = this._aacTrack.id; aacId = this._aacTrack.id;
id3Id = this._id3Track.id; id3Id = this._id3Track.id;
if (unknownPIDs) {
logger.log('reparse from beginning');
unknownPIDs = false;
// we set it to -188, the += 188 in the for loop will reset start to 0
start = -188;
}
} else {
logger.log('unknown PID found before PAT/PMT');
unknownPIDs = true;
} }
} }
} else { } else {
@ -472,8 +482,11 @@
//build sample from PES //build sample from PES
// Annex B to MP4 conversion to be done // Annex B to MP4 conversion to be done
if (units2.length) { if (units2.length) {
// only push AVC sample if keyframe already found. browsers expect a keyframe at first to start decoding // only push AVC sample if keyframe already found in this fragment OR
if (key === true || track.sps ) { // keyframe found in last fragment (track.sps) AND
// samples already appended (we already found a keyframe in this fragment) OR fragment is contiguous
if (key === true ||
(track.sps && (samples.length || this.contiguous))) {
avcSample = {units: { units : units2, length : length}, pts: pes.pts, dts: pes.dts, key: key}; avcSample = {units: { units : units2, length : length}, pts: pes.pts, dts: pes.dts, key: key};
samples.push(avcSample); samples.push(avcSample);
track.len += length; track.len += length;

View File

@ -1,5 +1,4 @@
var URLHelper = { var URLHelper = {
// build an absolute URL from a relative one using the provided baseURL // build an absolute URL from a relative one using the provided baseURL
// if relativeURL is an absolute URL it will be returned as is. // if relativeURL is an absolute URL it will be returned as is.
buildAbsoluteURL: function(baseURL, relativeURL) { buildAbsoluteURL: function(baseURL, relativeURL) {
@ -33,20 +32,29 @@ var URLHelper = {
baseURL = baseURLQuerySplit[1]; baseURL = baseURLQuerySplit[1];
} }
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL); var baseURLDomainSplit = /^(([a-z]+:)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?)?(\/.*)$/i.exec(baseURL);
var baseURLProtocol = baseURLDomainSplit[3]; if (!baseURLDomainSplit) {
var baseURLDomain = baseURLDomainSplit[1]; throw new Error('Error trying to parse base URL.');
var baseURLPath = baseURLDomainSplit[5]; }
// e.g. 'http:', 'https:', ''
var baseURLProtocol = baseURLDomainSplit[2] || '';
// e.g. 'http://example.com', '//example.com', ''
var baseURLProtocolDomain = baseURLDomainSplit[1] || '';
// e.g. '/a/b/c/playlist.m3u8'
var baseURLPath = baseURLDomainSplit[4];
var builtURL = null; var builtURL = null;
if (/^\/\//.test(relativeURL)) { if (/^\/\//.test(relativeURL)) {
builtURL = baseURLProtocol+'://'+URLHelper.buildAbsolutePath('', relativeURL.substring(2)); // relative url starts wth '//' so copy protocol (which may be '' if baseUrl didn't provide one)
builtURL = baseURLProtocol+'//'+URLHelper.buildAbsolutePath('', relativeURL.substring(2));
} }
else if (/^\//.test(relativeURL)) { else if (/^\//.test(relativeURL)) {
builtURL = baseURLDomain+URLHelper.buildAbsolutePath('', relativeURL.substring(1)); // relative url starts with '/' so start from root of domain
builtURL = baseURLProtocolDomain+'/'+URLHelper.buildAbsolutePath('', relativeURL.substring(1));
} }
else { else {
builtURL = URLHelper.buildAbsolutePath(baseURLDomain+baseURLPath, relativeURL); builtURL = URLHelper.buildAbsolutePath(baseURLProtocolDomain+baseURLPath, relativeURL);
} }
// put the query and hash parts back // put the query and hash parts back

View File

@ -34,6 +34,6 @@
"commit": "11c987b2eb3c73b388a79fc8aaea8ca01624f514" "commit": "11c987b2eb3c73b388a79fc8aaea8ca01624f514"
}, },
"_source": "git://github.com/Polymer/polymer.git", "_source": "git://github.com/Polymer/polymer.git",
"_target": "^1.1.0", "_target": "^1.0.0",
"_originalSource": "Polymer/polymer" "_originalSource": "Polymer/polymer"
} }

View File

@ -2971,9 +2971,10 @@ var AppInfo = {};
defineRoute({ defineRoute({
path: '/wizardfinish.html', path: '/wizardfinish.html',
dependencies: [], dependencies: ['paper-button'],
autoFocus: false, autoFocus: false,
anonymous: true anonymous: true,
controller: 'scripts/wizardfinishpage'
}); });
defineRoute({ defineRoute({

View File

@ -1,8 +1,10 @@
define(['jQuery'], function ($) { define(['loading'], function (loading) {
function onFinish() { function onFinish() {
ApiClient.ajax({ loading.show();
ApiClient.ajax({
url: ApiClient.getUrl('Startup/Complete'), url: ApiClient.getUrl('Startup/Complete'),
type: 'POST' type: 'POST'
@ -10,12 +12,15 @@
}).then(function () { }).then(function () {
Dashboard.navigate('dashboard.html'); Dashboard.navigate('dashboard.html');
loading.hide();
}); });
} }
$(document).on('pageinit', '#wizardFinishPage', function(){ return function (view, params) {
$('.btnWizardNext', this).on('click', onFinish); var self = this;
});
view.querySelector('.btnWizardNext').addEventListener('click', onFinish);
};
}); });

View File

@ -1,4 +1,4 @@
<div id="wizardFinishPage" data-role="page" class="page standalonePage wizardPage" data-require="scripts/wizardfinishpage,paper-button"> <div id="wizardFinishPage" data-role="page" class="page standalonePage wizardPage">
<div data-role="content"> <div data-role="content">