SPB Git forge

spb/admin-ka

Public
41commits 1branches 0releases
172.9 MBsize
maindefault branch
19 days agolast push
JavaScript 65.5% Python 17.8% CSS 13% HTML 3.7%
13.5 KB · 349 lines javascript
Raw Blame History
1"use strict";23Object.defineProperty(exports, "__esModule", {4  value: true5});6exports["default"] = exports.H264Parser = exports.H264Context = void 0;7var Log = _interopRequireWildcard(require("../util/logging.js"));8function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }9function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }10function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }11function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }12function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }13function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }14function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }15function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }16function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }17function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }18function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }19function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }20function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }21function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*22 * noVNC: HTML5 VNC client23 * Copyright (C) 2024 The noVNC authors24 * Licensed under MPL 2.0 (see LICENSE.txt)25 *26 * See README.md for usage and integration instructions.27 *28 */29var H264Parser = exports.H264Parser = /*#__PURE__*/function () {30  function H264Parser(data) {31    _classCallCheck(this, H264Parser);32    this._data = data;33    this._index = 0;34    this.profileIdc = null;35    this.constraintSet = null;36    this.levelIdc = null;37  }38  return _createClass(H264Parser, [{39    key: "_getStartSequenceLen",40    value: function _getStartSequenceLen(index) {41      var data = this._data;42      if (data[index + 0] == 0 && data[index + 1] == 0 && data[index + 2] == 0 && data[index + 3] == 1) {43        return 4;44      }45      if (data[index + 0] == 0 && data[index + 1] == 0 && data[index + 2] == 1) {46        return 3;47      }48      return 0;49    }50  }, {51    key: "_indexOfNextNalUnit",52    value: function _indexOfNextNalUnit(index) {53      var data = this._data;54      for (var i = index; i < data.length; ++i) {55        if (this._getStartSequenceLen(i) != 0) {56          return i;57        }58      }59      return -1;60    }61  }, {62    key: "_parseSps",63    value: function _parseSps(index) {64      this.profileIdc = this._data[index];65      this.constraintSet = this._data[index + 1];66      this.levelIdc = this._data[index + 2];67    }68  }, {69    key: "_parseNalUnit",70    value: function _parseNalUnit(index) {71      var firstByte = this._data[index];72      if (firstByte & 0x80) {73        throw new Error('H264 parsing sanity check failed, forbidden zero bit is set');74      }75      var unitType = firstByte & 0x1f;76      switch (unitType) {77        case 1:78          // coded slice, non-idr79          return {80            slice: true81          };82        case 5:83          // coded slice, idr84          return {85            slice: true,86            key: true87          };88        case 6:89          // sei90          return {};91        case 7:92          // sps93          this._parseSps(index + 1);94          return {};95        case 8:96          // pps97          return {};98        default:99          Log.Warn("Unhandled unit type: ", unitType);100          break;101      }102      return {};103    }104  }, {105    key: "parse",106    value: function parse() {107      var startIndex = this._index;108      var isKey = false;109      while (this._index < this._data.length) {110        var startSequenceLen = this._getStartSequenceLen(this._index);111        if (startSequenceLen == 0) {112          throw new Error('Invalid start sequence in bit stream');113        }114        var _this$_parseNalUnit = this._parseNalUnit(this._index + startSequenceLen),115          slice = _this$_parseNalUnit.slice,116          key = _this$_parseNalUnit.key;117        var nextIndex = this._indexOfNextNalUnit(this._index + startSequenceLen);118        if (nextIndex == -1) {119          this._index = this._data.length;120        } else {121          this._index = nextIndex;122        }123        if (key) {124          isKey = true;125        }126        if (slice) {127          break;128        }129      }130      if (startIndex === this._index) {131        return null;132      }133      return {134        frame: this._data.subarray(startIndex, this._index),135        key: isKey136      };137    }138  }]);139}();140var H264Context = exports.H264Context = /*#__PURE__*/function () {141  function H264Context(width, height) {142    _classCallCheck(this, H264Context);143    this.lastUsed = 0;144    this._width = width;145    this._height = height;146    this._profileIdc = null;147    this._constraintSet = null;148    this._levelIdc = null;149    this._decoder = null;150    this._pendingFrames = [];151  }152  return _createClass(H264Context, [{153    key: "_handleFrame",154    value: function _handleFrame(frame) {155      var pending = this._pendingFrames.shift();156      if (pending === undefined) {157        throw new Error("Pending frame queue empty when receiving frame from decoder");158      }159      if (pending.timestamp != frame.timestamp) {160        throw new Error("Video frame timestamp mismatch. Expected " + frame.timestamp + " but but got " + pending.timestamp);161      }162      pending.frame = frame;163      pending.ready = true;164      pending.resolve();165      if (!pending.keep) {166        frame.close();167      }168    }169  }, {170    key: "_handleError",171    value: function _handleError(e) {172      throw new Error("Failed to decode frame: " + e.message);173    }174  }, {175    key: "_configureDecoder",176    value: function _configureDecoder(profileIdc, constraintSet, levelIdc) {177      var _this = this;178      if (this._decoder === null || this._decoder.state === 'closed') {179        this._decoder = new VideoDecoder({180          output: function output(frame) {181            return _this._handleFrame(frame);182          },183          error: function error(e) {184            return _this._handleError(e);185          }186        });187      }188      var codec = 'avc1.' + profileIdc.toString(16).padStart(2, '0') + constraintSet.toString(16).padStart(2, '0') + levelIdc.toString(16).padStart(2, '0');189      this._decoder.configure({190        codec: codec,191        codedWidth: this._width,192        codedHeight: this._height,193        optimizeForLatency: true194      });195    }196  }, {197    key: "_preparePendingFrame",198    value: function _preparePendingFrame(timestamp) {199      var pending = {200        timestamp: timestamp,201        promise: null,202        resolve: null,203        frame: null,204        ready: false,205        keep: false206      };207      pending.promise = new Promise(function (resolve) {208        pending.resolve = resolve;209      });210      this._pendingFrames.push(pending);211      return pending;212    }213  }, {214    key: "decode",215    value: function decode(payload) {216      var parser = new H264Parser(payload);217      var result = null;218219      // Ideally, this timestamp should come from the server, but we'll just220      // approximate it instead.221      var timestamp = Math.round(window.performance.now() * 1e3);222      while (true) {223        var encodedFrame = parser.parse();224        if (encodedFrame === null) {225          break;226        }227        if (parser.profileIdc !== null) {228          self._profileIdc = parser.profileIdc;229          self._constraintSet = parser.constraintSet;230          self._levelIdc = parser.levelIdc;231        }232        if (this._decoder === null || this._decoder.state !== 'configured') {233          if (!encodedFrame.key) {234            Log.Warn("Missing key frame. Can't decode until one arrives");235            continue;236          }237          if (self._profileIdc === null) {238            Log.Warn('Cannot config decoder. Have not received SPS and PPS yet.');239            continue;240          }241          this._configureDecoder(self._profileIdc, self._constraintSet, self._levelIdc);242        }243        result = this._preparePendingFrame(timestamp);244        var chunk = new EncodedVideoChunk({245          timestamp: timestamp,246          type: encodedFrame.key ? 'key' : 'delta',247          data: encodedFrame.frame248        });249        try {250          this._decoder.decode(chunk);251        } catch (e) {252          Log.Warn("Failed to decode:", e);253        }254      }255256      // We only keep last frame of each payload257      if (result !== null) {258        result.keep = true;259      }260      return result;261    }262  }]);263}();264var H264Decoder = exports["default"] = /*#__PURE__*/function () {265  function H264Decoder() {266    _classCallCheck(this, H264Decoder);267    this._tick = 0;268    this._contexts = {};269  }270  return _createClass(H264Decoder, [{271    key: "_contextId",272    value: function _contextId(x, y, width, height) {273      return [x, y, width, height].join(',');274    }275  }, {276    key: "_findOldestContextId",277    value: function _findOldestContextId() {278      var oldestTick = Number.MAX_VALUE;279      var oldestKey = undefined;280      for (var _i = 0, _Object$entries = Object.entries(this._contexts); _i < _Object$entries.length; _i++) {281        var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),282          key = _Object$entries$_i[0],283          value = _Object$entries$_i[1];284        if (value.lastUsed < oldestTick) {285          oldestTick = value.lastUsed;286          oldestKey = key;287        }288      }289      return oldestKey;290    }291  }, {292    key: "_createContext",293    value: function _createContext(x, y, width, height) {294      var maxContexts = 64;295      if (Object.keys(this._contexts).length >= maxContexts) {296        var oldestContextId = this._findOldestContextId();297        delete this._contexts[oldestContextId];298      }299      var context = new H264Context(width, height);300      this._contexts[this._contextId(x, y, width, height)] = context;301      return context;302    }303  }, {304    key: "_getContext",305    value: function _getContext(x, y, width, height) {306      var context = this._contexts[this._contextId(x, y, width, height)];307      return context !== undefined ? context : this._createContext(x, y, width, height);308    }309  }, {310    key: "_resetContext",311    value: function _resetContext(x, y, width, height) {312      delete this._contexts[this._contextId(x, y, width, height)];313    }314  }, {315    key: "_resetAllContexts",316    value: function _resetAllContexts() {317      this._contexts = {};318    }319  }, {320    key: "decodeRect",321    value: function decodeRect(x, y, width, height, sock, display, depth) {322      var resetContextFlag = 1;323      var resetAllContextsFlag = 2;324      if (sock.rQwait("h264 header", 8)) {325        return false;326      }327      var length = sock.rQshift32();328      var flags = sock.rQshift32();329      if (sock.rQwait("h264 payload", length, 8)) {330        return false;331      }332      if (flags & resetAllContextsFlag) {333        this._resetAllContexts();334      } else if (flags & resetContextFlag) {335        this._resetContext(x, y, width, height);336      }337      var context = this._getContext(x, y, width, height);338      context.lastUsed = this._tick++;339      if (length !== 0) {340        var payload = sock.rQshiftBytes(length, false);341        var frame = context.decode(payload);342        if (frame !== null) {343          display.videoFrame(x, y, width, height, frame);344        }345      }346      return true;347    }348  }]);349}();