UNPKG

vue-ue-sdk

Version:

基于vue2实现的ue sdk

2,456 lines 97.3 kB
function ownKeys(object, enumerableOnly) {
  var keys = Object.keys(object);

  if (Object.getOwnPropertySymbols) {
    var symbols = Object.getOwnPropertySymbols(object);
    enumerableOnly && (symbols = symbols.filter(function (sym) {
      return Object.getOwnPropertyDescriptor(object, sym).enumerable;
    })), keys.push.apply(keys, symbols);
  }

  return keys;
}

function _objectSpread2(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = null != arguments[i] ? arguments[i] : {};
    i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
      _defineProperty(target, key, source[key]);
    }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
      Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
    });
  }

  return target;
}

function _regeneratorRuntime() {
  /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */

  _regeneratorRuntime = function () {
    return exports;
  };

  var exports = {},
      Op = Object.prototype,
      hasOwn = Op.hasOwnProperty,
      $Symbol = "function" == typeof Symbol ? Symbol : {},
      iteratorSymbol = $Symbol.iterator || "@@iterator",
      asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
      toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";

  function define(obj, key, value) {
    return Object.defineProperty(obj, key, {
      value: value,
      enumerable: !0,
      configurable: !0,
      writable: !0
    }), obj[key];
  }

  try {
    define({}, "");
  } catch (err) {
    define = function (obj, key, value) {
      return obj[key] = value;
    };
  }

  function wrap(innerFn, outerFn, self, tryLocsList) {
    var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
        generator = Object.create(protoGenerator.prototype),
        context = new Context(tryLocsList || []);
    return generator._invoke = function (innerFn, self, context) {
      var state = "suspendedStart";
      return function (method, arg) {
        if ("executing" === state) throw new Error("Generator is already running");

        if ("completed" === state) {
          if ("throw" === method) throw arg;
          return doneResult();
        }

        for (context.method = method, context.arg = arg;;) {
          var delegate = context.delegate;

          if (delegate) {
            var delegateResult = maybeInvokeDelegate(delegate, context);

            if (delegateResult) {
              if (delegateResult === ContinueSentinel) continue;
              return delegateResult;
            }
          }

          if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
            if ("suspendedStart" === state) throw state = "completed", context.arg;
            context.dispatchException(context.arg);
          } else "return" === context.method && context.abrupt("return", context.arg);
          state = "executing";
          var record = tryCatch(innerFn, self, context);

          if ("normal" === record.type) {
            if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
            return {
              value: record.arg,
              done: context.done
            };
          }

          "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
        }
      };
    }(innerFn, self, context), generator;
  }

  function tryCatch(fn, obj, arg) {
    try {
      return {
        type: "normal",
        arg: fn.call(obj, arg)
      };
    } catch (err) {
      return {
        type: "throw",
        arg: err
      };
    }
  }

  exports.wrap = wrap;
  var ContinueSentinel = {};

  function Generator() {}

  function GeneratorFunction() {}

  function GeneratorFunctionPrototype() {}

  var IteratorPrototype = {};
  define(IteratorPrototype, iteratorSymbol, function () {
    return this;
  });
  var getProto = Object.getPrototypeOf,
      NativeIteratorPrototype = getProto && getProto(getProto(values([])));
  NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
  var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);

  function defineIteratorMethods(prototype) {
    ["next", "throw", "return"].forEach(function (method) {
      define(prototype, method, function (arg) {
        return this._invoke(method, arg);
      });
    });
  }

  function AsyncIterator(generator, PromiseImpl) {
    function invoke(method, arg, resolve, reject) {
      var record = tryCatch(generator[method], generator, arg);

      if ("throw" !== record.type) {
        var result = record.arg,
            value = result.value;
        return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
          invoke("next", value, resolve, reject);
        }, function (err) {
          invoke("throw", err, resolve, reject);
        }) : PromiseImpl.resolve(value).then(function (unwrapped) {
          result.value = unwrapped, resolve(result);
        }, function (error) {
          return invoke("throw", error, resolve, reject);
        });
      }

      reject(record.arg);
    }

    var previousPromise;

    this._invoke = function (method, arg) {
      function callInvokeWithMethodAndArg() {
        return new PromiseImpl(function (resolve, reject) {
          invoke(method, arg, resolve, reject);
        });
      }

      return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
    };
  }

  function maybeInvokeDelegate(delegate, context) {
    var method = delegate.iterator[context.method];

    if (undefined === method) {
      if (context.delegate = null, "throw" === context.method) {
        if (delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method)) return ContinueSentinel;
        context.method = "throw", context.arg = new TypeError("The iterator does not provide a 'throw' method");
      }

      return ContinueSentinel;
    }

    var record = tryCatch(method, delegate.iterator, context.arg);
    if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
    var info = record.arg;
    return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
  }

  function pushTryEntry(locs) {
    var entry = {
      tryLoc: locs[0]
    };
    1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
  }

  function resetTryEntry(entry) {
    var record = entry.completion || {};
    record.type = "normal", delete record.arg, entry.completion = record;
  }

  function Context(tryLocsList) {
    this.tryEntries = [{
      tryLoc: "root"
    }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
  }

  function values(iterable) {
    if (iterable) {
      var iteratorMethod = iterable[iteratorSymbol];
      if (iteratorMethod) return iteratorMethod.call(iterable);
      if ("function" == typeof iterable.next) return iterable;

      if (!isNaN(iterable.length)) {
        var i = -1,
            next = function next() {
          for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;

          return next.value = undefined, next.done = !0, next;
        };

        return next.next = next;
      }
    }

    return {
      next: doneResult
    };
  }

  function doneResult() {
    return {
      value: undefined,
      done: !0
    };
  }

  return GeneratorFunction.prototype = GeneratorFunctionPrototype, define(Gp, "constructor", GeneratorFunctionPrototype), define(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
    var ctor = "function" == typeof genFun && genFun.constructor;
    return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
  }, exports.mark = function (genFun) {
    return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
  }, exports.awrap = function (arg) {
    return {
      __await: arg
    };
  }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
    return this;
  }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
    void 0 === PromiseImpl && (PromiseImpl = Promise);
    var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
    return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
      return result.done ? result.value : iter.next();
    });
  }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
    return this;
  }), define(Gp, "toString", function () {
    return "[object Generator]";
  }), exports.keys = function (object) {
    var keys = [];

    for (var key in object) keys.push(key);

    return keys.reverse(), function next() {
      for (; keys.length;) {
        var key = keys.pop();
        if (key in object) return next.value = key, next.done = !1, next;
      }

      return next.done = !0, next;
    };
  }, exports.values = values, Context.prototype = {
    constructor: Context,
    reset: function (skipTempReset) {
      if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
    },
    stop: function () {
      this.done = !0;
      var rootRecord = this.tryEntries[0].completion;
      if ("throw" === rootRecord.type) throw rootRecord.arg;
      return this.rval;
    },
    dispatchException: function (exception) {
      if (this.done) throw exception;
      var context = this;

      function handle(loc, caught) {
        return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
      }

      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i],
            record = entry.completion;
        if ("root" === entry.tryLoc) return handle("end");

        if (entry.tryLoc <= this.prev) {
          var hasCatch = hasOwn.call(entry, "catchLoc"),
              hasFinally = hasOwn.call(entry, "finallyLoc");

          if (hasCatch && hasFinally) {
            if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
            if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
          } else if (hasCatch) {
            if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
          } else {
            if (!hasFinally) throw new Error("try statement without catch or finally");
            if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
          }
        }
      }
    },
    abrupt: function (type, arg) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];

        if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
          var finallyEntry = entry;
          break;
        }
      }

      finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
      var record = finallyEntry ? finallyEntry.completion : {};
      return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
    },
    complete: function (record, afterLoc) {
      if ("throw" === record.type) throw record.arg;
      return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
    },
    finish: function (finallyLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
      }
    },
    catch: function (tryLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];

        if (entry.tryLoc === tryLoc) {
          var record = entry.completion;

          if ("throw" === record.type) {
            var thrown = record.arg;
            resetTryEntry(entry);
          }

          return thrown;
        }
      }

      throw new Error("illegal catch attempt");
    },
    delegateYield: function (iterable, resultName, nextLoc) {
      return this.delegate = {
        iterator: values(iterable),
        resultName: resultName,
        nextLoc: nextLoc
      }, "next" === this.method && (this.arg = undefined), ContinueSentinel;
    }
  }, exports;
}

function _typeof(obj) {
  "@babel/helpers - typeof";

  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
    return typeof obj;
  } : function (obj) {
    return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  }, _typeof(obj);
}

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }

  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}

function _asyncToGenerator(fn) {
  return function () {
    var self = this,
        args = arguments;
    return new Promise(function (resolve, reject) {
      var gen = fn.apply(self, args);

      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
      }

      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
      }

      _next(undefined);
    });
  };
}

function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }

  return obj;
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === "Object" && o.constructor) n = o.constructor.name;
  if (n === "Map" || n === "Set") return Array.from(o);
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;

  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

  return arr2;
}

function _createForOfIteratorHelper(o, allowArrayLike) {
  var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];

  if (!it) {
    if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
      if (it) o = it;
      var i = 0;

      var F = function () {};

      return {
        s: F,
        n: function () {
          if (i >= o.length) return {
            done: true
          };
          return {
            done: false,
            value: o[i++]
          };
        },
        e: function (e) {
          throw e;
        },
        f: F
      };
    }

    throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  var normalCompletion = true,
      didErr = false,
      err;
  return {
    s: function () {
      it = it.call(o);
    },
    n: function () {
      var step = it.next();
      normalCompletion = step.done;
      return step;
    },
    e: function (e) {
      didErr = true;
      err = e;
    },
    f: function () {
      try {
        if (!normalCompletion && it.return != null) it.return();
      } finally {
        if (didErr) throw err;
      }
    }
  };
}

function webRtcPlayer(parOptions) {
    parOptions = typeof parOptions !== 'undefined' ? parOptions : {};
    var self = this;
    var urlParams = new URLSearchParams(window.location.search);
    this.cfg = typeof parOptions.peerConnectionOptions !== 'undefined' ? parOptions.peerConnectionOptions : {};
    this.cfg.sdpSemantics = 'unified-plan';
    this.cfg.offerExtmapAllowMixed = false;
    this.forceTURN = urlParams.has('ForceTURN');
    if (this.forceTURN) {
        console.log('Forcing TURN usage by setting ICE Transport Policy in peer connection config.');
        this.cfg.iceTransportPolicy = 'relay';
    }
    this.cfg.bundlePolicy = 'balanced';
    this.forceMaxBundle = urlParams.has('ForceMaxBundle');
    if (this.forceMaxBundle) {
        this.cfg.bundlePolicy = 'max-bundle';
    }
    this.pcClient = null;
    this.dcClient = null;
    this.tnClient = null;
    this.sdpConstraints = {
        offerToReceiveAudio: 1,
        offerToReceiveVideo: 1,
        voiceActivityDetection: false
    };
    this.dataChannelOptions = { ordered: true };
    this.startVideoMuted = typeof parOptions.startVideoMuted !== 'undefined' ? parOptions.startVideoMuted : false;
    this.autoPlayAudio = typeof parOptions.autoPlayAudio !== 'undefined' ? parOptions.autoPlayAudio : true;
    this.useMic = urlParams.has('useMic');
    if (!this.useMic) {
        console.log('Microphone access is not enabled. Pass ?useMic in the url to enable it.');
    }
    var isLocalhostConnection = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
    var isHttpsConnection = location.protocol === 'https:';
    if (this.useMic && !isLocalhostConnection && !isHttpsConnection) {
        this.useMic = false;
        console.error('Microphone access in the browser will not work if you are not on HTTPS or localhost. Disabling mic access.');
        console.error('For testing you can enable HTTP microphone access Chrome by visiting chrome://flags/ and enabling \'unsafely-treat-insecure-origin-as-secure\'');
    }
    this.preferSFU = urlParams.has('preferSFU');
    console.log(this.preferSFU ? 'The browser will signal it would prefer an SFU connection. Remove ?preferSFU from the url to signal for P2P usage.' : 'The browser will signal for a P2P connection. Pass ?preferSFU in the url to signal for SFU usage.');
    this.latencyTestTimings = {
        TestStartTimeMs: null,
        UEReceiptTimeMs: null,
        UEEncodeMs: null,
        UECaptureToSendMs: null,
        UETransmissionTimeMs: null,
        BrowserReceiptTimeMs: null,
        FrameDisplayDeltaTimeMs: null,
        Reset: function Reset() {
            this.TestStartTimeMs = null;
            this.UEReceiptTimeMs = null;
            this.UEEncodeMs = null, this.UECaptureToSendMs = null, this.UETransmissionTimeMs = null;
            this.BrowserReceiptTimeMs = null;
            this.FrameDisplayDeltaTimeMs = null;
        },
        SetUETimings: function SetUETimings(UETimings) {
            this.UEReceiptTimeMs = UETimings.ReceiptTimeMs;
            this.UEEncodeMs = UETimings.EncodeMs, this.UECaptureToSendMs = UETimings.CaptureToSendMs, this.UETransmissionTimeMs = UETimings.TransmissionTimeMs;
            this.BrowserReceiptTimeMs = Date.now();
            this.OnAllLatencyTimingsReady(this);
        },
        SetFrameDisplayDeltaTime: function SetFrameDisplayDeltaTime(DeltaTimeMs) {
            if (this.FrameDisplayDeltaTimeMs == null) {
                this.FrameDisplayDeltaTimeMs = Math.round(DeltaTimeMs);
                this.OnAllLatencyTimingsReady(this);
            }
        },
        OnAllLatencyTimingsReady: function OnAllLatencyTimingsReady(Timings) {
        }
    };
    this.createWebRtcVideo = function () {
        var video = document.getElementById('streamingVideo');
        video.muted = 'muted';
        video.addEventListener('loadedmetadata', function (e) {
            if (self.onVideoInitialised) {
                self.onVideoInitialised();
            }
        }, true);
        if ('requestVideoFrameCallback' in HTMLVideoElement.prototype) {
            var onVideoFrameReady = function onVideoFrameReady(now, metadata) {
                if (metadata.receiveTime && metadata.expectedDisplayTime) {
                    var receiveToCompositeMs = metadata.presentationTime - metadata.receiveTime;
                    self.aggregatedStats.receiveToCompositeMs = receiveToCompositeMs;
                }
                video.requestVideoFrameCallback(onVideoFrameReady);
            };
            video.requestVideoFrameCallback(onVideoFrameReady);
        }
        return video;
    };
    this.video = this.createWebRtcVideo();
    this.availableVideoStreams = new Map();
    var onsignalingstatechange = function onsignalingstatechange(state) {
        console.info('Signaling state change. |', state.srcElement.signalingState, '|');
    };
    var oniceconnectionstatechange = function oniceconnectionstatechange(state) {
        console.info('Browser ICE connection |', state.srcElement.iceConnectionState, '|');
    };
    var onicegatheringstatechange = function onicegatheringstatechange(state) {
        console.info('Browser ICE gathering |', state.srcElement.iceGatheringState, '|');
    };
    var handleOnTrack = function handleOnTrack(e) {
        if (e.track) {
            console.log('Got track. | Kind=' + e.track.kind + ' | Id=' + e.track.id + ' | readyState=' + e.track.readyState + ' |');
        }
        if (e.track.kind == 'audio') {
            handleOnAudioTrack(e.streams[0]);
            return;
        } else
            e.track.kind == 'video';
        {
            var _iterator = _createForOfIteratorHelper(e.streams), _step;
            try {
                for (_iterator.s(); !(_step = _iterator.n()).done;) {
                    var s = _step.value;
                    if (!self.availableVideoStreams.has(s.id)) {
                        self.availableVideoStreams.set(s.id, s);
                    }
                }
            } catch (err) {
                _iterator.e(err);
            } finally {
                _iterator.f();
            }
            self.video.srcObject = e.streams[0];
            e.track.onunmute = function () {
                self.video.srcObject = e.streams[0];
                self.onNewVideoTrack(e.streams);
            };
        }
    };
    var handleOnAudioTrack = function handleOnAudioTrack(audioMediaStream) {
        if (self.video.srcObject == audioMediaStream) {
            return;
        } else if (self.video.srcObject && self.video.srcObject !== audioMediaStream) {
            var audioElem = document.createElement('Audio');
            audioElem.srcObject = audioMediaStream;
            if (!self.autoPlayAudio) {
                var clickToPlayAudio = function clickToPlayAudio() {
                    audioElem.play();
                    self.video.removeEventListener('click', clickToPlayAudio);
                };
                self.video.addEventListener('click', clickToPlayAudio);
            } else {
                audioElem.play();
            }
            console.log('Created new audio element to play seperate audio stream.');
        }
    };
    var onDataChannel = function onDataChannel(dataChannelEvent) {
        console.log('Data channel created for us by browser as we are a receiving peer.');
        self.dcClient = dataChannelEvent.channel;
        setupDataChannelCallbacks(self.dcClient);
    };
    var createDataChannel = function createDataChannel(pc, label, options) {
        var datachannel = pc.createDataChannel(label, options);
        console.log('Created datachannel ('.concat(label, ')'));
        setupDataChannelCallbacks(datachannel);
        return datachannel;
    };
    var setupDataChannelCallbacks = function setupDataChannelCallbacks(datachannel) {
        try {
            datachannel.binaryType = 'arraybuffer';
            datachannel.onopen = function (e) {
                console.log('Data channel connected');
                if (self.onDataChannelConnected) {
                    self.onDataChannelConnected();
                }
            };
            datachannel.onclose = function (e) {
                console.log('Data channel connected', e);
            };
            datachannel.onmessage = function (e) {
                if (self.onDataChannelMessage) {
                    self.onDataChannelMessage(e.data);
                }
            };
            datachannel.onerror = function (e) {
                console.error('Data channel error', e);
            };
            return datachannel;
        } catch (e) {
            console.warn('No data channel', e);
            return null;
        }
    };
    var onicecandidate = function onicecandidate(e) {
        var candidate = e.candidate;
        if (candidate && candidate.candidate) {
            console.log('%c[Browser ICE candidate]', 'background: violet; color: black', '| Type=', candidate.type, '| Protocol=', candidate.protocol, '| Address=', candidate.address, '| Port=', candidate.port, '|');
            self.onWebRtcCandidate(candidate);
        }
    };
    var handleCreateOffer = function handleCreateOffer(pc) {
        pc.createOffer(self.sdpConstraints).then(function (offer) {
            mungeSDPOffer(offer);
            pc.setLocalDescription(offer);
            if (self.onWebRtcOffer) {
                self.onWebRtcOffer(offer);
            }
        }, function () {
            console.warn('Couldn\'t create offer');
        });
    };
    var mungeSDPOffer = function mungeSDPOffer(offer) {
        offer.sdp = offer.sdp.replace('useinbandfec=1', 'useinbandfec=1;stereo=1;sprop-maxcapturerate=48000');
    };
    var setupPeerConnection = function setupPeerConnection(pc) {
        pc.onsignalingstatechange = onsignalingstatechange;
        pc.oniceconnectionstatechange = oniceconnectionstatechange;
        pc.onicegatheringstatechange = onicegatheringstatechange;
        pc.ontrack = handleOnTrack;
        pc.onicecandidate = onicecandidate;
        pc.ondatachannel = onDataChannel;
    };
    var generateAggregatedStatsFunction = function generateAggregatedStatsFunction() {
        if (!self.aggregatedStats)
            self.aggregatedStats = {};
        return function (stats) {
            var newStat = {};
            stats.forEach(function (stat) {
                if (stat.type == 'inbound-rtp' && !stat.isRemote && (stat.mediaType == 'video' || stat.id.toLowerCase().includes('video'))) {
                    newStat.timestamp = stat.timestamp;
                    newStat.bytesReceived = stat.bytesReceived;
                    newStat.framesDecoded = stat.framesDecoded;
                    newStat.packetsLost = stat.packetsLost;
                    newStat.bytesReceivedStart = self.aggregatedStats && self.aggregatedStats.bytesReceivedStart ? self.aggregatedStats.bytesReceivedStart : stat.bytesReceived;
                    newStat.framesDecodedStart = self.aggregatedStats && self.aggregatedStats.framesDecodedStart ? self.aggregatedStats.framesDecodedStart : stat.framesDecoded;
                    newStat.timestampStart = self.aggregatedStats && self.aggregatedStats.timestampStart ? self.aggregatedStats.timestampStart : stat.timestamp;
                    if (self.aggregatedStats && self.aggregatedStats.timestamp) {
                        if (self.aggregatedStats.bytesReceived) {
                            newStat.bitrate = 8 * (newStat.bytesReceived - self.aggregatedStats.bytesReceived) / (newStat.timestamp - self.aggregatedStats.timestamp);
                            newStat.bitrate = Math.floor(newStat.bitrate);
                            newStat.lowBitrate = self.aggregatedStats.lowBitrate && self.aggregatedStats.lowBitrate < newStat.bitrate ? self.aggregatedStats.lowBitrate : newStat.bitrate;
                            newStat.highBitrate = self.aggregatedStats.highBitrate && self.aggregatedStats.highBitrate > newStat.bitrate ? self.aggregatedStats.highBitrate : newStat.bitrate;
                        }
                        if (self.aggregatedStats.bytesReceivedStart) {
                            newStat.avgBitrate = 8 * (newStat.bytesReceived - self.aggregatedStats.bytesReceivedStart) / (newStat.timestamp - self.aggregatedStats.timestampStart);
                            newStat.avgBitrate = Math.floor(newStat.avgBitrate);
                        }
                        if (self.aggregatedStats.framesDecoded) {
                            newStat.framerate = (newStat.framesDecoded - self.aggregatedStats.framesDecoded) / ((newStat.timestamp - self.aggregatedStats.timestamp) / 1000);
                            newStat.framerate = Math.floor(newStat.framerate);
                            newStat.lowFramerate = self.aggregatedStats.lowFramerate && self.aggregatedStats.lowFramerate < newStat.framerate ? self.aggregatedStats.lowFramerate : newStat.framerate;
                            newStat.highFramerate = self.aggregatedStats.highFramerate && self.aggregatedStats.highFramerate > newStat.framerate ? self.aggregatedStats.highFramerate : newStat.framerate;
                        }
                        if (self.aggregatedStats.framesDecodedStart) {
                            newStat.avgframerate = (newStat.framesDecoded - self.aggregatedStats.framesDecodedStart) / ((newStat.timestamp - self.aggregatedStats.timestampStart) / 1000);
                            newStat.avgframerate = Math.floor(newStat.avgframerate);
                        }
                    }
                }
                if (stat.type == 'track' && (stat.trackIdentifier == 'video_label' || stat.kind == 'video')) {
                    newStat.framesDropped = stat.framesDropped;
                    newStat.framesReceived = stat.framesReceived;
                    newStat.framesDroppedPercentage = stat.framesDropped / stat.framesReceived * 100;
                    newStat.frameHeight = stat.frameHeight;
                    newStat.frameWidth = stat.frameWidth;
                    newStat.frameHeightStart = self.aggregatedStats && self.aggregatedStats.frameHeightStart ? self.aggregatedStats.frameHeightStart : stat.frameHeight;
                    newStat.frameWidthStart = self.aggregatedStats && self.aggregatedStats.frameWidthStart ? self.aggregatedStats.frameWidthStart : stat.frameWidth;
                }
                if (stat.type == 'candidate-pair' && stat.hasOwnProperty('currentRoundTripTime') && stat.currentRoundTripTime != 0) {
                    newStat.currentRoundTripTime = stat.currentRoundTripTime;
                }
            });
            if (self.aggregatedStats.receiveToCompositeMs) {
                newStat.receiveToCompositeMs = self.aggregatedStats.receiveToCompositeMs;
                self.latencyTestTimings.SetFrameDisplayDeltaTime(self.aggregatedStats.receiveToCompositeMs);
            }
            self.aggregatedStats = newStat;
            if (self.onAggregatedStats)
                self.onAggregatedStats(newStat);
        };
    };
    var setupTransceiversAsync = function () {
        var _ref = _asyncToGenerator(_regeneratorRuntime().mark(function _callee(pc) {
            var hasTransceivers, audioSendOptions, stream, _iterator2, _step2, transceiver, _iterator3, _step3, track, _iterator4, _step4, _track;
            return _regeneratorRuntime().wrap(function _callee$(_context) {
                while (1) {
                    switch (_context.prev = _context.next) {
                    case 0:
                        hasTransceivers = pc.getTransceivers().length > 0;
                        pc.addTransceiver('video', { direction: 'recvonly' });
                        if (self.useMic) {
                            _context.next = 6;
                            break;
                        }
                        pc.addTransceiver('audio', { direction: 'recvonly' });
                        _context.next = 11;
                        break;
                    case 6:
                        audioSendOptions = self.useMic ? {
                            autoGainControl: false,
                            channelCount: 1,
                            echoCancellation: false,
                            latency: 0,
                            noiseSuppression: false,
                            sampleRate: 48000,
                            volume: 1
                        } : false;
                        _context.next = 9;
                        return navigator.mediaDevices.getUserMedia({
                            video: false,
                            audio: audioSendOptions
                        });
                    case 9:
                        stream = _context.sent;
                        if (stream) {
                            if (hasTransceivers) {
                                _iterator2 = _createForOfIteratorHelper(pc.getTransceivers());
                                try {
                                    for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
                                        transceiver = _step2.value;
                                        if (transceiver && transceiver.receiver && transceiver.receiver.track && transceiver.receiver.track.kind === 'audio') {
                                            _iterator3 = _createForOfIteratorHelper(stream.getTracks());
                                            try {
                                                for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
                                                    track = _step3.value;
                                                    if (track.kind && track.kind == 'audio') {
                                                        transceiver.sender.replaceTrack(track);
                                                        transceiver.direction = 'sendrecv';
                                                    }
                                                }
                                            } catch (err) {
                                                _iterator3.e(err);
                                            } finally {
                                                _iterator3.f();
                                            }
                                        }
                                    }
                                } catch (err) {
                                    _iterator2.e(err);
                                } finally {
                                    _iterator2.f();
                                }
                            } else {
                                _iterator4 = _createForOfIteratorHelper(stream.getTracks());
                                try {
                                    for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
                                        _track = _step4.value;
                                        if (_track.kind && _track.kind == 'audio') {
                                            pc.addTransceiver(_track, { direction: 'sendrecv' });
                                        }
                                    }
                                } catch (err) {
                                    _iterator4.e(err);
                                } finally {
                                    _iterator4.f();
                                }
                            }
                        } else {
                            pc.addTransceiver('audio', { direction: 'recvonly' });
                        }
                    case 11:
                    case 'end':
                        return _context.stop();
                    }
                }
            }, _callee);
        }));
        return function setupTransceiversAsync(_x) {
            return _ref.apply(this, arguments);
        };
    }();
    this.setVideoEnabled = function (enabled) {
        self.video.srcObject.getTracks().forEach(function (track) {
            return track.enabled = enabled;
        });
    };
    this.startLatencyTest = function (onTestStarted) {
        if (!self.video) {
            return;
        }
        self.latencyTestTimings.Reset();
        self.latencyTestTimings.TestStartTimeMs = Date.now();
        onTestStarted(self.latencyTestTimings.TestStartTimeMs);
    };
    this.handleCandidateFromServer = function (iceCandidate) {
        var candidate = new RTCIceCandidate(iceCandidate);
        console.log('%c[Unreal ICE candidate]', 'background: pink; color: black', '| Type=', candidate.type, '| Protocol=', candidate.protocol, '| Address=', candidate.address, '| Port=', candidate.port, '|');
        if (self.forceTURN) {
            if (candidate.candidate.indexOf('relay') < 0) {
                console.warn('Dropping candidate because it was not TURN relay.', '| Type=', candidate.type, '| Protocol=', candidate.protocol, '| Address=', candidate.address, '| Port=', candidate.port, '|');
                return;
            }
        }
        self.pcClient.addIceCandidate(candidate)['catch'](function (e) {
            console.error('Failed to add ICE candidate', e);
        });
    };
    this.createOffer = function () {
        if (self.pcClient) {
            console.log('Closing existing PeerConnection');
            self.pcClient.close();
            self.pcClient = null;
        }
        self.pcClient = new RTCPeerConnection(self.cfg);
        setupPeerConnection(self.pcClient);
        setupTransceiversAsync(self.pcClient)['finally'](function () {
            self.dcClient = createDataChannel(self.pcClient, 'cirrus', self.dataChannelOptions);
            handleCreateOffer(self.pcClient);
        });
    };
    this.receiveOffer = function (offer) {
        var offerDesc = new RTCSessionDescription(offer);
        if (!self.pcClient) {
            console.log('Creating a new PeerConnection in the browser.');
            self.pcClient = new RTCPeerConnection(self.cfg);
            setupPeerConnection(self.pcClient);
            self.pcClient.setRemoteDescription(offerDesc).then(function () {
                setupTransceiversAsync(self.pcClient)['finally'](function () {
                    self.pcClient.createAnswer().then(function (answer) {
                        return self.pcClient.setLocalDescription(answer);
                    }).then(function () {
                        if (self.onWebRtcAnswer) {
                            self.onWebRtcAnswer(self.pcClient.currentLocalDescription);
                        }
                    }).then(function () {
                        var receivers = self.pcClient.getReceivers();
                        var _iterator5 = _createForOfIteratorHelper(receivers), _step5;
                        try {
                            for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
                                var receiver = _step5.value;
                                receiver.playoutDelayHint = 0;
                            }
                        } catch (err) {
                            _iterator5.e(err);
                        } finally {
                            _iterator5.f();
                        }
                    })['catch'](function (error) {
                        return console.error('createAnswer() failed:', error);
                    });
                });
            });
        }
    };
    this.receiveAnswer = function (answer) {
        var answerDesc = new RTCSessionDescription(answer);
        self.pcClient.setRemoteDescription(answerDesc);
        var receivers = self.pcClient.getReceivers();
        var _iterator6 = _createForOfIteratorHelper(receivers), _step6;
        try {
            for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
                var receiver = _step6.value;
                receiver.playoutDelayHint = 0;
            }
        } catch (err) {
            _iterator6.e(err);
        } finally {
            _iterator6.f();
        }
    };
    this.close = function () {
        if (self.pcClient) {
            console.log('Closing existing peerClient');
            self.pcClient.close();
            self.pcClient = null;
        }
        if (self.aggregateStatsIntervalId)
            clearInterval(self.aggregateStatsIntervalId);
    };
    this.send = function (data) {
        if (self.dcClient && self.dcClient.readyState == 'open') {
            self.dcClient.send(data);
        }
    };
    this.getStats = function (onStats) {
        if (self.pcClient && onStats) {
            self.pcClient.getStats(null).then(function (stats) {
                onStats(stats);
            });
        }
    };
    this.aggregateStats = function (checkInterval) {
        var calcAggregatedStats = generateAggregatedStatsFunction();
        var printAggregatedStats = function printAggregatedStats() {
            self.getStats(calcAggregatedStats);
        };
        self.aggregateStatsIntervalId = setInterval(printAggregatedStats, checkInterval);
    };
}

function ajax(options) {
    var path = options.path, method = options.method, data = options.data;
    return new Promise(function (resolve, reject) {
        var request = new XMLHttpRequest();
        request.open(method, path);
        request.send(data);
        request.onreadystatechange = function () {
            if (request.readyState === 4) {
                if (request.status >= 200 && request.status < 300) {
                    resolve.call(undefined, JSON.parse(request.responseText));
                } else if (request.status >= 400) {
                    reject.call(undefined, request);
                }
            }
        };
    });
}

var haveEvents = 'GamepadEvent' in window;
var haveWebkitEvents = 'WebKitGamepadEvent' in window;
var controllers = {};
var rAF = window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.requestAnimationFrame;
var kbEvent = document.createEvent('KeyboardEvent');
typeof kbEvent.initKeyboardEvent !== 'undefined' ? 'initKeyboardEvent' : 'initKeyEvent';
var webRtcPlayerObj = null;
var ws;
var WS_OPEN_STATE = 1;
var lastTimeResized = new Date().getTime();
var resizeTimeout;
var onDataChannelConnected;
var responseEventListeners = new Map();
var freezeFrameOverlay = null;
var shouldShowPlayOverlay = true;
var freezeFrame = {
    receiving: false,
    size: 0,
    jpeg: undefined,
    height: 0,
    width: 0,
    valid: false
};
var file = {
    mimetype: '',
    extension: '',
    receiving: false,
    size: 0,
    data: [],
    valid: false,
    timestampStart: undefined
};
var afk = {
    enabled: true,
    warnTimeout: 120,
    closeTimeout: 30,
    active: false,
    overlay: undefined,
    warnTimer: undefined,
    countdown: 0,
    countdownTimer: undefined
};
var editTextButton = undefined;
var hiddenInput = undefined;
function scanGamepads() {
    var gamepads = navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : [];
    for (var i = 0; i < gamepads.length; i++) {
        if (gamepads[i] && gamepads[i].index in controllers) {
            controllers[gamepads[i].index].currentState = gamepads[i];
        }
    }
}
function updateStatus() {
    scanGamepads();
    for (j in controllers) {
        var controller = controllers[j];
        var currentState = controller.currentState;
        var prevState = controller.prevState;
        for (var i = 0; i < currentState.buttons.length; i++) {
            var currButton = currentState.buttons[i];
            var prevButton = prevState.buttons[i];
            if (currButton.pressed && !prevButton.pressed) {
                if (i == 6) {
                    emitControllerAxisMove(j, 5, currButton.value);
                } else if (i == 7) {
                    emitControllerAxisMove(j, 6, currButton.value);
                } else {
                    emitControllerButtonPressed(j, i, 0);
                }
            } else if (!currButton.pressed && prevButton.pressed) {
                if (i == 6) {
                    emitControllerAxisMove(j, 5, 0);
                } else if (i == 7) {
                    emitControllerAxisMove(j, 6, 0);
                } else {
                    emitControllerButtonReleased(j, i);
                }
            } else if (currButton.pressed && prevButton.pressed) {
                if (i == 6) {
                    emitControllerAxisMove(j, 5, currButton.value);
                } else if (i == 7) {
                    emitControllerAxisMove(j, 6, currButton.value);
                } else {
                    emitControllerButtonPressed(j, i, 1);
                }
            }
        }
        for (var _i = 0; _i < currentState.axes.length; _i += 2) {
            var x = parseFloat(currentState.axes[_i].toFixed(4));
            var y = -parseFloat(currentState.axes[_i + 1].toFixed(4));
            if (_i === 0) {
                emitControllerAxisMove(j, 1, x);
                emitControllerAxisMove(j, 2, y);
            } else if (_i === 2) {
                emitControllerAxisMove(j, 3, x);
                emitControllerAxisMove(j, 4, y);
            }
        }
        controllers[j].prevState = currentState;
    }
    rAF(updateStatus);
}
function emitControllerButtonPressed(controllerIndex, buttonIndex, isRepeat) {
    Data = new DataView(new ArrayBuffer(4));
    Data.setUint8(0, MessageType.GamepadButtonPressed);
    Data.setUint8(1, controllerIndex);
    Data.setUint8(2, buttonIndex);
    Data.setUint8(3, isRepeat);
}
function emitControllerButtonReleased(controllerIndex, buttonIndex) {
    Data = new DataView(new ArrayBuffer(3));
    Data.setUint8(0, MessageType.GamepadButtonReleased);
    Data.setUint8(1, controllerIndex);
    Data.setUint8(2, buttonIndex);
}
function emitControllerAxisMove(controllerIndex, axisIndex, analogValue) {
    Data = new DataView(new ArrayBuffer(11));
    Data.setUint8(0, MessageType.GamepadAnalog);
    Data.setUint8(1, controllerIndex);
    Data.setUint8(2, axisIndex);
    Data.setFloat64(3, analogValue, true);
    sendInputData(Data.buffer);
}
function gamepadConnectHandler(e) {
    console.log('Gamepad connect handler');
    gamepad = e.gamepad;
    controllers[gamepad.index] = {};
    controllers[gamepad.index].currentState = gamepad;
    controllers[gamepad.index].prevState = gamepad;
    console.log('gamepad: ' + gamepad.id + ' connected');
    rAF(updateStatus);
}
function gamepadDisconnectHandler(e) {
    console.log('Gamepad disconnect handler');
    console.log('gamepad: ' + e.gamepad.id + ' disconnected');
    delete controllers[e.gamepad.index];
}
function setupHtmlEvents() {
    window.addEventListener('resize', resizePlayerStyle, true);
    window.addEventListener('orientationchange', onOrientationChange);
    if (haveEvents) {
        window.addEventListener('gamepadconnected', gamepadConnectHandler);
        window.addEventListener('gamepaddisconnected', gamepadDisconnectHandler);
    } else if (haveWebkitEvents) {
        window.addEventListener('webkitgamepadconnected', gamepadConnectHandler);
        window.addEventListener('webkitgamepaddisconnected', gamepadDisconnectHandler);
    }
}
function setOverlay(htmlClass, htmlElement, onClickFunction) {
    var videoPlayOverlay = document.getElementById('videoPlayOverlay');
    if (!videoPlayOverlay) {
        var playerDiv = document.getElementById('player');
        videoPlayOverlay = document.createElement('div');
        videoPlayOverlay.id = 'videoPlayOverlay';
        playerDiv.appendChild(videoPlayOverlay);
    }
    while (videoPlayOverlay.lastChild) {
        videoPlayOverlay.removeChild(videoPlayOverlay.lastChild);
    }
    if (htmlElement)
        videoPlayOverlay.appendChild(htmlElement);
    if (onClickFunction) {
        videoPlayOverlay.addEventListener('click', function onOverlayClick(event) {
            onClickFunction(event);
            videoPlayOverlay.removeEventListener('click', onOverlayClick);
        });
    }
    var cl = videoPlayOverlay.classList;
    for (var i = cl.length - 1; i >= 0; i--) {
        cl.remove(cl[i]);
    }
    videoPlayOverlay.classList.add(htmlClass);
}
function showConnectOverlay() {
    setTimeout(function () {
        connect();
        startAfkWarningTimer();
    }, 300);
}
function showTextOverlay(text) {
    var textOverlay = document.createElement('div');
    textOverlay.id = 'messageOverlay';
    textOverlay.innerHTML = text ? text : '';
    setOverlay('textDisplayState', textOverlay);
}
function playVideoStream() {
    if (webRtcPlayerObj && webRtcPlayerObj.video) {
        webRtcPlayerObj.video.play()['catch'](function (onRejectedReason) {
            console.error(onRejectedReason);
            console.log('Browser does not support autoplaying video without interaction - to resolve this we are going to show the play button overlay.');
            showPlayOverlay();
        });
        requestInitialSettings();
        showFreezeFrameOverlay();
        hideOverlay();
    } else {
        console.error('Could not player video stream because webRtcPlayerObj.video was not valid.');
    }
}
function showPlayOverlay() {
    setTimeout(function () {
        if (webRtcPlayerObj) {
            playVideoStream();
        }
    }, 500);
}
function updateAfkOverlayText() {
    afk.overlay.innerHTML = '<center>没有检测到活跃状态\uFF0C自动断开连接计时 ' + afk.countdown + ' s,点击继续连接</center>';
}
function showAfkOverlay() {
    stopAfkWarningTimer();
    afk.overlay = document.createElement('div');
    afk.overlay.id = 'afkOverlay';
    afk.overlay.style = 'position: relative;text-align: center;z-index:1000;';
    setOverlay('clickableState', afk.overlay, function (event) {
        hideOverlay();
        clearInterval(afk.countdownTimer);
        startAfkWarningTimer();
    });
    afk.countdown = afk.closeTimeout;
    updateAfkOverlayText();
    afk.countdownTimer = setInterval(function () {
        afk.countdown--;
        if (afk.countdown == 0) {
            clearInterval(afk.countdownTimer);
            hideOverlay();
            ws.close();
        } else {
            updateAfkOverlayText();
        }
    }, 1000);
}
function hideOverlay() {
    setOverlay('hiddenState');
}
function startAfkWarningTimer() {
    afk.active = afk.enabled;
    resetAfkWarningTimer();
}
function stopAfkWarningTimer() {
    afk.active = false;
}
function resetAfkWarningTimer() {
    if (afk.active) {
        clearTimeout(afk.warnTimer);
        afk.warnTimer = setTimeout(function () {
            showAfkOverlay();
        }, afk.warnTimeout * 1000);
    }
}
function sendInputData(data) {
    if (webRtcPlayerObj) {
        resetAfkWarningTimer();
        webRtcPlayerObj.send(data);
    }
}
var ToClientMessageType = {
    QualityControlOwnership: 0,
    Response: 1,
    Command: 2,
    FreezeFrame: 3,
    UnfreezeFrame: 4,
    VideoEncoderAvgQP: 5,
    LatencyTest: 6,
    InitialSettings: 7,
    FileExtension: 8,
    FileMimeType: 9,
    FileContents: 10
};
function setupWebRtcPlayer(htmlElement, config) {
    webRtcPlayerObj = new webRtcPlayer(config);
    htmlElement.appendChild(webRtcPlayerObj.video);
    htmlElement.appendChild(freezeFrameOverlay);
    webRtcPlayerObj.onWebRtcOffer = function (offer) {
        if (ws && ws.readyState === WS_OPEN_STATE) {
            var offerStr = JSON.stringify(offer);
            console.log('%c[Outbound SS message (offer)]', 'background: lightgreen; color: black', offer);
            ws.send(offerStr);
        }
    };
    webRtcPlayerObj.onWebRtcCandidate = function (candidate) {
        if (ws && ws.readyState === WS_OPEN_STATE) {
            ws.send(JSON.stringify({
                type: 'iceCandidate',
                candidate: candidate
            }));
        }
    };
    webRtcPlayerObj.onWebRtcAnswer = function (answer) {
        if (ws && ws.readyState === WS_OPEN_STATE) {
            var answerStr = JSON.stringify(answer);
            console.log('%c[Outbound SS message (answer)]', 'background: lightgreen; color: black', answer);
            ws.send(answerStr);
        }
    };
    webRtcPlayerObj.onVideoInitialised = function () {
        if (ws && ws.readyState === WS_OPEN_STATE) {
            if (shouldShowPlayOverlay) {
                showPlayOverlay();
                resizePlayerStyle();
            } else {
                resizePlayerStyle();
                playVideoStream();
            }
        }
    };
    webRtcPlayerObj.onDataChannelConnected = function () {
        if (onDataChannelConnected) {
            onDataChannelConnected();
        }
        if (ws && ws.readyState === WS_OPEN_STATE) {
            showTextOverlay('WebRTC data channel connected... waiting for video');
        }
    };
    function showFreezeFrame() {
        var base64 = btoa(freezeFrame.jpeg.reduce(function (data, _byte) {
            return data + String.fromCharCode(_byte);
        }, ''));
        var freezeFrameImage = document.getElementById('freezeFrameOverlay').childNodes[0];
        freezeFrameImage.src = 'data:image/jpeg;base64,' + base64;
        freezeFrameImage.onload = function () {
            freezeFrame.height = freezeFrameImage.naturalHeight;
            freezeFrame.width = freezeFrameImage.naturalWidth;
            resizeFreezeFrameOverlay();
            if (shouldShowPlayOverlay) {
                showPlayOverlay();
                resizePlayerStyle();
            } else {
                showFreezeFrameOverlay();
            }
            webRtcPlayerObj.setVideoEnabled(false);
        };
    }
    function processFileExtension(view) {
        if (!file.receiving) {
            file.mimetype = '';
            file.extension = '';
            file.receiving = true;
            file.valid = false;
            file.size = 0;
            file.data = [];
            file.timestampStart = new Date().getTime();
            console.log('Received first chunk of file');
        }
        var extensionAsString = new TextDecoder('utf-16').decode(view.slice(1));
        console.log(extensionAsString);
        file.extension = extensionAsString;
    }
    function processFileMimeType(view) {
        if (!file.receiving) {
            file.mimetype = '';
            file.extension = '';
            file.receiving = true;
            file.valid = false;
            file.size = 0;
            file.data = [];
            file.timestampStart = new Date().getTime();
            console.log('Received first chunk of file');
        }
        var mimeAsString = new TextDecoder('utf-16').decode(view.slice(1));
        console.log(mimeAsString);
        file.mimetype = mimeAsString;
    }
    function processFileContents(view) {
        if (!file.receiving)
            return;
        file.size = Math.ceil(new DataView(view.slice(1, 5).buffer).getInt32(0, true) / 16379);
        var fileBytes = view.slice(1 + 4);
        file.data.push(fileBytes);
        console.log('Received file chunk: '.concat(file.data.length, '/').concat(file.size));
        if (file.data.length === file.size) {
            file.receiving = false;
            file.valid = true;
            console.log('Received complete file');
            var transferDuration = new Date().getTime() - file.timestampStart;
            var transferBitrate = Math.round(file.size * 16 * 1024 / transferDuration);
            console.log('Average transfer bitrate: '.concat(transferBitrate, 'kb/s over ').concat(transferDuration / 1000, ' seconds'));
            var received = new Blob(file.data, { type: file.mimetype });
            var a = document.createElement('a');
            a.setAttribute('href', URL.createObjectURL(received));
            a.setAttribute('download', 'transfer.'.concat(file.extension));
            var aj = $(a);
            aj.appendTo('body');
            aj.remove();
        } else if (file.data.length > file.size) {
            file.receiving = false;
            console.error('Received bigger file than advertised: '.concat(file.data.length, '/').concat(file.size));
        }
    }
    function processFreezeFrameMessage(view) {
        if (!freezeFrame.receiving) {
            freezeFrame.receiving = true;
            freezeFrame.valid = false;
            freezeFrame.size = 0;
            freezeFrame.jpeg = undefined;
        }
        freezeFrame.size = new DataView(view.slice(1, 5).buffer).getInt32(0, true);
        var jpegBytes = view.slice(1 + 4);
        if (freezeFrame.jpeg) {
            var jpeg = new Uint8Array(freezeFrame.jpeg.length + jpegBytes.length);
            jpeg.set(freezeFrame.jpeg, 0);
            jpeg.set(jpegBytes, freezeFrame.jpeg.length);
            freezeFrame.jpeg = jpeg;
        } else {
            freezeFrame.jpeg = jpegBytes;
            freezeFrame.receiving = true;
            console.log('received first chunk of freeze frame: '.concat(freezeFrame.jpeg.length, '/').concat(freezeFrame.size));
        }
        if (freezeFrame.jpeg.length === freezeFrame.size) {
            freezeFrame.receiving = false;
            freezeFrame.valid = true;
            console.log('received complete freeze frame '.concat(freezeFrame.size));
            showFreezeFrame();
        } else if (freezeFrame.jpeg.length > freezeFrame.size) {
            console.error('received bigger freeze frame than advertised: '.concat(freezeFrame.jpeg.length, '/').concat(freezeFrame.size));
            freezeFrame.jpeg = undefined;
            freezeFrame.receiving = false;
        }
    }
    webRtcPlayerObj.onNewVideoTrack = function (streams) {
        if (webRtcPlayerObj.video && webRtcPlayerObj.video.srcObject && webRtcPlayerObj.onVideoInitialised) {
            webRtcPlayerObj.onVideoInitialised();
        }
    };
    webRtcPlayerObj.onDataChannelMessage = function (data) {
        var view = new Uint8Array(data);
        if (view[0] === ToClientMessageType.Response) {
            var response = new TextDecoder('utf-16').decode(data.slice(1));
            onResponse(response);
        } else if (view[0] === ToClientMessageType.Command) {
            var commandAsString = new TextDecoder('utf-16').decode(data.slice(1));
            console.log(commandAsString);
            var command = JSON.parse(commandAsString);
            if (command.command === 'onScreenKeyboard') {
                showOnScreenKeyboard(command);
            }
        } else if (view[0] === ToClientMessageType.FreezeFrame) {
            processFreezeFrameMessage(view);
        } else if (view[0] === ToClientMessageType.UnfreezeFrame) {
            invalidateFreezeFrameOverlay();
        } else if (view[0] === ToClientMessageType.VideoEncoderAvgQP) {
            new TextDecoder('utf-16').decode(data.slice(1));
        } else if (view[0] == ToClientMessageType.LatencyTest) {
            var latencyTimingsAsString = new TextDecoder('utf-16').decode(data.slice(1));
            console.log('Got latency timings from UE.');
            console.log(latencyTimingsAsString);
            var latencyTimingsFromUE = JSON.parse(latencyTimingsAsString);
            if (webRtcPlayerObj) {
                webRtcPlayerObj.latencyTestTimings.SetUETimings(latencyTimingsFromUE);
            }
        } else if (view[0] == ToClientMessageType.FileExtension) {
            processFileExtension(view);
        } else if (view[0] == ToClientMessageType.FileMimeType) {
            processFileMimeType(view);
        } else if (view[0] == ToClientMessageType.FileContents) {
            processFileContents(view);
        } else {
            console.error('unrecognized data received, packet ID '.concat(view[0]));
        }
    };
    registerInputs(webRtcPlayerObj.video);
    if ('ontouchstart' in document.documentElement) {
        createOnScreenKeyboardHelpers(htmlElement);
    }
    return webRtcPlayerObj.video;
}
function setupStats() {
    webRtcPlayerObj.onAggregatedStats = function (aggregatedStats) {
        (aggregatedStats.timestamp - aggregatedStats.timestampStart) / 1000;
    };
    webRtcPlayerObj.aggregateStats(1 * 1000);
}
function onWebRtcOffer(webRTCData) {
    webRtcPlayerObj.receiveOffer(webRTCData);
    setupStats();
}
function onWebRtcAnswer(webRTCData) {
    webRtcPlayerObj.receiveAnswer(webRTCData);
    setupStats();
}
function onWebRtcIce(iceCandidate) {
    if (webRtcPlayerObj) {
        webRtcPlayerObj.handleCandidateFromServer(iceCandidate);
    }
}
var styleWidth;
var styleHeight;
var styleTop;
var styleLeft;
var styleCursor = 'default';
var styleAdditional;
var ControlSchemeType = {
    LockedMouse: 0,
    HoveringMouse: 1
};
var inputOptions = {
    controlScheme: ControlSchemeType.HoveringMouse,
    suppressBrowserKeys: true,
    fakeMouseWithTouches: false
};
function resizePlayerStyleToFillWindow(playerElement) {
    var videoElement = playerElement.getElementsByTagName('VIDEO');
    var windowAspectRatio = window.innerHeight / window.innerWidth;
    var playerAspectRatio = playerElement.clientHeight / playerElement.clientWidth;
    var videoAspectRatio = videoElement.videoHeight / videoElement.videoWidth;
    if (isNaN(videoAspectRatio)) {
        styleWidth = window.innerWidth;
        styleHeight = window.innerHeight;
        styleTop = 0;
        styleLeft = 0;
        playerElement.style = 'top: ' + styleTop + 'px; left: ' + styleLeft + 'px; width: ' + styleWidth + 'px; height: ' + styleHeight + 'px; cursor: ' + styleCursor + '; ' + styleAdditional;
    } else if (windowAspectRatio < playerAspectRatio) {
        styleWidth = Math.floor(window.innerHeight / videoAspectRatio);
        styleHeight = window.innerHeight;
        styleTop = 0;
        styleLeft = Math.floor((window.innerWidth - styleWidth) * 0.5);
        playerElement.style = 'top: ' + styleTop + 'px; left: ' + styleLeft + 'px; width: ' + styleWidth + 'px; height: ' + styleHeight + 'px; cursor: ' + styleCursor + '; ' + styleAdditional;
    } else {
        styleWidth = window.innerWidth;
        styleHeight = Math.floor(window.innerWidth * videoAspectRatio);
        styleTop = Math.floor((window.innerHeight - styleHeight) * 0.5);
        styleLeft = 0;
        playerElement.style = 'top: ' + styleTop + 'px; left: ' + styleLeft + 'px; width: ' + styleWidth + 'px; height: ' + styleHeight + 'px; cursor: ' + styleCursor + '; ' + styleAdditional;
    }
}
function resizePlayerStyleToActualSize(playerElement) {
    var videoElement = playerElement.getElementsByTagName('VIDEO');
    if (videoElement.length > 0) {
        styleWidth = videoElement[0].videoWidth;
        styleHeight = videoElement[0].videoHeight;
        var Top = Math.floor((window.innerHeight - styleHeight) * 0.5);
        var Left = Math.floor((window.innerWidth - styleWidth) * 0.5);
        styleTop = Top > 0 ? Top : 0;
        styleLeft = Left > 0 ? Left : 0;
        playerElement.style = 'top: ' + styleTop + 'px; left: ' + styleLeft + 'px; width: ' + styleWidth + 'px; height: ' + styleHeight + 'px; cursor: ' + styleCursor + '; ' + styleAdditional;
    }
}
function resizePlayerStyleToArbitrarySize(playerElement) {
    playerElement.getElementsByTagName('VIDEO');
    playerElement.style = 'top: 0px; left: 0px; width: ' + styleWidth + 'px; height: ' + styleHeight + 'px; cursor: ' + styleCursor + '; ' + styleAdditional;
}
function setupFreezeFrameOverlay() {
    freezeFrameOverlay = document.createElement('div');
    freezeFrameOverlay.id = 'freezeFrameOverlay';
    freezeFrameOverlay.style.display = 'none';
    freezeFrameOverlay.style.pointerEvents = 'none';
    freezeFrameOverlay.style.position = 'absolute';
    freezeFrameOverlay.style.zIndex = '20';
    var freezeFrameImage = document.createElement('img');
    freezeFrameImage.style.position = 'absolute';
    freezeFrameOverlay.appendChild(freezeFrameImage);
}
function showFreezeFrameOverlay() {
    if (freezeFrame.valid) {
        freezeFrameOverlay.classList.add('freezeframeBackground');
        freezeFrameOverlay.style.display = 'block';
    }
}
function invalidateFreezeFrameOverlay() {
    freezeFrameOverlay.style.display = 'none';
    freezeFrame.valid = false;
    freezeFrameOverlay.classList.remove('freezeframeBackground');
    if (webRtcPlayerObj) {
        webRtcPlayerObj.setVideoEnabled(true);
    }
}
function resizeFreezeFrameOverlay() {
    if (freezeFrame.width !== 0 && freezeFrame.height !== 0) {
        var displayWidth = 0;
        var displayHeight = 0;
        var displayTop = 0;
        var displayLeft = 0;
        var checkBox = document.getElementById('enlarge-display-to-fill-window-tgl');
        var playerElement = document.getElementById('player');
        if (checkBox !== null && checkBox.checked) {
            var windowAspectRatio = window.innerWidth / window.innerHeight;
            var videoAspectRatio = freezeFrame.width / freezeFrame.height;
            if (windowAspectRatio < videoAspectRatio) {
                displayWidth = window.innerWidth;
                displayHeight = Math.floor(window.innerWidth / videoAspectRatio);
                displayTop = Math.floor((window.innerHeight - displayHeight) * 0.5);
                displayLeft = 0;
            } else {
                displayWidth = Math.floor(window.innerHeight * videoAspectRatio);
                displayHeight = window.innerHeight;
                displayTop = 0;
                displayLeft = Math.floor((window.innerWidth - displayWidth) * 0.5);
            }
        } else {
            var playerAspectRatio = playerElement.offsetWidth / playerElement.offsetHeight;
            var _videoAspectRatio = freezeFrame.width / freezeFrame.height;
            if (playerAspectRatio < _videoAspectRatio) {
                displayWidth = playerElement.offsetWidth;
                displayHeight = Math.floor(playerElement.offsetWidth / _videoAspectRatio);
                displayTop = Math.floor((playerElement.offsetHeight - displayHeight) * 0.5);
                displayLeft = 0;
            } else {
                displayWidth = Math.floor(playerElement.offsetHeight * _videoAspectRatio);
                displayHeight = playerElement.offsetHeight;
                displayTop = 0;
                displayLeft = Math.floor((playerElement.offsetWidth - displayWidth) * 0.5);
            }
        }
        var freezeFrameImage = document.getElementById('freezeFrameOverlay').childNodes[0];
        freezeFrameOverlay.style.width = playerElement.offsetWidth + 'px';
        freezeFrameOverlay.style.height = playerElement.offsetHeight + 'px';
        freezeFrameOverlay.style.left = 0 + 'px';
        freezeFrameOverlay.style.top = 0 + 'px';
        freezeFrameImage.style.width = displayWidth + 'px';
        freezeFrameImage.style.height = displayHeight + 'px';
        freezeFrameImage.style.left = displayLeft + 'px';
        freezeFrameImage.style.top = displayTop + 'px';
    }
}
function resizePlayerStyle(event) {
    var playerElement = document.getElementById('player');
    if (!playerElement)
        return;
    updateVideoStreamSize();
    if (playerElement.classList.contains('fixed-size')) {
        setupMouseAndFreezeFrame(playerElement);
        return;
    }
    var checkBox = document.getElementById('enlarge-display-to-fill-window-tgl');
    var windowSmallerThanPlayer = window.innerWidth < playerElement.videoWidth || window.innerHeight < playerElement.videoHeight;
    if (checkBox !== null) {
        if (checkBox.checked || windowSmallerThanPlayer) {
            resizePlayerStyleToFillWindow(playerElement);
        } else {
            resizePlayerStyleToActualSize(playerElement);
        }
    } else {
        resizePlayerStyleToArbitrarySize(playerElement);
    }
    setupMouseAndFreezeFrame(playerElement);
}
function setupMouseAndFreezeFrame(playerElement) {
    playerElement.getBoundingClientRect();
    setupNormalizeAndQuantize();
    resizeFreezeFrameOverlay();
}
function updateVideoStreamSize() {
    var now = new Date().getTime();
    if (now - lastTimeResized > 1000) {
        var playerElement = document.getElementById('player');
        if (!playerElement)
            return;
        var descriptor = { ConsoleCommand: 'setres ' + playerElement.clientWidth + 'x' + playerElement.clientHeight };
        emitCommand(descriptor);
        console.log(descriptor);
        lastTimeResized = new Date().getTime();
    } else {
        console.log('Resizing too often - skipping');
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(updateVideoStreamSize, 1000);
    }
}
var _orientationChangeTimeout;
function onOrientationChange(event) {
    clearTimeout(_orientationChangeTimeout);
    _orientationChangeTimeout = setTimeout(function () {
        resizePlayerStyle();
    }, 500);
}
var MessageType = {
    IFrameRequest: 0,
    RequestQualityControl: 1,
    FpsRequest: 2,
    AverageBitrateRequest: 3,
    StartStreaming: 4,
    StopStreaming: 5,
    LatencyTest: 6,
    RequestInitialSettings: 7,
    UIInteraction: 50,
    Command: 51,
    KeyDown: 60,
    KeyUp: 61,
    KeyPress: 62,
    MouseEnter: 70,
    MouseLeave: 71,
    MouseDown: 72,
    MouseUp: 73,
    MouseMove: 74,
    MouseWheel: 75,
    TouchStart: 80,
    TouchEnd: 81,
    TouchMove: 82,
    GamepadButtonPressed: 90,
    GamepadButtonReleased: 91,
    GamepadAnalog: 92
};
function emitDescriptor(messageType, descriptor) {
    var descriptorAsString = JSON.stringify(descriptor);
    var data = new DataView(new ArrayBuffer(1 + 2 + 2 * descriptorAsString.length));
    var byteIdx = 0;
    data.setUint8(byteIdx, messageType);
    byteIdx++;
    data.setUint16(byteIdx, descriptorAsString.length, true);
    byteIdx += 2;
    for (var i = 0; i < descriptorAsString.length; i++) {
        data.setUint16(byteIdx, descriptorAsString.charCodeAt(i), true);
        byteIdx += 2;
    }
    sendInputData(data.buffer);
}
function emitUIInteraction(descriptor) {
    emitDescriptor(MessageType.UIInteraction, descriptor);
}
function emitCommand(descriptor) {
    emitDescriptor(MessageType.Command, descriptor);
}
function requestInitialSettings() {
    sendInputData(new Uint8Array([MessageType.RequestInitialSettings]).buffer);
}
var normalizeAndQuantizeUnsigned = undefined;
var normalizeAndQuantizeSigned = undefined;
var unquantizeAndDenormalizeUnsigned = undefined;
function setupNormalizeAndQuantize() {
    var playerElement = document.getElementById('player');
    var videoElement = playerElement.getElementsByTagName('video');
    if (playerElement && videoElement.length > 0) {
        var playerAspectRatio = playerElement.clientHeight / playerElement.clientWidth;
        var videoAspectRatio = videoElement[0].videoHeight / videoElement[0].videoWidth;
        if (playerAspectRatio > videoAspectRatio) {
            var ratio = playerAspectRatio / videoAspectRatio;
            normalizeAndQuantizeUnsigned = function normalizeAndQuantizeUnsigned(x, y) {
                var normalizedX = x / playerElement.clientWidth;
                var normalizedY = ratio * (y / playerElement.clientHeight - 0.5) + 0.5;
                if (normalizedX < 0 || normalizedX > 1 || normalizedY < 0 || normalizedY > 1) {
                    return {
                        inRange: false,
                        x: 65535,
                        y: 65535
                    };
                } else {
                    return {
                        inRange: true,
                        x: normalizedX * 65536,
                        y: normalizedY * 65536
                    };
                }
            };
            unquantizeAndDenormalizeUnsigned = function unquantizeAndDenormalizeUnsigned(x, y) {
                var normalizedX = x / 65536;
                var normalizedY = (y / 65536 - 0.5) / ratio + 0.5;
                return {
                    x: normalizedX * playerElement.clientWidth,
                    y: normalizedY * playerElement.clientHeight
                };
            };
            normalizeAndQuantizeSigned = function normalizeAndQuantizeSigned(x, y) {
                var normalizedX = x / (0.5 * playerElement.clientWidth);
                var normalizedY = ratio * y / (0.5 * playerElement.clientHeight);
                return {
                    x: normalizedX * 32767,
                    y: normalizedY * 32767
                };
            };
        } else {
            var _ratio = videoAspectRatio / playerAspectRatio;
            normalizeAndQuantizeUnsigned = function normalizeAndQuantizeUnsigned(x, y) {
                var normalizedX = _ratio * (x / playerElement.clientWidth - 0.5) + 0.5;
                var normalizedY = y / playerElement.clientHeight;
                if (normalizedX < 0 || normalizedX > 1 || normalizedY < 0 || normalizedY > 1) {
                    return {
                        inRange: false,
                        x: 65535,
                        y: 65535
                    };
                } else {
                    return {
                        inRange: true,
                        x: normalizedX * 65536,
                        y: normalizedY * 65536
                    };
                }
            };
            unquantizeAndDenormalizeUnsigned = function unquantizeAndDenormalizeUnsigned(x, y) {
                var normalizedX = (x / 65536 - 0.5) / _ratio + 0.5;
                var normalizedY = y / 65536;
                return {
                    x: normalizedX * playerElement.clientWidth,
                    y: normalizedY * playerElement.clientHeight
                };
            };
            normalizeAndQuantizeSigned = function normalizeAndQuantizeSigned(x, y) {
                var normalizedX = _ratio * x / (0.5 * playerElement.clientWidth);
                var normalizedY = y / (0.5 * playerElement.clientHeight);
                return {
                    x: normalizedX * 32767,
                    y: normalizedY * 32767
                };
            };
        }
    }
}
function emitMouseMove(x, y, deltaX, deltaY) {
    var coord = normalizeAndQuantizeUnsigned(x, y);
    var delta = normalizeAndQuantizeSigned(deltaX, deltaY);
    var Data = new DataView(new ArrayBuffer(9));
    Data.setUint8(0, MessageType.MouseMove);
    Data.setUint16(1, coord.x, true);
    Data.setUint16(3, coord.y, true);
    Data.setInt16(5, delta.x, true);
    Data.setInt16(7, delta.y, true);
    sendInputData(Data.buffer);
}
function emitMouseDown(button, x, y) {
    var coord = normalizeAndQuantizeUnsigned(x, y);
    var Data = new DataView(new ArrayBuffer(6));
    Data.setUint8(0, MessageType.MouseDown);
    Data.setUint8(1, button);
    Data.setUint16(2, coord.x, true);
    Data.setUint16(4, coord.y, true);
    sendInputData(Data.buffer);
}
function emitMouseUp(button, x, y) {
    var coord = normalizeAndQuantizeUnsigned(x, y);
    var Data = new DataView(new ArrayBuffer(6));
    Data.setUint8(0, MessageType.MouseUp);
    Data.setUint8(1, button);
    Data.setUint16(2, coord.x, true);
    Data.setUint16(4, coord.y, true);
    sendInputData(Data.buffer);
}
function emitMouseWheel(delta, x, y) {
    var coord = normalizeAndQuantizeUnsigned(x, y);
    var Data = new DataView(new ArrayBuffer(7));
    Data.setUint8(0, MessageType.MouseWheel);
    Data.setInt16(1, delta, true);
    Data.setUint16(3, coord.x, true);
    Data.setUint16(5, coord.y, true);
    sendInputData(Data.buffer);
}
var MouseButton = {
    MainButton: 0,
    AuxiliaryButton: 1,
    SecondaryButton: 2,
    FourthButton: 3,
    FifthButton: 4
};
var MouseButtonsMask = {
    PrimaryButton: 1,
    SecondaryButton: 2,
    AuxiliaryButton: 4,
    FourthButton: 8,
    FifthButton: 16
};
function releaseMouseButtons(buttons, x, y) {
    if (buttons & MouseButtonsMask.PrimaryButton) {
        emitMouseUp(MouseButton.MainButton, x, y);
    }
    if (buttons & MouseButtonsMask.SecondaryButton) {
        emitMouseUp(MouseButton.SecondaryButton, x, y);
    }
    if (buttons & MouseButtonsMask.AuxiliaryButton) {
        emitMouseUp(MouseButton.AuxiliaryButton, x, y);
    }
    if (buttons & MouseButtonsMask.FourthButton) {
        emitMouseUp(MouseButton.FourthButton, x, y);
    }
    if (buttons & MouseButtonsMask.FifthButton) {
        emitMouseUp(MouseButton.FifthButton, x, y);
    }
}
function pressMouseButtons(buttons, x, y) {
    if (buttons & MouseButtonsMask.PrimaryButton) {
        emitMouseDown(MouseButton.MainButton, x, y);
    }
    if (buttons & MouseButtonsMask.SecondaryButton) {
        emitMouseDown(MouseButton.SecondaryButton, x, y);
    }
    if (buttons & MouseButtonsMask.AuxiliaryButton) {
        emitMouseDown(MouseButton.AuxiliaryButton, x, y);
    }
    if (buttons & MouseButtonsMask.FourthButton) {
        emitMouseDown(MouseButton.FourthButton, x, y);
    }
    if (buttons & MouseButtonsMask.FifthButton) {
        emitMouseDown(MouseButton.FifthButton, x, y);
    }
}
function registerInputs(playerElement) {
    if (!playerElement)
        return;
    registerMouseEnterAndLeaveEvents(playerElement);
    registerTouchEvents(playerElement);
}
function createOnScreenKeyboardHelpers(htmlElement) {
    if (document.getElementById('hiddenInput') === null) {
        hiddenInput = document.createElement('input');
        hiddenInput.id = 'hiddenInput';
        hiddenInput.maxLength = 0;
        htmlElement.appendChild(hiddenInput);
    }
    if (document.getElementById('editTextButton') === null) {
        editTextButton = document.createElement('button');
        editTextButton.id = 'editTextButton';
        editTextButton.innerHTML = 'edit text';
        htmlElement.appendChild(editTextButton);
        editTextButton.classList.add('hiddenState');
        editTextButton.addEventListener('click', function () {
            hiddenInput.focus();
        });
    }
}
function showOnScreenKeyboard(command) {
    if (command.showOnScreenKeyboard) {
        editTextButton.classList.remove('hiddenState');
        var pos = unquantizeAndDenormalizeUnsigned(command.x, command.y);
        editTextButton.style.top = pos.y.toString() + 'px';
        editTextButton.style.left = (pos.x - 40).toString() + 'px';
    } else {
        editTextButton.classList.add('hiddenState');
        hiddenInput.blur();
    }
}
function registerMouseEnterAndLeaveEvents(playerElement) {
    playerElement.onmouseenter = function (e) {
        var Data = new DataView(new ArrayBuffer(1));
        Data.setUint8(0, MessageType.MouseEnter);
        sendInputData(Data.buffer);
        playerElement.pressMouseButtons(e);
    };
    playerElement.onmouseleave = function (e) {
        var Data = new DataView(new ArrayBuffer(1));
        Data.setUint8(0, MessageType.MouseLeave);
        sendInputData(Data.buffer);
        playerElement.releaseMouseButtons(e);
    };
}
function registerLockedMouseEvents(playerElement) {
    var x = playerElement.width / 2;
    var y = playerElement.height / 2;
    playerElement.requestPointerLock = playerElement.requestPointerLock || playerElement.mozRequestPointerLock;
    document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock;
    playerElement.onclick = function () {
        playerElement.requestPointerLock();
    };
    document.addEventListener('pointerlockchange', lockStateChange, false);
    document.addEventListener('mozpointerlockchange', lockStateChange, false);
    function lockStateChange() {
        if (document.pointerLockElement === playerElement || document.mozPointerLockElement === playerElement) {
            console.log('Pointer locked');
            document.addEventListener('mousemove', updatePosition, false);
        } else {
            console.log('The pointer lock status is now unlocked');
            document.removeEventListener('mousemove', updatePosition, false);
        }
    }
    function updatePosition(e) {
        x += e.movementX;
        y += e.movementY;
        if (x > styleWidth) {
            x -= styleWidth;
        }
        if (y > styleHeight) {
            y -= styleHeight;
        }
        if (x < 0) {
            x = styleWidth + x;
        }
        if (y < 0) {
            y = styleHeight - y;
        }
        emitMouseMove(x, y, e.movementX, e.movementY);
    }
    playerElement.onmousedown = function (e) {
        emitMouseDown(e.button, x, y);
    };
    playerElement.onmouseup = function (e) {
        emitMouseUp(e.button, x, y);
    };
    playerElement.onmousewheel = function (e) {
        emitMouseWheel(e.wheelDelta, x, y);
    };
    playerElement.pressMouseButtons = function (e) {
        pressMouseButtons(e.buttons, x, y);
    };
    playerElement.releaseMouseButtons = function (e) {
        releaseMouseButtons(e.buttons, x, y);
    };
}
function registerHoveringMouseEvents(playerElement) {
    playerElement.onmousemove = function (e) {
        emitMouseMove(e.offsetX, e.offsetY, e.movementX, e.movementY);
        e.preventDefault();
    };
    playerElement.onmousedown = function (e) {
        emitMouseDown(e.button, e.offsetX, e.offsetY);
        e.preventDefault();
    };
    playerElement.onmouseup = function (e) {
        emitMouseUp(e.button, e.offsetX, e.offsetY);
        e.preventDefault();
    };
    playerElement.oncontextmenu = function (e) {
        emitMouseUp(e.button, e.offsetX, e.offsetY);
        e.preventDefault();
    };
    if ('onmousewheel' in playerElement) {
        playerElement.onmousewheel = function (e) {
            emitMouseWheel(e.wheelDelta, e.offsetX, e.offsetY);
            e.preventDefault();
        };
    } else {
        playerElement.addEventListener('DOMMouseScroll', function (e) {
            emitMouseWheel(e.detail * -120, e.offsetX, e.offsetY);
            e.preventDefault();
        }, false);
    }
    playerElement.pressMouseButtons = function (e) {
        pressMouseButtons(e.buttons, e.offsetX, e.offsetY);
    };
    playerElement.releaseMouseButtons = function (e) {
        releaseMouseButtons(e.buttons, e.offsetX, e.offsetY);
    };
}
function registerTouchEvents(playerElement) {
    var fingers = [
        9,
        8,
        7,
        6,
        5,
        4,
        3,
        2,
        1,
        0
    ];
    var fingerIds = {};
    function rememberTouch(touch) {
        var finger = fingers.pop();
        if (finger === undefined) {
            console.log('exhausted touch indentifiers');
        }
        fingerIds[touch.identifier] = finger;
    }
    function forgetTouch(touch) {
        fingers.push(fingerIds[touch.identifier]);
        delete fingerIds[touch.identifier];
    }
    function emitTouchData(type, touches) {
        var data = new DataView(new ArrayBuffer(2 + 7 * touches.length));
        data.setUint8(0, type);
        data.setUint8(1, touches.length);
        var _byte2 = 2;
        for (var t = 0; t < touches.length; t++) {
            var touch = touches[t];
            var x = touch.clientX - playerElement.offsetLeft;
            var y = touch.clientY - playerElement.offsetTop;
            var coord = normalizeAndQuantizeUnsigned(x, y);
            data.setUint16(_byte2, coord.x, true);
            _byte2 += 2;
            data.setUint16(_byte2, coord.y, true);
            _byte2 += 2;
            data.setUint8(_byte2, fingerIds[touch.identifier], true);
            _byte2 += 1;
            data.setUint8(_byte2, 255 * touch.force, true);
            _byte2 += 1;
            data.setUint8(_byte2, coord.inRange ? 1 : 0, true);
            _byte2 += 1;
        }
        sendInputData(data.buffer);
    }
    {
        playerElement.ontouchstart = function (e) {
            for (var t = 0; t < e.changedTouches.length; t++) {
                rememberTouch(e.changedTouches[t]);
            }
            emitTouchData(MessageType.TouchStart, e.changedTouches);
            e.preventDefault();
        };
        playerElement.ontouchend = function (e) {
            emitTouchData(MessageType.TouchEnd, e.changedTouches);
            for (var t = 0; t < e.changedTouches.length; t++) {
                forgetTouch(e.changedTouches[t]);
            }
            e.preventDefault();
        };
        playerElement.ontouchmove = function (e) {
            emitTouchData(MessageType.TouchMove, e.touches);
            e.preventDefault();
        };
    }
}
function isKeyCodeBrowserKey(keyCode) {
    return keyCode >= 112 && keyCode <= 123 || keyCode === 9;
}
var SpecialKeyCodes = {
    BackSpace: 8,
    Shift: 16,
    Control: 17,
    Alt: 18,
    RightShift: 253,
    RightControl: 254,
    RightAlt: 255
};
function getKeyCode(e) {
    if (e.keyCode === SpecialKeyCodes.Shift && e.code === 'ShiftRight')
        return SpecialKeyCodes.RightShift;
    else if (e.keyCode === SpecialKeyCodes.Control && e.code === 'ControlRight')
        return SpecialKeyCodes.RightControl;
    else if (e.keyCode === SpecialKeyCodes.Alt && e.code === 'AltRight')
        return SpecialKeyCodes.RightAlt;
    else
        return e.keyCode;
}
function registerKeyboardEvents() {
    document.onkeydown = function (e) {
        sendInputData(new Uint8Array([
            MessageType.KeyDown,
            getKeyCode(e),
            e.repeat
        ]).buffer);
        if (e.keyCode === SpecialKeyCodes.BackSpace) {
            document.onkeypress({ charCode: SpecialKeyCodes.BackSpace });
        }
        if (isKeyCodeBrowserKey(e.keyCode)) {
            e.preventDefault();
        }
    };
    document.onkeyup = function (e) {
        sendInputData(new Uint8Array([
            MessageType.KeyUp,
            getKeyCode(e)
        ]).buffer);
        if (isKeyCodeBrowserKey(e.keyCode)) {
            e.preventDefault();
        }
    };
    document.onkeypress = function (e) {
        var data = new DataView(new ArrayBuffer(3));
        data.setUint8(0, MessageType.KeyPress);
        data.setUint16(1, e.charCode, true);
        sendInputData(data.buffer);
    };
}
function start() {
    {
        showConnectOverlay();
        invalidateFreezeFrameOverlay();
        shouldShowPlayOverlay = true;
        resizePlayerStyle();
    }
}
function connect() {
    window.WebSocket = window.WebSocket || window.MozWebSocket;
    if (!window.WebSocket) {
        alert('Your browser doesn\'t support WebSocket');
        return;
    }
    ws = new WebSocket('ws://' + signalServer);
    ws.onmessage = function (event) {
        var msg = JSON.parse(event.data);
        if (msg.type === 'config') {
            console.log('%c[Inbound SS (config)]', 'background: lightblue; color: black', msg);
            onConfig(msg);
        } else if (msg.type === 'playerCount') {
            console.log('%c[Inbound SS (playerCount)]', 'background: lightblue; color: black', msg);
        } else if (msg.type === 'offer') {
            console.log('%c[Inbound SS (offer)]', 'background: lightblue; color: black', msg);
            onWebRtcOffer(msg);
        } else if (msg.type === 'answer') {
            console.log('%c[Inbound SS (answer)]', 'background: lightblue; color: black', msg);
            onWebRtcAnswer(msg);
        } else if (msg.type === 'iceCandidate') {
            onWebRtcIce(msg.candidate);
        } else if (msg.type === 'warning' && msg.warning) {
            console.warn(msg.warning);
        } else {
            console.error('Invalid SS message type', msg.type);
        }
    };
    ws.onerror = function (event) {
        console.log('WS error: '.concat(JSON.stringify(event)));
    };
    ws.onclose = function (event) {
        console.log('WS closed: '.concat(JSON.stringify(event.code), ' - ').concat(event.reason));
        ws = undefined;
        var playerDiv = document.getElementById('player');
        if (webRtcPlayerObj) {
            playerDiv.removeChild(webRtcPlayerObj.video);
            webRtcPlayerObj.close();
            webRtcPlayerObj = undefined;
        }
        showTextOverlay('Disconnected: '.concat(event.reason));
        setTimeout(start, 4000);
    };
}
function onConfig(config) {
    var playerDiv = document.getElementById('player');
    var playerElement = setupWebRtcPlayer(playerDiv, config);
    resizePlayerStyle();
    switch (inputOptions.controlScheme) {
    case ControlSchemeType.HoveringMouse:
        registerHoveringMouseEvents(playerElement);
        break;
    case ControlSchemeType.LockedMouse:
        registerLockedMouseEvents(playerElement);
        break;
    default:
        console.log('ERROR: Unknown control scheme '.concat(inputOptions.controlScheme));
        registerLockedMouseEvents(playerElement);
        break;
    }
}
var signalServer = 'localhost:80';
onDataChannelConnected = null;
function load() {
    setupHtmlEvents();
    setupFreezeFrameOverlay();
    registerKeyboardEvents();
    start();
}
function api_send(proto, data, callback) {
    var jsonData = {
        command: 'event',
        func_name: proto,
        args: data
    };
    {
        console.log('send:', jsonData);
    }
    responseEventListeners.set(proto, callback);
    emitUIInteraction(jsonData);
}
function onResponse(response) {
    console.log(_typeof(response));
    {
        console.log('recv:', response);
    }
    var jsonData = JSON.parse(response);
    if (jsonData.command !== 'event') {
        console.log('unexpected response:', response);
        return;
    }
    var proto = jsonData.func_name;
    var callback = responseEventListeners.get(proto);
    if (callback) {
        callback(jsonData.args);
    }
}
function api_register(proto, callback) {
    responseEventListeners.set(proto, callback);
}
function api_unregister(proto) {
    responseEventListeners['delete'](proto);
}
function app_load(signalServerAddr, onFinish) {
    console.log('ws to signal server: ', signalServerAddr);
    signalServer = signalServerAddr;
    onDataChannelConnected = onFinish;
    load();
}
function app_load2(url, onFinish) {
    ajax({
        path: url,
        method: 'get'
    }).then(function (res) {
        if (res && res.data) {
            app_load(res.data, onFinish);
        }
    });
}
function app_load3(url, option, onFinish) {
    afk = _objectSpread2(_objectSpread2({}, afk), option);
    ajax({
        path: url,
        method: 'get'
    }).then(function (res) {
        if (res && res.data) {
            app_load(res.data, onFinish);
        }
    });
}

function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
    if (typeof shadowMode !== 'boolean') {
        createInjectorSSR = createInjector;
        createInjector = shadowMode;
        shadowMode = false;
    }
    // Vue.extend constructor export interop.
    const options = typeof script === 'function' ? script.options : script;
    // render functions
    if (template && template.render) {
        options.render = template.render;
        options.staticRenderFns = template.staticRenderFns;
        options._compiled = true;
        // functional template
        if (isFunctionalTemplate) {
            options.functional = true;
        }
    }
    // scopedId
    if (scopeId) {
        options._scopeId = scopeId;
    }
    let hook;
    if (moduleIdentifier) {
        // server build
        hook = function (context) {
            // 2.3 injection
            context =
                context || // cached call
                    (this.$vnode && this.$vnode.ssrContext) || // stateful
                    (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
            // 2.2 with runInNewContext: true
            if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
                context = __VUE_SSR_CONTEXT__;
            }
            // inject component styles
            if (style) {
                style.call(this, createInjectorSSR(context));
            }
            // register component module identifier for async chunk inference
            if (context && context._registeredComponents) {
                context._registeredComponents.add(moduleIdentifier);
            }
        };
        // used by ssr in case component is cached and beforeCreate
        // never gets called
        options._ssrRegister = hook;
    }
    else if (style) {
        hook = shadowMode
            ? function (context) {
                style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
            }
            : function (context) {
                style.call(this, createInjector(context));
            };
    }
    if (hook) {
        if (options.functional) {
            // register for functional component in vue file
            const originalRender = options.render;
            options.render = function renderWithStyleInjection(h, context) {
                hook.call(context);
                return originalRender(h, context);
            };
        }
        else {
            // inject component registration as beforeCreate hook
            const existing = options.beforeCreate;
            options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
        }
    }
    return script;
}

/* script */
/* template */
var __vue_render__ = function () {
  var _vm = this;
  var _h = _vm.$createElement;
  _vm._self._c || _h;
  return _vm._m(0)
};
var __vue_staticRenderFns__ = [
  function () {
    var _vm = this;
    var _h = _vm.$createElement;
    var _c = _vm._self._c || _h;
    return _c("div", { attrs: { id: "playerUI" } }, [
      _c("div", { attrs: { id: "player" } }),
      _vm._v(" "),
      _c("video", {
        staticStyle: {
          width: "100%",
          height: "100%",
          position: "absolute",
          "object-fit": "fill",
        },
        attrs: { id: "streamingVideo", playsinline: "" },
      }),
    ])
  },
];
__vue_render__._withStripped = true;

  /* style */
  const __vue_inject_styles__ = undefined;
  /* scoped */
  const __vue_scope_id__ = "data-v-3b6435f9";
  /* module identifier */
  const __vue_module_identifier__ = undefined;
  /* functional template */
  const __vue_is_functional_template__ = false;
  /* style inject */
  
  /* style inject SSR */
  
  /* style inject shadow dom */
  

  
  const __vue_component__ = /*#__PURE__*/normalizeComponent(
    { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
    __vue_inject_styles__,
    {},
    __vue_scope_id__,
    __vue_is_functional_template__,
    __vue_module_identifier__,
    false,
    undefined,
    undefined,
    undefined
  );

  var __vue_component__$1 = __vue_component__;

var METHOD_TYPE = {
    CHANE_RISK_CHART: 'changeRiskChart',
    CHANE_MONITOR_CHART: 'changeMonitorChart',
    GO_TO_WATER_DETAIL: 'goToWaterDetail',
    GO_TO_FIRE_DETAIL: 'goToFireDetail',
    SWITCH_FIRE: 'switchFire',
    SWITCH_WATER: 'switchWater',
    CHANGE_3D_SCENE: 'change3DScene',
    MARK_SYMBOL: 'markSymbol',
    ON_ENTER_3D_SCENE: 'Enter3DSecene'
};
var SCENE_TYPE = {
    FIRE: 'fire',
    WATER: 'water',
    TECHNOLOGY: 'technology',
    TECHNOLOGY_DETAIL: 'technologyDetail',
    TECHNOLOGY_DETAIL_FIRE: 'technologyDetailFire',
    TECHNOLOGY_DETAIL_WATER: 'technologyDetailWater'
};
var MARK_TYPE = {
    DEFAULT: 'default',
    GAS: 'gas',
    HEAT: 'heat',
    BRIDGE: 'bridge',
    PIPE: 'pipe',
    WATER_SUPPLY: 'waterSupply',
    DRAIN: 'drain',
    SUBWAY_TUNNEL: 'subwayTunnel',
    ELEVATOR: 'elevator',
    FIRE_CONTROL: 'fireControl'
};

export { MARK_TYPE, METHOD_TYPE, SCENE_TYPE, __vue_component__$1 as UEPlayer, api_register, api_send, api_unregister, app_load, app_load2, app_load3 };