├── .gitignore
├── LICENSE
├── README.md
├── app.js
├── bin
└── www
├── config
└── example.json
├── package.json
├── public
├── images
│ └── eyevinn-logo-square.png
├── javascripts
│ ├── hls.min.js
│ ├── hover.js
│ ├── shaka-player.compiled.js
│ └── viewer.js
└── stylesheets
│ └── style.css
├── routes
└── index.js
├── screenshot.png
└── views
├── error.ejs
└── index.ejs
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2016 Eyevinn Technology
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This is a web based multiview screen for HLS and MPEG-DASH streams based on hls.js and Shaka Player. Recommended to run in fullscreen mode.
2 |
3 | 
4 |
5 | Demo: http://labs.eyevinn.se/multiview/?config=example.json
6 |
7 | Some limitations apply:
8 |
9 | - No support for DRM protected content as this is often solutions specific to each site
10 | - Only tested in Chrome and Safari
11 |
12 | # Installation
13 |
14 | Get the code from Github or fork the repository if you plan to contribute to this project.
15 |
16 | `git clone https://github.com/Eyevinn/ott-multiview.git`
17 |
18 | Install the necessary node modules:
19 |
20 | > npm install
21 |
22 | Start the Node express app:
23 |
24 | > npm start
25 |
26 | # ENV vars
27 |
28 | To start a listener on a port other than 3000, set/export the `PORT` ENV var.
29 | To start a HTTPs server, export:
30 | ```
31 | SSL_KEY=/path/to/key
32 | SSL_CRT=/path/to/cert
33 | SSL_CA=/path/to/CA/cert
34 | ```
35 |
36 | If you wish to auto redirect from HTTP (TCP 80) to HTTPs, set/export:
37 | ```
38 | REDIRECT_HTTP=true
39 | ```
40 | **Note that you can only start a listener on TCP 80 and 443 as a super user since these are well known port.**
41 |
42 | # Usage
43 |
44 | When the Node express app is up and running you can direct your Chrome browser to:
45 |
46 | > http://localhost:3000/?config=example.json`
47 |
48 | where `example.json` is a configuration file placed in the directory `config/` and can look like this:
49 | ```json
50 | {
51 | "row0": [
52 | { "title": "View port title",
53 | "manifest": "http://example.com/master.m3u8",
54 | "type": "hls" }
55 | ],
56 | "row1": [
57 | { "title": "View port title 2",
58 | "manifest": "http://example.com/manifest.mpd",
59 | "type": "dash" }
60 | ]
61 | }
62 | ```
63 |
64 | If a row doesn't have 4 sources, you may opt to add a placeholder video to be displayed.
65 | For example, adding:
66 | ```
67 | "placeholder": [
68 | { "title": "NO SIGNAL",
69 | "manifest": "path/to/placeholder/videostream.mpd",
70 | "type": "dash"
71 | }
72 | ]
73 | ```
74 | Will play path/to/placeholder/videostream.mpd in the extra divs.
75 | If no `placeholder` is defined, these divs' `display` attribute will be set to `none`, effectively hiding them.
76 |
77 | To toggle audio on or off click on the viewport that you want to listen to. A green border indicates for which viewport the audio is enabled. You can also use the keyboard keys 1-8.
78 |
79 | ## Keyboard Shortcuts
80 | - SPACE - toggle play / pause for all viewports
81 | - 1-8 - activate audio for viewport 1 to 8
82 | - F - toggle fullscreen mode
83 |
84 | # Contribution
85 |
86 | We are very happy if you want to contribute to this project. Just follow the "normal" procedures and:
87 |
88 | 1. Fork this repository
89 | 2. Create a topic branch in your fork
90 | 3. Add feature or fix bug in the topic branch
91 | 4. Issue a pull request explaining what has been done
92 |
93 | # About Eyevinn Technology
94 |
95 | Eyevinn Technology is an independent consultant firm specialized in video and streaming. Independent in a way that we are not commercially tied to any platform or technology vendor.
96 |
97 | At Eyevinn, every software developer consultant has a dedicated budget reserved for open source development and contribution to the open source community. This give us room for innovation, team building and personal competence development. And also gives us as a company a way to contribute back to the open source community.
98 |
99 | Want to know more about Eyevinn and how it is to work here. Contact us at work@eyevinn.se!
100 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Eyevinn Technology. All rights reserved
2 | // Use of this source code is governed by a MIT License
3 | // license that can be found in the LICENSE file.
4 | // Author: Jonas Birme (Eyevinn Technology)
5 | var express = require('express');
6 | var path = require('path');
7 | var favicon = require('serve-favicon');
8 | var logger = require('morgan');
9 | var cookieParser = require('cookie-parser');
10 | var bodyParser = require('body-parser');
11 |
12 | var routes = require('./routes/index');
13 |
14 | var app = express();
15 |
16 | // view engine setup
17 | app.set('views', path.join(__dirname, 'views'));
18 | app.set('view engine', 'ejs');
19 |
20 | // uncomment after placing your favicon in /public
21 | //app.use(favicon(__dirname + '/public/favicon.ico'));
22 | app.use(logger('dev'));
23 | app.use(bodyParser.json());
24 | app.use(bodyParser.urlencoded({ extended: false }));
25 | app.use(cookieParser());
26 | app.use(express.static(path.join(__dirname, 'public')));
27 |
28 | app.use('/', routes);
29 |
30 | // catch 404 and forward to error handler
31 | app.use(function(req, res, next) {
32 | var err = new Error('Not Found');
33 | err.status = 404;
34 | next(err);
35 | });
36 |
37 | // error handlers
38 |
39 | // development error handler
40 | // will print stacktrace
41 | if (app.get('env') === 'development') {
42 | app.use(function(err, req, res, next) {
43 | res.status(err.status || 500);
44 | res.render('error', {
45 | message: err.message,
46 | error: err
47 | });
48 | });
49 | }
50 |
51 | // production error handler
52 | // no stacktraces leaked to user
53 | app.use(function(err, req, res, next) {
54 | res.status(err.status || 500);
55 | res.render('error', {
56 | message: err.message,
57 | error: {}
58 | });
59 | });
60 |
61 |
62 | module.exports = app;
63 |
--------------------------------------------------------------------------------
/bin/www:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var debug = require('debug')('ott-multiview');
3 | var app = require('../app');
4 | var fs = require('fs');
5 | var https = require('https');
6 | var http = require('http');
7 |
8 |
9 | app.set('port', process.env.PORT || 3000);
10 |
11 | // If these ENV vars are all set, start Express over HTTPs
12 | if (process.env.SSL_KEY && process.env.SSL_CRT && process.env.SSL_CA) {
13 | var sslOptions = {
14 | key: fs.readFileSync(process.env.SSL_KEY),
15 | cert: fs.readFileSync(process.env.SSL_CRT),
16 | ca: fs.readFileSync(process.env.SSL_CA),
17 | requestCert: true,
18 | rejectUnauthorized: false
19 | };
20 | var server = https.createServer(sslOptions, app).listen(app.get('port'), function(){
21 | debug("Secure Express server listening on port "+ app.get('port'));
22 | });
23 | // Is a redirect from HTTP (TCP 80) needed? Note that you can only start a listener on TCP 80 as a super user since it's a well known port
24 | if (process.env.REDIRECT_HTTP === 'true'){
25 | // Redirect from http port 80 to https
26 | http.createServer(function (req, res) {
27 | res.writeHead(301, { "Location": "https://" + req.headers['host'].replace('80',app.get('port')) + req.url });
28 | res.end();
29 | }).listen(80);
30 | }
31 |
32 | // If SSL cert and key vars are unset, start a HTTP server
33 | }else{
34 | var server = http.createServer(app).listen(app.get('port'), function(){
35 | debug('Express server listening on port ' + server.address().port);
36 | });
37 | }
38 |
39 | app.use((err, req, res, next) => {
40 | debug(err);
41 | next();
42 | })
43 |
44 |
--------------------------------------------------------------------------------
/config/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "row0": [
3 | { "title": "Example 1",
4 | "manifest": "https://content.jwplatform.com/manifests/vM7nH0Kl.m3u8",
5 | "type": "hls"
6 | },
7 | { "title": "Example 2",
8 | "manifest": "https://content.jwplatform.com/manifests/vM7nH0Kl.m3u8",
9 | "type": "hls"
10 | },
11 | { "title": "Example 3",
12 | "manifest": "https://content.jwplatform.com/manifests/vM7nH0Kl.m3u8",
13 | "type": "hls"
14 | },
15 | { "title": "Example 4",
16 | "manifest": "https://content.jwplatform.com/manifests/vM7nH0Kl.m3u8",
17 | "type": "hls"
18 | }
19 | ],
20 | "row1": [
21 | { "title": "Example 5",
22 | "manifest": "https://www.bok.net/dash/tears_of_steel/cleartext/stream.mpd",
23 | "type": "dash"
24 | },
25 | { "title": "Example 6",
26 | "manifest": "https://www.bok.net/dash/tears_of_steel/cleartext/stream.mpd",
27 | "type": "dash"
28 | },
29 | { "title": "Example 7",
30 | "manifest": "https://www.bok.net/dash/tears_of_steel/cleartext/stream.mpd",
31 | "type": "dash"
32 | },
33 | { "title": "Example 8",
34 | "manifest": "https://www.bok.net/dash/tears_of_steel/cleartext/stream.mpd",
35 | "type": "dash"
36 | }
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ott-multiview",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "node ./bin/www"
7 | },
8 | "dependencies": {
9 | "express": "~4.9.0",
10 | "body-parser": "~1.8.1",
11 | "cookie-parser": "~1.3.3",
12 | "morgan": "~1.9.1",
13 | "serve-favicon": "~2.1.3",
14 | "debug": "~4.1.1",
15 | "ejs": "~0.8.5"
16 | }
17 | }
--------------------------------------------------------------------------------
/public/images/eyevinn-logo-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Eyevinn/ott-multiview/bbde5f834578c3b76272425efc7a487e794d0c3e/public/images/eyevinn-logo-square.png
--------------------------------------------------------------------------------
/public/javascripts/hover.js:
--------------------------------------------------------------------------------
1 | /* When hovering over vp we want to display an overlay box with
2 | statistics information about that specific video */
3 | window.onload = function() {
4 | // Hide at startup so not displaying a uninitialized div
5 | $('.videoInfo').hide();
6 |
7 | var updateVideoStatsTimer;
8 | var statsDiv;
9 | var stats;
10 | var videoId;
11 | var displayStats = false;
12 |
13 | /* hover over vp */
14 | $('.vp').hover(function(){
15 | /* get video id */
16 | videoId = $(this).find('video').attr('id');
17 |
18 | /* find div where stats will be displayed */
19 | statsDiv = $(this).find('.videoInfo');
20 | statsDiv.show();
21 | displayStats = true;
22 |
23 | /* updatde stats */
24 | updateVideoStatsTimer = setInterval(function(){ onTimer() }, 1000);
25 |
26 | }, function() {
27 | displayStats = false;
28 | statsDiv = $(this).find('.videoInfo');
29 | statsDiv.hide();
30 | });
31 |
32 | // Get video stats and add them to html div
33 | function onTimer(){
34 | if (displayStats == true)
35 | { //Statistics for HLS video not yet available
36 | if (shakaPlayers[videoId] === undefined) {
37 | statsDiv.html('
No data available
');
38 | } else {
39 |
40 | stats = shakaPlayers[videoId].getStats();
41 | statsDiv.html( 'Video id: ' + videoId + ' '+
42 | 'Decoded frames: ' + stats.decodedFrames + ' '+
43 | 'Dropped frames: ' + stats.droppedFrames + ' '+
44 | 'Buffering time: ' + stats.bufferingTime.toFixed(2) + ' s '+
45 | 'Playtime: ' + (stats.playTime.toFixed(1)) + ' s '+
46 | 'Stream bandwidth: ' + (stats.streamBandwidth)/1000 + ' kbps '+
47 | 'Estimated bandwidth: ' + stats.estimatedBandWidth + ' kbps '+
48 | //'Switch history: ' + stats.switchHistory + ' '+
49 | 'Width: ' + stats.width + ' pxls '+
50 | 'Height: ' + stats.height + ' pxls
');
51 | }
52 | }
53 | else {
54 | clearInterval(updateVideoStatsTimer);
55 | }
56 | }
57 | // add audio meter overlay to video divs
58 | //$('#audioMeter').html('Audio meter!');
59 | };
60 |
--------------------------------------------------------------------------------
/public/javascripts/shaka-player.compiled.js:
--------------------------------------------------------------------------------
1 | (function(){var g={};
2 | (function(window){var k,aa=this;aa.fd=!0;function m(a,b){var c=a.split("."),d=aa;c[0]in d||!d.execScript||d.execScript("var "+c[0]);for(var e;c.length&&(e=c.shift());)c.length||void 0===b?d[e]?d=d[e]:d=d[e]={}:d[e]=b}function ba(a){var b=n;function c(){}c.prototype=b.prototype;a.nd=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.gd=function(a,c,f){return b.prototype[c].apply(a,Array.prototype.slice.call(arguments,2))}};/*
3 |
4 | Copyright 2016 Google Inc.
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 | */
18 | function ca(a){this.c=Math.exp(Math.log(.5)/a);this.b=this.a=0}function da(a,b,c){var d=Math.pow(a.c,b);a.a=c*(1-d)+d*a.a;a.b+=b}function ea(a){return a.a/(1-Math.pow(a.c,a.b))};function fa(){this.c=new ca(2);this.f=new ca(5);this.a=0;this.b=5E5}fa.prototype.setDefaultEstimate=function(a){this.b=a};fa.prototype.getBandwidthEstimate=function(){return 128E3>this.a?this.b:Math.min(ea(this.c),ea(this.f))};function ga(){}function ha(){};function q(){this.h=null;this.f=!1;this.b=new fa;this.g={};this.a={};this.i=!1;this.c=null}m("shaka.abr.SimpleAbrManager",q);q.prototype.stop=function(){this.h=null;this.f=!1;this.g={};this.a={};this.c=null};q.prototype.stop=q.prototype.stop;q.prototype.init=function(a){this.h=a};q.prototype.init=q.prototype.init;
19 | q.prototype.chooseStreams=function(a){for(var b in a)this.g[b]=a[b];b=this.a.audio;var c=this.a.video,d={};"audio"in a&&(b=ia(this));"video"in a&&((c=ja(this,"video",b))?(d.video=c,this.a.video=c):delete this.a.video);"audio"in a&&((b=ja(this,"audio",c))?(d.audio=b,this.a.audio=b):delete this.a.audio);"text"in a&&(d.text=a.text.streams[0]);this.c=Date.now();return d};q.prototype.chooseStreams=q.prototype.chooseStreams;q.prototype.enable=function(){this.f=!0};q.prototype.enable=q.prototype.enable;
20 | q.prototype.disable=function(){this.f=!1};q.prototype.disable=q.prototype.disable;q.prototype.segmentDownloaded=function(a,b,c){var d=this.b;b-=a;16E3>c||(a=8E3*c/b,b/=1E3,d.a+=c,da(d.c,b,a),da(d.f,b,a));if(null!=this.c&&this.f)a:{if(!this.i){if(!(128E3<=this.b.a))break a;this.i=!0}else if(8E3>Date.now()-this.c)break a;c={};d=ia(this);a=ja(this,"video",d);if(d=ja(this,"audio",a))c.audio=d,this.a.audio=d;a&&(c.video=a,this.a.video=a);this.c=Date.now();this.b.getBandwidthEstimate();this.h(c)}};
21 | q.prototype.segmentDownloaded=q.prototype.segmentDownloaded;q.prototype.getBandwidthEstimate=function(){return this.b.getBandwidthEstimate()};q.prototype.getBandwidthEstimate=q.prototype.getBandwidthEstimate;q.prototype.setDefaultEstimate=function(a){this.b.setDefaultEstimate(a)};q.prototype.setDefaultEstimate=q.prototype.setDefaultEstimate;function ia(a){a=a.g.audio;if(!a)return null;a=ka(a);return a[Math.floor(a.length/2)]}
22 | function ja(a,b,c){b=a.g[b];if(!b)return null;b=ka(b);c=c&&c.bandwidth||0;a=a.b.getBandwidthEstimate();for(var d=b[0],e=0;e=(f.bandwidth+c)/.95&&a<=g&&(d=f)}}return d}function ka(a){return a.streams.slice(0).filter(function(a){return a.allowedByApplication&&a.allowedByKeySystem}).sort(function(a,c){return a.bandwidth-c.bandwidth})};var la=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#(.*))?$/;function ma(a){var b;a instanceof ma?(na(this,a.T),this.ka=a.ka,this.U=a.U,oa(this,a.wa),this.P=a.P,pa(this,qa(a.a)),this.da=a.da):a&&(b=String(a).match(la))?(na(this,b[1]||"",!0),this.ka=ra(b[2]||""),this.U=ra(b[3]||"",!0),oa(this,b[4]),this.P=ra(b[5]||"",!0),pa(this,b[6]||"",!0),this.da=ra(b[7]||"")):this.a=new sa(null)}k=ma.prototype;k.T="";k.ka="";k.U="";k.wa=null;k.P="";k.da="";
23 | k.toString=function(){var a=[],b=this.T;b&&a.push(ta(b,ua,!0),":");if(b=this.U){a.push("//");var c=this.ka;c&&a.push(ta(c,ua,!0),"@");a.push(encodeURIComponent(b).replace(/%25([0-9a-fA-F]{2})/g,"%$1"));b=this.wa;null!=b&&a.push(":",String(b))}if(b=this.P)this.U&&"/"!=b.charAt(0)&&a.push("/"),a.push(ta(b,"/"==b.charAt(0)?va:wa,!0));(b=this.a.toString())&&a.push("?",b);(b=this.da)&&a.push("#",ta(b,xa));return a.join("")};
24 | k.resolve=function(a){var b=new ma(this);"data"===b.T&&(b=new ma);var c=!!a.T;c?na(b,a.T):c=!!a.ka;c?b.ka=a.ka:c=!!a.U;c?b.U=a.U:c=null!=a.wa;var d=a.P;if(c)oa(b,a.wa);else if(c=!!a.P){if("/"!=d.charAt(0))if(this.U&&!this.P)d="/"+d;else{var e=b.P.lastIndexOf("/");-1!=e&&(d=b.P.substr(0,e+1)+d)}if(".."==d||"."==d)d="";else if(-1!=d.indexOf("./")||-1!=d.indexOf("/.")){for(var e=!d.lastIndexOf("/",0),d=d.split("/"),f=[],g=0;gb)throw Error("Bad port number "+b);a.wa=b}else a.wa=null}function pa(a,b,c){b instanceof sa?a.a=b:(c||(b=ta(b,ya)),a.a=new sa(b))}function ra(a,b){return a?b?decodeURI(a):decodeURIComponent(a):""}
26 | function ta(a,b,c){return"string"==typeof a?(a=encodeURI(a).replace(b,za),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,"%$1")),a):null}function za(a){a=a.charCodeAt(0);return"%"+(a>>4&15).toString(16)+(a&15).toString(16)}var ua=/[#\/\?@]/g,wa=/[\#\?:]/g,va=/[\#\?]/g,ya=/[\#\?@]/g,xa=/#/g;function sa(a){this.b=a||null}sa.prototype.a=null;sa.prototype.c=null;
27 | sa.prototype.toString=function(){if(this.b)return this.b;if(!this.a)return"";var a=[],b;for(b in this.a)for(var c=encodeURIComponent(b),d=this.a[b],e=0;e=a[b]}.bind(null,b);if(b[0]||b[2]){if(!b[1]&&!b[3])return Pa(a,!0);if(c(0)&&c(1)&&c(2)&&c(3))return D(a)}else return Pa(a,!1);throw new r(2,2003);}
40 | function Ra(a){a=unescape(encodeURIComponent(a));for(var b=new Uint8Array(a.length),c=0;cc||d&&1E3>c)this.a.splice(b,1),a.close();Ta(this.v)}};k.zc=function(){Na(this.A,function(a,b){return"expired"==b})&&this.g(new r(6,6014));this.R(this.A)};
64 | function nb(){var a=[],b=[{contentType:'video/mp4; codecs="avc1.42E01E"'},{contentType:'video/webm; codecs="vp8"'}],c=[{videoCapabilities:b,persistentState:"required",sessionTypes:["persistent-license"]},{videoCapabilities:b}],d={};"org.w3.clearkey com.widevine.alpha com.microsoft.playready com.apple.fps.2_0 com.apple.fps.1_0 com.apple.fps com.adobe.primetime".split(" ").forEach(function(b){var e=navigator.requestMediaKeySystemAccess(b,c).then(function(a){return a.createMediaKeys()}).then(function(a){var c=
65 | !1;try{a.createSession("persistent-license"),c=!0}catch(l){}d[b]={persistentState:c}},function(){d[b]=null});a.push(e)});return Promise.all(a).then(function(){return d})}k.lc=function(){for(var a=0;a=b?null:new vb(a,b,c)}m("shaka.media.TextEngine.makeCue",ub);var vb=window.VTTCue||window.TextTrackCue;tb.prototype.o=function(){this.c&&wb(this,function(){return!0});this.c=this.g=null;return Promise.resolve()};
67 | function xb(a,b,c,d){var e=a.h;return Promise.resolve().then(function(){if(this.c){var a=this.g(b,e,c,d,this.i);if(null!=c&&null!=d){for(var g=0;g=this.f);++g)this.c.addCue(a[g]);null==this.b&&(this.b=c);this.a=Math.min(d,this.f)}}}.bind(a))}
68 | tb.prototype.remove=function(a,b){return Promise.resolve().then(function(){this.c&&(wb(this,function(c){return c.startTime>=b||c.endTime<=a?!1:!0}),null==this.b||b<=this.b||a>=this.a||(a<=this.b&&b>=this.a?this.b=this.a=null:a<=this.b&&bthis.b&&b>=this.a&&(this.a=a)))}.bind(this))};function yb(a,b){return null==a.a||a.aa.end(0)-a.start(0)?null:a.length?a.end(a.length-1):null}function Ab(a,b){var c=0;if(!a||1==a.length&&1E-6>a.end(0)-a.start(0))return c;for(var d=!1,e=0;e=a.start(e)&&b=a.start(e)-a.end(e-1))c+=a.end(e)-a.start(e),c+=a.start(e)-a.end(e-1);else if(0=a.end(e-1))if(.04>=a.start(e)-b)c+=a.end(e)-b,d=!0;else break;else d=!1;return c};function Bb(a,b,c){this.g=a;this.f=b;this.j=c;this.c={};this.b=null;this.a={};this.h=new z;this.i=!1}
69 | function Cb(){var a={};'video/mp4; codecs="avc1.42E01E",video/mp4; codecs="avc3.42E01E",video/mp4; codecs="hvc1.1.6.L93.90",audio/mp4; codecs="mp4a.40.2",audio/mp4; codecs="ac-3",audio/mp4; codecs="ec-3",video/webm; codecs="vp8",video/webm; codecs="vp9",video/webm; codecs="av1",audio/webm; codecs="vorbis",audio/webm; codecs="opus",video/mp2t; codecs="avc1.42E01E",video/mp2t; codecs="avc3.42E01E",video/mp2t; codecs="hvc1.1.6.L93.90",video/mp2t; codecs="mp4a.40.2",video/mp2t; codecs="ac-3",video/mp2t; codecs="ec-3",video/mp2t; codecs="mp4a.40.2",text/vtt,application/mp4; codecs="wvtt",application/ttml+xml,application/mp4; codecs="stpp"'.split(",").forEach(function(b){a[b]=!!F[b]||
70 | MediaSource.isTypeSupported(b);var c=b.split(";")[0];a[c]=a[c]||a[b]});return a}k=Bb.prototype;k.o=function(){this.i=!0;var a=[],b;for(b in this.a){var c=this.a[b],d=c[0];this.a[b]=c.slice(0,1);d&&a.push(d.p["catch"](w));for(d=1;dc.end(0)-c.start(0)?null:1==c.length&&0>c.start(0)?0:c.length?c.start(0):null);return c}function Fb(a,b){return"text"==b?a.b.a:zb(Eb(a,b))}
72 | function Gb(a,b,c){"text"==b?(b=yb(a.b,c),b||(b=yb(a.b,c+.1))&&(b+=.1)):(a=Eb(a,b),b=Ab(a,c),b||(b=Ab(a,c+.1))&&(b+=.1));return b}function Eb(a,b){try{return a.c[b].buffered}catch(c){return null}}function Hb(a,b,c,d,e){return"text"==b?xb(a.b,c,d,e):Ib(a,b,a.Uc.bind(a,b,c))}k.remove=function(a,b,c){return"text"==a?this.b.remove(b,c):Ib(this,a,this.yb.bind(this,a,b,c))};
73 | function Jb(a,b){return"text"==b?a.b.remove(0,Infinity):Promise.all([Ib(a,b,a.yb.bind(a,b,0,a.f.duration)),Ib(a,b,a.Sb.bind(a,b))])}function Kb(a,b,c){return"text"==b?(a.b.h=c,Promise.resolve()):Ib(a,b,a.Kc.bind(a,b,c))}function Lb(a,b,c){return"text"==b?(a.b.f=c,Promise.resolve()):Promise.all([Ib(a,b,a.Jb.bind(a,b)),Ib(a,b,a.Ic.bind(a,b,c))])}k.endOfStream=function(a){return Mb(this,function(){a?this.f.endOfStream(a):this.f.endOfStream()}.bind(this))};
74 | k.za=function(a){return Mb(this,function(){this.f.duration=a}.bind(this))};k.ea=function(){return this.f.duration};k.Uc=function(a,b){this.c[a].appendBuffer(b)};k.yb=function(a,b,c){c<=b?this.va(a):this.c[a].remove(b,c)};k.Jb=function(a){var b=this.c[a].appendWindowEnd;this.c[a].abort();this.c[a].appendWindowEnd=b;this.va(a)};k.Sb=function(a){this.g.currentTime-=.001;this.va(a)};k.Kc=function(a,b){this.c[a].timestampOffset=b;this.va(a)};k.Ic=function(a,b){this.c[a].appendWindowEnd=b+.04;this.va(a)};
75 | k.Vc=function(a){this.a[a][0].p.reject(new r(3,3014,this.g.error?this.g.error.code:0))};k.va=function(a){var b=this.a[a][0];b&&(b.p.resolve(),Nb(this,a))};function Ib(a,b,c){if(a.i)return Promise.reject();c={start:c,p:new x};a.a[b].push(c);if(1==a.a[b].length)try{c.start()}catch(d){"QuotaExceededError"==d.name?c.p.reject(new r(3,3017,b)):c.p.reject(new r(3,3015,d)),Nb(a,b)}return c.p}
76 | function Mb(a,b){if(a.i)return Promise.reject();var c=[],d;for(d in a.c){var e=new x,f={start:function(a){a.resolve()}.bind(null,e),p:e};a.a[d].push(f);c.push(e);1==a.a[d].length&&f.start()}return Promise.all(c).then(function(){var a,c;try{b()}catch(l){c=Promise.reject(new r(3,3015,l))}for(a in this.c)Nb(this,a);return c}.bind(a),function(){return Promise.reject()}.bind(a))}function Nb(a,b){a.a[b].shift();var c=a.a[b][0];if(c)try{c.start()}catch(d){c.p.reject(new r(3,3015,d)),Nb(a,b)}};function Ob(a,b,c){this.a=a;this.M=b;this.D=c}m("shaka.media.InitSegmentReference",Ob);function G(a,b,c,d,e,f){this.position=a;this.startTime=b;this.endTime=c;this.a=d;this.M=e;this.D=f}m("shaka.media.SegmentReference",G);function I(a,b){this.g=a;this.j=b;this.c=this.a=Infinity;this.b=1;this.i=this.f=0;this.h=!0}m("shaka.media.PresentationTimeline",I);I.prototype.ea=function(){return this.a};I.prototype.getDuration=I.prototype.ea;I.prototype.za=function(a){this.a=a};I.prototype.setDuration=I.prototype.za;I.prototype.Wb=function(){return this.g};I.prototype.getPresentationStartTime=I.prototype.Wb;I.prototype.Cb=function(a){this.i=a};I.prototype.setClockOffset=I.prototype.Cb;I.prototype.Fb=function(a){this.h=a};
77 | I.prototype.setStatic=I.prototype.Fb;I.prototype.Xb=function(){return this.c};I.prototype.getSegmentAvailabilityDuration=I.prototype.Xb;I.prototype.Eb=function(a){this.c=a};I.prototype.setSegmentAvailabilityDuration=I.prototype.Eb;I.prototype.Fa=function(a,b){b.length&&(this.b=b.reduce(function(a,b){return Math.max(a,b.endTime-b.startTime)},this.b),a||(this.f=Math.max(this.f,b[0].startTime)))};I.prototype.notifySegments=I.prototype.Fa;I.prototype.Wa=function(a){this.b=Math.max(this.b,a)};
78 | I.prototype.notifyMaxSegmentDuration=I.prototype.Wa;I.prototype.V=function(){return Infinity==this.a&&!this.h};I.prototype.isLive=I.prototype.V;I.prototype.ga=function(){return Infinity!=this.a&&!this.h};I.prototype.isInProgress=I.prototype.ga;I.prototype.ra=function(){return Math.max(Math.min(this.f,this.fa()),this.sa())};I.prototype.getEarliestStart=I.prototype.ra;I.prototype.sa=function(){return Infinity==this.c?0:Math.max(0,this.fa()-this.c-this.j)};I.prototype.getSegmentAvailabilityStart=I.prototype.sa;
79 | I.prototype.fa=function(){return this.V()||this.ga()?Math.min(Math.max(0,(Date.now()+this.i)/1E3-this.b-this.g),this.a):this.a};I.prototype.getSegmentAvailabilityEnd=I.prototype.fa;I.prototype.Sa=function(){return Math.max(0,this.fa()-(this.V()||this.ga()?this.j:0))};I.prototype.getSeekRangeEnd=I.prototype.Sa;function Pb(a,b,c,d,e,f){this.a=a;this.c=b;this.j=c;this.s=d;this.l=e;this.m=f;this.b=new z;this.g=!1;this.h=1;this.i=this.f=null;0a.c.ea()?a.c.ra():Math.max(a.c.Sa(),a.c.ra())}function Vb(a,b){b!=a.g&&(a.g=b,Wb(a,a.h),a.l(b))}function Qb(a){Rb(a);a.i=window.setTimeout(a.qc.bind(a),250)}function Rb(a){a.i&&(window.clearTimeout(a.i),a.i=null)}k.qc=function(){this.i=null;Qb(this);var a=Ab(this.a.buffered,this.a.currentTime),b=zb(this.a.buffered)>=this.a.duration-.05||this.a.ended;this.g?(b||a>this.j)&&Vb(this,!1):!b&&.5>a&&Vb(this,!0)};k.Ra=function(){return this.h};
81 | function Wb(a,b){null!=a.f&&(window.clearInterval(a.f),a.f=null);a.h=b;a.a.playbackRate=a.g||0>b?0:b;!a.g&&0>b&&(a.f=window.setInterval(function(){this.a.currentTime+=b/4}.bind(a),250))}k.mc=function(){this.a.playbackRate!=(this.g||0>this.h?0:this.h)&&Wb(this,this.a.playbackRate)};
82 | k.pb=function(){this.b.aa(this.a,"loadedmetadata");var a=Ub(this);.001>Math.abs(this.a.currentTime-a)?(A(this.b,this.a,"seeking",this.rb.bind(this)),A(this.b,this.a,"playing",this.qb.bind(this))):(A(this.b,this.a,"seeking",this.oc.bind(this)),this.a.currentTime=a)};k.oc=function(){this.b.aa(this.a,"seeking");A(this.b,this.a,"seeking",this.rb.bind(this));A(this.b,this.a,"playing",this.qb.bind(this))};k.rb=function(){var a=this.a.currentTime,b=Xb(this,a);.001e?e:b;c=d+1;d=c+a.j;return b>=d&&b<=e||Ab(a.a.buffered,b)&&b>=c&&b<=e?b:b>e?e:e=c&&b<=e?b:Math.min(d+2,e)}function Yb(a,b,c){a.a.currentTime=c;var d=0,e=function(){!this.a||10<=d++||this.a.currentTime!=b||(this.a.currentTime=c,setTimeout(e,100))}.bind(a);setTimeout(e,100)}
84 | function Tb(a,b){var c=a.c.ra();if(bc?c:b};function Zb(a,b,c,d,e,f,g,h,l){this.m=a;this.c=b;this.K=c;this.a=d;this.G=e;this.v=f;this.j=g;this.w=h||null;this.A=l||null;this.g=null;this.i=1;this.C=Promise.resolve();this.h=[];this.l={};this.b={};this.f=this.s=this.J=!1}Zb.prototype.o=function(){for(var a in this.b)$b(this.b[a]);this.g=this.b=this.l=this.h=this.A=this.w=this.j=this.v=this.G=this.C=this.a=this.K=this.c=this.m=null;this.f=!0;return Promise.resolve()};
85 | Zb.prototype.configure=function(a){this.g=a;this.m.j=this.i*Math.max(this.a.minBufferTime||0,this.g.rebufferingGoal)};Zb.prototype.init=function(){var a=this.G(this.a.periods[ac(this,Sb(this.m))]);return La(a)?Promise.reject(new r(5,5005)):bc(this,a).then(function(){this.w&&this.w()}.bind(this))};function cc(a){return a.a.periods[ac(a,Sb(a.m))]}function dc(a){return Ma(a.b,function(a){return a.stream})}function ec(a,b){var c={};c.text=b;return bc(a,c)}
86 | function fc(a,b,c,d){var e=a.b[b];!e&&"text"==b&&a.g.ignoreTextStreamFailures?ec(a,c):e&&(b=a.h[gc(a,c)])&&b.xa&&(b=a.l[c.id])&&b.xa&&e.stream!=c&&(e.stream=c,e.La=!0,d&&!e.ca&&(e.ha?e.la=!0:($b(e),hc(a,e))))}
87 | function bc(a,b){var c=ac(a,Sb(a.m)),d=Ma(b,function(a){return a.mimeType+(a.codecs?'; codecs="'+a.codecs+'"':"")});a.c.init(d,a.g.useRelativeCueTimestamps);ic(a);d=C(b);return jc(a,d).then(function(){if(!this.f)for(var a in b){var d=b[a];this.b[a]||(this.b[a]={stream:d,type:a,ta:null,W:null,La:!0,Ma:c,endOfStream:!1,ha:!1,ba:null,la:!1,ca:!1,$a:!1},kc(this,this.b[a],0))}}.bind(a))}
88 | function lc(a,b){var c=a.h[b];if(c)return c.I;c={I:new x,xa:!1};a.h[b]=c;var d=a.a.periods[b].streamSets.map(function(a){return a.streams}).reduce(v,[]);a.C=a.C.then(function(){if(!this.f)return jc(this,d)}.bind(a)).then(function(){this.f||(this.h[b].I.resolve(),this.h[b].xa=!0)}.bind(a))["catch"](function(a){this.f||(this.h[b].I.reject(),delete this.h[b],this.j(a))}.bind(a));return c.I}
89 | function jc(a,b){for(var c=[],d=0;db?a.c.za(b):a.c.za(Math.pow(2,32))}
90 | Zb.prototype.R=function(a){if(!this.f&&!a.ha&&null!=a.ba&&!a.ca)if(a.ba=null,a.la)hc(this,a);else{try{var b=mc(this,a);null!=b&&kc(this,a,b)}catch(c){this.j(c);return}b=C(this.b);nc(this,a);b.every(function(a){return a.endOfStream})&&this.c.endOfStream()}};
91 | function mc(a,b){var c=Sb(a.m),d=b.ta&&b.W?a.a.periods[gc(a,b.ta)].startTime+b.W.endTime:c,e=gc(a,b.stream),f=ac(a,d),g=a.a.periods[f],h=Fb(a.c,b.type),l=null;e==f&&(l=oc(a,b,c,h,f));if((l?g.startTime+l.startTime-c:Gb(a.c,b.type,c))>=Math.max(a.i*Math.max(a.a.minBufferTime||0,a.g.rebufferingGoal),a.i*a.g.bufferingGoal))return.5;if(d>=a.a.presentationTimeline.ea())return b.endOfStream=!0,null;b.endOfStream=!1;if(f!=e)return b.Ma=f,null;d=Fb(a.c,b.type);d=oc(a,b,c,d,e);if(!d)return 1;pc(a,b,c,e,d);
92 | return null}function oc(a,b,c,d,e){if(b.W&&b.stream==b.ta)return c=b.W.position+1,qc(a,b,e,c);c=b.W?b.stream.findSegmentPosition(Math.max(0,a.a.periods[gc(a,b.ta)].startTime+b.W.endTime-a.a.periods[e].startTime)):b.stream.findSegmentPosition(Math.max(0,(d||c)-a.a.periods[e].startTime));if(null==c)return null;var f=null;null==d&&(f=qc(a,b,e,Math.max(0,c-1)));return f||qc(a,b,e,c)}
93 | function qc(a,b,c,d){c=a.a.periods[c];b=b.stream.getSegmentReference(d);if(!b)return null;a=a.a.presentationTimeline;d=a.fa();return c.startTime+b.endTimed?null:b}
94 | function pc(a,b,c,d,e){var f=a.a.periods[d],g=b.stream,h=a.a.periods[d+1],l=null,l=h?h.startTime:a.a.presentationTimeline.ea();d=rc(a,b,d,l);b.ha=!0;b.La=!1;h=sc(a,e);Promise.all([d,h]).then(function(a){if(!this.f&&!this.s)return tc(this,b,c,f,g,e,a[1])}.bind(a)).then(function(){this.f||this.s||(b.ha=!1,b.$a=!1,kc(this,b,0),uc(this,g))}.bind(a))["catch"](function(a){this.f||this.s||(b.ha=!1,1001==a.code||1002==a.code||1003==a.code?"text"==b.type&&this.g.ignoreTextStreamFailures&&1001==a.code?delete this.b.text:
95 | (this.j(a),kc(this,b,4)):3017==a.code?vc(this,b,a):this.j(a))}.bind(a))}function vc(a,b,c){if(!C(a.b).some(function(a){return a!=b&&a.$a})){var d=Math.round(100*a.i);if(20=c?Promise.resolve():a.c.remove(b.type,d,d+c).then(function(){}.bind(a))}
98 | function uc(a,b){if(!a.J&&(a.J=C(a.b).every(function(a){return!a.la&&!a.ca&&a.W}),a.J)){var c=gc(a,b);a.h[c]||lc(a,c).then(function(){this.v()}.bind(a))["catch"](w);for(c=0;c=a.a.periods[c].startTime)return c;return 0}function gc(a,b){for(var c=0;c=Cc&&c==b.split("-")[0]||a>=Dc&&c.split("-")[0]==b.split("-")[0]?!0:!1}var Cc=1,Dc=2;function Ec(a){a=a.toLowerCase().split("-");var b=Fc[a[0]];b&&(a[0]=b);return a.join("-")}
104 | var Fc={aar:"aa",abk:"ab",afr:"af",aka:"ak",alb:"sq",amh:"am",ara:"ar",arg:"an",arm:"hy",asm:"as",ava:"av",ave:"ae",aym:"ay",aze:"az",bak:"ba",bam:"bm",baq:"eu",bel:"be",ben:"bn",bih:"bh",bis:"bi",bod:"bo",bos:"bs",bre:"br",bul:"bg",bur:"my",cat:"ca",ces:"cs",cha:"ch",che:"ce",chi:"zh",chu:"cu",chv:"cv",cor:"kw",cos:"co",cre:"cr",cym:"cy",cze:"cs",dan:"da",deu:"de",div:"dv",dut:"nl",dzo:"dz",ell:"el",eng:"en",epo:"eo",est:"et",eus:"eu",ewe:"ee",fao:"fo",fas:"fa",fij:"fj",fin:"fi",fra:"fr",fre:"fr",
105 | fry:"fy",ful:"ff",geo:"ka",ger:"de",gla:"gd",gle:"ga",glg:"gl",glv:"gv",gre:"el",grn:"gn",guj:"gu",hat:"ht",hau:"ha",heb:"he",her:"hz",hin:"hi",hmo:"ho",hrv:"hr",hun:"hu",hye:"hy",ibo:"ig",ice:"is",ido:"io",iii:"ii",iku:"iu",ile:"ie",ina:"ia",ind:"id",ipk:"ik",isl:"is",ita:"it",jav:"jv",jpn:"ja",kal:"kl",kan:"kn",kas:"ks",kat:"ka",kau:"kr",kaz:"kk",khm:"km",kik:"ki",kin:"rw",kir:"ky",kom:"kv",kon:"kg",kor:"ko",kua:"kj",kur:"ku",lao:"lo",lat:"la",lav:"lv",lim:"li",lin:"ln",lit:"lt",ltz:"lb",lub:"lu",
106 | lug:"lg",mac:"mk",mah:"mh",mal:"ml",mao:"mi",mar:"mr",may:"ms",mkd:"mk",mlg:"mg",mlt:"mt",mon:"mn",mri:"mi",msa:"ms",mya:"my",nau:"na",nav:"nv",nbl:"nr",nde:"nd",ndo:"ng",nep:"ne",nld:"nl",nno:"nn",nob:"nb",nor:"no",nya:"ny",oci:"oc",oji:"oj",ori:"or",orm:"om",oss:"os",pan:"pa",per:"fa",pli:"pi",pol:"pl",por:"pt",pus:"ps",que:"qu",roh:"rm",ron:"ro",rum:"ro",run:"rn",rus:"ru",sag:"sg",san:"sa",sin:"si",slk:"sk",slo:"sk",slv:"sl",sme:"se",smo:"sm",sna:"sn",snd:"sd",som:"so",sot:"st",spa:"es",sqi:"sq",
107 | srd:"sc",srp:"sr",ssw:"ss",sun:"su",swa:"sw",swe:"sv",tah:"ty",tam:"ta",tat:"tt",tel:"te",tgk:"tg",tgl:"tl",tha:"th",tib:"bo",tir:"ti",ton:"to",tsn:"tn",tso:"ts",tuk:"tk",tur:"tr",twi:"tw",uig:"ug",ukr:"uk",urd:"ur",uzb:"uz",ven:"ve",vie:"vi",vol:"vo",wel:"cy",wln:"wa",wol:"wo",xho:"xh",yid:"yi",yor:"yo",zha:"za",zho:"zh",zul:"zu"};function Gc(a,b,c){var d=!1;a.streamSets.forEach(function(a){a.streams.forEach(function(e){var f=e.allowedByApplication;e.allowedByApplication=!0;if("video"==a.type){if(e.widthb.maxWidth||e.width>c.width||e.heightb.maxHeight||e.height>c.height||e.width*e.heightb.maxPixels||e.bandwidthb.maxVideoBandwidth)e.allowedByApplication=!1}else"audio"==a.type&&(e.bandwidth
108 | b.maxAudioBandwidth)&&(e.allowedByApplication=!1);f!=e.allowedByApplication&&(d=!0)})});return d}
109 | function Hc(a,b,c){var d="",e=null;a&&a.C&&(d=a.keySystem(),e=a.m);for(a=0;ae.indexOf(p)?(f.streams.splice(h,1),--h):!g||l.mimeType==g.mimeType&&l.codecs.split(".")[0]==
110 | g.codecs.split(".")[0]||(f.streams.splice(h,1),--h):(f.streams.splice(h,1),--h)}f.streams.length||(c.streamSets.splice(a,1),--a)}}}
111 | function Ic(a,b){return a.streamSets.map(function(a){var c=b?b[a.type]:null;return a.streams.filter(function(a){return a.allowedByApplication&&a.allowedByKeySystem}).map(function(b){return{id:b.id,active:c==b,type:a.type,bandwidth:b.bandwidth,language:a.language,kind:b.kind||null,width:b.width||null,height:b.height||null,frameRate:b.frameRate||void 0,codecs:b.codecs||null}})}).reduce(v,[])}
112 | function Jc(a,b){for(var c=0;ce?(e=b,d.video=a):b==e&&Nc(a)a.streams.length)return b;a.streams.forEach(function(a){b+=a.bandwidth});return b/a.streams.length}function Mc(a){var b=0;if(!a)return b;a.streams.forEach(function(a){a.height>b&&(b=a.height)});return b};function K(a,b){n.call(this);this.w=!1;this.f=a;this.m=null;this.v=new z;this.gb=new q;this.na=this.c=this.l=this.b=this.i=this.oa=this.G=this.A=this.g=this.h=null;this.Ib=1E9;this.ma=[];this.Ca=!1;this.qa=!0;this.j=null;this.s={};this.a=Oc(this);this.Ba={width:Infinity,height:Infinity};this.C=[];this.R=this.J=this.pa=0;b&&b(this);this.h=new y(this.Pc.bind(this));this.oa=Pc(this);for(var c=0;cthis.ma.indexOf(a.id)}.bind(this))};K.prototype.getTracks=K.prototype.getTracks;
126 | K.prototype.Hc=function(a,b){if(this.b){var c=Jc(cc(this.b),a);if(c){var d=c.stream;d.allowedByApplication&&d.allowedByKeySystem&&(this.C.push({timestamp:Date.now()/1E3,id:d.id,type:a.type,fromAdaptation:!1}),c={},c[a.type]=d,"text"!=a.type&&(d=dc(this.b).text,this.configure({abr:{enabled:!1}}),c.text=d),Xc(this,c,b))}}};K.prototype.selectTrack=K.prototype.Hc;K.prototype.bc=function(){return"showing"==this.m.mode};K.prototype.isTextTrackVisible=K.prototype.bc;
127 | K.prototype.Jc=function(a){this.m.mode=a?"showing":"hidden";Yc(this)};K.prototype.setTextTrackVisibility=K.prototype.Jc;K.prototype.Vb=function(){return new Date(1E3*this.c.presentationTimeline.g+1E3*this.f.currentTime)};K.prototype.getPlayheadTimeAsDate=K.prototype.Vb;
128 | K.prototype.getStats=function(){Zc(this);var a={},b={},c=this.f&&this.f.getVideoPlaybackQuality?this.f.getVideoPlaybackQuality():{};this.b&&(b=dc(this.b),a=b.video||{},b=b.audio||{});return{width:a.width||0,height:a.height||0,streamBandwidth:a.bandwidth+b.bandwidth||0,decodedFrames:Number(c.totalVideoFrames),droppedFrames:Number(c.droppedVideoFrames),estimatedBandwidth:this.a.abr.manager.getBandwidthEstimate(),playTime:this.pa,bufferingTime:this.J,switchHistory:this.C.slice(0)}};
129 | K.prototype.getStats=K.prototype.getStats;
130 | K.prototype.addTextTrack=function(a,b,c,d,e){if(!this.b)return Promise.reject();for(var f=cc(this.b),g,h=0;hb&&(b+=Math.pow(2,32)),b=b.toString(16));this.$(new r(3,3016,a,b))}}};
142 | k.Nc=function(a){var b=["output-restricted","internal-error"],c=cc(this.b),d=!1;c.streamSets.forEach(function(c){c.streams.forEach(function(c){var e=c.allowedByKeySystem;c.keyId&&c.keyId in a&&(c.allowedByKeySystem=0>b.indexOf(a[c.keyId]));e!=c.allowedByKeySystem&&(d=!0)})});Wc(this,c);d&&Sc(this)};var ad="ended play playing pause pausing ratechange seeked seeking timeupdate volumechange".split(" "),bd="buffered currentTime duration ended loop muted paused playbackRate seeking videoHeight videoWidth volume".split(" "),cd=["loop","playbackRate"],dd=["pause","play"],ed=["adaptation","buffering","error","texttrackvisibility","trackschanged"],gd="getConfiguration getManifestUri getPlaybackRate getTracks getStats isBuffering isLive isTextTrackVisible seekRange".split(" "),hd=[["getConfiguration",
143 | "configure"]],id=[["isTextTrackVisible","setTextTrackVisibility"]],jd="configure resetConfiguration trickPlay cancelTrickPlay selectTrack setTextTrackVisibility addTextTrack".split(" "),kd=["load","unload"];
144 | function ld(a){return JSON.stringify(a,function(a,c){if("manager"!=a&&"function"!=typeof c){if(c instanceof Event||c instanceof J){var b={},e;for(e in c){var f=c[e];f&&"object"==typeof f||e in Event||(b[e]=f)}return b}if(c instanceof TimeRanges)for(b={__type__:"TimeRanges",length:c.length,start:[],end:[]},e=0;ec?"-Infinity":"Infinity":c;return b}})}
145 | function md(a){return JSON.parse(a,function(a,c){return"NaN"==c?NaN:"-Infinity"==c?-Infinity:"Infinity"==c?Infinity:c&&"object"==typeof c&&"TimeRanges"==c.__type__?nd(c):c})}function nd(a){return{length:a.length,start:function(b){return a.start[b]},end:function(b){return a.end[b]}}};function od(a,b,c,d,e){this.C=a;this.l=b;this.w=c;this.A=d;this.s=e;this.c=this.j=this.h=!1;this.v="";this.a=this.i=null;this.b={video:{},player:{}};this.m=0;this.f={};this.g=null}k=od.prototype;k.o=function(){pd(this);this.a&&(this.a.leave(function(){},function(){}),this.a=null);this.A=this.w=this.l=null;this.c=this.j=this.h=!1;this.g=this.f=this.b=this.i=null;return Promise.resolve()};k.O=function(){return this.c};k.Za=function(){return this.v};
146 | k.init=function(){if(window.chrome&&chrome.cast&&chrome.cast.isAvailable){delete window.__onGCastApiAvailable;this.h=!0;this.l();var a=new chrome.cast.SessionRequest(this.C),a=new chrome.cast.ApiConfig(a,this.fc.bind(this),this.nc.bind(this),"origin_scoped");chrome.cast.initialize(a,function(){},function(){})}else window.__onGCastApiAvailable=function(a){a&&this.init()}.bind(this)};k.ab=function(a){this.i=a;this.c&&qd(this,{type:"appData",appData:this.i})};
147 | k.cast=function(a){if(!this.h)return Promise.reject(new r(8,8E3));if(!this.j)return Promise.reject(new r(8,8001));if(this.c)return Promise.reject(new r(8,8002));this.g=new x;chrome.cast.requestSession(this.Xa.bind(this,a),this.mb.bind(this));return this.g};k.Ka=function(){this.c&&(pd(this),this.a&&(this.a.stop(function(){},function(){}),this.a=null))};
148 | k.get=function(a,b){if("video"==a){if(0<=dd.indexOf(b))return this.xb.bind(this,a,b)}else if("player"==a){if(0<=jd.indexOf(b))return this.xb.bind(this,a,b);if(0<=kd.indexOf(b))return this.Cc.bind(this,a,b);if(0<=gd.indexOf(b))return this.ub.bind(this,a,b)}return this.ub(a,b)};k.set=function(a,b,c){this.b[a][b]=c;qd(this,{type:"set",targetName:a,property:b,value:c})};
149 | k.Xa=function(a,b){this.a=b;this.a.addUpdateListener(this.nb.bind(this));this.a.addMessageListener("urn:x-cast:com.google.shaka.v2",this.gc.bind(this));this.nb();qd(this,{type:"init",initState:a,appData:this.i});this.g.resolve()};k.mb=function(a){var b=8003;switch(a.code){case "cancel":b=8004;break;case "timeout":b=8005;break;case "receiver_unavailable":b=8006}this.g.reject(new r(8,b,a))};k.ub=function(a,b){return this.b[a][b]};
150 | k.xb=function(a,b){qd(this,{type:"call",targetName:a,methodName:b,args:Array.prototype.slice.call(arguments,2)})};k.Cc=function(a,b){var c=Array.prototype.slice.call(arguments,2),d=new x,e=this.m.toString();this.m++;this.f[e]=d;qd(this,{type:"asyncCall",targetName:a,methodName:b,args:c,id:e});return d};k.fc=function(a){var b=this.s();this.g=new x;this.Xa(b,a)};k.nc=function(a){this.j="available"==a;this.l()};
151 | k.nb=function(){var a=this.a?"connected"==this.a.status:!1;if(this.c&&!a){this.A();for(var b in this.b)this.b[b]={};pd(this)}this.v=(this.c=a)?this.a.receiver.friendlyName:"";this.l()};function pd(a){for(var b in a.f){var c=a.f[b];delete a.f[b];c.reject(new r(7,7E3))}}
152 | k.gc=function(a,b){var c=md(b);switch(c.type){case "event":var d=c.targetName,e=c.event;this.w(d,new J(e.type,e));break;case "update":e=c.update;for(d in e){var c=this.b[d]||{},f;for(f in e[d])c[f]=e[d][f]}break;case "asyncComplete":if(d=c.id,f=c.error,c=this.f[d],delete this.f[d],c)if(f){d=new r(f.category,f.code);for(e in f)d[e]=f[e];c.reject(d)}else c.resolve()}};function qd(a,b){var c=ld(b);a.a.sendMessage("urn:x-cast:com.google.shaka.v2",c,function(){},ga)};function L(a,b,c){n.call(this);this.c=a;this.b=b;this.h=this.f=this.g=this.i=this.j=null;this.a=new od(c,this.Qc.bind(this),this.Rc.bind(this),this.Sc.bind(this),this.kb.bind(this));rd(this)}ba(L);m("shaka.cast.CastProxy",L);L.prototype.o=function(a){a&&this.a&&this.a.Ka();a=[this.h?this.h.o():null,this.b?this.b.o():null,this.a?this.a.o():null];this.a=this.h=this.i=this.j=this.b=this.c=null;return Promise.all(a)};L.prototype.destroy=L.prototype.o;L.prototype.Yb=function(){return this.j};
153 | L.prototype.getVideo=L.prototype.Yb;L.prototype.Ub=function(){return this.i};L.prototype.getPlayer=L.prototype.Ub;L.prototype.Kb=function(){return this.a?this.a.h&&this.a.j:!1};L.prototype.canCast=L.prototype.Kb;L.prototype.O=function(){return this.a?this.a.O():!1};L.prototype.isCasting=L.prototype.O;L.prototype.Za=function(){return this.a?this.a.Za():""};L.prototype.receiverName=L.prototype.Za;L.prototype.cast=function(){var a=this.kb();return this.a.cast(a).then(function(){return this.b.fb()}.bind(this))};
154 | L.prototype.cast=L.prototype.cast;L.prototype.ab=function(a){this.a.ab(a)};L.prototype.setAppData=L.prototype.ab;L.prototype.Yc=function(){var a=this.a;if(a.c){var b=a.s();chrome.cast.requestSession(a.Xa.bind(a,b),a.mb.bind(a))}};L.prototype.suggestDisconnect=L.prototype.Yc;L.prototype.Ka=function(){this.a.Ka()};L.prototype.forceDisconnect=L.prototype.Ka;
155 | function rd(a){a.a.init();a.h=new z;ad.forEach(function(a){A(this.h,this.c,a,this.dd.bind(this))}.bind(a));ed.forEach(function(a){A(this.h,this.b,a,this.yc.bind(this))}.bind(a));a.j={};for(var b in a.c)Object.defineProperty(a.j,b,{configurable:!1,enumerable:!0,get:a.cd.bind(a,b),set:a.ed.bind(a,b)});a.i={};for(b in a.b)Object.defineProperty(a.i,b,{configurable:!1,enumerable:!0,get:a.xc.bind(a,b)});a.g=new n;a.g.K=a.j;a.f=new n;a.f.K=a.i}k=L.prototype;
156 | k.kb=function(){var a={video:{},player:{},playerAfterLoad:{},manifest:this.b.na,startTime:null};this.c.pause();cd.forEach(function(b){a.video[b]=this.c[b]}.bind(this));this.c.ended||(a.startTime=this.c.currentTime);hd.forEach(function(b){var c=b[1];b=this.b[b[0]]();a.player[c]=b}.bind(this));id.forEach(function(b){var c=b[1];b=this.b[b[0]]();a.playerAfterLoad[c]=b}.bind(this));return a};k.Qc=function(){this.dispatchEvent(new J("caststatuschanged"))};
157 | k.Sc=function(){hd.forEach(function(a){var b=a[1];a=this.a.get("player",a[0])();this.b[b](a)}.bind(this));var a=this.a.get("player","getManifestUri")(),b=this.a.get("video","ended"),c=Promise.resolve(),d=this.c.autoplay,e=null;b||(e=this.a.get("video","currentTime"));a&&(this.c.autoplay=!1,c=this.b.load(a,e),c["catch"](function(a){this.b.dispatchEvent(new J("error",{detail:a}))}.bind(this)));var f={};cd.forEach(function(a){f[a]=this.a.get("video",a)}.bind(this));c.then(function(){cd.forEach(function(a){this.c[a]=
158 | f[a]}.bind(this));id.forEach(function(a){var b=a[1];a=this.a.get("player",a[0])();this.b[b](a)}.bind(this));this.c.autoplay=d;a&&this.c.play()}.bind(this))};
159 | k.cd=function(a){if("addEventListener"==a)return this.g.addEventListener.bind(this.g);if("removeEventListener"==a)return this.g.removeEventListener.bind(this.g);if(this.a.O()&&!Object.keys(this.a.b.video).length){var b=this.c[a];if("function"!=typeof b)return b}return this.a.O()?this.a.get("video",a):(b=this.c[a],"function"==typeof b&&(b=b.bind(this.c)),b)};k.ed=function(a,b){this.a.O()?this.a.set("video",a,b):this.c[a]=b};k.dd=function(a){this.a.O()||this.g.dispatchEvent(new J(a.type,a))};
160 | k.xc=function(a){return"addEventListener"==a?this.f.addEventListener.bind(this.f):"removeEventListener"==a?this.f.removeEventListener.bind(this.f):"getNetworkingEngine"==a?this.b.lb.bind(this.b):this.a.O()&&!Object.keys(this.a.b.video).length&&0<=gd.indexOf(a)||!this.a.O()?(a=this.b[a],a.bind(this.b)):this.a.get("player",a)};k.yc=function(a){this.a.O()||this.f.dispatchEvent(a)};k.Rc=function(a,b){this.a.O()&&("video"==a?this.g.dispatchEvent(b):"player"==a&&this.f.dispatchEvent(b))};function M(a,b,c){n.call(this);this.b=a;this.a=b;this.i={video:a,player:b};this.j=c||function(){};this.h=!1;this.c=!0;this.f=this.g=null;sd(this)}ba(M);m("shaka.cast.CastReceiver",M);M.prototype.$b=function(){return this.h};M.prototype.isConnected=M.prototype.$b;M.prototype.ac=function(){return this.c};M.prototype.isIdle=M.prototype.ac;
161 | M.prototype.o=function(){var a=this.a?this.a.o():Promise.resolve();null!=this.f&&window.clearTimeout(this.f);this.j=this.i=this.a=this.b=null;this.h=!1;this.c=!0;this.f=this.g=null;return a.then(function(){cast.receiver.CastReceiverManager.getInstance().stop()})};M.prototype.destroy=M.prototype.o;
162 | function sd(a){var b=cast.receiver.CastReceiverManager.getInstance();b.onSenderConnected=a.sb.bind(a);b.onSenderDisconnected=a.sb.bind(a);b.onSystemVolumeChanged=a.Rb.bind(a);a.g=b.getCastMessageBus("urn:x-cast:com.google.shaka.v2");a.g.onMessage=a.hc.bind(a);b.start();ad.forEach(function(a){this.b.addEventListener(a,this.vb.bind(this,"video"))}.bind(a));ed.forEach(function(a){this.a.addEventListener(a,this.vb.bind(this,"player"))}.bind(a));a.a.Db(1920,1080);a.a.addEventListener("loading",function(){this.c=
163 | !1;td(this)}.bind(a));a.b.addEventListener("playing",function(){this.c=!1;td(this)}.bind(a));a.a.addEventListener("unloading",function(){this.c=!0;td(this)}.bind(a));a.b.addEventListener("ended",function(){window.setTimeout(function(){this.b&&this.b.ended&&(this.c=!0,td(this))}.bind(this),5E3)}.bind(a))}k=M.prototype;k.sb=function(){this.h=!!cast.receiver.CastReceiverManager.getInstance().getSenders().length;td(this)};
164 | function td(a){Promise.resolve().then(function(){this.dispatchEvent(new J("caststatuschanged"))}.bind(a))}
165 | function ud(a,b,c){for(var d in b.player)a.a[d](b.player[d]);a.j(c);c=Promise.resolve();var e=a.b.autoplay;b.manifest&&(a.b.autoplay=!1,c=a.a.load(b.manifest,b.startTime),c["catch"](function(a){this.a.dispatchEvent(new J("error",{detail:a}))}.bind(a)));c.then(function(){for(var a in b.video){var c=b.video[a];this.b[a]=c}for(a in b.playerAfterLoad)c=b.playerAfterLoad[a],this.a[a](c);this.b.autoplay=e;b.manifest&&this.b.play()}.bind(a))}
166 | k.vb=function(a,b){this.Ya();vd(this,{type:"event",targetName:a,event:b})};k.Ya=function(){null!=this.f&&window.clearTimeout(this.f);this.f=window.setTimeout(this.Ya.bind(this),500);var a={video:{},player:{}};bd.forEach(function(b){a.video[b]=this.b[b]}.bind(this));gd.forEach(function(b){a.player[b]=this.a[b]()}.bind(this));var b=cast.receiver.CastReceiverManager.getInstance().getSystemVolume();b&&(a.video.volume=b.level,a.video.muted=b.muted);vd(this,{type:"update",update:a})};
167 | k.Rb=function(){var a=cast.receiver.CastReceiverManager.getInstance().getSystemVolume();a&&vd(this,{type:"update",update:{video:{volume:a.level,muted:a.muted}}});vd(this,{type:"event",targetName:"video",event:{type:"volumechange"}})};
168 | k.hc=function(a){var b=md(a.data);switch(b.type){case "init":ud(this,b.initState,b.appData);this.Ya();break;case "appData":this.j(b.appData);break;case "set":var c=b.targetName,d=b.property,e=b.value;if("video"==c)if(b=cast.receiver.CastReceiverManager.getInstance(),"volume"==d){b.setSystemVolumeLevel(e);break}else if("muted"==d){b.setSystemVolumeMuted(e);break}this.i[c][d]=e;break;case "call":c=b.targetName;d=b.methodName;e=b.args;c=this.i[c];c[d].apply(c,e);break;case "asyncCall":c=b.targetName,
169 | d=b.methodName,e=b.args,b=b.id,a=a.senderId,c=this.i[c],c[d].apply(c,e).then(this.Bb.bind(this,a,b,null),this.Bb.bind(this,a,b))}};k.Bb=function(a,b,c){vd(this,{type:"asyncComplete",id:b,error:c},a)};function vd(a,b,c){a.h&&(b=ld(b),c?a.g.getCastChannel(c).send(b):a.g.broadcast(b))};function wd(a,b){var c=N(a,b);return 1!=c.length?null:c[0]}function N(a,b){return Array.prototype.filter.call(a.childNodes,function(a){return a.tagName==b})}function xd(a){return(a=a.firstChild)&&a.nodeType==Node.TEXT_NODE?a.nodeValue.trim():null}function O(a,b,c,d){var e=null;a=a.getAttribute(b);null!=a&&(e=c(a));return null==e?void 0!==d?d:null:e}function yd(a){if(!a)return null;a=Date.parse(a);return isNaN(a)?null:Math.floor(a/1E3)}
170 | function P(a){if(!a)return null;a=/^P(?:([0-9]*)Y)?(?:([0-9]*)M)?(?:([0-9]*)D)?(?:T(?:([0-9]*)H)?(?:([0-9]*)M)?(?:([0-9.]*)S)?)?$/.exec(a);if(!a)return null;a=31536E3*Number(a[1]||null)+2592E3*Number(a[2]||null)+86400*Number(a[3]||null)+3600*Number(a[4]||null)+60*Number(a[5]||null)+Number(a[6]||null);return isFinite(a)?a:null}function zd(a){var b=/([0-9]+)-([0-9]+)/.exec(a);if(!b)return null;a=Number(b[1]);if(!isFinite(a))return null;b=Number(b[2]);return isFinite(b)?{start:a,end:b}:null}
171 | function Ad(a){a=Number(a);return a%1?null:a}function Bd(a){a=Number(a);return!(a%1)&&0b||(c[c.length-1]=new G(a.position,a.startTime,b,a.a,a.M,a.D)))}}function Q(a,b){if(!b.length)return a;var c=b.map(function(a){return new ma(a)});return a.map(function(a){return new ma(a)}).map(function(a){return c.map(a.resolve.bind(a))}).reduce(v,[]).map(function(a){return a.toString()})}
177 | function Od(a,b){var c=Pd(a,b,"timescale"),d=1;c&&(d=Bd(c)||1);c=Pd(a,b,"duration");(c=Bd(c||""))&&(c/=d);var e=Pd(a,b,"startNumber"),f=Pd(a,b,"presentationTimeOffset"),g=Cd(e||"");if(null==e||null==g)g=1;var h=Qd(a,b,"SegmentTimeline"),e=null;if(h){for(var e=d,l=Number(f),p=a.H.duration||Infinity,h=N(h,"S"),t=[],u=0,E=0;EB)if(E+1=B)break;B=Math.ceil((B-H)/ob)-1}else{if(Infinity==p)break;else if(H/e>=p)break;B=Math.ceil((p*e-H)/ob)-1}0a.b.byteLength&&Vd();var c=a.b.buffer.slice(a.a,a.a+b);a.a+=b;return new Uint8Array(c)}function S(a,b){a.a+b>a.b.byteLength&&Vd();a.a+=b}
181 | function Zd(a){var b=a.a;try{for(;Td(a)&&a.b.getUint8(a.a);)a.a+=1}catch(c){Vd()}b=a.b.buffer.slice(b,a.a);a.a+=1;return D(b)}function Vd(){throw new r(3,3E3);};function $d(a,b){for(;Td(b);){var c=b.a,d=R(b),e=R(b);1==d?d=Xd(b):d||(d=b.b.byteLength-c);if(e==a)return d;S(b,d-(b.a-c))}return-1}function ae(a,b){for(var c=new Rd(new DataView(a)),d=[[1836019574,0],[1953653099,0],[1835297121,0],[1835626086,0],[1937007212,0],[1937011556,8],[b,0]],e=-1,f=0;f>>31;l&=2147483647;var t=R(a);S(a,4);if(1==p)throw new r(3,3006);e.push(new G(e.length,d/h,(d+t)/h,function(){return c},b,b+l-1));d+=t;b+=l}return e};function T(a){this.a=a}m("shaka.media.SegmentIndex",T);T.prototype.o=function(){this.a=null;return Promise.resolve()};T.prototype.destroy=T.prototype.o;T.prototype.find=function(a){for(var b=this.a.length-1;0<=b;--b){var c=this.a[b];if(a>=c.startTime&&aa||a>=this.a.length?null:this.a[a]};T.prototype.get=T.prototype.get;
182 | T.prototype.Va=function(a){for(var b=[],c=0,d=0;cf.startTime||(.1a);++b);this.a.splice(0,b)};T.prototype.evict=T.prototype.Qa;function ce(a){this.b=a;this.a=new Rd(a);de||(de=[new Uint8Array([255]),new Uint8Array([127,255]),new Uint8Array([63,255,255]),new Uint8Array([31,255,255,255]),new Uint8Array([15,255,255,255,255]),new Uint8Array([7,255,255,255,255,255]),new Uint8Array([3,255,255,255,255,255,255]),new Uint8Array([1,255,255,255,255,255,255,255])])}var de;
184 | function ee(a){var b;b=fe(a);if(7=c&&!(b&1<<8-c);c++);if(8a||c&&a>=c?null:Math.floor(a/d)},getSegmentReference:function(a){var b=a*d;return new G(a,b,b+d,function(){var c=Md(g,l,a+e,h,b*f);return Q(p,[c])},0,null)}}}
196 | function we(a,b){for(var c=[],d=0;da.s||(a.f=window.setTimeout(a.Tc.bind(a),1E3*Math.max(Math.max(3,a.s)-b,0)))}
209 | function De(a,b,c){b=b||{contentType:"",mimeType:"",codecs:"",frameRate:void 0};c=c||b.N;var d=N(a,"BaseURL").map(xd),e=a.getAttribute("contentType")||b.contentType,f=a.getAttribute("mimeType")||b.mimeType,g=O(a,"frameRate",Dd)||b.frameRate;e||(e=f.split("/")[0]);return{N:Q(c,d),Ga:wd(a,"SegmentBase")||b.Ga,Z:wd(a,"SegmentList")||b.Z,Ha:wd(a,"SegmentTemplate")||b.Ha,width:O(a,"width",Cd)||b.width,height:O(a,"height",Cd)||b.height,contentType:e,mimeType:f,codecs:a.getAttribute("codecs")||b.codecs,
210 | frameRate:g,id:a.getAttribute("id")}}
211 | function Ee(a){var b={};a.forEach(function(a){b[a.id]=[a]});a.forEach(function(a){var c=b[a.id];a.Zc.forEach(function(a){(a=b[a])&&a!=c&&(c.push.apply(c,a),a.forEach(function(a){b[a.id]=c}))})});var c=[],d=[];C(b).forEach(function(a){if(!(0<=d.indexOf(a))){d.push(a);var b=new Ia;a.forEach(function(a){b.push(a.contentType||"",a)});b.keys().forEach(function(a){var d=new Ia;b.get(a).forEach(function(a){d.push(a.language,a)});d.keys().forEach(function(b){var e=d.get(b);b={language:b,type:a,primary:e.some(function(a){return a.cc}),
212 | drmInfos:e.map(function(a){return a.drmInfos}).reduce(v,[]),streams:e.map(function(a){return a.streams}).reduce(v,[])};c.push(b)})})}});return c}function Fe(a){var b;b=0+(a.Ga?1:0);b+=a.Z?1:0;b+=a.Ha?1:0;if(!b)return"text"==a.contentType||"application"==a.contentType?!0:!1;1!=b&&(a.Ga&&(a.Z=null),a.Ha=null);return!0}
213 | function Ge(a,b,c,d){b=Q(b,[c]);b=Ga(b,a.c.retryParameters);b.method=d;return a.a.request(0,b).then(function(a){if("HEAD"==d){if(!a.headers||!a.headers.date)return 0;a=a.headers.date}else a=D(a.data);a=Date.parse(a);return isNaN(a)?0:a-Date.now()})}
214 | function Ce(a,b,c,d){c=c.map(function(a){return{scheme:a.getAttribute("schemeIdUri"),value:a.getAttribute("value")}});var e=a.c.dash.clockSyncUri;d&&!c.length&&e&&c.push({scheme:"urn:mpeg:dash:utc:http-head:2014",value:e});return Aa(c,function(a){var c=a.value;switch(a.scheme){case "urn:mpeg:dash:utc:http-head:2014":case "urn:mpeg:dash:utc:http-head:2012":return Ge(this,b,c,"HEAD");case "urn:mpeg:dash:utc:http-xsdate:2014":case "urn:mpeg:dash:utc:http-iso:2014":case "urn:mpeg:dash:utc:http-xsdate:2012":case "urn:mpeg:dash:utc:http-iso:2012":return Ge(this,
215 | b,c,"GET");case "urn:mpeg:dash:utc:direct:2014":case "urn:mpeg:dash:utc:direct:2012":return a=Date.parse(c),isNaN(a)?0:a-Date.now();case "urn:mpeg:dash:utc:http-ntp:2014":case "urn:mpeg:dash:utc:ntp:2014":case "urn:mpeg:dash:utc:sntp:2014":return Promise.reject();default:return Promise.reject()}}.bind(a))["catch"](function(){return 0})}k.Dc=function(a,b,c){a=Ga(a,this.c.retryParameters);null!=b&&(a.headers.Range="bytes="+b+"-"+(null!=c?c:""));return this.a.request(1,a).then(function(a){return a.data})};
216 | k.Ja=function(a,b){if(1==a){var c=new Rd(new DataView(b.data)),d=$d(1701671783,c);if(-1!=d){var e=c.a-8+d;S(c,4);d=Zd(c);if("urn:mpeg:dash:event:2012"==d)ye(this);else{var f=Zd(c),g=R(c),h=R(c),l=R(c),p=R(c),c=Yd(c,e-c.a);this.m(new J("emsg",{detail:{md:d,value:f,Ia:g,ld:h,jd:l,id:p,kd:c}}))}}}};qb.mpd=xe;pb["application/dash+xml"]=xe;function U(a,b){var c=D(a),d=[],e=new DOMParser,f=null;try{f=e.parseFromString(c,"text/xml")}catch(p){throw new r(2,2005);}if(f){var g,h;if(c=f.getElementsByTagName("tt")[0])e=c.getAttribute("ttp:frameRate"),f=c.getAttribute("ttp:subFrameRate"),g=c.getAttribute("ttp:frameRateMultiplier"),h=c.getAttribute("ttp:tickRate");else throw new r(2,2006);e=new He(e,f,g,h);f=U.b(c.getElementsByTagName("styling")[0]);g=U.b(c.getElementsByTagName("layout")[0]);c=U.b(c.getElementsByTagName("body")[0]);for(h=0;h<
217 | c.length;h++){var l=U.c(c[h],b,e,f,g);l&&d.push(l)}}return d}m("shaka.media.TtmlTextParser",U);U.l=/^(\d{2,}):(\d{2}):(\d{2}):(\d{2})\.?(\d+)?$/;U.s=/^(?:(\d{2,}):)?(\d{2}):(\d{2})$/;U.m=/^(?:(\d{2,}):)?(\d{2}):(\d{2}\.\d{2,})$/;U.v=/^(\d*\.?\d*)f$/;U.A=/^(\d*\.?\d*)t$/;U.w=/^(?:(\d*\.?\d*)h)?(?:(\d*\.?\d*)m)?(?:(\d*\.?\d*)s)?(?:(\d*\.?\d*)ms)?$/;U.j=/^(\d{1,2}|100)% (\d{1,2}|100)%$/;U.Ca={left:"start",center:"center",right:"end",start:"start",end:"end"};
218 | U.b=function(a){var b=[];if(!a)return b;var c=a.childNodes;if("p"==a.nodeName)for(var d=0;dc.length)return null;var d=null;if(a=U.oa(a,b))for(b=0;ba[0].indexOf("--\x3e")&&(e=a[0],a.splice(0,1));var f=new Je(a[0]),g=V.a(f),h=Ke(f,/[ \t]+--\x3e[ \t]+/g),l=V.a(f);if(null==g||!h||null==l)throw new r(2,2001);g+=b;l+=b;d&&(g+=c,l+=c);a=ub(g,l,a.slice(1).join("\n").trim());if(!a)return null;Ke(f,/[ \t]+/gm);for(b=Le(f);b;)V.i(a,b),Ke(f,/[ \t]+/gm),b=Le(f);null!=e&&(a.id=e);return a};
225 | V.i=function(a,b){var c;if(c=/^align:(start|middle|center|end|left|right)$/.exec(b))a.align=c[1],"center"==c[1]&&"center"!=a.align&&(a.position="auto",a.align="middle");else if(c=/^vertical:(lr|rl)$/.exec(b))a.c=c[1];else if(c=/^size:(\d{1,2}|100)%$/.exec(b))a.size=Number(c[1]);else if(c=/^position:(\d{1,2}|100)%(?:,(line-left|line-right|center|start|end))?$/.exec(b))a.position=Number(c[1]),c[2]&&(a.g=c[2]);else if(c=/^line:(\d{1,2}|100)%(?:,(start|end|center))?$/.exec(b))a.f=!1,a.a=Number(c[1]),
226 | c[2]&&(a.b=c[2]);else if(c=/^line:(-?\d+)(?:,(start|end|center))?$/.exec(b))a.f=!0,a.a=Number(c[1]),c[2]&&(a.b=c[2])};V.a=function(a){a=Ke(a,/(?:(\d{1,}):)?(\d{2}):(\d{2})\.(\d{3})/g);if(!a)return null;var b=Number(a[2]),c=Number(a[3]);return 59c.length||"data"!=c[0])throw new r(1,1004,a);c=c.slice(1).join(":").split(",");if(2>c.length)throw new r(1,1004,a);var d=c[0],c=window.decodeURIComponent(c.slice(1).join(",")),d=d.split(";"),e=null;1=b.status){var e=b.getAllResponseHeaders().split("\r\n").reduce(function(a,b){var c=b.split(": ");a[c[0].toLowerCase()]=c.slice(1).join(": ");return a},{});b.responseURL&&(a=b.responseURL);c({uri:a,data:b.response,headers:e})}else{e=null;try{e=
228 | Qa(b.response)}catch(l){}d(new r(1,1001,a,b.status,e))}};e.onerror=function(){d(new r(1,1002,a))};e.ontimeout=function(){d(new r(1,1003,a))};for(var f in b.headers)e.setRequestHeader(f,b.headers[f]);e.send(b.body)})}m("shaka.net.HttpPlugin",Ne);Ea.http=Ne;Ea.https=Ne;function Oe(){this.a=null;this.c=[];this.b={}}k=Oe.prototype;
229 | k.init=function(a){if(!window.indexedDB)return Promise.reject(new r(9,9E3));var b=window.indexedDB.open("shaka_offline_db",1),c=new x;b.onupgradeneeded=function(b){b=b.target.result;for(var c in a)b.createObjectStore(c,{keyPath:a[c]})};b.onsuccess=function(a){this.a=a.target.result;c.resolve()}.bind(this);b.onerror=Pe.bind(null,b,c);return c.then(function(){var b=Object.keys(a);return Promise.all(b.map(function(a){return Qe(this,a).then(function(b){this.b[a]=b}.bind(this))}.bind(this)))}.bind(this))};
230 | k.o=function(){return Promise.all(this.c.map(function(a){try{a.transaction.abort()}catch(b){}return a.I["catch"](w)})).then(function(){this.a&&(this.a.close(),this.a=null)}.bind(this))};k.get=function(a,b){return Re(this,a,"readonly",function(a){return a.get(b)})};k.forEach=function(a,b){return Re(this,a,"readonly",function(a){return a.openCursor()},function(a){a&&(b(a.value),a["continue"]())})};function Se(a,b,c){return Re(a,b,"readwrite",function(a){return a.put(c)})}
231 | k.remove=function(a,b){return Re(this,a,"readwrite",function(a){return a["delete"](b)})};function Te(a,b){var c=[];return Re(a,"segment","readwrite",function(a){return a.openCursor()},function(a){if(a){if(b(a.value)){var d=a["delete"](),f=new x;d.onsuccess=f.resolve;d.onerror=Pe.bind(null,d,f);c.push(f)}a["continue"]()}}).then(function(){return Promise.all(c)}).then(function(){return c.length})}
232 | function Qe(a,b){var c=0;return Re(a,b,"readonly",function(a){return a.openCursor(null,"prev")},function(a){a&&(c=a.key+1)}).then(function(){return c})}
233 | function Re(a,b,c,d,e){c=a.a.transaction([b],c);var f=d(c.objectStore(b)),g=new x;e&&(f.onsuccess=function(a){e(a.target.result)});f.onerror=Pe.bind(null,f,g);var h={transaction:c,I:g};a.c.push(h);var l=function(){this.c.splice(this.c.indexOf(h),1)}.bind(a);c.oncomplete=function(){l();g.resolve(f.result)};c.onerror=function(a){l();Pe(f,g,a)};return g}function Pe(a,b,c){"AbortError"==a.error.name?b.reject(new r(9,9002)):b.reject(new r(9,9001,a.error));c.preventDefault()};var Ue={manifest:"key",segment:"key"};function Ve(a){return{offlineUri:"offline:"+a.key,originalManifestUri:a.originalManifestUri,duration:a.duration,size:a.size,tracks:a.periods[0].streams.map(function(a){return{id:a.id,active:!1,type:a.contentType,bandwidth:0,language:a.language,kind:a.kind||null,width:a.width,height:a.height,frameRate:a.frameRate,codecs:a.codecs}}),appMetadata:a.appMetadata}};function We(){}m("shaka.offline.OfflineManifestParser",We);We.prototype.configure=function(){};We.prototype.start=function(a){var b=/^offline:([0-9]+)$/.exec(a);if(!b)return Promise.reject(new r(1,9004,a));var c=Number(b[1]),d=new Oe;return d.init(Ue).then(function(){return d.get("manifest",c)}).then(function(a){if(!a)throw new r(9,9003,c);return Xe(a)}).then(function(a){return d.o().then(function(){return a})},function(a){return d.o().then(function(){throw a;})})};We.prototype.stop=function(){return Promise.resolve()};
234 | function Xe(a){var b=new I(null,0);b.za(a.duration);var c=a.drmInfo?[a.drmInfo]:[];return{presentationTimeline:b,minBufferTime:10,offlineSessionIds:a.sessionIds,periods:a.periods.map(function(a){return{startTime:a.startTime,streamSets:a.streams.map(function(d){var e=d.segments.map(function(a,b){return new G(b,a.startTime,a.endTime,function(){return[a.uri]},0,null)});b.Fa(a.startTime,e);e=new T(e);return{language:d.language,type:d.contentType,primary:d.primary,drmInfos:c,streams:[{id:d.id,createSegmentIndex:Promise.resolve.bind(Promise),
235 | findSegmentPosition:e.find.bind(e),getSegmentReference:e.get.bind(e),initSegmentReference:d.initSegmentUri?new Ob(function(){return[d.initSegmentUri]},0,null):null,presentationTimeOffset:d.presentationTimeOffset,mimeType:d.mimeType,codecs:d.codecs,bandwidth:0,width:d.width||void 0,height:d.height||void 0,kind:d.kind,encrypted:d.encrypted,keyId:d.keyId,allowedByApplication:!0,allowedByKeySystem:!0}]}})}})}}pb["application/x-offline-manifest"]=We;function Ye(a){if(/^offline:([0-9]+)$/.exec(a)){var b={uri:a,data:new ArrayBuffer(0),headers:{"content-type":"application/x-offline-manifest"}};return Promise.resolve(b)}if(b=/^offline:[0-9]+\/[0-9]+\/([0-9]+)$/.exec(a)){var c=Number(b[1]),d=new Oe;return d.init(Ue).then(function(){return d.get("segment",c)}).then(function(b){return d.o().then(function(){if(!b)throw new r(9,9003,c);return{uri:a,data:b.data,headers:{}}})})}return Promise.reject(new r(1,9004,a))}m("shaka.offline.OfflineScheme",Ye);
236 | Ea.offline=Ye;function Ze(a,b,c){this.b={};this.i=c;this.m=a;this.l=b;this.j=this.a=null;this.f=this.g=this.h=this.c=0}Ze.prototype.o=function(){var a=this.j||Promise.resolve();this.b={};this.j=this.a=this.l=this.m=this.i=null;return a};function $e(a,b,c,d,e){a.b[b]=a.b[b]||[];a.b[b].push({uris:c.a(),M:c.M,D:c.D,hb:d,Da:e})}
237 | function af(a,b){a.c=0;a.h=0;a.g=0;a.f=0;C(a.b).forEach(function(a){a.forEach(function(a){null!=a.D?this.c+=a.D-a.M+1:this.g+=a.hb}.bind(this))}.bind(a));a.a=b;a.a.size=a.c;var c=C(a.b).map(function(a){var b=0,c=function(){if(!this.i)return Promise.reject(new r(9,9002));if(b>=a.length)return Promise.resolve();var d=a[b++];return bf(this,d).then(c)}.bind(this);return c()}.bind(a));a.b={};return a.j=Promise.all(c)}
238 | function bf(a,b){var c=Ga(b.uris,a.l);if(b.M||null!=b.D)c.headers.Range="bytes="+b.M+"-"+(null==b.D?"":b.D);var d;return a.m.request(1,c).then(function(a){if(!this.a)return Promise.reject(new r(9,9002));d=a.data.byteLength;return b.Da(a.data)}.bind(a)).then(function(){if(!this.a)return Promise.reject(new r(9,9002));null==b.D?(this.a.size+=d,this.f+=b.hb):this.h+=d;var a=(this.h+this.f)/(this.c+this.g),c=Ve(this.a);this.i.progressCallback(c,a)}.bind(a))};function X(a){this.a=new Oe;this.c=a;this.j=cf(this);this.g=null;this.v=!1;this.i=null;this.l=[];this.f=-1;this.m=0;this.b=null;this.h=new Ze(a.h,a.getConfiguration().streaming.retryParameters,this.j)}m("shaka.offline.Storage",X);function df(){return!!window.indexedDB}X.support=df;
239 | X.prototype.o=function(){var a=this.l,b=this.a,c=this.h?this.h.o()["catch"](function(){}).then(function(){return Promise.all(a.map(function(a){return b.remove("segment",a)}))}).then(function(){return b.o()}):Promise.resolve();this.j=this.c=this.h=this.a=null;return c};X.prototype.destroy=X.prototype.o;X.prototype.configure=function(a){Ac(this.j,a,cf(this),{},"")};X.prototype.configure=X.prototype.configure;
240 | X.prototype.Wc=function(a,b,c){function d(a){f=a}if(this.v)return Promise.reject(new r(9,9006));this.v=!0;var e,f=null;return ef(this).then(function(){Y(this);return ff(this,a,d,c)}.bind(this)).then(function(c){Y(this);this.b=c.manifest;this.g=c.Qb;if(this.b.presentationTimeline.V()||this.b.presentationTimeline.ga())throw new r(9,9005,a);this.b.periods.forEach(this.s.bind(this));this.f=this.a.b.manifest++;this.m=0;c=this.b.periods.map(this.w.bind(this));var d=this.g.b,f=gb(this.g);if(d){if(!f.length)throw new r(9,
241 | 9007,a);d.initData=[]}e={key:this.f,originalManifestUri:a,duration:this.m,size:0,periods:c,sessionIds:f,drmInfo:d,appMetadata:b};return af(this.h,e)}.bind(this)).then(function(){Y(this);if(f)throw f;return Se(this.a,"manifest",e)}.bind(this)).then(function(){return gf(this)}.bind(this)).then(function(){return Ve(e)}.bind(this))["catch"](function(a){return gf(this)["catch"](w).then(function(){throw a;})}.bind(this))};X.prototype.store=X.prototype.Wc;
242 | X.prototype.remove=function(a){function b(a){6013!=a.code&&(e=a)}var c=a.offlineUri,d=/^offline:([0-9]+)$/.exec(c);if(!d)return Promise.reject(new r(9,9004,c));var e=null,f,g,h=Number(d[1]);return ef(this).then(function(){Y(this);return this.a.get("manifest",h)}.bind(this)).then(function(a){Y(this);if(!a)throw new r(9,9003,c);f=a;a=Xe(f);g=new Za(this.c.h,b,function(){});g.configure(this.c.getConfiguration().drm);return g.init(a,!0)}.bind(this)).then(function(){return db(g,f.sessionIds)}.bind(this)).then(function(){return g.o()}.bind(this)).then(function(){Y(this);
243 | if(e)throw e;var b=f.periods.map(function(a){return a.streams.map(function(a){var b=a.segments.map(function(a){a=/^offline:[0-9]+\/[0-9]+\/([0-9]+)$/.exec(a.uri);return Number(a[1])});a.initSegmentUri&&(a=/^offline:[0-9]+\/[0-9]+\/([0-9]+)$/.exec(a.initSegmentUri),b.push(Number(a[1])));return b}).reduce(v,[])}).reduce(v,[]),c=0,d=b.length,g=this.j.progressCallback;return Te(this.a,function(e){e=b.indexOf(e.key);0<=e&&(g(a,c/d),c++);return 0<=e}.bind(this))}.bind(this)).then(function(){Y(this);this.j.progressCallback(a,
244 | 1);return this.a.remove("manifest",h)}.bind(this))};X.prototype.remove=X.prototype.remove;X.prototype.list=function(){var a=[];return ef(this).then(function(){Y(this);return this.a.forEach("manifest",function(b){a.push(Ve(b))})}.bind(this)).then(function(){return a})};X.prototype.list=X.prototype.list;
245 | function ff(a,b,c,d){function e(){}var f=a.c.h,g=a.c.getConfiguration(),h,l,p;return sb(b,f,g.manifest.retryParameters,d).then(function(a){Y(this);p=new a;p.configure(g.manifest);return p.start(b,f,this.s.bind(this),c)}.bind(a)).then(function(a){Y(this);h=a;l=new Za(f,c,e);l.configure(g.drm);return l.init(h,!0)}.bind(a)).then(function(){Y(this);return hf(h)}.bind(a)).then(function(){Y(this);return cb(l)}.bind(a)).then(function(){Y(this);return p.stop()}.bind(a)).then(function(){Y(this);return{manifest:h,
246 | Qb:l}}.bind(a))["catch"](function(a){if(p)return p.stop().then(function(){throw a;});throw a;})}
247 | X.prototype.A=function(a){var b=[],c=a.filter(function(a){return"video"==a.type&&480>=a.height});c.sort(function(a,b){return b.bandwidth-a.bandwidth});c.length&&b.push(c[0]);for(var d=Ec(this.c.getConfiguration().preferredAudioLanguage),c=[0,Cc,Dc],e=a.filter(function(a){return"audio"==a.type}),c=c.map(function(a){return e.filter(function(b){b=Ec(b.language);return Bc(a,d,b)})}),f=e,g=0;g=c.a.length)){for(var d=[],e=0;ea.indexOf("Apple")))if(0<=b.indexOf("Version/8"))window.MediaSource=null;else{var c=MediaSource.prototype.addSourceBuffer;MediaSource.prototype.addSourceBuffer=function(){var a=c.apply(this,arguments);a.abort=function(){};return a}}}});function Z(a){this.c=[];this.b=[];this.ja=Of;if(a)try{a(this.X.bind(this),this.a.bind(this))}catch(b){this.a(b)}}var Of=0;function Pf(a){var b=new Z;b.X(a);return b}function Qf(a){var b=new Z;b.a(a);return b}function Rf(a){function b(a,b,c){a.ja==Of&&(e[b]=c,d++,d==e.length&&a.X(e))}var c=new Z;if(!a.length)return c.X([]),c;for(var d=0,e=Array(a.length),f=c.a.bind(c),g=0;g= 49 && ev.keyCode <= 56) {
181 | // 1-8
182 | var idx = ev.keyCode - 49;
183 | var row = 0;
184 | if (idx > 3) {
185 | idx -= 4;
186 | row = 1;
187 | }
188 | videoelemid = 'vp' + row + idx;
189 | activateViewPort(videoelemid);
190 | }
191 | }
192 |
193 | function initKeyControls() {
194 | document.addEventListener("keypress", onKeyPress, false);
195 | }
196 |
--------------------------------------------------------------------------------
/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | html {
2 | background-color: #000;
3 | }
4 |
5 | body {
6 | padding: 0px;
7 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
8 | background-color: #000;
9 | color: #fff;
10 | }
11 |
12 | a {
13 | color: #00B7FF;
14 | }
15 |
16 | th {
17 | padding: 0.3em;
18 | }
19 |
20 | .row {
21 | margin-right: -15px;
22 | margin-left: -15px;
23 | align-items: center;
24 | align-content: center;
25 | display: flex;
26 | justify-content: center;
27 | }
28 |
29 | .videoInfo {
30 | background-color: rgba(0,0,0,0.80);
31 | border-radius: 5%;
32 | padding-top: 1em;
33 | padding-left: 1em;
34 | padding-bottom: 1em;
35 | z-index: 1000;
36 | position: absolute;
37 | width: 60%;
38 | height: auto;
39 | left: 20%;
40 | top: 10%;
41 | }
42 |
43 | .tiny {
44 | font-size: 8px;
45 | }
46 |
47 | .vp {
48 | border: 1px solid #fff;
49 | min-height: 200px;
50 | padding: 0px;
51 | text-align: center;
52 | }
53 |
54 | .info {
55 | background: url('../images/eyevinn-logo-square.png');
56 | background-color: #fff;
57 | background-repeat: no-repeat;
58 | background-position: center;
59 | background-size: auto 280px;
60 | min-height: 280px;
61 | color: #000;
62 | text-align: center;
63 | padding: 2px;
64 | }
65 |
66 | .vp-large {
67 | min-height: 280px;
68 | }
69 |
70 | video {
71 | width: 100%;
72 | min-height: 200px;
73 | border: 1px solid #777777;
74 | }
75 |
76 | .video-active {
77 | opacity: 1;
78 | }
79 |
80 | .video-paused {
81 | opacity: 0.5;
82 | }
83 |
84 | .video-buffering {
85 | border: 3px solid red;
86 | }
87 |
88 | .video-unmuted {
89 | border: 3px solid green;
90 | }
91 |
92 | .title {
93 | width: 90%;
94 | margin-left: auto;
95 | margin-right: auto;
96 | margin-top: 0px;
97 | position: relative;
98 | bottom: 10px;
99 | }
100 |
101 | .overlay {
102 | position: relative;
103 | width: 100%;
104 | top: -20px;
105 | background-color: #000;
106 | opacity: 0.8;
107 | z-index: 20;
108 | }
109 |
110 | .shortcut {
111 | z-index: 15;
112 | font-size: 8px;
113 | position: absolute;
114 | right: 10px;
115 | top: 10px;
116 | border: 1px solid;
117 | padding: 3px;
118 | background-color: #000;
119 | }
120 |
121 |
--------------------------------------------------------------------------------
/routes/index.js:
--------------------------------------------------------------------------------
1 | // Copyright 2016 Eyevinn Technology. All rights reserved
2 | // Use of this source code is governed by a MIT License
3 | // license that can be found in the LICENSE file.
4 | // Author: Jonas Birme (Eyevinn Technology)
5 | var express = require('express');
6 | var router = express.Router();
7 | const fs = require('fs');
8 | const path = require('path');
9 |
10 | function initiateDefaultConf() {
11 | return {
12 | "row0": [],
13 | "row1": []
14 | };
15 | }
16 |
17 | /* GET home page. */
18 | router.get('/', function(req, res) {
19 | conf = req.query.config;
20 | var confobj = initiateDefaultConf();
21 | if(conf) {
22 | var confpath = '../config/'+conf;
23 | console.log("Loading config " + confpath);
24 | if (fs.existsSync(path.join(__dirname, confpath))) {
25 | var confobj = JSON.parse(fs.readFileSync(path.join(__dirname, confpath), 'utf8'));
26 | }
27 | }
28 | res.render('index', { title: 'Eyevinn Technology OTT Multiview', conf: JSON.stringify(confobj) });
29 | });
30 |
31 | module.exports = router;
32 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Eyevinn/ott-multiview/bbde5f834578c3b76272425efc7a487e794d0c3e/screenshot.png
--------------------------------------------------------------------------------
/views/error.ejs:
--------------------------------------------------------------------------------
1 | <%= message %>
2 | <%= error.status %>
3 | <%= error.stack %>
4 |
--------------------------------------------------------------------------------
/views/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= title %>
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
Based on hls.js and ShakaPlayer
19 |
20 |
26 |
Click on viewport to activate audio | SPACE - pause/resume | F - toggle fullscreen | 1-8 - activate viewport
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
1
35 |
36 |
37 |
38 |
39 |
40 |
41 |
2
42 |
43 |
44 |
45 |
46 |
47 |
48 |
3
49 |
50 |
51 |
52 |
53 |
54 |
55 |
4
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
5
65 |
66 |
67 |
68 |
69 |
70 |
71 |
6
72 |
73 |
74 |
75 |
76 |
77 |
78 |
7
79 |
80 |
81 |
82 |
83 |
84 |
85 |
8
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
103 |
104 |
105 |
--------------------------------------------------------------------------------