UNPKG

24.9 kBJavaScriptView Raw
1/**
2 * @file videojs-contrib-hls.js
3 *
4 * The main file for the HLS project.
5 * License: https://github.com/videojs/videojs-contrib-hls/blob/master/LICENSE
6 */
7'use strict';
8
9var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
10
11var _get = function get(_x4, _x5, _x6) { var _again = true; _function: while (_again) { var object = _x4, property = _x5, receiver = _x6; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x4 = parent; _x5 = property; _x6 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
12
13function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
14
15function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
16
17function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
18
19var _globalDocument = require('global/document');
20
21var _globalDocument2 = _interopRequireDefault(_globalDocument);
22
23var _playlistLoader = require('./playlist-loader');
24
25var _playlistLoader2 = _interopRequireDefault(_playlistLoader);
26
27var _playlist = require('./playlist');
28
29var _playlist2 = _interopRequireDefault(_playlist);
30
31var _xhr = require('./xhr');
32
33var _xhr2 = _interopRequireDefault(_xhr);
34
35var _aesDecrypter = require('aes-decrypter');
36
37var _binUtils = require('./bin-utils');
38
39var _binUtils2 = _interopRequireDefault(_binUtils);
40
41var _videojsContribMediaSources = require('videojs-contrib-media-sources');
42
43var _m3u8Parser = require('m3u8-parser');
44
45var _m3u8Parser2 = _interopRequireDefault(_m3u8Parser);
46
47var _videoJs = require('video.js');
48
49var _videoJs2 = _interopRequireDefault(_videoJs);
50
51var _masterPlaylistController = require('./master-playlist-controller');
52
53var _config = require('./config');
54
55var _config2 = _interopRequireDefault(_config);
56
57var _renditionMixin = require('./rendition-mixin');
58
59var _renditionMixin2 = _interopRequireDefault(_renditionMixin);
60
61var _globalWindow = require('global/window');
62
63var _globalWindow2 = _interopRequireDefault(_globalWindow);
64
65var _playbackWatcher = require('./playback-watcher');
66
67var _playbackWatcher2 = _interopRequireDefault(_playbackWatcher);
68
69var _reloadSourceOnError = require('./reload-source-on-error');
70
71var _reloadSourceOnError2 = _interopRequireDefault(_reloadSourceOnError);
72
73var _playlistSelectorsJs = require('./playlist-selectors.js');
74
75var Hls = {
76 PlaylistLoader: _playlistLoader2['default'],
77 Playlist: _playlist2['default'],
78 Decrypter: _aesDecrypter.Decrypter,
79 AsyncStream: _aesDecrypter.AsyncStream,
80 decrypt: _aesDecrypter.decrypt,
81 utils: _binUtils2['default'],
82
83 STANDARD_PLAYLIST_SELECTOR: _playlistSelectorsJs.lastBandwidthSelector,
84 INITIAL_PLAYLIST_SELECTOR: _playlistSelectorsJs.lowestBitrateCompatibleVariantSelector,
85 comparePlaylistBandwidth: _playlistSelectorsJs.comparePlaylistBandwidth,
86 comparePlaylistResolution: _playlistSelectorsJs.comparePlaylistResolution,
87
88 xhr: (0, _xhr2['default'])()
89};
90
91// 0.5 MB/s
92var INITIAL_BANDWIDTH = 4194304;
93
94// Define getter/setters for config properites
95['GOAL_BUFFER_LENGTH', 'MAX_GOAL_BUFFER_LENGTH', 'GOAL_BUFFER_LENGTH_RATE', 'BUFFER_LOW_WATER_LINE', 'MAX_BUFFER_LOW_WATER_LINE', 'BUFFER_LOW_WATER_LINE_RATE', 'BANDWIDTH_VARIANCE'].forEach(function (prop) {
96 Object.defineProperty(Hls, prop, {
97 get: function get() {
98 _videoJs2['default'].log.warn('using Hls.' + prop + ' is UNSAFE be sure you know what you are doing');
99 return _config2['default'][prop];
100 },
101 set: function set(value) {
102 _videoJs2['default'].log.warn('using Hls.' + prop + ' is UNSAFE be sure you know what you are doing');
103
104 if (typeof value !== 'number' || value < 0) {
105 _videoJs2['default'].log.warn('value of Hls.' + prop + ' must be greater than or equal to 0');
106 return;
107 }
108
109 _config2['default'][prop] = value;
110 }
111 });
112});
113
114/**
115 * Updates the selectedIndex of the QualityLevelList when a mediachange happens in hls.
116 *
117 * @param {QualityLevelList} qualityLevels The QualityLevelList to update.
118 * @param {PlaylistLoader} playlistLoader PlaylistLoader containing the new media info.
119 * @function handleHlsMediaChange
120 */
121var handleHlsMediaChange = function handleHlsMediaChange(qualityLevels, playlistLoader) {
122 var newPlaylist = playlistLoader.media();
123 var selectedIndex = -1;
124
125 for (var i = 0; i < qualityLevels.length; i++) {
126 if (qualityLevels[i].id === newPlaylist.uri) {
127 selectedIndex = i;
128 break;
129 }
130 }
131
132 qualityLevels.selectedIndex_ = selectedIndex;
133 qualityLevels.trigger({
134 selectedIndex: selectedIndex,
135 type: 'change'
136 });
137};
138
139/**
140 * Adds quality levels to list once playlist metadata is available
141 *
142 * @param {QualityLevelList} qualityLevels The QualityLevelList to attach events to.
143 * @param {Object} hls Hls object to listen to for media events.
144 * @function handleHlsLoadedMetadata
145 */
146var handleHlsLoadedMetadata = function handleHlsLoadedMetadata(qualityLevels, hls) {
147 hls.representations().forEach(function (rep) {
148 qualityLevels.addQualityLevel(rep);
149 });
150 handleHlsMediaChange(qualityLevels, hls.playlists);
151};
152
153// HLS is a source handler, not a tech. Make sure attempts to use it
154// as one do not cause exceptions.
155Hls.canPlaySource = function () {
156 return _videoJs2['default'].log.warn('HLS is no longer a tech. Please remove it from ' + 'your player\'s techOrder.');
157};
158
159/**
160 * Whether the browser has built-in HLS support.
161 */
162Hls.supportsNativeHls = (function () {
163 var video = _globalDocument2['default'].createElement('video');
164
165 // native HLS is definitely not supported if HTML5 video isn't
166 if (!_videoJs2['default'].getTech('Html5').isSupported()) {
167 return false;
168 }
169
170 // HLS manifests can go by many mime-types
171 var canPlay = [
172 // Apple santioned
173 'application/vnd.apple.mpegurl',
174 // Apple sanctioned for backwards compatibility
175 'audio/mpegurl',
176 // Very common
177 'audio/x-mpegurl',
178 // Very common
179 'application/x-mpegurl',
180 // Included for completeness
181 'video/x-mpegurl', 'video/mpegurl', 'application/mpegurl'];
182
183 return canPlay.some(function (canItPlay) {
184 return (/maybe|probably/i.test(video.canPlayType(canItPlay))
185 );
186 });
187})();
188
189/**
190 * HLS is a source handler, not a tech. Make sure attempts to use it
191 * as one do not cause exceptions.
192 */
193Hls.isSupported = function () {
194 return _videoJs2['default'].log.warn('HLS is no longer a tech. Please remove it from ' + 'your player\'s techOrder.');
195};
196
197var Component = _videoJs2['default'].getComponent('Component');
198
199/**
200 * The Hls Handler object, where we orchestrate all of the parts
201 * of HLS to interact with video.js
202 *
203 * @class HlsHandler
204 * @extends videojs.Component
205 * @param {Object} source the soruce object
206 * @param {Tech} tech the parent tech object
207 * @param {Object} options optional and required options
208 */
209
210var HlsHandler = (function (_Component) {
211 _inherits(HlsHandler, _Component);
212
213 function HlsHandler(source, tech, options) {
214 var _this = this;
215
216 _classCallCheck(this, HlsHandler);
217
218 _get(Object.getPrototypeOf(HlsHandler.prototype), 'constructor', this).call(this, tech, options.hls);
219
220 // tech.player() is deprecated but setup a reference to HLS for
221 // backwards-compatibility
222 if (tech.options_ && tech.options_.playerId) {
223 var _player = (0, _videoJs2['default'])(tech.options_.playerId);
224
225 if (!_player.hasOwnProperty('hls')) {
226 Object.defineProperty(_player, 'hls', {
227 get: function get() {
228 _videoJs2['default'].log.warn('player.hls is deprecated. Use player.tech_.hls instead.');
229 tech.trigger({ type: 'usage', name: 'hls-player-access' });
230 return _this;
231 }
232 });
233 }
234 }
235
236 this.tech_ = tech;
237 this.source_ = source;
238 this.stats = {};
239 this.ignoreNextSeekingEvent_ = false;
240 this.setOptions_();
241
242 // overriding native HLS only works if audio tracks have been emulated
243 // error early if we're misconfigured:
244 if (this.options_.overrideNative && (tech.featuresNativeVideoTracks || tech.featuresNativeAudioTracks)) {
245 throw new Error('Overriding native HLS requires emulated tracks. ' + 'See https://git.io/vMpjB');
246 }
247
248 // listen for fullscreenchange events for this player so that we
249 // can adjust our quality selection quickly
250 this.on(_globalDocument2['default'], ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange'], function (event) {
251 var fullscreenElement = _globalDocument2['default'].fullscreenElement || _globalDocument2['default'].webkitFullscreenElement || _globalDocument2['default'].mozFullScreenElement || _globalDocument2['default'].msFullscreenElement;
252
253 if (fullscreenElement && fullscreenElement.contains(_this.tech_.el())) {
254 _this.masterPlaylistController_.fastQualityChange_();
255 }
256 });
257
258 this.on(this.tech_, 'seeking', function () {
259 if (this.ignoreNextSeekingEvent_) {
260 this.ignoreNextSeekingEvent_ = false;
261 return;
262 }
263
264 this.setCurrentTime(this.tech_.currentTime());
265 });
266 this.on(this.tech_, 'error', function () {
267 if (this.masterPlaylistController_) {
268 this.masterPlaylistController_.pauseLoading();
269 }
270 });
271
272 this.on(this.tech_, 'play', this.play);
273 }
274
275 /**
276 * The Source Handler object, which informs video.js what additional
277 * MIME types are supported and sets up playback. It is registered
278 * automatically to the appropriate tech based on the capabilities of
279 * the browser it is running in. It is not necessary to use or modify
280 * this object in normal usage.
281 */
282
283 _createClass(HlsHandler, [{
284 key: 'setOptions_',
285 value: function setOptions_() {
286 var _this2 = this;
287
288 // defaults
289 this.options_.withCredentials = this.options_.withCredentials || false;
290
291 if (typeof this.options_.blacklistDuration !== 'number') {
292 this.options_.blacklistDuration = 5 * 60;
293 }
294
295 // start playlist selection at a reasonable bandwidth for
296 // broadband internet (0.5 MB/s) or mobile (0.0625 MB/s)
297 if (typeof this.options_.bandwidth !== 'number') {
298 this.options_.bandwidth = INITIAL_BANDWIDTH;
299 }
300
301 // If the bandwidth number is unchanged from the initial setting
302 // then this takes precedence over the enableLowInitialPlaylist option
303 this.options_.enableLowInitialPlaylist = this.options_.enableLowInitialPlaylist && this.options_.bandwidth === INITIAL_BANDWIDTH;
304
305 // grab options passed to player.src
306 ['withCredentials', 'bandwidth'].forEach(function (option) {
307 if (typeof _this2.source_[option] !== 'undefined') {
308 _this2.options_[option] = _this2.source_[option];
309 }
310 });
311
312 this.bandwidth = this.options_.bandwidth;
313 }
314
315 /**
316 * called when player.src gets called, handle a new source
317 *
318 * @param {Object} src the source object to handle
319 */
320 }, {
321 key: 'src',
322 value: function src(_src) {
323 var _this3 = this;
324
325 // do nothing if the src is falsey
326 if (!_src) {
327 return;
328 }
329 this.setOptions_();
330 // add master playlist controller options
331 this.options_.url = this.source_.src;
332 this.options_.tech = this.tech_;
333 this.options_.externHls = Hls;
334
335 this.masterPlaylistController_ = new _masterPlaylistController.MasterPlaylistController(this.options_);
336 this.playbackWatcher_ = new _playbackWatcher2['default'](_videoJs2['default'].mergeOptions(this.options_, {
337 seekable: function seekable() {
338 return _this3.seekable();
339 }
340 }));
341
342 this.masterPlaylistController_.on('error', function () {
343 var player = _videoJs2['default'].players[_this3.tech_.options_.playerId];
344
345 player.error(_this3.masterPlaylistController_.error);
346 });
347
348 // `this` in selectPlaylist should be the HlsHandler for backwards
349 // compatibility with < v2
350 this.masterPlaylistController_.selectPlaylist = this.selectPlaylist ? this.selectPlaylist.bind(this) : Hls.STANDARD_PLAYLIST_SELECTOR.bind(this);
351
352 this.masterPlaylistController_.selectInitialPlaylist = Hls.INITIAL_PLAYLIST_SELECTOR.bind(this);
353
354 // re-expose some internal objects for backwards compatibility with < v2
355 this.playlists = this.masterPlaylistController_.masterPlaylistLoader_;
356 this.mediaSource = this.masterPlaylistController_.mediaSource;
357
358 // Proxy assignment of some properties to the master playlist
359 // controller. Using a custom property for backwards compatibility
360 // with < v2
361 Object.defineProperties(this, {
362 selectPlaylist: {
363 get: function get() {
364 return this.masterPlaylistController_.selectPlaylist;
365 },
366 set: function set(selectPlaylist) {
367 this.masterPlaylistController_.selectPlaylist = selectPlaylist.bind(this);
368 }
369 },
370 throughput: {
371 get: function get() {
372 return this.masterPlaylistController_.mainSegmentLoader_.throughput.rate;
373 },
374 set: function set(throughput) {
375 this.masterPlaylistController_.mainSegmentLoader_.throughput.rate = throughput;
376 // By setting `count` to 1 the throughput value becomes the starting value
377 // for the cumulative average
378 this.masterPlaylistController_.mainSegmentLoader_.throughput.count = 1;
379 }
380 },
381 bandwidth: {
382 get: function get() {
383 return this.masterPlaylistController_.mainSegmentLoader_.bandwidth;
384 },
385 set: function set(bandwidth) {
386 this.masterPlaylistController_.mainSegmentLoader_.bandwidth = bandwidth;
387 // setting the bandwidth manually resets the throughput counter
388 // `count` is set to zero that current value of `rate` isn't included
389 // in the cumulative average
390 this.masterPlaylistController_.mainSegmentLoader_.throughput = {
391 rate: 0,
392 count: 0
393 };
394 }
395 },
396 /**
397 * `systemBandwidth` is a combination of two serial processes bit-rates. The first
398 * is the network bitrate provided by `bandwidth` and the second is the bitrate of
399 * the entire process after that - decryption, transmuxing, and appending - provided
400 * by `throughput`.
401 *
402 * Since the two process are serial, the overall system bandwidth is given by:
403 * sysBandwidth = 1 / (1 / bandwidth + 1 / throughput)
404 */
405 systemBandwidth: {
406 get: function get() {
407 var invBandwidth = 1 / (this.bandwidth || 1);
408 var invThroughput = undefined;
409
410 if (this.throughput > 0) {
411 invThroughput = 1 / this.throughput;
412 } else {
413 invThroughput = 0;
414 }
415
416 var systemBitrate = Math.floor(1 / (invBandwidth + invThroughput));
417
418 return systemBitrate;
419 },
420 set: function set() {
421 _videoJs2['default'].log.error('The "systemBandwidth" property is read-only');
422 }
423 }
424 });
425
426 Object.defineProperties(this.stats, {
427 bandwidth: {
428 get: function get() {
429 return _this3.bandwidth || 0;
430 },
431 enumerable: true
432 },
433 mediaRequests: {
434 get: function get() {
435 return _this3.masterPlaylistController_.mediaRequests_() || 0;
436 },
437 enumerable: true
438 },
439 mediaRequestsAborted: {
440 get: function get() {
441 return _this3.masterPlaylistController_.mediaRequestsAborted_() || 0;
442 },
443 enumerable: true
444 },
445 mediaRequestsTimedout: {
446 get: function get() {
447 return _this3.masterPlaylistController_.mediaRequestsTimedout_() || 0;
448 },
449 enumerable: true
450 },
451 mediaRequestsErrored: {
452 get: function get() {
453 return _this3.masterPlaylistController_.mediaRequestsErrored_() || 0;
454 },
455 enumerable: true
456 },
457 mediaTransferDuration: {
458 get: function get() {
459 return _this3.masterPlaylistController_.mediaTransferDuration_() || 0;
460 },
461 enumerable: true
462 },
463 mediaBytesTransferred: {
464 get: function get() {
465 return _this3.masterPlaylistController_.mediaBytesTransferred_() || 0;
466 },
467 enumerable: true
468 },
469 mediaSecondsLoaded: {
470 get: function get() {
471 return _this3.masterPlaylistController_.mediaSecondsLoaded_() || 0;
472 },
473 enumerable: true
474 }
475 });
476
477 this.tech_.one('canplay', this.masterPlaylistController_.setupFirstPlay.bind(this.masterPlaylistController_));
478
479 this.masterPlaylistController_.on('selectedinitialmedia', function () {
480 // Add the manual rendition mix-in to HlsHandler
481 (0, _renditionMixin2['default'])(_this3);
482 });
483
484 // the bandwidth of the primary segment loader is our best
485 // estimate of overall bandwidth
486 this.on(this.masterPlaylistController_, 'progress', function () {
487 this.tech_.trigger('progress');
488 });
489
490 // In the live case, we need to ignore the very first `seeking` event since
491 // that will be the result of the seek-to-live behavior
492 this.on(this.masterPlaylistController_, 'firstplay', function () {
493 this.ignoreNextSeekingEvent_ = true;
494 });
495
496 this.tech_.ready(function () {
497 return _this3.setupQualityLevels_();
498 });
499
500 // do nothing if the tech has been disposed already
501 // this can occur if someone sets the src in player.ready(), for instance
502 if (!this.tech_.el()) {
503 return;
504 }
505
506 this.tech_.src(_videoJs2['default'].URL.createObjectURL(this.masterPlaylistController_.mediaSource));
507 }
508
509 /**
510 * Initializes the quality levels and sets listeners to update them.
511 *
512 * @method setupQualityLevels_
513 * @private
514 */
515 }, {
516 key: 'setupQualityLevels_',
517 value: function setupQualityLevels_() {
518 var _this4 = this;
519
520 var player = _videoJs2['default'].players[this.tech_.options_.playerId];
521
522 if (player && player.qualityLevels) {
523 this.qualityLevels_ = player.qualityLevels();
524
525 this.masterPlaylistController_.on('selectedinitialmedia', function () {
526 handleHlsLoadedMetadata(_this4.qualityLevels_, _this4);
527 });
528
529 this.playlists.on('mediachange', function () {
530 handleHlsMediaChange(_this4.qualityLevels_, _this4.playlists);
531 });
532 }
533 }
534
535 /**
536 * Begin playing the video.
537 */
538 }, {
539 key: 'play',
540 value: function play() {
541 this.masterPlaylistController_.play();
542 }
543
544 /**
545 * a wrapper around the function in MasterPlaylistController
546 */
547 }, {
548 key: 'setCurrentTime',
549 value: function setCurrentTime(currentTime) {
550 this.masterPlaylistController_.setCurrentTime(currentTime);
551 }
552
553 /**
554 * a wrapper around the function in MasterPlaylistController
555 */
556 }, {
557 key: 'duration',
558 value: function duration() {
559 return this.masterPlaylistController_.duration();
560 }
561
562 /**
563 * a wrapper around the function in MasterPlaylistController
564 */
565 }, {
566 key: 'seekable',
567 value: function seekable() {
568 return this.masterPlaylistController_.seekable();
569 }
570
571 /**
572 * Abort all outstanding work and cleanup.
573 */
574 }, {
575 key: 'dispose',
576 value: function dispose() {
577 if (this.playbackWatcher_) {
578 this.playbackWatcher_.dispose();
579 }
580 if (this.masterPlaylistController_) {
581 this.masterPlaylistController_.dispose();
582 }
583 if (this.qualityLevels_) {
584 this.qualityLevels_.dispose();
585 }
586 _get(Object.getPrototypeOf(HlsHandler.prototype), 'dispose', this).call(this);
587 }
588 }]);
589
590 return HlsHandler;
591})(Component);
592
593var HlsSourceHandler = function HlsSourceHandler(mode) {
594 return {
595 canHandleSource: function canHandleSource(srcObj) {
596 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
597
598 var localOptions = _videoJs2['default'].mergeOptions(_videoJs2['default'].options, options);
599
600 // this forces video.js to skip this tech/mode if its not the one we have been
601 // overriden to use, by returing that we cannot handle the source.
602 if (localOptions.hls && localOptions.hls.mode && localOptions.hls.mode !== mode) {
603 return false;
604 }
605 return HlsSourceHandler.canPlayType(srcObj.type, localOptions);
606 },
607 handleSource: function handleSource(source, tech) {
608 var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
609
610 var localOptions = _videoJs2['default'].mergeOptions(_videoJs2['default'].options, options, { hls: { mode: mode } });
611
612 if (mode === 'flash') {
613 // We need to trigger this asynchronously to give others the chance
614 // to bind to the event when a source is set at player creation
615 tech.setTimeout(function () {
616 tech.trigger('loadstart');
617 }, 1);
618 }
619
620 tech.hls = new HlsHandler(source, tech, localOptions);
621 tech.hls.xhr = (0, _xhr2['default'])();
622
623 tech.hls.src(source.src);
624 return tech.hls;
625 },
626 canPlayType: function canPlayType(type) {
627 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
628
629 var localOptions = _videoJs2['default'].mergeOptions(_videoJs2['default'].options, options);
630
631 if (HlsSourceHandler.canPlayType(type, localOptions)) {
632 return 'maybe';
633 }
634 return '';
635 }
636 };
637};
638
639HlsSourceHandler.canPlayType = function (type, options) {
640 // No support for IE 10 or below
641 if (_videoJs2['default'].browser.IE_VERSION && _videoJs2['default'].browser.IE_VERSION <= 10) {
642 return false;
643 }
644
645 var mpegurlRE = /^(audio|video|application)\/(x-|vnd\.apple\.)?mpegurl/i;
646
647 // favor native HLS support if it's available
648 if (!options.hls.overrideNative && Hls.supportsNativeHls) {
649 return false;
650 }
651 return mpegurlRE.test(type);
652};
653
654if (typeof _videoJs2['default'].MediaSource === 'undefined' || typeof _videoJs2['default'].URL === 'undefined') {
655 _videoJs2['default'].MediaSource = _videojsContribMediaSources.MediaSource;
656 _videoJs2['default'].URL = _videojsContribMediaSources.URL;
657}
658
659var flashTech = _videoJs2['default'].getTech('Flash');
660
661// register source handlers with the appropriate techs
662if (_videojsContribMediaSources.MediaSource.supportsNativeMediaSources()) {
663 _videoJs2['default'].getTech('Html5').registerSourceHandler(HlsSourceHandler('html5'), 0);
664}
665if (_globalWindow2['default'].Uint8Array && flashTech) {
666 flashTech.registerSourceHandler(HlsSourceHandler('flash'));
667}
668
669_videoJs2['default'].HlsHandler = HlsHandler;
670_videoJs2['default'].HlsSourceHandler = HlsSourceHandler;
671_videoJs2['default'].Hls = Hls;
672if (!_videoJs2['default'].use) {
673 _videoJs2['default'].registerComponent('Hls', Hls);
674}
675_videoJs2['default'].m3u8 = _m3u8Parser2['default'];
676_videoJs2['default'].options.hls = _videoJs2['default'].options.hls || {};
677
678if (_videoJs2['default'].registerPlugin) {
679 _videoJs2['default'].registerPlugin('reloadSourceOnError', _reloadSourceOnError2['default']);
680} else {
681 _videoJs2['default'].plugin('reloadSourceOnError', _reloadSourceOnError2['default']);
682}
683
684module.exports = {
685 Hls: Hls,
686 HlsHandler: HlsHandler,
687 HlsSourceHandler: HlsSourceHandler
688};
\No newline at end of file