mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
update components
This commit is contained in:
parent
2a72f0256e
commit
048ba20590
26 changed files with 1377 additions and 136 deletions
|
@ -15,12 +15,12 @@
|
|||
},
|
||||
"devDependencies": {},
|
||||
"ignore": [],
|
||||
"version": "1.0.49",
|
||||
"_release": "1.0.49",
|
||||
"version": "1.0.54",
|
||||
"_release": "1.0.54",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.0.49",
|
||||
"commit": "460488b5fd0723a72995cc23f9f8cb5a860bd370"
|
||||
"tag": "1.0.54",
|
||||
"commit": "a4de1d3f633579c3583d83990577cc252a9187ad"
|
||||
},
|
||||
"_source": "git://github.com/MediaBrowser/emby-webcomponents.git",
|
||||
"_target": "~1.0.0",
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
window.removeEventListener('popstate', onHashChange);
|
||||
|
||||
if (!self.closedByBack) {
|
||||
if (!self.closedByBack && isHistoryEnabled(dlg)) {
|
||||
var state = history.state || {};
|
||||
if (state.dialogId == hash) {
|
||||
history.back();
|
||||
|
@ -60,9 +60,15 @@
|
|||
removeScrollLockOnClose = true;
|
||||
}
|
||||
|
||||
historyManager.pushState({ dialogId: hash }, "Dialog", hash);
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
historyManager.pushState({ dialogId: hash }, "Dialog", hash);
|
||||
|
||||
window.addEventListener('popstate', onHashChange);
|
||||
window.addEventListener('popstate', onHashChange);
|
||||
}
|
||||
}
|
||||
|
||||
function isHistoryEnabled(dlg) {
|
||||
return dlg.getAttribute('data-history') == 'true';
|
||||
}
|
||||
|
||||
function open(dlg) {
|
||||
|
@ -76,7 +82,11 @@
|
|||
function close(dlg) {
|
||||
|
||||
if (dlg.opened) {
|
||||
history.back();
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
history.back();
|
||||
} else {
|
||||
dlg.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +121,10 @@
|
|||
dlg.setAttribute('data-lockscroll', 'true');
|
||||
}
|
||||
|
||||
if (options.enableHistory !== false) {
|
||||
dlg.setAttribute('data-history', 'true');
|
||||
}
|
||||
|
||||
// without this safari will scroll the background instead of the dialog contents
|
||||
// but not needed here since this is already on top of an existing dialog
|
||||
// but skip it in IE because it's causing the entire browser to hang
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
define(['paperdialoghelper', 'inputManager', 'connectionManager', 'browser', 'css!./style', 'html!./icons', 'iron-icon-set'], function (paperdialoghelper, inputmanager, connectionManager, browser) {
|
||||
define(['paperdialoghelper', 'inputManager', 'connectionManager', 'browser', 'css!./style', 'html!./icons', 'iron-icon-set', 'paper-fab', 'paper-icon-button'], function (paperdialoghelper, inputmanager, connectionManager, browser) {
|
||||
|
||||
return function (options) {
|
||||
|
||||
|
@ -9,7 +9,7 @@ define(['paperdialoghelper', 'inputManager', 'connectionManager', 'browser', 'cs
|
|||
function createElements(options) {
|
||||
|
||||
dlg = paperdialoghelper.createDialog({
|
||||
exitAnimationDuration: 800,
|
||||
exitAnimationDuration: options.interactive ? 400 : 800,
|
||||
size: 'fullscreen'
|
||||
});
|
||||
|
||||
|
@ -22,7 +22,7 @@ define(['paperdialoghelper', 'inputManager', 'connectionManager', 'browser', 'cs
|
|||
html += '<div>';
|
||||
html += '<div class="slideshowSwiperContainer"><div class="swiper-wrapper"></div></div>';
|
||||
|
||||
html += '<paper-icon-button icon="slideshow:arrow-back" class="btnSlideshowExit" tabindex="-1"></paper-icon-button>';
|
||||
html += '<paper-fab mini icon="slideshow:arrow-back" class="btnSlideshowExit" tabindex="-1"></paper-fab>';
|
||||
|
||||
html += '<div class="slideshowControlBar">';
|
||||
html += '<paper-icon-button icon="slideshow:skip-previous" class="btnSlideshowPrevious slideshowButton"></paper-icon-button>';
|
||||
|
@ -77,7 +77,7 @@ define(['paperdialoghelper', 'inputManager', 'connectionManager', 'browser', 'cs
|
|||
swiperInstance = new Swiper(dlg.querySelector('.slideshowSwiperContainer'), {
|
||||
// Optional parameters
|
||||
direction: 'horizontal',
|
||||
loop: true,
|
||||
loop: options.loop !== false,
|
||||
autoplay: options.interval || 8000,
|
||||
// Disable preloading of all images
|
||||
preloadImages: false,
|
||||
|
@ -142,6 +142,15 @@ define(['paperdialoghelper', 'inputManager', 'connectionManager', 'browser', 'cs
|
|||
|
||||
function nextImage() {
|
||||
if (swiperInstance) {
|
||||
|
||||
if (options.loop === false) {
|
||||
|
||||
if (swiperInstance.activeIndex >= swiperInstance.slides.length - 1) {
|
||||
paperdialoghelper.close(dlg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
swiperInstance.slideNext();
|
||||
} else {
|
||||
stopInterval();
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
background-repeat: no-repeat;
|
||||
margin: 0 !important;
|
||||
color: #fff;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.slideshowImage.cover {
|
||||
|
@ -46,13 +47,17 @@
|
|||
.btnSlideshowExit {
|
||||
z-index: 1002;
|
||||
position: absolute;
|
||||
top: 1%;
|
||||
left: .5%;
|
||||
top: 1.5vh;
|
||||
left: 1.5vh;
|
||||
width: 6vh;
|
||||
height: 6vh;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
paper-fab.btnSlideshowExit {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.slideshowControlBar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.4.7",
|
||||
"version": "0.4.8",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
"authors": [
|
||||
|
@ -15,11 +15,11 @@
|
|||
"test",
|
||||
"tests"
|
||||
],
|
||||
"_release": "0.4.7",
|
||||
"_release": "0.4.8",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v0.4.7",
|
||||
"commit": "9c1a7e7d768346dcc4012e8b80f73e823af5ff20"
|
||||
"tag": "v0.4.8",
|
||||
"commit": "de1534ca184ffa3a313fc5b433713512f6ab1c27"
|
||||
},
|
||||
"_source": "git://github.com/dailymotion/hls.js.git",
|
||||
"_target": "~0.4.5",
|
||||
|
|
19
dashboard-ui/bower_components/hls.js/API.md
vendored
19
dashboard-ui/bower_components/hls.js/API.md
vendored
|
@ -209,7 +209,9 @@ configuration parameters could be provided to hls.js upon instantiation of Hls O
|
|||
fLoader: customFragmentLoader,
|
||||
pLoader: customPlaylistLoader,
|
||||
xhrSetup : XMLHttpRequestSetupCallback,
|
||||
abrController : customAbrController
|
||||
abrController : customAbrController,
|
||||
timelineController: TimelineController,
|
||||
enableCEA708Captions: true
|
||||
};
|
||||
|
||||
|
||||
|
@ -403,6 +405,21 @@ parameter should be a class providing 2 getter/setters and a destroy() method:
|
|||
- get/set autoLevelCapping : get/set : capping/max level value that could be used by ABR Controller
|
||||
- destroy() : should clean-up all used resources
|
||||
|
||||
#### ```timelineController```
|
||||
(default : internal track timeline controller)
|
||||
|
||||
customized text track syncronization controller
|
||||
|
||||
parameter should be a class a destroy() method:
|
||||
|
||||
- destroy() : should clean-up all used resources
|
||||
|
||||
#### ```enableCEA708Captions```
|
||||
(default : true)
|
||||
|
||||
whether or not to enable CEA-708 captions
|
||||
|
||||
parameter should be a boolean
|
||||
|
||||
## Video Binding/Unbinding API
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.4.6",
|
||||
"version": "0.4.8",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
"authors": [
|
||||
|
|
|
@ -225,7 +225,6 @@ $(document).ready(function() {
|
|||
|
||||
loadStream(decodeURIComponent(getURLParam('src','http://www.streambox.fr/playlists/x36xhzz/x36xhzz.m3u8')));
|
||||
|
||||
|
||||
function loadStream(url) {
|
||||
hideCanvas();
|
||||
if(Hls.isSupported()) {
|
||||
|
|
744
dashboard-ui/bower_components/hls.js/dist/hls.js
vendored
744
dashboard-ui/bower_components/hls.js/dist/hls.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.4.6",
|
||||
"version": "0.4.8",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
"authors": "Guillaume du Pontavice <guillaume.dupontavice@dailymotion.com>",
|
||||
|
|
|
@ -60,11 +60,12 @@ class LevelController extends EventHandler {
|
|||
|
||||
// only keep level with supported audio/video codecs
|
||||
levels = levels.filter(function(level) {
|
||||
var checkSupported = function(codec) { return MediaSource.isTypeSupported(`video/mp4;codecs=${codec}`);};
|
||||
var checkSupportedAudio = function(codec) { return MediaSource.isTypeSupported(`audio/mp4;codecs=${codec}`);};
|
||||
var checkSupportedVideo = function(codec) { return MediaSource.isTypeSupported(`video/mp4;codecs=${codec}`);};
|
||||
var audioCodec = level.audioCodec, videoCodec = level.videoCodec;
|
||||
|
||||
return (!audioCodec || checkSupported(audioCodec)) &&
|
||||
(!videoCodec || checkSupported(videoCodec));
|
||||
return (!audioCodec || checkSupportedAudio(audioCodec)) &&
|
||||
(!videoCodec || checkSupportedVideo(videoCodec));
|
||||
});
|
||||
|
||||
if(levels.length) {
|
||||
|
|
|
@ -1076,7 +1076,7 @@ class MSEMediaController extends EventHandler {
|
|||
logger.log(`selected A/V codecs for sourceBuffers:${audioCodec},${videoCodec}`);
|
||||
// create source Buffer and link them to MediaSource
|
||||
if (audioCodec) {
|
||||
sb = this.sourceBuffer.audio = this.mediaSource.addSourceBuffer(`video/mp4;codecs=${audioCodec}`);
|
||||
sb = this.sourceBuffer.audio = this.mediaSource.addSourceBuffer(`audio/mp4;codecs=${audioCodec}`);
|
||||
sb.addEventListener('updateend', this.onsbue);
|
||||
sb.addEventListener('error', this.onsbe);
|
||||
}
|
||||
|
|
69
dashboard-ui/bower_components/hls.js/src/controller/timeline-controller.js
vendored
Normal file
69
dashboard-ui/bower_components/hls.js/src/controller/timeline-controller.js
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Timeline Controller
|
||||
*/
|
||||
|
||||
import Event from '../events';
|
||||
import EventHandler from '../event-handler';
|
||||
import CEA708Interpreter from '../utils/cea-708-interpreter';
|
||||
|
||||
class TimelineController extends EventHandler {
|
||||
|
||||
constructor(hls) {
|
||||
super(hls, Event.MEDIA_ATTACHING,
|
||||
Event.MEDIA_DETACHING,
|
||||
Event.FRAG_PARSING_USERDATA,
|
||||
Event.MANIFEST_LOADING,
|
||||
Event.FRAG_LOADED);
|
||||
|
||||
this.hls = hls;
|
||||
this.config = hls.config;
|
||||
|
||||
if (this.config.enableCEA708Captions)
|
||||
{
|
||||
this.cea708Interpreter = new CEA708Interpreter();
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
EventHandler.prototype.destroy.call(this);
|
||||
}
|
||||
|
||||
onMediaAttaching(data) {
|
||||
var media = this.media = data.media;
|
||||
this.cea708Interpreter.attach(media);
|
||||
}
|
||||
|
||||
onMediaDetaching() {
|
||||
this.cea708Interpreter.detach();
|
||||
}
|
||||
|
||||
onManifestLoading()
|
||||
{
|
||||
this.lastPts = Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
onFragLoaded(data)
|
||||
{
|
||||
var pts = data.frag.start; //Number.POSITIVE_INFINITY;
|
||||
|
||||
// if this is a frag for a previously loaded timerange, remove all captions
|
||||
// TODO: consider just removing captions for the timerange
|
||||
if (pts <= this.lastPts)
|
||||
{
|
||||
this.cea708Interpreter.clear();
|
||||
}
|
||||
|
||||
this.lastPts = pts;
|
||||
}
|
||||
|
||||
onFragParsingUserdata(data) {
|
||||
// push all of the CEA-708 messages into the interpreter
|
||||
// immediately. It will create the proper timestamps based on our PTS value
|
||||
for (var i=0; i<data.samples.length; i++)
|
||||
{
|
||||
this.cea708Interpreter.push(data.samples[i].pts, data.samples[i].bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default TimelineController;
|
|
@ -72,6 +72,12 @@ var DemuxerWorker = function (self) {
|
|||
var objData = {event: event, samples: data.samples};
|
||||
self.postMessage(objData);
|
||||
});
|
||||
|
||||
observer.on(Event.FRAG_PARSING_USERDATA, function(event, data) {
|
||||
var objData = {event: event, samples: data.samples};
|
||||
self.postMessage(objData);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
export default DemuxerWorker;
|
||||
|
|
|
@ -101,6 +101,11 @@ class Demuxer {
|
|||
samples: ev.data.samples
|
||||
});
|
||||
break;
|
||||
case Event.FRAG_PARSING_USERDATA:
|
||||
this.hls.trigger(Event.FRAG_PARSING_USERDATA, {
|
||||
samples: ev.data.samples
|
||||
});
|
||||
break;
|
||||
default:
|
||||
this.hls.trigger(ev.data.event, ev.data.data);
|
||||
break;
|
||||
|
|
|
@ -125,6 +125,15 @@ class ExpGolomb {
|
|||
return this.readBits(8);
|
||||
}
|
||||
|
||||
// ():int
|
||||
readUShort() {
|
||||
return this.readBits(16);
|
||||
}
|
||||
// ():int
|
||||
readUInt() {
|
||||
return this.readBits(32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Advance the ExpGolomb decoder past a scaling list. The scaling
|
||||
* list is optionally transmitted as part of a sequence parameter
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
this.remuxerClass = remuxerClass;
|
||||
this.lastCC = 0;
|
||||
this.remuxer = new this.remuxerClass(observer);
|
||||
this._userData = [];
|
||||
}
|
||||
|
||||
static probe(data) {
|
||||
|
@ -42,6 +43,7 @@
|
|||
this._avcTrack = {type: 'video', id :-1, sequenceNumber: 0, samples : [], len : 0, nbNalu : 0};
|
||||
this._aacTrack = {type: 'audio', 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.remuxer.switchLevel();
|
||||
}
|
||||
|
||||
|
@ -81,6 +83,9 @@
|
|||
avcId = this._avcTrack.id,
|
||||
aacId = this._aacTrack.id,
|
||||
id3Id = this._id3Track.id;
|
||||
|
||||
// don't parse last TS packet if incomplete
|
||||
len -= len % 188;
|
||||
// loop through TS packets
|
||||
for (start = 0; start < len; start += 188) {
|
||||
if (data[start] === 0x47) {
|
||||
|
@ -165,7 +170,7 @@
|
|||
}
|
||||
|
||||
remux() {
|
||||
this.remuxer.remux(this._aacTrack,this._avcTrack, this._id3Track, this.timeOffset, this.contiguous);
|
||||
this.remuxer.remux(this._aacTrack, this._avcTrack, this._id3Track, this._txtTrack, this.timeOffset, this.contiguous);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
@ -281,8 +286,10 @@
|
|||
debug = false,
|
||||
key = false,
|
||||
length = 0,
|
||||
expGolombDecoder,
|
||||
avcSample,
|
||||
push;
|
||||
push,
|
||||
i;
|
||||
// no NALu found
|
||||
if (units.length === 0 && samples.length > 0) {
|
||||
// append pes.data to previous NAL unit
|
||||
|
@ -298,6 +305,7 @@
|
|||
//free pes.data to save up some memory
|
||||
pes.data = null;
|
||||
var debugString = '';
|
||||
|
||||
units.forEach(unit => {
|
||||
switch(unit.type) {
|
||||
//NDR
|
||||
|
@ -315,11 +323,67 @@
|
|||
}
|
||||
key = true;
|
||||
break;
|
||||
//SEI
|
||||
case 6:
|
||||
push = true;
|
||||
if(debug) {
|
||||
debugString += 'SEI ';
|
||||
}
|
||||
expGolombDecoder = new ExpGolomb(unit.data);
|
||||
|
||||
// skip frameType
|
||||
expGolombDecoder.readUByte();
|
||||
|
||||
var payloadType = expGolombDecoder.readUByte();
|
||||
|
||||
// TODO: there can be more than one payload in an SEI packet...
|
||||
// TODO: need to read type and size in a while loop to get them all
|
||||
if (payloadType === 4)
|
||||
{
|
||||
var payloadSize = 0;
|
||||
|
||||
do {
|
||||
payloadSize = expGolombDecoder.readUByte();
|
||||
}
|
||||
while (payloadSize === 255);
|
||||
|
||||
var countryCode = expGolombDecoder.readUByte();
|
||||
|
||||
if (countryCode === 181)
|
||||
{
|
||||
var providerCode = expGolombDecoder.readUShort();
|
||||
|
||||
if (providerCode === 49)
|
||||
{
|
||||
var userStructure = expGolombDecoder.readUInt();
|
||||
|
||||
if (userStructure === 0x47413934)
|
||||
{
|
||||
var userDataType = expGolombDecoder.readUByte();
|
||||
|
||||
// Raw CEA-608 bytes wrapped in CEA-708 packet
|
||||
if (userDataType === 3)
|
||||
{
|
||||
var firstByte = expGolombDecoder.readUByte();
|
||||
var secondByte = expGolombDecoder.readUByte();
|
||||
|
||||
var totalCCs = 31 & firstByte;
|
||||
var byteArray = [firstByte, secondByte];
|
||||
|
||||
for (i=0; i<totalCCs; i++)
|
||||
{
|
||||
// 3 bytes per CC
|
||||
byteArray.push(expGolombDecoder.readUByte());
|
||||
byteArray.push(expGolombDecoder.readUByte());
|
||||
byteArray.push(expGolombDecoder.readUByte());
|
||||
}
|
||||
|
||||
this._txtTrack.samples.push({type: 3, pts: pes.pts, bytes: byteArray});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
//SPS
|
||||
case 7:
|
||||
|
@ -328,7 +392,7 @@
|
|||
debugString += 'SPS ';
|
||||
}
|
||||
if(!track.sps) {
|
||||
var expGolombDecoder = new ExpGolomb(unit.data);
|
||||
expGolombDecoder = new ExpGolomb(unit.data);
|
||||
var config = expGolombDecoder.readSPS();
|
||||
track.width = config.width;
|
||||
track.height = config.height;
|
||||
|
@ -337,7 +401,7 @@
|
|||
track.duration = this.remuxer.timescale * this._duration;
|
||||
var codecarray = unit.data.subarray(1, 4);
|
||||
var codecstring = 'avc1.';
|
||||
for (var i = 0; i < 3; i++) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
var h = codecarray[i].toString(16);
|
||||
if (h.length < 2) {
|
||||
h = '0' + h;
|
||||
|
@ -358,7 +422,7 @@
|
|||
}
|
||||
break;
|
||||
case 9:
|
||||
push = true;
|
||||
push = false;
|
||||
if(debug) {
|
||||
debugString += 'AUD ';
|
||||
}
|
||||
|
@ -443,10 +507,6 @@
|
|||
}
|
||||
lastUnitStart = i;
|
||||
lastUnitType = unitType;
|
||||
if (unitType === 1 || unitType === 5) {
|
||||
// OPTI !!! if IDR/NDR unit, consider it is last NALu
|
||||
i = len;
|
||||
}
|
||||
state = 0;
|
||||
} else {
|
||||
state = 0;
|
||||
|
|
|
@ -33,6 +33,8 @@ module.exports = {
|
|||
FRAG_LOADED: 'hlsFragLoaded',
|
||||
// fired when Init Segment has been extracted from fragment - data: { moov : moov MP4 box, codecs : codecs found while parsing fragment}
|
||||
FRAG_PARSING_INIT_SEGMENT: 'hlsFragParsingInitSegment',
|
||||
// fired when parsing sei text is completed - data: { samples : [ sei samples pes ] }
|
||||
FRAG_PARSING_USERDATA: 'hlsFragParsingUserdata',
|
||||
// fired when parsing id3 is completed - data: { samples : [ id3 samples pes ] }
|
||||
FRAG_PARSING_METADATA: 'hlsFragParsingMetadata',
|
||||
// fired when moof/mdat have been extracted from fragment - data: { moof : moof MP4 box, mdat : mdat MP4 box}
|
||||
|
|
|
@ -10,6 +10,7 @@ import FragmentLoader from './loader/fragment-loader';
|
|||
import AbrController from './controller/abr-controller';
|
||||
import MSEMediaController from './controller/mse-media-controller';
|
||||
import LevelController from './controller/level-controller';
|
||||
import TimelineController from './controller/timeline-controller';
|
||||
//import FPSController from './controller/fps-controller';
|
||||
import {logger, enableLogs} from './utils/logger';
|
||||
import XhrLoader from './utils/xhr-loader';
|
||||
|
@ -65,7 +66,9 @@ class Hls {
|
|||
fLoader: undefined,
|
||||
pLoader: undefined,
|
||||
abrController : AbrController,
|
||||
mediaController: MSEMediaController
|
||||
mediaController: MSEMediaController,
|
||||
timelineController: TimelineController,
|
||||
enableCEA708Captions: true
|
||||
};
|
||||
}
|
||||
return Hls.defaultConfig;
|
||||
|
@ -105,6 +108,7 @@ class Hls {
|
|||
this.levelController = new LevelController(this);
|
||||
this.abrController = new config.abrController(this);
|
||||
this.mediaController = new config.mediaController(this);
|
||||
this.timelineController = new config.timelineController(this);
|
||||
this.keyLoader = new KeyLoader(this);
|
||||
//this.fpsController = new FPSController(this);
|
||||
}
|
||||
|
@ -117,6 +121,7 @@ class Hls {
|
|||
this.fragmentLoader.destroy();
|
||||
this.levelController.destroy();
|
||||
this.mediaController.destroy();
|
||||
this.timelineController.destroy();
|
||||
this.keyLoader.destroy();
|
||||
//this.fpsController.destroy();
|
||||
this.url = null;
|
||||
|
|
|
@ -18,10 +18,11 @@ class DummyRemuxer {
|
|||
insertDiscontinuity() {
|
||||
}
|
||||
|
||||
remux(audioTrack,videoTrack,id3Track,timeOffset) {
|
||||
remux(audioTrack,videoTrack,id3Track,textTrack,timeOffset) {
|
||||
this._remuxAACSamples(audioTrack,timeOffset);
|
||||
this._remuxAVCSamples(videoTrack,timeOffset);
|
||||
this._remuxID3Samples(id3Track,timeOffset);
|
||||
this._remuxTextSamples(textTrack,timeOffset);
|
||||
}
|
||||
|
||||
_remuxAVCSamples(track, timeOffset) {
|
||||
|
@ -59,6 +60,17 @@ class DummyRemuxer {
|
|||
//please lint
|
||||
timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
_remuxTextSamples(track,timeOffset) {
|
||||
var textSample,bytes;
|
||||
// loop through track.samples
|
||||
while (track.samples.length) {
|
||||
textSample = track.samples.shift();
|
||||
bytes = textSample.bytes;
|
||||
}
|
||||
//please lint
|
||||
timeOffset = timeOffset;
|
||||
}
|
||||
}
|
||||
|
||||
export default DummyRemuxer;
|
||||
|
|
|
@ -355,16 +355,16 @@ class MP4 {
|
|||
0x00, 0x48, 0x00, 0x00, // vertresolution
|
||||
0x00, 0x00, 0x00, 0x00, // reserved
|
||||
0x00, 0x01, // frame_count
|
||||
0x13,
|
||||
0x76, 0x69, 0x64, 0x65,
|
||||
0x6f, 0x6a, 0x73, 0x2d,
|
||||
0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x69, 0x62, 0x2d,
|
||||
0x68, 0x6c, 0x73, 0x00,
|
||||
0x12,
|
||||
0x64, 0x61, 0x69, 0x6C, //dailymotion/hls.js
|
||||
0x79, 0x6D, 0x6F, 0x74,
|
||||
0x69, 0x6F, 0x6E, 0x2F,
|
||||
0x68, 0x6C, 0x73, 0x2E,
|
||||
0x6A, 0x73, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, // compressorname
|
||||
0x00, 0x18, // depth = 24
|
||||
0x00, 0x18, // depth = 24
|
||||
0x11, 0x11]), // pre_defined = -1
|
||||
avcc,
|
||||
MP4.box(MP4.types.btrt, new Uint8Array([
|
||||
|
|
|
@ -32,7 +32,7 @@ class MP4Remuxer {
|
|||
this.ISGenerated = false;
|
||||
}
|
||||
|
||||
remux(audioTrack,videoTrack,id3Track,timeOffset, contiguous) {
|
||||
remux(audioTrack,videoTrack,id3Track,textTrack,timeOffset, contiguous) {
|
||||
// generate Init Segment if needed
|
||||
if (!this.ISGenerated) {
|
||||
this.generateIS(audioTrack,videoTrack,timeOffset);
|
||||
|
@ -49,6 +49,10 @@ class MP4Remuxer {
|
|||
if (id3Track.samples.length) {
|
||||
this.remuxID3(id3Track,timeOffset);
|
||||
}
|
||||
//logger.log('nb ID3 samples:' + audioTrack.samples.length);
|
||||
if (textTrack.samples.length) {
|
||||
this.remuxText(textTrack,timeOffset);
|
||||
}
|
||||
//notify end of parsing
|
||||
this.observer.trigger(Event.FRAG_PARSED);
|
||||
}
|
||||
|
@ -264,6 +268,7 @@ class MP4Remuxer {
|
|||
pts = aacSample.pts;
|
||||
} else {
|
||||
logger.warn('dropping past audio frame');
|
||||
track.len -= aacSample.unit.byteLength;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -309,12 +314,17 @@ class MP4Remuxer {
|
|||
// remember first PTS of our aacSamples, ensure value is positive
|
||||
firstPTS = Math.max(0, ptsnorm);
|
||||
firstDTS = Math.max(0, dtsnorm);
|
||||
/* concatenate the audio data and construct the mdat in place
|
||||
(need 8 more bytes to fill length and mdat type) */
|
||||
mdat = new Uint8Array(track.len + 8);
|
||||
view = new DataView(mdat.buffer);
|
||||
view.setUint32(0, mdat.byteLength);
|
||||
mdat.set(MP4.types.mdat, 4);
|
||||
if(track.len > 0) {
|
||||
/* concatenate the audio data and construct the mdat in place
|
||||
(need 8 more bytes to fill length and mdat type) */
|
||||
mdat = new Uint8Array(track.len + 8);
|
||||
view = new DataView(mdat.buffer);
|
||||
view.setUint32(0, mdat.byteLength);
|
||||
mdat.set(MP4.types.mdat, 4);
|
||||
} else {
|
||||
// no audio samples
|
||||
return;
|
||||
}
|
||||
}
|
||||
mdat.set(unit, offset);
|
||||
offset += unit.byteLength;
|
||||
|
@ -382,6 +392,29 @@ class MP4Remuxer {
|
|||
timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
remuxText(track,timeOffset) {
|
||||
track.samples.sort(function(a, b) {
|
||||
return (a.pts-b.pts);
|
||||
});
|
||||
|
||||
var length = track.samples.length, sample;
|
||||
// consume samples
|
||||
if(length) {
|
||||
for(var index = 0; index < length; index++) {
|
||||
sample = track.samples[index];
|
||||
// setting text pts, dts to relative time
|
||||
// using this._initPTS and this._initDTS to calculate relative time
|
||||
sample.pts = ((sample.pts - this._initPTS) / this.PES_TIMESCALE);
|
||||
}
|
||||
this.observer.trigger(Event.FRAG_PARSING_USERDATA, {
|
||||
samples:track.samples
|
||||
});
|
||||
}
|
||||
|
||||
track.samples = [];
|
||||
timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
_PTSNormalize(value, reference) {
|
||||
var offset;
|
||||
if (reference === undefined) {
|
||||
|
|
380
dashboard-ui/bower_components/hls.js/src/utils/cea-708-interpreter.js
vendored
Normal file
380
dashboard-ui/bower_components/hls.js/src/utils/cea-708-interpreter.js
vendored
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* CEA-708 interpreter
|
||||
*/
|
||||
|
||||
class CEA708Interpreter {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
attach(media) {
|
||||
this.media = media;
|
||||
this.display = [];
|
||||
this.memory = [];
|
||||
}
|
||||
|
||||
detach()
|
||||
{
|
||||
this.clear();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
}
|
||||
|
||||
_createCue()
|
||||
{
|
||||
var VTTCue = window.VTTCue || window.TextTrackCue;
|
||||
|
||||
this.cue = new VTTCue(-1, -1, '');
|
||||
this.cue.text = '';
|
||||
this.cue.pauseOnExit = false;
|
||||
|
||||
// make sure it doesn't show up before it's ready
|
||||
this.startTime = Number.MAX_VALUE;
|
||||
|
||||
// show it 'forever' once we do show it
|
||||
// (we'll set the end time once we know it later)
|
||||
this.cue.endTime = Number.MAX_VALUE;
|
||||
|
||||
this.memory.push(this.cue);
|
||||
}
|
||||
|
||||
clear()
|
||||
{
|
||||
if (this._textTrack && this._textTrack.cues)
|
||||
{
|
||||
while (this._textTrack.cues.length > 0)
|
||||
{
|
||||
this._textTrack.removeCue(this._textTrack.cues[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
push(timestamp, bytes)
|
||||
{
|
||||
if (!this.cue)
|
||||
{
|
||||
this._createCue();
|
||||
}
|
||||
|
||||
var count = bytes[0] & 31;
|
||||
var position = 2;
|
||||
var byte, ccbyte1, ccbyte2, ccValid, ccType;
|
||||
|
||||
for (var j=0; j<count; j++)
|
||||
{
|
||||
byte = bytes[position++];
|
||||
ccbyte1 = 0x7F & bytes[position++];
|
||||
ccbyte2 = 0x7F & bytes[position++];
|
||||
ccValid = ((4 & byte) === 0 ? false : true);
|
||||
ccType = (3 & byte);
|
||||
|
||||
if (ccbyte1 === 0 && ccbyte2 === 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ccValid)
|
||||
{
|
||||
if (ccType === 0) // || ccType === 1
|
||||
{
|
||||
// Standard Characters
|
||||
if (0x20 & ccbyte1 || 0x40 & ccbyte1)
|
||||
{
|
||||
this.cue.text += this._fromCharCode(ccbyte1) + this._fromCharCode(ccbyte2);
|
||||
}
|
||||
// Special Characters
|
||||
else if ((ccbyte1 === 0x11 || ccbyte1 === 0x19) && ccbyte2 >= 0x30 && ccbyte2 <= 0x3F)
|
||||
{
|
||||
// extended chars, e.g. musical note, accents
|
||||
switch (ccbyte2)
|
||||
{
|
||||
case 48:
|
||||
this.cue.text += '®';
|
||||
break;
|
||||
case 49:
|
||||
this.cue.text += '°';
|
||||
break;
|
||||
case 50:
|
||||
this.cue.text += '½';
|
||||
break;
|
||||
case 51:
|
||||
this.cue.text += '¿';
|
||||
break;
|
||||
case 52:
|
||||
this.cue.text += '™';
|
||||
break;
|
||||
case 53:
|
||||
this.cue.text += '¢';
|
||||
break;
|
||||
case 54:
|
||||
this.cue.text += '';
|
||||
break;
|
||||
case 55:
|
||||
this.cue.text += '£';
|
||||
break;
|
||||
case 56:
|
||||
this.cue.text += '♪';
|
||||
break;
|
||||
case 57:
|
||||
this.cue.text += ' ';
|
||||
break;
|
||||
case 58:
|
||||
this.cue.text += 'è';
|
||||
break;
|
||||
case 59:
|
||||
this.cue.text += 'â';
|
||||
break;
|
||||
case 60:
|
||||
this.cue.text += 'ê';
|
||||
break;
|
||||
case 61:
|
||||
this.cue.text += 'î';
|
||||
break;
|
||||
case 62:
|
||||
this.cue.text += 'ô';
|
||||
break;
|
||||
case 63:
|
||||
this.cue.text += 'û';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((ccbyte1 === 0x11 || ccbyte1 === 0x19) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F)
|
||||
{
|
||||
// Mid-row codes: color/underline
|
||||
switch (ccbyte2)
|
||||
{
|
||||
case 0x20:
|
||||
// White
|
||||
break;
|
||||
case 0x21:
|
||||
// White Underline
|
||||
break;
|
||||
case 0x22:
|
||||
// Green
|
||||
break;
|
||||
case 0x23:
|
||||
// Green Underline
|
||||
break;
|
||||
case 0x24:
|
||||
// Blue
|
||||
break;
|
||||
case 0x25:
|
||||
// Blue Underline
|
||||
break;
|
||||
case 0x26:
|
||||
// Cyan
|
||||
break;
|
||||
case 0x27:
|
||||
// Cyan Underline
|
||||
break;
|
||||
case 0x28:
|
||||
// Red
|
||||
break;
|
||||
case 0x29:
|
||||
// Red Underline
|
||||
break;
|
||||
case 0x2A:
|
||||
// Yellow
|
||||
break;
|
||||
case 0x2B:
|
||||
// Yellow Underline
|
||||
break;
|
||||
case 0x2C:
|
||||
// Magenta
|
||||
break;
|
||||
case 0x2D:
|
||||
// Magenta Underline
|
||||
break;
|
||||
case 0x2E:
|
||||
// Italics
|
||||
break;
|
||||
case 0x2F:
|
||||
// Italics Underline
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((ccbyte1 === 0x14 || ccbyte1 === 0x1C) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F)
|
||||
{
|
||||
// Mid-row codes: color/underline
|
||||
switch (ccbyte2)
|
||||
{
|
||||
case 0x20:
|
||||
// TODO: shouldn't affect roll-ups...
|
||||
this._clearActiveCues(timestamp);
|
||||
// RCL: Resume Caption Loading
|
||||
// begin pop on
|
||||
break;
|
||||
case 0x21:
|
||||
// BS: Backspace
|
||||
this.cue.text = this.cue.text.substr(0, this.cue.text.length-1);
|
||||
break;
|
||||
case 0x22:
|
||||
// AOF: reserved (formerly alarm off)
|
||||
break;
|
||||
case 0x23:
|
||||
// AON: reserved (formerly alarm on)
|
||||
break;
|
||||
case 0x24:
|
||||
// DER: Delete to end of row
|
||||
break;
|
||||
case 0x25:
|
||||
// RU2: roll-up 2 rows
|
||||
//this._rollup(2);
|
||||
break;
|
||||
case 0x26:
|
||||
// RU3: roll-up 3 rows
|
||||
//this._rollup(3);
|
||||
break;
|
||||
case 0x27:
|
||||
// RU4: roll-up 4 rows
|
||||
//this._rollup(4);
|
||||
break;
|
||||
case 0x28:
|
||||
// FON: Flash on
|
||||
break;
|
||||
case 0x29:
|
||||
// RDC: Resume direct captioning
|
||||
this._clearActiveCues(timestamp);
|
||||
break;
|
||||
case 0x2A:
|
||||
// TR: Text Restart
|
||||
break;
|
||||
case 0x2B:
|
||||
// RTD: Resume Text Display
|
||||
break;
|
||||
case 0x2C:
|
||||
// EDM: Erase Displayed Memory
|
||||
this._clearActiveCues(timestamp);
|
||||
break;
|
||||
case 0x2D:
|
||||
// CR: Carriage Return
|
||||
// only affects roll-up
|
||||
//this._rollup(1);
|
||||
break;
|
||||
case 0x2E:
|
||||
// ENM: Erase non-displayed memory
|
||||
this._text = '';
|
||||
break;
|
||||
case 0x2F:
|
||||
this._flipMemory(timestamp);
|
||||
// EOC: End of caption
|
||||
// hide any displayed captions and show any hidden one
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((ccbyte1 === 0x17 || ccbyte1 === 0x1F) && ccbyte2 >= 0x21 && ccbyte2 <= 0x23)
|
||||
{
|
||||
// Mid-row codes: color/underline
|
||||
switch (ccbyte2)
|
||||
{
|
||||
case 0x21:
|
||||
// TO1: tab offset 1 column
|
||||
break;
|
||||
case 0x22:
|
||||
// TO1: tab offset 2 column
|
||||
break;
|
||||
case 0x23:
|
||||
// TO1: tab offset 3 column
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Probably a pre-amble address code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_fromCharCode(byte)
|
||||
{
|
||||
switch (byte)
|
||||
{
|
||||
case 42:
|
||||
return 'á';
|
||||
|
||||
case 2:
|
||||
return 'á';
|
||||
|
||||
case 2:
|
||||
return 'é';
|
||||
|
||||
case 4:
|
||||
return 'í';
|
||||
|
||||
case 5:
|
||||
return 'ó';
|
||||
|
||||
case 6:
|
||||
return 'ú';
|
||||
|
||||
case 3:
|
||||
return 'ç';
|
||||
|
||||
case 4:
|
||||
return '÷';
|
||||
|
||||
case 5:
|
||||
return 'Ñ';
|
||||
|
||||
case 6:
|
||||
return 'ñ';
|
||||
|
||||
case 7:
|
||||
return '█';
|
||||
|
||||
default:
|
||||
return String.fromCharCode(byte);
|
||||
}
|
||||
}
|
||||
|
||||
_flipMemory(timestamp)
|
||||
{
|
||||
this._clearActiveCues(timestamp);
|
||||
this._flushCaptions(timestamp);
|
||||
}
|
||||
|
||||
_flushCaptions(timestamp)
|
||||
{
|
||||
if (!this._has708)
|
||||
{
|
||||
this._textTrack = this.media.addTextTrack('captions', 'English', 'en');
|
||||
this._has708 = true;
|
||||
}
|
||||
|
||||
for (var i=0; i<this.memory.length; i++)
|
||||
{
|
||||
this.memory[i].startTime = timestamp;
|
||||
this._textTrack.addCue(this.memory[i]);
|
||||
this.display.push(this.memory[i]);
|
||||
}
|
||||
|
||||
this.memory = [];
|
||||
this.cue = null;
|
||||
}
|
||||
|
||||
_clearActiveCues(timestamp)
|
||||
{
|
||||
for (var i=0; i<this.display.length; i++)
|
||||
{
|
||||
this.display[i].endTime = timestamp;
|
||||
}
|
||||
|
||||
this.display = [];
|
||||
}
|
||||
|
||||
/* _rollUp(n)
|
||||
{
|
||||
// TODO: implement roll-up captions
|
||||
}
|
||||
*/
|
||||
_clearBufferedCues()
|
||||
{
|
||||
//remove them all...
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CEA708Interpreter;
|
||||
|
|
@ -46,8 +46,7 @@ var URLHelper = {
|
|||
builtURL = baseURLDomain+URLHelper.buildAbsolutePath('', relativeURL.substring(1));
|
||||
}
|
||||
else {
|
||||
var newPath = URLHelper.buildAbsolutePath(baseURLPath, relativeURL);
|
||||
builtURL = baseURLDomain + newPath;
|
||||
builtURL = URLHelper.buildAbsolutePath(baseURLDomain+baseURLPath, relativeURL);
|
||||
}
|
||||
|
||||
// put the query and hash parts back
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue