1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

add tv genre configuration options

This commit is contained in:
Luke Pulverenti 2016-06-03 15:32:10 -04:00
parent 81ab24a44c
commit f13258a120
24 changed files with 261 additions and 143 deletions

View file

@ -15,12 +15,12 @@
}, },
"devDependencies": {}, "devDependencies": {},
"ignore": [], "ignore": [],
"version": "1.4.16", "version": "1.4.17",
"_release": "1.4.16", "_release": "1.4.17",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "1.4.16", "tag": "1.4.17",
"commit": "b564ac84f300199b48a8a2338111d6b7609b671b" "commit": "26ee95baf54887c88d2aadf768ded7aa75a65fb7"
}, },
"_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

@ -30,7 +30,7 @@
.inputLabel { .inputLabel {
display: inline-block; display: inline-block;
transition: all .25s ease-out; transition: all .2s ease-out;
} }
.inputLabel.blank { .inputLabel.blank {

View file

@ -2,10 +2,13 @@
var EmbyInputPrototype = Object.create(HTMLInputElement.prototype); var EmbyInputPrototype = Object.create(HTMLInputElement.prototype);
var inputId = 0;
EmbyInputPrototype.createdCallback = function () { EmbyInputPrototype.createdCallback = function () {
if (!this.id) { if (!this.id) {
this.id = 'input' + new Date().getTime(); this.id = 'embyinput' + inputId;
inputId++;
} }
}; };

View file

@ -103,6 +103,8 @@
} }
} }
var inputId = 0;
EmbySelectPrototype.createdCallback = function () { EmbySelectPrototype.createdCallback = function () {
var parent = this.parentNode; var parent = this.parentNode;
@ -112,8 +114,10 @@
parent.replaceChild(div, this); parent.replaceChild(div, this);
div.appendChild(this); div.appendChild(this);
} }
if (!this.id) { if (!this.id) {
this.id = 'select' + new Date().getTime(); this.id = 'embyselect' + inputId;
inputId++;
} }
this.removeEventListener('mousedown', onMouseDown); this.removeEventListener('mousedown', onMouseDown);

View file

@ -186,7 +186,7 @@
.channelHeaderCell { .channelHeaderCell {
border-bottom: .65vh solid #121212 !important; border-bottom: .65vh solid #121212 !important;
background-size: auto 65.7%; background-size: auto 70%;
background-position: 90% center; background-position: 90% center;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
@ -234,7 +234,7 @@
} }
.layout-tv .channelPrograms, .layout-tv .channelHeaderCell { .layout-tv .channelPrograms, .layout-tv .channelHeaderCell {
height: 7.6vh; height: 9vh;
} }
} }
@ -365,13 +365,12 @@
height: auto !important; height: auto !important;
} }
.programCell:focus, .channelHeaderCell:focus, .btnSelectDate:focus { .programCell, .channelHeaderCell, .btnSelectDate {
background-color: #52B54B;
outline: none !important; outline: none !important;
} }
.programCell:focus .programAccent { .programCell:focus, .channelHeaderCell:focus, .btnSelectDate:focus {
background-color: transparent !important; background-color: #555;
} }
.timerIcon, .seriesTimerIcon { .timerIcon, .seriesTimerIcon {

View file

@ -307,6 +307,7 @@
// but since mobile browsers are often underpowered, // but since mobile browsers are often underpowered,
// it can help performance to get them out of the markup // it can help performance to get them out of the markup
var showIndicators = window.innerWidth >= 800; var showIndicators = window.innerWidth >= 800;
showIndicators = false;
var options = { var options = {
showHdIcon: showIndicators, showHdIcon: showIndicators,

View file

@ -1,6 +1,6 @@
{ {
"name": "hls.js", "name": "hls.js",
"version": "0.5.33", "version": "0.5.34",
"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.33", "_release": "0.5.34",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v0.5.33", "tag": "v0.5.34",
"commit": "bee1aea020de895904cef15962e71c062338e22e" "commit": "fe719c8631da6014babef8c5914f59b1620769a6"
}, },
"_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.33", "version": "0.5.34",
"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

@ -2373,7 +2373,7 @@ var StreamController = function (_EventHandler) {
var currentLevel = this.levels[this.level], var currentLevel = this.levels[this.level],
details = currentLevel.details, details = currentLevel.details,
duration = details.totalduration, duration = details.totalduration,
start = fragCurrent.start, start = fragCurrent.startDTS !== undefined ? fragCurrent.startDTS : fragCurrent.start,
level = fragCurrent.level, level = fragCurrent.level,
sn = fragCurrent.sn, sn = fragCurrent.sn,
audioCodec = currentLevel.audioCodec || this.config.defaultAudioCodec; audioCodec = currentLevel.audioCodec || this.config.defaultAudioCodec;
@ -2495,7 +2495,7 @@ var StreamController = function (_EventHandler) {
_logger.logger.log('parsed ' + data.type + ',PTS:[' + data.startPTS.toFixed(3) + ',' + data.endPTS.toFixed(3) + '],DTS:[' + data.startDTS.toFixed(3) + '/' + data.endDTS.toFixed(3) + '],nb:' + data.nb); _logger.logger.log('parsed ' + data.type + ',PTS:[' + data.startPTS.toFixed(3) + ',' + data.endPTS.toFixed(3) + '],DTS:[' + data.startDTS.toFixed(3) + '/' + data.endDTS.toFixed(3) + '],nb:' + data.nb);
var drift = _levelHelper2.default.updateFragPTS(level.details, frag.sn, data.startPTS, data.endPTS), var drift = _levelHelper2.default.updateFragPTSDTS(level.details, frag.sn, data.startPTS, data.endPTS, data.startDTS, data.endDTS),
hls = this.hls; hls = this.hls;
hls.trigger(_events2.default.LEVEL_PTS_UPDATED, { details: level.details, level: this.level, drift: drift }); hls.trigger(_events2.default.LEVEL_PTS_UPDATED, { details: level.details, level: this.level, drift: drift });
@ -2645,7 +2645,7 @@ var StreamController = function (_EventHandler) {
_logger.logger.log('target seek position:' + targetSeekPosition); _logger.logger.log('target seek position:' + targetSeekPosition);
} }
var bufferInfo = _bufferHelper2.default.bufferInfo(media, currentTime, 0), var bufferInfo = _bufferHelper2.default.bufferInfo(media, currentTime, 0),
expectedPlaying = !(media.paused || media.ended || media.seeking || readyState < 2), expectedPlaying = !(media.paused || media.ended || media.seeking || media.buffered.length === 0),
jumpThreshold = 0.4, jumpThreshold = 0.4,
// tolerance needed as some browsers stalls playback before reaching buffered range end // tolerance needed as some browsers stalls playback before reaching buffered range end
playheadMoving = currentTime > media.playbackRate * this.lastCurrentTime; playheadMoving = currentTime > media.playbackRate * this.lastCurrentTime;
@ -4581,14 +4581,14 @@ var TSDemuxer = function () {
value: function switchLevel() { value: function switchLevel() {
this.pmtParsed = false; this.pmtParsed = false;
this._pmtId = -1; this._pmtId = -1;
this.lastAacPTS = null;
this.aacOverFlow = null;
this._avcTrack = { container: 'video/mp2t', type: 'video', id: -1, sequenceNumber: 0, samples: [], len: 0, nbNalu: 0 }; this._avcTrack = { container: 'video/mp2t', type: 'video', id: -1, sequenceNumber: 0, samples: [], len: 0, nbNalu: 0 };
this._aacTrack = { container: 'video/mp2t', type: 'audio', id: -1, sequenceNumber: 0, samples: [], len: 0 }; this._aacTrack = { container: 'video/mp2t', type: 'audio', id: -1, sequenceNumber: 0, samples: [], len: 0 };
this._id3Track = { type: 'id3', id: -1, sequenceNumber: 0, samples: [], len: 0 }; this._id3Track = { type: 'id3', id: -1, sequenceNumber: 0, samples: [], len: 0 };
this._txtTrack = { type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0 }; this._txtTrack = { type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0 };
// flush any partial content // flush any partial content
this.aacOverFlow = null; this.aacOverFlow = null;
this.aacLastPTS = null;
this.avcNaluState = 0;
this.remuxer.switchLevel(); this.remuxer.switchLevel();
} }
}, { }, {
@ -4917,6 +4917,22 @@ var TSDemuxer = function () {
pes.data = null; pes.data = null;
var debugString = ''; var debugString = '';
var pushAccesUnit = function pushAccesUnit() {
if (units2.length) {
// only push AVC sample if keyframe already found in this fragment OR
// 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 };
samples.push(avcSample);
track.len += length;
track.nbNalu += units2.length;
}
units2 = [];
length = 0;
}
};
units.forEach(function (unit) { units.forEach(function (unit) {
switch (unit.type) { switch (unit.type) {
//NDR //NDR
@ -5029,6 +5045,7 @@ var TSDemuxer = function () {
if (debug) { if (debug) {
debugString += 'AUD '; debugString += 'AUD ';
} }
pushAccesUnit();
break; break;
default: default:
push = false; push = false;
@ -5043,19 +5060,7 @@ var TSDemuxer = function () {
if (debug || debugString.length) { if (debug || debugString.length) {
_logger.logger.log(debugString); _logger.logger.log(debugString);
} }
//build sample from PES pushAccesUnit();
// Annex B to MP4 conversion to be done
if (units2.length) {
// only push AVC sample if keyframe already found in this fragment OR
// 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 };
samples.push(avcSample);
track.len += length;
track.nbNalu += units2.length;
}
}
} }
}, { }, {
key: '_parseAVCNALu', key: '_parseAVCNALu',
@ -5064,7 +5069,7 @@ var TSDemuxer = function () {
len = array.byteLength, len = array.byteLength,
value, value,
overflow, overflow,
state = 0; state = this.avcNaluState;
var units = [], var units = [],
unit, unit,
unitType, unitType,
@ -5099,22 +5104,45 @@ var TSDemuxer = function () {
//logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength); //logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
units.push(unit); units.push(unit);
} else { } else {
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit. // lastUnitStart is undefined => this is the first start code found in this PES packet
overflow = i - state - 1; // first check if start code delimiter is overlapping between 2 PES packets,
if (overflow) { // ie it started in last packet (lastState not zero)
// and ended at the beginning of this PES packet (i <= 4 - lastState)
var lastState = this.avcNaluState;
if (lastState && i <= 4 - lastState) {
// start delimiter overlapping between PES packets
// strip start delimiter bytes from the end of last NAL unit
var track = this._avcTrack, var track = this._avcTrack,
samples = track.samples; samples = track.samples;
//logger.log('first NALU found with overflow:' + overflow);
if (samples.length) { if (samples.length) {
var lastavcSample = samples[samples.length - 1], var lastavcSample = samples[samples.length - 1],
lastUnits = lastavcSample.units.units, lastUnits = lastavcSample.units.units,
lastUnit = lastUnits[lastUnits.length - 1], lastUnit = lastUnits[lastUnits.length - 1];
tmp = new Uint8Array(lastUnit.data.byteLength + overflow); // check if lastUnit had a state different from zero
tmp.set(lastUnit.data, 0); if (lastUnit.state) {
tmp.set(array.subarray(0, overflow), lastUnit.data.byteLength); // strip last bytes
lastUnit.data = tmp; lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState);
lastavcSample.units.length += overflow; lastavcSample.units.length -= lastState;
track.len += overflow; track.len -= lastState;
}
}
}
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
overflow = i - state - 1;
if (overflow > 0) {
var _track = this._avcTrack,
_samples = _track.samples;
//logger.log('first NALU found with overflow:' + overflow);
if (_samples.length) {
var _lastavcSample = _samples[_samples.length - 1],
_lastUnits = _lastavcSample.units.units,
_lastUnit = _lastUnits[_lastUnits.length - 1],
tmp = new Uint8Array(_lastUnit.data.byteLength + overflow);
tmp.set(_lastUnit.data, 0);
tmp.set(array.subarray(0, overflow), _lastUnit.data.byteLength);
_lastUnit.data = tmp;
_lastavcSample.units.length += overflow;
_track.len += overflow;
} }
} }
} }
@ -5130,9 +5158,10 @@ var TSDemuxer = function () {
} }
} }
if (lastUnitStart) { if (lastUnitStart) {
unit = { data: array.subarray(lastUnitStart, len), type: lastUnitType }; unit = { data: array.subarray(lastUnitStart, len), type: lastUnitType, state: state };
units.push(unit); units.push(unit);
//logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength); //logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
this.avcNaluState = state;
} }
return units; return units;
} }
@ -5146,7 +5175,7 @@ var TSDemuxer = function () {
duration = this._duration, duration = this._duration,
audioCodec = this.audioCodec, audioCodec = this.audioCodec,
aacOverFlow = this.aacOverFlow, aacOverFlow = this.aacOverFlow,
lastAacPTS = this.lastAacPTS, aacLastPTS = this.aacLastPTS,
config, config,
frameLength, frameLength,
frameDuration, frameDuration,
@ -5198,8 +5227,8 @@ var TSDemuxer = function () {
// if last AAC frame is overflowing, we should ensure timestamps are contiguous: // if last AAC frame is overflowing, we should ensure timestamps are contiguous:
// first sample PTS should be equal to last sample PTS + frameDuration // first sample PTS should be equal to last sample PTS + frameDuration
if (aacOverFlow && lastAacPTS) { if (aacOverFlow && aacLastPTS) {
var newPTS = lastAacPTS + frameDuration; var newPTS = aacLastPTS + frameDuration;
if (Math.abs(newPTS - pts) > 1) { if (Math.abs(newPTS - pts) > 1) {
_logger.logger.log('AAC: align PTS for overlapping frames by ' + Math.round((newPTS - pts) / 90)); _logger.logger.log('AAC: align PTS for overlapping frames by ' + Math.round((newPTS - pts) / 90));
pts = newPTS; pts = newPTS;
@ -5239,7 +5268,7 @@ var TSDemuxer = function () {
aacOverFlow = null; aacOverFlow = null;
} }
this.aacOverFlow = aacOverFlow; this.aacOverFlow = aacOverFlow;
this.lastAacPTS = stamp; this.aacLastPTS = stamp;
} }
}, { }, {
key: '_parseID3PES', key: '_parseID3PES',
@ -5667,7 +5696,7 @@ var LevelHelper = function () {
// if at least one fragment contains PTS info, recompute PTS information for all fragments // if at least one fragment contains PTS info, recompute PTS information for all fragments
if (PTSFrag) { if (PTSFrag) {
LevelHelper.updateFragPTS(newDetails, PTSFrag.sn, PTSFrag.startPTS, PTSFrag.endPTS); LevelHelper.updateFragPTSDTS(newDetails, PTSFrag.sn, PTSFrag.startPTS, PTSFrag.endPTS, PTSFrag.startDTS, PTSFrag.endDTS);
} else { } else {
// ensure that delta is within oldfragments range // ensure that delta is within oldfragments range
// also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61]) // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61])
@ -5686,8 +5715,8 @@ var LevelHelper = function () {
return; return;
} }
}, { }, {
key: 'updateFragPTS', key: 'updateFragPTSDTS',
value: function updateFragPTS(details, sn, startPTS, endPTS) { value: function updateFragPTSDTS(details, sn, startPTS, endPTS, startDTS, endDTS) {
var fragIdx, fragments, frag, i; var fragIdx, fragments, frag, i;
// exit if sn out of range // exit if sn out of range
if (sn < details.startSN || sn > details.endSN) { if (sn < details.startSN || sn > details.endSN) {
@ -5699,12 +5728,16 @@ var LevelHelper = function () {
if (!isNaN(frag.startPTS)) { if (!isNaN(frag.startPTS)) {
startPTS = Math.min(startPTS, frag.startPTS); startPTS = Math.min(startPTS, frag.startPTS);
endPTS = Math.max(endPTS, frag.endPTS); endPTS = Math.max(endPTS, frag.endPTS);
startDTS = Math.min(startDTS, frag.startDTS);
endDTS = Math.max(endDTS, frag.endDTS);
} }
var drift = startPTS - frag.start; var drift = startPTS - frag.start;
frag.start = frag.startPTS = startPTS; frag.start = frag.startPTS = startPTS;
frag.endPTS = endPTS; frag.endPTS = endPTS;
frag.startDTS = startDTS;
frag.endDTS = endDTS;
frag.duration = endPTS - startPTS; frag.duration = endPTS - startPTS;
// adjust fragment PTS/duration from seqnum-1 to frag 0 // adjust fragment PTS/duration from seqnum-1 to frag 0
for (i = fragIdx; i > 0; i--) { for (i = fragIdx; i > 0; i--) {

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.33", "version": "0.5.34",
"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",
@ -19,7 +19,7 @@
"prebuild": "npm run clean & npm run test", "prebuild": "npm run clean & npm run test",
"build": "npm run babel && browserify -t [babelify] -s Hls src/index.js --debug | exorcist dist/hls.js.map -b . > dist/hls.js", "build": "npm run babel && browserify -t [babelify] -s Hls src/index.js --debug | exorcist dist/hls.js.map -b . > dist/hls.js",
"postbuild": "npm run minify", "postbuild": "npm run minify",
"prerelease": "npm run prebuild && npm run build && npm run postbuild && git add dist/* && git commit -m 'update dist'", "prerelease": "npm run prebuild && npm run build && npm run postbuild && git add --ignore-errors dist/* && git commit -m 'update dist'",
"patch": "npm run prerelease && mversion p", "patch": "npm run prerelease && mversion p",
"minor": "npm run prerelease && mversion mi", "minor": "npm run prerelease && mversion mi",
"major": "npm run prerelease && mversion ma", "major": "npm run prerelease && mversion ma",

View file

@ -764,7 +764,7 @@ class StreamController extends EventHandler {
var currentLevel = this.levels[this.level], var currentLevel = this.levels[this.level],
details = currentLevel.details, details = currentLevel.details,
duration = details.totalduration, duration = details.totalduration,
start = fragCurrent.start, start = fragCurrent.startDTS !== undefined ? fragCurrent.startDTS : fragCurrent.start,
level = fragCurrent.level, level = fragCurrent.level,
sn = fragCurrent.sn, sn = fragCurrent.sn,
audioCodec = currentLevel.audioCodec || this.config.defaultAudioCodec; audioCodec = currentLevel.audioCodec || this.config.defaultAudioCodec;
@ -880,7 +880,7 @@ class StreamController extends EventHandler {
logger.log(`parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb}`); logger.log(`parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb}`);
var drift = LevelHelper.updateFragPTS(level.details,frag.sn,data.startPTS,data.endPTS), var drift = LevelHelper.updateFragPTSDTS(level.details,frag.sn,data.startPTS,data.endPTS,data.startDTS,data.endDTS),
hls = this.hls; hls = this.hls;
hls.trigger(Event.LEVEL_PTS_UPDATED, {details: level.details, level: this.level, drift: drift}); hls.trigger(Event.LEVEL_PTS_UPDATED, {details: level.details, level: this.level, drift: drift});
@ -1024,7 +1024,7 @@ _checkBuffer() {
logger.log(`target seek position:${targetSeekPosition}`); logger.log(`target seek position:${targetSeekPosition}`);
} }
var bufferInfo = BufferHelper.bufferInfo(media,currentTime,0), var bufferInfo = BufferHelper.bufferInfo(media,currentTime,0),
expectedPlaying = !(media.paused || media.ended || media.seeking || readyState < 2), expectedPlaying = !(media.paused || media.ended || media.seeking || media.buffered.length === 0),
jumpThreshold = 0.4, // tolerance needed as some browsers stalls playback before reaching buffered range end jumpThreshold = 0.4, // tolerance needed as some browsers stalls playback before reaching buffered range end
playheadMoving = currentTime > media.playbackRate*this.lastCurrentTime; playheadMoving = currentTime > media.playbackRate*this.lastCurrentTime;

View file

@ -37,14 +37,14 @@
switchLevel() { switchLevel() {
this.pmtParsed = false; this.pmtParsed = false;
this._pmtId = -1; this._pmtId = -1;
this.lastAacPTS = null;
this.aacOverFlow = null;
this._avcTrack = {container : 'video/mp2t', type: 'video', id :-1, sequenceNumber: 0, samples : [], len : 0, nbNalu : 0}; this._avcTrack = {container : 'video/mp2t', type: 'video', id :-1, sequenceNumber: 0, samples : [], len : 0, nbNalu : 0};
this._aacTrack = {container : 'video/mp2t', type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0}; this._aacTrack = {container : 'video/mp2t', type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0};
this._id3Track = {type: 'id3', id :-1, sequenceNumber: 0, samples : [], len : 0}; this._id3Track = {type: 'id3', id :-1, sequenceNumber: 0, samples : [], len : 0};
this._txtTrack = {type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0}; this._txtTrack = {type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0};
// flush any partial content // flush any partial content
this.aacOverFlow = null; this.aacOverFlow = null;
this.aacLastPTS = null;
this.avcNaluState = 0;
this.remuxer.switchLevel(); this.remuxer.switchLevel();
} }
@ -344,6 +344,23 @@
pes.data = null; pes.data = null;
var debugString = ''; var debugString = '';
var pushAccesUnit = function() {
if (units2.length) {
// only push AVC sample if keyframe already found in this fragment OR
// 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};
samples.push(avcSample);
track.len += length;
track.nbNalu += units2.length;
}
units2 = [];
length = 0;
}
};
units.forEach(unit => { units.forEach(unit => {
switch(unit.type) { switch(unit.type) {
//NDR //NDR
@ -463,6 +480,7 @@
if(debug) { if(debug) {
debugString += 'AUD '; debugString += 'AUD ';
} }
pushAccesUnit();
break; break;
default: default:
push = false; push = false;
@ -477,25 +495,12 @@
if(debug || debugString.length) { if(debug || debugString.length) {
logger.log(debugString); logger.log(debugString);
} }
//build sample from PES pushAccesUnit();
// Annex B to MP4 conversion to be done
if (units2.length) {
// only push AVC sample if keyframe already found in this fragment OR
// 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};
samples.push(avcSample);
track.len += length;
track.nbNalu += units2.length;
}
}
} }
_parseAVCNALu(array) { _parseAVCNALu(array) {
var i = 0, len = array.byteLength, value, overflow, state = 0; var i = 0, len = array.byteLength, value, overflow, state = this.avcNaluState;
var units = [], unit, unitType, lastUnitStart, lastUnitType; var units = [], unit, unitType, lastUnitStart, lastUnitType;
//logger.log('PES:' + Hex.hexDump(array)); //logger.log('PES:' + Hex.hexDump(array));
while (i < len) { while (i < len) {
@ -526,14 +531,37 @@
//logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength); //logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength);
units.push(unit); units.push(unit);
} else { } else {
// lastUnitStart is undefined => this is the first start code found in this PES packet
// first check if start code delimiter is overlapping between 2 PES packets,
// ie it started in last packet (lastState not zero)
// and ended at the beginning of this PES packet (i <= 4 - lastState)
let lastState = this.avcNaluState;
if(lastState && (i <= 4 - lastState)) {
// start delimiter overlapping between PES packets
// strip start delimiter bytes from the end of last NAL unit
let track = this._avcTrack,
samples = track.samples;
if (samples.length) {
let lastavcSample = samples[samples.length - 1],
lastUnits = lastavcSample.units.units,
lastUnit = lastUnits[lastUnits.length - 1];
// check if lastUnit had a state different from zero
if (lastUnit.state) {
// strip last bytes
lastUnit.data = lastUnit.data.subarray(0,lastUnit.data.byteLength - lastState);
lastavcSample.units.length -= lastState;
track.len -= lastState;
}
}
}
// If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit. // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.
overflow = i - state - 1; overflow = i - state - 1;
if (overflow) { if (overflow > 0) {
var track = this._avcTrack, let track = this._avcTrack,
samples = track.samples; samples = track.samples;
//logger.log('first NALU found with overflow:' + overflow); //logger.log('first NALU found with overflow:' + overflow);
if (samples.length) { if (samples.length) {
var lastavcSample = samples[samples.length - 1], let lastavcSample = samples[samples.length - 1],
lastUnits = lastavcSample.units.units, lastUnits = lastavcSample.units.units,
lastUnit = lastUnits[lastUnits.length - 1], lastUnit = lastUnits[lastUnits.length - 1],
tmp = new Uint8Array(lastUnit.data.byteLength + overflow); tmp = new Uint8Array(lastUnit.data.byteLength + overflow);
@ -557,9 +585,10 @@
} }
} }
if (lastUnitStart) { if (lastUnitStart) {
unit = {data: array.subarray(lastUnitStart, len), type: lastUnitType}; unit = {data: array.subarray(lastUnitStart, len), type: lastUnitType, state : state};
units.push(unit); units.push(unit);
//logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength); //logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);
this.avcNaluState = state;
} }
return units; return units;
} }
@ -572,7 +601,7 @@
duration = this._duration, duration = this._duration,
audioCodec = this.audioCodec, audioCodec = this.audioCodec,
aacOverFlow = this.aacOverFlow, aacOverFlow = this.aacOverFlow,
lastAacPTS = this.lastAacPTS, aacLastPTS = this.aacLastPTS,
config, frameLength, frameDuration, frameIndex, offset, headerLength, stamp, len, aacSample; config, frameLength, frameDuration, frameIndex, offset, headerLength, stamp, len, aacSample;
if (aacOverFlow) { if (aacOverFlow) {
var tmp = new Uint8Array(aacOverFlow.byteLength + data.byteLength); var tmp = new Uint8Array(aacOverFlow.byteLength + data.byteLength);
@ -616,8 +645,8 @@
// if last AAC frame is overflowing, we should ensure timestamps are contiguous: // if last AAC frame is overflowing, we should ensure timestamps are contiguous:
// first sample PTS should be equal to last sample PTS + frameDuration // first sample PTS should be equal to last sample PTS + frameDuration
if(aacOverFlow && lastAacPTS) { if(aacOverFlow && aacLastPTS) {
var newPTS = lastAacPTS+frameDuration; var newPTS = aacLastPTS+frameDuration;
if(Math.abs(newPTS-pts) > 1) { if(Math.abs(newPTS-pts) > 1) {
logger.log(`AAC: align PTS for overlapping frames by ${Math.round((newPTS-pts)/90)}`); logger.log(`AAC: align PTS for overlapping frames by ${Math.round((newPTS-pts)/90)}`);
pts=newPTS; pts=newPTS;
@ -659,7 +688,7 @@
aacOverFlow = null; aacOverFlow = null;
} }
this.aacOverFlow = aacOverFlow; this.aacOverFlow = aacOverFlow;
this.lastAacPTS = stamp; this.aacLastPTS = stamp;
} }
_parseID3PES(pes) { _parseID3PES(pes) {

View file

@ -42,7 +42,7 @@ class LevelHelper {
// if at least one fragment contains PTS info, recompute PTS information for all fragments // if at least one fragment contains PTS info, recompute PTS information for all fragments
if(PTSFrag) { if(PTSFrag) {
LevelHelper.updateFragPTS(newDetails,PTSFrag.sn,PTSFrag.startPTS,PTSFrag.endPTS); LevelHelper.updateFragPTSDTS(newDetails,PTSFrag.sn,PTSFrag.startPTS,PTSFrag.endPTS,PTSFrag.startDTS,PTSFrag.endDTS);
} else { } else {
// ensure that delta is within oldfragments range // ensure that delta is within oldfragments range
// also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61]) // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61])
@ -61,7 +61,7 @@ class LevelHelper {
return; return;
} }
static updateFragPTS(details,sn,startPTS,endPTS) { static updateFragPTSDTS(details,sn,startPTS,endPTS,startDTS,endDTS) {
var fragIdx, fragments, frag, i; var fragIdx, fragments, frag, i;
// exit if sn out of range // exit if sn out of range
if (sn < details.startSN || sn > details.endSN) { if (sn < details.startSN || sn > details.endSN) {
@ -73,12 +73,16 @@ class LevelHelper {
if(!isNaN(frag.startPTS)) { if(!isNaN(frag.startPTS)) {
startPTS = Math.min(startPTS,frag.startPTS); startPTS = Math.min(startPTS,frag.startPTS);
endPTS = Math.max(endPTS, frag.endPTS); endPTS = Math.max(endPTS, frag.endPTS);
startDTS = Math.min(startDTS,frag.startDTS);
endDTS = Math.max(endDTS, frag.endDTS);
} }
var drift = startPTS - frag.start; var drift = startPTS - frag.start;
frag.start = frag.startPTS = startPTS; frag.start = frag.startPTS = startPTS;
frag.endPTS = endPTS; frag.endPTS = endPTS;
frag.startDTS = startDTS;
frag.endDTS = endDTS;
frag.duration = endPTS - startPTS; frag.duration = endPTS - startPTS;
// adjust fragment PTS/duration from seqnum-1 to frag 0 // adjust fragment PTS/duration from seqnum-1 to frag 0
for(i = fragIdx ; i > 0 ; i--) { for(i = fragIdx ; i > 0 ; i--) {

View file

@ -30,14 +30,14 @@
"web-component-tester": "polymer/web-component-tester#^3.4.0" "web-component-tester": "polymer/web-component-tester#^3.4.0"
}, },
"ignore": [], "ignore": [],
"homepage": "https://github.com/PolymerElements/iron-a11y-announcer", "homepage": "https://github.com/polymerelements/iron-a11y-announcer",
"_release": "1.0.4", "_release": "1.0.4",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.0.4", "tag": "v1.0.4",
"commit": "5ce3eb8c4282bb53cd72e348858dc6be6b4c50b9" "commit": "5ce3eb8c4282bb53cd72e348858dc6be6b4c50b9"
}, },
"_source": "git://github.com/PolymerElements/iron-a11y-announcer.git", "_source": "git://github.com/polymerelements/iron-a11y-announcer.git",
"_target": "^1.0.0", "_target": "^1.0.0",
"_originalSource": "PolymerElements/iron-a11y-announcer" "_originalSource": "polymerelements/iron-a11y-announcer"
} }

View file

@ -26,14 +26,14 @@
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
}, },
"main": "iron-meta.html", "main": "iron-meta.html",
"homepage": "https://github.com/polymerelements/iron-meta", "homepage": "https://github.com/PolymerElements/iron-meta",
"_release": "1.1.1", "_release": "1.1.1",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.1.1", "tag": "v1.1.1",
"commit": "e171ee234b482219c9514e6f9551df48ef48bd9f" "commit": "e171ee234b482219c9514e6f9551df48ef48bd9f"
}, },
"_source": "git://github.com/polymerelements/iron-meta.git", "_source": "git://github.com/PolymerElements/iron-meta.git",
"_target": "^1.0.0", "_target": "^1.0.0",
"_originalSource": "polymerelements/iron-meta" "_originalSource": "PolymerElements/iron-meta"
} }

View file

@ -28,14 +28,14 @@
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0" "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
}, },
"ignore": [], "ignore": [],
"homepage": "https://github.com/PolymerElements/iron-resizable-behavior", "homepage": "https://github.com/polymerelements/iron-resizable-behavior",
"_release": "1.0.3", "_release": "1.0.3",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "v1.0.3", "tag": "v1.0.3",
"commit": "dda1df6aaf452aedf3e52ff0cf69e72439452216" "commit": "dda1df6aaf452aedf3e52ff0cf69e72439452216"
}, },
"_source": "git://github.com/PolymerElements/iron-resizable-behavior.git", "_source": "git://github.com/polymerelements/iron-resizable-behavior.git",
"_target": "^1.0.0", "_target": "^1.0.0",
"_originalSource": "PolymerElements/iron-resizable-behavior" "_originalSource": "polymerelements/iron-resizable-behavior"
} }

View file

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

View file

@ -1,20 +1,31 @@
define(['jQuery', 'paper-checkbox', 'paper-button', 'paper-input', 'paper-item-body', 'paper-icon-item'], function ($) { define(['jQuery', 'paper-checkbox', 'paper-button', 'emby-input', 'paper-item-body', 'paper-icon-item'], function ($) {
return function (page, providerId, options) { return function (page, providerId, options) {
var self = this; var self = this;
function getListingProvider(config, id) {
if (config && id) {
return config.ListingProviders.filter(function (i) {
return i.Id == id;
})[0] || getListingProvider();
}
return ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/Default'));
}
function reload() { function reload() {
Dashboard.showLoadingMsg(); Dashboard.showLoadingMsg();
ApiClient.getNamedConfiguration("livetv").then(function (config) { ApiClient.getNamedConfiguration("livetv").then(function (config) {
var info = config.ListingProviders.filter(function (i) { getListingProvider(config, providerId).then(function (info) {
return i.Id == providerId;
})[0] || {};
page.querySelector('.txtPath').value = info.Path || ''; page.querySelector('.txtPath').value = info.Path || '';
page.querySelector('.txtKids').value = (info.KidsGenres || []).join('|');
page.querySelector('.txtNews').value = (info.NewsGenres || []).join('|');
page.querySelector('.txtSports').value = (info.SportsGenres || []).join('|');
page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; page.querySelector('.chkAllTuners').checked = info.EnableAllTuners;
@ -27,6 +38,14 @@
refreshTunerDevices(page, info, config.TunerHosts); refreshTunerDevices(page, info, config.TunerHosts);
Dashboard.hideLoadingMsg(); Dashboard.hideLoadingMsg();
}); });
});
}
function getGenres(txtInput) {
var value = txtInput.value;
return value ? value.split('|') : [];
} }
function submitListingsForm() { function submitListingsForm() {
@ -42,7 +61,13 @@
})[0] || {}; })[0] || {};
info.Type = 'xmltv'; info.Type = 'xmltv';
info.Path = page.querySelector('.txtPath').value; info.Path = page.querySelector('.txtPath').value;
info.KidsGenres = getGenres(page.querySelector('.txtKids'));
info.NewsGenres = getGenres(page.querySelector('.txtNews'));
info.SportsGenres = getGenres(page.querySelector('.txtSports'));
info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; info.EnableAllTuners = page.querySelector('.chkAllTuners').checked;
info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (i) { info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (i) {
return i.checked; return i.checked;

View file

@ -2,8 +2,22 @@
<form> <form>
<div> <div>
<div> <div class="inputContainer">
<paper-input class="txtPath" label="${LabelPath}" required="required" autocomplete="off"></paper-input> <input is="emby-input" class="txtPath" label="${LabelPath}" required="required" autocomplete="off" />
</div>
<div class="inputContainer">
<input is="emby-input" class="txtKids" label="${LabelKidsGenres}" autocomplete="off" />
<div class="fieldDescription">${XmlTvKidsGenresHelp}</div>
</div>
<div class="inputContainer">
<input is="emby-input" class="txtNews" label="${LabelNewsGenres}" autocomplete="off" />
<div class="fieldDescription"></div>
<div class="fieldDescription">${XmlTvNewsGenresHelp}</div>
</div>
<div class="inputContainer">
<input is="emby-input" class="txtSports" label="${LabelSportsGenres}" autocomplete="off" />
<div class="fieldDescription">${XmlTvSportsGenresHelp}</div>
</div>
</div> </div>
<div> <div>
<br /> <br />

View file

@ -6,7 +6,7 @@
<br /> <br />
<div> <div>
<paper-button raised class="btnRefresh"><iron-icon icon="refresh"></iron-icon><span>${ButtonScanLibrary}</span></paper-button> <paper-button raised class="btnRefresh subdued"><iron-icon icon="refresh"></iron-icon><span>${ButtonScanLibrary}</span></paper-button>
<progress max="100" min="0" style="display: inline-block; vertical-align: middle;" class="refreshProgress"></progress> <progress max="100" min="0" style="display: inline-block; vertical-align: middle;" class="refreshProgress"></progress>
</div> </div>
</div> </div>

View file

@ -31,7 +31,7 @@
</div> </div>
<div> <div>
<paper-button raised class="btnRefresh block"><iron-icon icon="refresh"></iron-icon><span>${ButtonRefreshGuideData}</span></paper-button> <paper-button raised class="btnRefresh block subdued"><iron-icon icon="refresh"></iron-icon><span>${ButtonRefreshGuideData}</span></paper-button>
<progress max="100" min="0" style="width: 100%;" class="refreshGuideProgress"></progress> <progress max="100" min="0" style="width: 100%;" class="refreshGuideProgress"></progress>
</div> </div>
</div> </div>

View file

@ -2357,5 +2357,11 @@
"HeaderHealthMonitor": "Health Monitor", "HeaderHealthMonitor": "Health Monitor",
"HealthMonitorNoAlerts": "There are no active alerts.", "HealthMonitorNoAlerts": "There are no active alerts.",
"RecordingPathChangeMessage": "Changing your recording folder will not migrate existing recordings from the old location to the new. You'll need to move them manually if desired.", "RecordingPathChangeMessage": "Changing your recording folder will not migrate existing recordings from the old location to the new. You'll need to move them manually if desired.",
"VisualLoginFormHelp": "Select a user or sign in manually" "VisualLoginFormHelp": "Select a user or sign in manually",
"LabelSportsGenres": "Sports genres:",
"XmlTvSportsGenresHelp": "Programs with these genres will be categorized as sports programs. Separate multiple with '|'.",
"LabelNewsGenres": "News genres:",
"XmlTvNewsGenresHelp": "Programs with these genres will be categorized as news programs. Separate multiple with '|'.",
"LabelKidsGenres": "Children's genres:",
"XmlTvKidsGenresHelp": "Programs with these genres will be categorized as programs for children. Separate multiple with '|'."
} }