define(["globalize", "browser", "require", "events", "loading", "dom", "playbackManager", "appRouter", "connectionManager", "htmlMediaHelper", "./basehtmlplayer", "Modernizr"], function(globalize, browser, require, events, loading, dom, playbackManager, appRouter, connectionManager, htmlMediaHelper, BaseHtmlPlayer, Modernizr) {
	"use strict";
	var supportedFeatures;

	function getMediaStreamTracks(mediaSource, type) {
		return mediaSource.MediaStreams.filter(function(s) {
			return s.Type === type
		})
	}
	function getMediaStreamSubtitleTracks(mediaSource) {
		return mediaSource.MediaStreams.filter(function(s) {
			return "Subtitle" === s.Type
		})
	}
	function setTracks(elem, tracksHtml) {
		elem.innerHTML = tracksHtml
	}
	function getTextTrackUrl(track, item, mediaSource) {
		if (window.Windows && mediaSource.IsLocal && track.Path) return Windows.Storage.StorageFile.getFileFromPathAsync(track.Path).then(function(file) {
			var trackUrl = URL.createObjectURL(file, {
				oneTimeOnly: !0
			});
			return Promise.resolve(trackUrl)
		});
		if (mediaSource.IsLocal && track.Path) return Promise.resolve(track.Path);
		var url = playbackManager.getSubtitleUrl(track, item.ServerId);
		return Promise.resolve(url)
	}
	function HtmlVideoPlayer() {
		var videoDialog, subtitleTrackIndexToSetOnPlaying, audioTrackIndexToSetOnPlaying, currentClock, currentAssRenderer;
		BaseHtmlPlayer.call(this), browser.edgeUwp ? this.name = "Windows Video Player" : this.name = "Web Video Player", this.id = "htmlvideoplayer", this.mediaType = "video";
		var videoSubtitlesElem, currentTrackEvents, customTrackIndex = -(this.priority = 1),
			self = this;

		function onEnded() {
			destroyCustomTrack(this), htmlMediaHelper.onEndedInternal(self, this, onError)
		}
		function onTimeUpdate(e) {
			var time, currentPlayOptions, timeMs;
			self._started && ((time = this.currentTime) && !self._timeUpdated && (self._timeUpdated = !0, function(elem) {
				if (elem !== self._mediaElement) return;
				if (0 === elem.videoWidth && 0 === elem.videoHeight) {
					var mediaSource = (self._currentPlayOptions || {}).mediaSource;
					if (!mediaSource) return htmlMediaHelper.onErrorInternal(self, "mediadecodeerror");
					if (getMediaStreamTracks(mediaSource, "Video").length) htmlMediaHelper.onErrorInternal(self, "mediadecodeerror")
				}
			}(this)), self._currentTime = time, (currentPlayOptions = self._currentPlayOptions) && (timeMs = 1e3 * time - self._currentSubtitleOffset, function(timeMs) {
				var clock = currentClock;
				if (clock) {
					try {
						clock.seek(timeMs / 1e3)
					} catch (err) {
						console.log("Error in libjass: " + err)
					}
					return
				}
				var selectedTrackEvent, trackEvents = currentTrackEvents,
					subtitleTextElement = videoSubtitlesElem;
				if (trackEvents && subtitleTextElement) {
					for (var WebVTT, seconds = timeMs / 1e3, i = 0; i < trackEvents.length; i++) {
						var currentTrackEvent = trackEvents[i];
						if (currentTrackEvent.startTime <= seconds && currentTrackEvent.endTime >= seconds) {
							selectedTrackEvent = currentTrackEvent;
							break
						}
					}
					selectedTrackEvent && selectedTrackEvent.text ? (subtitleTextElement.innerHTML = "", WebVTT = window.WebVTT, subtitleTextElement.appendChild(WebVTT.convertCueToDOMTree(window, selectedTrackEvent.text)), subtitleTextElement.classList.remove("hide")) : subtitleTextElement.classList.add("hide")
				}
			}(timeMs += (currentPlayOptions.transcodingOffsetTicks || 0) / 1e4)), events.trigger(self, "timeupdate"))
		}
		function onVolumeChange() {
			htmlMediaHelper.saveVolume(this.volume), events.trigger(self, "volumechange")
		}
		function onRateChange() {
			events.trigger(self, "playbackratechange")
		}
		function onNavigatedToOsd() {
			var dlg = videoDialog;
			dlg && (dlg.classList.remove("videoPlayerContainer-withBackdrop"), dlg.classList.remove("videoPlayerContainer-onTop"))
		}
		function setInitialSubtitleTrack() {
			null != subtitleTrackIndexToSetOnPlaying && setCurrentTrackElement(subtitleTrackIndexToSetOnPlaying)
		}
		function setInitialAudioTrack() {
			var index = audioTrackIndexToSetOnPlaying;
			null != index && self.canSetAudioStreamIndex() && self.setAudioStreamIndex(index)
		}
		function ensureNavigated() {
			self._navigated || (self._navigated = !0, appRouter.showVideoOsd().then(onNavigatedToOsd))
		}
		function onPlaying(e) {
			self._started || (self._started = !0, loading.hide(), self.seekOnPlaybackStart(e.target, self._currentPlayOptions.playerStartPositionTicks), self._currentPlayOptions.fullscreen ? ensureNavigated() : (appRouter.setTransparency("backdrop"), videoDialog.classList.remove("videoPlayerContainer-withBackdrop"), videoDialog.classList.remove("videoPlayerContainer-onTop")), null != subtitleTrackIndexToSetOnPlaying && setTimeout(setInitialSubtitleTrack, 400), null != audioTrackIndexToSetOnPlaying && setTimeout(setInitialAudioTrack, 300)), events.trigger(self, "playing")
		}
		function onPlayWithPromiseResolved(result) {
			return result.autoplayed || (self._currentPlayOptions.fullscreen ? ensureNavigated() : (appRouter.setTransparency("backdrop"), videoDialog.classList.remove("videoPlayerContainer-withBackdrop"), videoDialog.classList.remove("videoPlayerContainer-onTop"))), Promise.resolve()
		}
		function onPlay(e) {
			events.trigger(self, "unpause")
		}
		function onClick() {
			events.trigger(self, "click")
		}
		function onDblClick() {
			events.trigger(self, "dblclick")
		}
		function onPause() {
			events.trigger(self, "pause")
		}
		function onError() {
			var type, errorCode = this.error && this.error.code || 0,
				errorMessage = this.error && this.error.message || "";
			switch (console.log("Media element error: " + errorCode.toString() + " " + errorMessage), errorCode) {
			case 1:
				return;
			case 2:
				type = "network";
				break;
			case 3:
				if (self._hlsPlayer) return void htmlMediaHelper.handleHlsJsMediaError(self);
				type = "mediadecodeerror";
				break;
			case 4:
				type = "medianotsupported";
				break;
			default:
				return
			}
			htmlMediaHelper.onErrorInternal(self, type)
		}
		function destroyCustomTrack(videoElement) {
			var subtitlesContainer;
			if (self._resizeObserver && (self._resizeObserver.disconnect(), self._resizeObserver = null), videoSubtitlesElem && ((subtitlesContainer = videoSubtitlesElem.parentNode) &&
			function(elem) {
				var parentNode = elem.parentNode;
				if (parentNode) try {
					parentNode.removeChild(elem)
				} catch (err) {
					console.log("Error removing dialog element: " + err)
				}
			}(subtitlesContainer), videoSubtitlesElem = null), currentTrackEvents = null, videoElement) for (var allTracks = videoElement.textTracks || [], i = 0; i < allTracks.length; i++) {
				var currentTrack = allTracks[i]; - 1 !== currentTrack.label.indexOf("manualTrack") && (currentTrack.mode = "disabled")
			}
			customTrackIndex = -1, currentClock = null, self._currentAspectRatio = null, self._currentSubtitleOffset = 0;
			var subtitlesOctopus = self.currentSubtitlesOctopus;
			subtitlesOctopus && (subtitlesOctopus.dispose(), self.currentSubtitlesOctopus = null), currentAssRenderer && currentAssRenderer.setEnabled(!1), currentAssRenderer = null
		}
		function fetchVttSubtitles(track, item, mediaSource) {
			var promises = [getTextTrackUrl(track, item, mediaSource), require(["./vtt.min"])];
			return Promise.all(promises).then(function(responses) {
				var url = responses[0];
				return new Promise(function(resolve, reject) {
					var xhr = new XMLHttpRequest;
					xhr.open("GET", url, !0), xhr.onload = function(e) {
						var WebVTT = window.WebVTT,
							parser = new WebVTT.Parser(window, WebVTT.StringDecoder()),
							cues = [];
						parser.oncue = function(cue) {
							cues.push(cue)
						}, parser.onflush = function() {
							resolve(cues)
						};
						var vtt = this.response;
						parser.parse(vtt), parser.flush()
					}, xhr.onerror = reject, xhr.send()
				})
			})
		}
		function setTrackForCustomDisplay(videoElement, track) {
			var currentPlayOptions, item, mediaSource;
			track ? customTrackIndex !== track.Index && (item = (currentPlayOptions = self._currentPlayOptions).item, mediaSource = currentPlayOptions.mediaSource, destroyCustomTrack(videoElement), customTrackIndex = track.Index, function(videoElement, track, item, mediaSource) {
				if (!mediaSource.IsLocal || track.IsExternal) {
					var format = (track.Codec || "").toLowerCase();
					if ("ssa" === format || "ass" === format) return function(videoElement, track, item, mediaSource) {
						if (window.Worker &&
						function() {
							var elem = document.createElement("canvas");
							return !(!elem.getContext || !elem.getContext("2d"))
						}() && !browser.web0s) return function(videoElement, track, item, mediaSource) {
							require(["SubtitlesOctopus"], function() {
								getTextTrackUrl(track, item, mediaSource).then(function(textTrackUrl) {
									self.currentSubtitlesOctopus = new SubtitlesOctopus({
										video: videoElement,
										subUrl: textTrackUrl,
										workerUrl: appRouter.baseUrl() + "/bower_components/javascriptsubtitlesoctopus/dist/subtitles-octopus-worker.js",
										legacyWorkerUrl: appRouter.baseUrl() + "/bower_components/javascriptsubtitlesoctopus/dist/subtitles-octopus-worker-legacy.js",
										fonts: function(track) {
											var language = (track.Language || "").toLowerCase();
											return -1 === ["dut", "eng", "fin", "fre", "ger", "heb", "hun", "ita", "nor", "pol", "por", "rus", "spa", "swe"].indexOf(language)
										}(track) ? [appRouter.baseUrl() + "/modules/fonts/subfont.woff2"] : [],
										onError: function() {
											htmlMediaHelper.onErrorInternal(self, "mediadecodeerror")
										},
										lossyRender: null != window.createImageBitmap,
										detectAlphaBug: !browser.chromecast
									}), self._resizeObserver || (self._resizeObserver = new ResizeObserver(onVideoResize, {}), self._resizeObserver.observe(videoElement))
								})
							})
						}(videoElement, track, item, mediaSource);
						!
						function(videoElement, track, item, mediaSource) {
							var rendererSettings = {
								enableSvg: !1
							};
							require(["libjass"], function(libjass) {
								getTextTrackUrl(track, item, mediaSource).then(function(textTrackUrl) {
									libjass.ASS.fromUrl(textTrackUrl).then(function(ass) {
										var clock = new libjass.renderers.ManualClock;
										currentClock = clock;
										var renderer = new libjass.renderers.WebRenderer(ass, clock, videoElement.parentNode, rendererSettings);
										(currentAssRenderer = renderer).addEventListener("ready", function() {
											try {
												renderer.resize(videoElement.offsetWidth, videoElement.offsetHeight, 0, 0), self._resizeObserver || (self._resizeObserver = new ResizeObserver(onVideoResize, {}), self._resizeObserver.observe(videoElement))
											} catch (ex) {}
										})
									}, function(e) {
										htmlMediaHelper.onErrorInternal(self, "mediadecodeerror")
									})
								})
							})
						}(videoElement, track, item, mediaSource)
					}(videoElement, track, item, mediaSource)
				}
				if (function() {
					if (browser.ps4) return !0;
					if (browser.firefox) return !0;
					if (browser.netcast) return !0;
					if (browser.web0s && browser.sdkVersion && browser.sdkVersion < 3) return !0;
					return !1
				}()) return function(videoElement, track, item, mediaSource) {
					fetchVttSubtitles(track, item, mediaSource).then(function(cues) {
						var subtitlesContainer, elem, innerElem;
						videoSubtitlesElem || ((subtitlesContainer = document.createElement("div")).classList.add("videoSubtitles"), subtitlesContainer.innerHTML = '<div class="videoSubtitlesInner"></div>', videoSubtitlesElem = subtitlesContainer.querySelector(".videoSubtitlesInner"), elem = subtitlesContainer, innerElem = videoSubtitlesElem, require(["userSettings", "subtitleAppearanceHelper"], function(userSettings, subtitleAppearanceHelper) {
							subtitleAppearanceHelper.applyStyles({
								text: innerElem,
								window: elem
							}, userSettings.getSubtitleAppearanceSettings())
						}), videoElement.parentNode.appendChild(subtitlesContainer), currentTrackEvents = cues)
					})
				}(videoElement, track, item, mediaSource);
				var i, length, trackElement = null,
					expectedId = "manualTrack" + track.Index,
					allTracks = videoElement.textTracks;
				for (i = 0; i < allTracks.length; i++) {
					var currentTrack = allTracks[i];
					if (currentTrack.label === expectedId) {
						trackElement = currentTrack;
						break
					}
					currentTrack.mode = "disabled"
				}
				trackElement ? trackElement.mode = "showing" : (trackElement = videoElement.addTextTrack("subtitles", "manualTrack" + track.Index, track.Language || "und"), fetchVttSubtitles(track, item, mediaSource).then(function(cues) {
					for (console.log("downloaded " + cues.length + " track events"), i = 0, length = cues.length; i < length; i++) {
						var trackEvent = cues[i],
							cue = new(window.VTTCue || window.TextTrackCue)(trackEvent.startTime, trackEvent.endTime, trackEvent.text);
						trackElement.addCue(cue)
					}
					trackElement.mode = "showing"
				}))
			}(videoElement, track, item, mediaSource)) : destroyCustomTrack(videoElement)
		}
		function onVideoResize() {
			browser.iOS ? setTimeout(resetVideoRendererSize, 500) : resetVideoRendererSize()
		}
		function resetVideoRendererSize() {
			var subtitlesOctopus = self.currentSubtitlesOctopus;
			subtitlesOctopus && subtitlesOctopus.resize();
			var videoElement, width, height, renderer = currentAssRenderer;
			renderer && (width = (videoElement = self._mediaElement).offsetWidth, height = videoElement.offsetHeight, console.log("videoElement resized: " + width + "x" + height), renderer.resize(width, height, 0, 0))
		}
		function setCueAppearance() {
			require(["userSettings", "subtitleAppearanceHelper"], function(userSettings, subtitleAppearanceHelper) {
				var appearance, html, elementId = self.id + "-cuestyle",
					styleElem = document.querySelector("#" + elementId);
				styleElem || ((styleElem = document.createElement("style")).id = elementId, styleElem.type = "text/css", document.getElementsByTagName("head")[0].appendChild(styleElem)), styleElem.innerHTML = (appearance = subtitleAppearanceHelper.getStyles(userSettings.getSubtitleAppearanceSettings(), !0), html = ".htmlvideoplayer" + "::cue {", html += appearance.text.map(function(s) {
					return s.name + ":" + s.value + " !important;"
				}).join(""), html += "}")
			})
		}
		function setCurrentTrackElement(streamIndex) {
			self.setSubtitleOffset(0);
			var playMethod, currentPlayOptions = self._currentPlayOptions,
				mediaSource = currentPlayOptions.mediaSource;
			browser.web0s && browser.sdkVersion && browser.sdkVersion < 3 && ("DirectStream" !== (playMethod = currentPlayOptions.playMethod) && "DirectPlay" !== playMethod || "mkv" === mediaSource.Container && (streamIndex = -1)), console.log("Setting new text track index to: " + streamIndex);
			var mediaStreamTextTracks = getMediaStreamSubtitleTracks(mediaSource),
				track = -1 === streamIndex ? null : mediaStreamTextTracks.filter(function(t) {
					return t.Index === streamIndex
				})[0];
			if (!
			function(currentSrc, track) {
				if (track) {
					if ("Embed" === track.DeliveryMethod) return 1;
					if ("Hls" === track.DeliveryMethod) return 1
				}
				if (!(browser.firefox && -1 !== (currentSrc || "").toLowerCase().indexOf(".m3u8") || browser.chromecast && -1 !== (currentSrc || "").toLowerCase().indexOf(".m3u8") || browser.ps4 || browser.netcast || browser.web0s && browser.sdkVersion && browser.sdkVersion < 3)) {
					if (track) {
						var format = (track.Codec || "").toLowerCase();
						if ("ssa" === format || "ass" === format) return
					}
					return 1
				}
			}(self._currentSrc, track) ? (setTrackForCustomDisplay(self._mediaElement, track), streamIndex = -1, track = null) : (setTrackForCustomDisplay(self._mediaElement, null), -1 !== streamIndex && setCueAppearance()), self._shakaPlayer)!
			function(shakaPlayer, track) {
				var i, newTrack, allTracks = shakaPlayer.getTextTracks(),
					expectedId = track.Index;
				for (console.log(JSON.stringify(allTracks)), i = 0; i < allTracks.length; i++) {
					var currentTrack = allTracks[i];
					if (currentTrack.id === expectedId) {
						newTrack = currentTrack;
						break
					}
				}
				newTrack && shakaPlayer.selectTextTrack(newTrack), shakaPlayer.setTextTrackVisibility(null != newTrack)
			}(self._shakaPlayer, track);
			else {
				for (var targetIndex = -1, expectedId = "textTrack" + streamIndex, elemTextTracks = self._mediaElement.textTracks, i = 0; i < elemTextTracks.length; i++) {
					var tt = elemTextTracks[i];
					tt.id === expectedId && (targetIndex = i), tt.mode = "disabled"
				}
				targetIndex < 0 && (mediaStreamTextTracks = mediaStreamTextTracks.filter(function(s) {
					return s.IsTextSubtitleStream && "ass" !== s.Codec && "ssa" !== s.Codec
				}), track && "Hls" === track.DeliveryMethod ? targetIndex = mediaStreamTextTracks.indexOf(track) : (browser.msie || browser.edge) && (targetIndex = -1 !== streamIndex && track ? mediaStreamTextTracks.indexOf(track) : -1)), 0 <= targetIndex && targetIndex < elemTextTracks.length && (elemTextTracks[targetIndex].mode = "showing")
			}
		}
		self.play = function(options) {
			return browser.msie && "Transcode" === options.playMethod && !window.MediaSource ? (window.alert("Internet Explorer&#x4E0D;&#x652F;&#x6301;&#x64AD;&#x653E;&#x6B64;&#x5185;&#x5BB9;&#xFF0C;&#x8981;&#x83B7;&#x5F97;&#x66F4;&#x597D;&#x7684;&#x4F53;&#x9A8C;&#xFF0C;&#x8BF7;&#x5C1D;&#x8BD5;&#x4F7F;&#x7528;&#x5176;&#x5B83;&#x6D4F;&#x89C8;&#x5668;&#xFF0C;&#x5982;Microsoft Edge&#x3001;Google Chrome&#x3001;Firefox&#x6216;Opera&#x3002;"), Promise.reject()) : (self._started = !1, self._navigated = !1, self._timeUpdated = !1, self._currentTime = null, function(options) {
				(browser.tizen || browser.orsay || browser.web0s || browser.operaTv || browser.netcast || browser.iOS || browser.chromecast) && (options.backdropUrl = null);
				var dlg = document.querySelector(".videoPlayerContainer");
				return dlg ? (options.backdropUrl && (dlg.classList.add("videoPlayerContainer-withBackdrop"), dlg.style.backgroundImage = "url('" + options.backdropUrl + "')"), Promise.resolve(dlg.querySelector("video"))) : require(["css!./style"]).then(function() {
					loading.show(), (dlg = document.createElement("div")).classList.add("videoPlayerContainer"), options.backdropUrl && (dlg.classList.add("videoPlayerContainer-withBackdrop"), dlg.style.backgroundImage = "url('" + options.backdropUrl + "')"), options.fullscreen && dlg.classList.add("videoPlayerContainer-onTop");
					var html = "",
						cssClass = "htmlvideoplayer";
					(browser.edge || browser.msie) && (cssClass += " htmlvideoplayer-edge"), html += '<video class="' + cssClass + '" preload="metadata" autoplay="autoplay" webkit-playsinline playsinline>', html += "</video>", dlg.innerHTML = html;
					var elem, videoElement = dlg.querySelector("video");
					return videoElement.volume = htmlMediaHelper.getSavedVolume(), videoElement.addEventListener("timeupdate", onTimeUpdate), videoElement.addEventListener("ended", onEnded), videoElement.addEventListener("volumechange", onVolumeChange), videoElement.addEventListener("pause", onPause), videoElement.addEventListener("playing", onPlaying), videoElement.addEventListener("play", onPlay), videoElement.addEventListener("click", onClick), videoElement.addEventListener("dblclick", onDblClick), videoElement.addEventListener("ratechange", onRateChange), browser.chromecast || videoElement.classList.add("moveUpSubtitles"), document.body.insertBefore(dlg, document.body.firstChild), videoDialog = dlg, self._mediaElement = videoElement, browser.chromecast && (cast.framework.CastReceiverContext.getInstance().getPlayerManager().setMediaElement(videoElement), self.bindMediaManagerEvents()), options.fullscreen && Modernizr.cssanimations && !browser.chromecast && !browser.web0s ? (elem = dlg, new Promise(function(resolve, reject) {
						elem.style.animation = "htmlvideoplayer-zoomin 240ms ease-in normal", dom.addEventListener(elem, "animationend", resolve, {
							once: !0
						})
					}).then(function() {
						return videoElement
					})) : videoElement
				})
			}(options).then(function(elem) {
				return function(streamInfo) {
					var isHls = -1 !== streamInfo.url.toLowerCase().indexOf(".m3u8"),
						mediaSource = streamInfo.mediaSource,
						item = streamInfo.item;
					if (mediaSource && item && !mediaSource.RunTimeTicks && isHls && "Transcode" === streamInfo.playMethod && (browser.iOS || browser.osx)) {
						var hlsPlaylistUrl = streamInfo.url.replace("master.m3u8", "live.m3u8");
						return loading.show(), console.log("prefetching hls playlist: " + hlsPlaylistUrl), connectionManager.getApiClient(item).ajax({
							type: "GET",
							url: hlsPlaylistUrl
						}).then(function() {
							return console.log("completed prefetching hls playlist: " + hlsPlaylistUrl), loading.hide(), streamInfo.url = hlsPlaylistUrl, Promise.resolve()
						}, function() {
							return console.log("error prefetching hls playlist: " + hlsPlaylistUrl), loading.hide(), Promise.resolve()
						})
					}
					return Promise.resolve()
				}(options, options.mediaSource).then(function() {
					return function(elem, options) {
						elem.removeEventListener("error", onError);
						var val = options.url;
						console.log("playing url: " + val);
						var seconds = (options.playerStartPositionTicks || 0) / 1e7;
						seconds && (val += "#t=" + seconds);
						htmlMediaHelper.destroyHlsPlayer(self), htmlMediaHelper.destroyFlvPlayer(self), htmlMediaHelper.destroyCastPlayer(self);
						var tracks = getMediaStreamSubtitleTracks(options.mediaSource); {
							var initialSubtitleStream;
							null != (subtitleTrackIndexToSetOnPlaying = null == options.mediaSource.DefaultSubtitleStreamIndex ? -1 : options.mediaSource.DefaultSubtitleStreamIndex) && 0 <= subtitleTrackIndexToSetOnPlaying && ((initialSubtitleStream = function(mediaStreams, index) {
								for (var i = 0, length = mediaStreams.length; i < length; i++) if (mediaStreams[i].Index === index) return mediaStreams[i];
								return null
							}(options.mediaSource.MediaStreams, subtitleTrackIndexToSetOnPlaying)) && "Encode" !== initialSubtitleStream.DeliveryMethod || (subtitleTrackIndexToSetOnPlaying = -1))
						}
						audioTrackIndexToSetOnPlaying = "Transcode" === options.playMethod ? null : options.mediaSource.DefaultAudioStreamIndex, self._currentPlayOptions = options;
						var crossOrigin = htmlMediaHelper.getCrossOriginValue(options.mediaSource, options.playMethod);
						crossOrigin && (elem.crossOrigin = crossOrigin);
						var hasHlsTextTracks = function(tracks) {
								return 0 < tracks.filter(function(t) {
									return "Hls" === t.DeliveryMethod
								}).length
							}(tracks = tracks.filter(function(s) {
								return s.IsTextSubtitleStream && "ass" !== s.Codec && "ssa" !== s.Codec
							}));
						return function(tracks, item, mediaSource) {
							var trackPromises = tracks.map(function(t) {
								return "External" !== t.DeliveryMethod ? Promise.resolve("") : getTextTrackUrl(t, item, mediaSource).then(function(textTrackUrl) {
									var defaultAttribute = mediaSource.DefaultSubtitleStreamIndex === t.Index ? " default" : "",
										language = t.Language || "und",
										label = t.Language || "und";
									return '<track id="textTrack' + t.Index + '" label="' + label + '" kind="subtitles" src="' + textTrackUrl + '" srclang="' + language + '"' + defaultAttribute + " />\n"
								})
							});
							return Promise.all(trackPromises).then(function(trackTags) {
								return trackTags.join("")
							})
						}(tracks, options.item, options.mediaSource).then(function(tracksHtml) {
							return htmlMediaHelper.enableHlsShakaPlayer(options.mediaSource.RunTimeTicks, "Video") && -1 !== val.indexOf(".m3u8") ? (setTracks(elem, tracksHtml), self.setSrcWithShakaPlayer(elem, options, val)) : "Transcode" !== options.playMethod && "flv" === options.mediaSource.Container ? (setTracks(elem, tracksHtml), self.setSrcWithFlvJs(elem, options, val)) : browser.chromecast ? self.setCurrentSrcChromecast(elem, options, val, hasHlsTextTracks, tracksHtml) : htmlMediaHelper.enableHlsJsPlayer(options.mediaSource.RunTimeTicks, "Video") && -1 !== val.indexOf(".m3u8") ? (hasHlsTextTracks || setTracks(elem, tracksHtml), self.setSrcWithHlsJs(elem, options, val, onError).then(onPlayWithPromiseResolved)) : (elem.autoplay = !0, htmlMediaHelper.applySrc(elem, val, options).then(function() {
								return setTracks(elem, tracksHtml), self._currentSrc = val, htmlMediaHelper.playWithPromise(elem, onError).then(onPlayWithPromiseResolved)
							}))
						})
					}(elem, options)
				})
			}))
		}, self.loadIntoPlayer = function(elem, options, val, media, data, customData) {
			var hasHlsTextTracks = customData.hasHlsTextTracks,
				tracksHtml = customData.tracksHtml;
			if (-1 !== val.indexOf(".m3u8")) {
				if (options.mediaSource.RunTimeTicks) {
					setTracks(elem, tracksHtml), self._castPlayer && self._castPlayer.unload(), self._castPlayer = null;
					var contentType = media.contentType.toLowerCase(),
						host = new cast.player.api.Host({
							url: val,
							mediaElement: elem
						}),
						protocol = cast.player.api.CreateHlsStreamingProtocol(host);
					return console.log("loading playback url: " + val), console.log("contentType: " + contentType), host.onError = function(errorCode) {
						console.log("Fatal Error - " + errorCode)
					}, elem.autoplay = !1, self._castPlayer = new cast.player.api.Player(host), self._castPlayer.load(protocol, data.currentTime || 0), self._castPlayer.playWhenHaveEnoughData(), Promise.resolve()
				}
				if (htmlMediaHelper.enableHlsJsPlayer(options.mediaSource.RunTimeTicks, "Video") && -1 !== val.indexOf(".m3u8")) return hasHlsTextTracks || setTracks(elem, tracksHtml), self.setSrcWithHlsJs(elem, options, val, onError)
			}
			return elem.autoplay = !0, htmlMediaHelper.applySrc(elem, val, options).then(function() {
				return setTracks(elem, tracksHtml), self._currentSrc = val, htmlMediaHelper.playWithPromise(elem, onError).then(onPlayWithPromiseResolved)
			})
		}, self.setSubtitleStreamIndex = function(index) {
			setCurrentTrackElement(index)
		}, self.setAudioStreamIndex = function(index) {
			var instance, profile, mediaSource, streams = (profile = (instance = self)._lastProfile, getMediaStreamTracks(mediaSource = instance._currentPlayOptions.mediaSource, "Audio").filter(function(stream) {
				return playbackManager.isAudioStreamSupported(stream, mediaSource, profile)
			}));
			if (!(streams.length < 2)) {
				for (var audioIndex = -1, i = 0, length = streams.length; i < length && (audioIndex++, streams[i].Index !== index); i++);
				if (-1 !== audioIndex) {
					var elem = self._mediaElement;
					if (elem) {
						var elemAudioTracks = elem.audioTracks || [];
						if (!(elemAudioTracks.length < 2)) {
							for (console.log("found " + elemAudioTracks.length + " audio tracks"), i = 0, length = elemAudioTracks.length; i < length; i++) audioIndex === i ? (console.log("setting audio track " + i + " to enabled"), elemAudioTracks[i].enabled = !0) : (console.log("setting audio track " + i + " to disabled"), elemAudioTracks[i].enabled = !1);
							setTimeout(function() {
								elem.currentTime = elem.currentTime
							}, 100)
						}
					}
				}
			}
		}, self.stop = function(destroyPlayer) {
			var elem = self._mediaElement,
				src = self._currentSrc;
			return elem && (src && elem.pause(), htmlMediaHelper.onEndedInternal(self, elem, onError), destroyPlayer && self.destroy()), destroyCustomTrack(elem), Promise.resolve()
		}, self.destroy = function() {
			htmlMediaHelper.destroyHlsPlayer(self), htmlMediaHelper.destroyFlvPlayer(self), appRouter.setTransparency("none");
			var videoElement = self._mediaElement;
			videoElement && (self._mediaElement = null, destroyCustomTrack(videoElement), browser.chromecast && self.unBindMediaManagerEvents(), videoElement.removeEventListener("timeupdate", onTimeUpdate), videoElement.removeEventListener("ended", onEnded), videoElement.removeEventListener("volumechange", onVolumeChange), videoElement.removeEventListener("pause", onPause), videoElement.removeEventListener("playing", onPlaying), videoElement.removeEventListener("play", onPlay), videoElement.removeEventListener("click", onClick), videoElement.removeEventListener("dblclick", onDblClick), videoElement.removeEventListener("ratechange", onRateChange), videoElement.parentNode.removeChild(videoElement));
			var dlg = videoDialog;
			dlg && (videoDialog = null, dlg.parentNode.removeChild(dlg))
		}, self.destroyCustomTrack = destroyCustomTrack
	}
	function onPictureInPictureError(err) {
		console.log("Picture in picture error: " + err.toString())
	}
	function setSubtitleOffset(instance, elem, val) {
		var subtitlesOctopus = instance.currentSubtitlesOctopus;
		subtitlesOctopus && (subtitlesOctopus.timeOffset = -val / 1e3);
		for (var textTracks = elem.textTracks || [], i = 0, length = textTracks.length; i < length; i++) {
			var track = textTracks[i];
			if ("showing" === track.mode) {
				var cues = track.cues;
				if (cues) try {
					!
					function(cues, val) {
						val /= 1e3;
						for (var i = 0, length = cues.length; i < length; i++) {
							var cue = cues[i];
							null == cue.originalStartTime && (cue.originalStartTime = cue.startTime), null == cue.originalEndTime && (cue.originalEndTime = cue.endTime), cue.startTime = cue.originalStartTime + val, cue.endTime = cue.originalEndTime + val
						}
					}(cues, val)
				} catch (err) {
					console.log("error in setSubtitleOffsetIntoCues: " + err)
				}
			}
		}
	}
	return Object.assign(HtmlVideoPlayer.prototype, BaseHtmlPlayer.prototype), HtmlVideoPlayer.prototype.supports = function(feature) {
		var list, video;
		return supportedFeatures || (list = [], (video = document.createElement("video")).webkitSupportsPresentationMode && "function" == typeof video.webkitSetPresentationMode && -1 === navigator.userAgent.toLowerCase().indexOf("os 9") && list.push("PictureInPicture"), (document.pictureInPictureEnabled || window.Windows && Windows.UI.ViewManagement.ApplicationView.getForCurrentView().isViewModeSupported(Windows.UI.ViewManagement.ApplicationViewMode.compactOverlay)) && list.push("PictureInPicture"), list.push("SetBrightness"), Modernizr.objectfit && list.push("SetAspectRatio"), list.push("SetSubtitleOffset"), list.push("SetPlaybackRate"), supportedFeatures = list), -1 !== supportedFeatures.indexOf(feature)
	}, HtmlVideoPlayer.prototype.canSetAudioStreamIndex = function(index) {
		if (browser.tizen || browser.orsay) return !0;
		if (browser.web0s && browser.sdkVersion && browser.sdkVersion < 3) return !1;
		var video = this._mediaElement;
		return !(!video || !video.audioTracks)
	}, HtmlVideoPlayer.prototype.setPictureInPictureEnabled = function(isEnabled) {
		var video = this._mediaElement;
		document.pictureInPictureEnabled ? video && (isEnabled ? video.requestPictureInPicture().
		catch (onPictureInPictureError) : document.exitPictureInPicture().
		catch (onPictureInPictureError)) : window.Windows ? (this.isPip = isEnabled) ? Windows.UI.ViewManagement.ApplicationView.getForCurrentView().tryEnterViewModeAsync(Windows.UI.ViewManagement.ApplicationViewMode.compactOverlay) : Windows.UI.ViewManagement.ApplicationView.getForCurrentView().tryEnterViewModeAsync(Windows.UI.ViewManagement.ApplicationViewMode.
	default) : video && video.webkitSupportsPresentationMode && "function" == typeof video.webkitSetPresentationMode && video.webkitSetPresentationMode(isEnabled ? "picture-in-picture" : "inline")
	}, HtmlVideoPlayer.prototype.isPictureInPictureEnabled = function() {
		if (document.pictureInPictureEnabled) return !!document.pictureInPictureElement;
		if (window.Windows) return this.isPip || !1;
		var video = this._mediaElement;
		return !!video && "picture-in-picture" === video.webkitPresentationMode
	}, HtmlVideoPlayer.prototype.setBrightness = function(val) {
		var rawValue, cssValue, elem = this._mediaElement;
		elem && (val = Math.max(0, val), rawValue = val = Math.min(100, val), cssValue = 100 <= (rawValue = Math.max(20, rawValue)) ? "none" : rawValue / 100, elem.style["-webkit-filter"] = "brightness(" + cssValue + ");", elem.style.filter = "brightness(" + cssValue + ")", elem.brightnessValue = val, events.trigger(this, "brightnesschange"))
	}, HtmlVideoPlayer.prototype.getBrightness = function() {
		var elem = this._mediaElement;
		if (elem) {
			var val = elem.brightnessValue;
			return null == val ? 100 : val
		}
	}, HtmlVideoPlayer.prototype.setAspectRatio = function(val) {
		var mediaElement = this._mediaElement;
		mediaElement && ("auto" === val ? mediaElement.style.removeProperty("object-fit") : mediaElement.style["object-fit"] = val), this._currentAspectRatio = val
	}, HtmlVideoPlayer.prototype.getAspectRatio = function() {
		return this._currentAspectRatio || "auto"
	}, HtmlVideoPlayer.prototype.getSupportedAspectRatios = function() {
		return [{
			name: globalize.translate("Auto"),
			id: "auto"
		}, {
			name: globalize.translate("Cover"),
			id: "cover"
		}, {
			name: globalize.translate("Fill"),
			id: "fill"
		}]
	}, HtmlVideoPlayer.prototype.getSubtitleOffset = function(val) {
		return this._currentSubtitleOffset
	}, HtmlVideoPlayer.prototype.setSubtitleOffset = function(val) {
		var elem = this._mediaElement;
		elem && (this._currentSubtitleOffset = val, setSubtitleOffset(this, elem, val))
	}, HtmlVideoPlayer.prototype.incrementSubtitleOffset = function(val) {
		var newVal, elem = this._mediaElement;
		elem && (newVal = this._currentSubtitleOffset + val, this._currentSubtitleOffset = newVal, setSubtitleOffset(this, elem, newVal))
	}, HtmlVideoPlayer.prototype.togglePictureInPicture = function() {
		return this.setPictureInPictureEnabled(!this.isPictureInPictureEnabled())
	}, HtmlVideoPlayer.prototype.getStats = function() {
		var mediaElement = this._mediaElement,
			playOptions = this._currentPlayOptions || [],
			categories = [];
		if (!mediaElement) return Promise.resolve({
			categories: categories
		});
		var link, protocol, mediaCategory = {
			stats: [],
			type: "media"
		};
		categories.push(mediaCategory), playOptions.url && ((link = document.createElement("a")).setAttribute("href", playOptions.url), (protocol = (link.protocol || "").replace(":", "")) && mediaCategory.stats.push({
			label: "&#x4F20;&#x8F93;&#x534F;&#x8BAE;:",
			value: protocol
		}), link = null), this._hlsPlayer || this._shakaPlayer ? mediaCategory.stats.push({
			label: "&#x4E32;&#x6D41;&#x7C7B;&#x578B;:",
			value: "HLS"
		}) : mediaCategory.stats.push({
			label: "&#x4E32;&#x6D41;&#x7C7B;&#x578B;:",
			value: "Video"
		});
		var videoCategory = {
			stats: [],
			type: "video"
		};
		categories.push(videoCategory);
		var playbackQuality, droppedVideoFrames, corruptedVideoFrames, height = mediaElement.videoHeight,
			width = mediaElement.videoWidth;
		return width && height && videoCategory.stats.push({
			label: "&#x89C6;&#x9891;&#x5206;&#x8FA8;&#x7387;:",
			value: width + "x" + height
		}), mediaElement.getVideoPlaybackQuality && (droppedVideoFrames = (playbackQuality = mediaElement.getVideoPlaybackQuality()).droppedVideoFrames || 0, videoCategory.stats.push({
			label: "&#x4E22;&#x5E27;&#x6570;&#x91CF;:",
			value: droppedVideoFrames
		}), corruptedVideoFrames = playbackQuality.corruptedVideoFrames || 0, videoCategory.stats.push({
			label: "&#x635F;&#x574F;&#x7684;&#x5E27;:",
			value: corruptedVideoFrames
		})), Promise.resolve({
			categories: categories
		})
	}, HtmlVideoPlayer
});
