UNPKG

trtc-electron-sdk

Version:

trtc electron sdk

243 lines (242 loc) 10.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_isequal_1 = __importDefault(require("lodash.isequal")); const trtc_define_1 = require("../../trtc_define"); const util_1 = require("../util"); const RGBACanvas3DRenderer_1 = __importDefault(require("./RGBACanvas3DRenderer")); const I420Canvas3DRenderer_1 = __importDefault(require("./I420Canvas3DRenderer")); const logger_1 = __importDefault(require("../../logger")); const UP_LIMIT_COUNT = 16; let currentCreatedCount = 0; class Canvas3dRenderer { constructor(pixelFormat, view, options) { this.i420Width = 640; this.i420Height = 360; this.i420Rotation = 0; if (currentCreatedCount < UP_LIMIT_COUNT) { currentCreatedCount = currentCreatedCount + 1; logger_1.default.debug('currentCreatedCount=', currentCreatedCount); } else { throw new Error('WebGL context reach up limit'); } this.pixelFormat = pixelFormat; this.viewContainer = view; this.contentMode = trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit; const viewWrapper = document.createElement('div'); viewWrapper.className = 'trtc-webgl'; Object.assign(viewWrapper.style, { width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' }); this.viewWrapper = viewWrapper; this.canvas = null; this.cacheCanvasOptions = {}; this.canvas3DRenderer = null; this.onContextLost = options.onContextLost || null; this._handleContextLost = this._handleContextLost.bind(this); this.bind(view); } _handleContextLost(e) { logger_1.default.warn("_handleContextLost:", e); this.onContextLost && this.onContextLost(); this.destroy(); } _createCanvas3DRenderer() { if (this.canvas) { try { if (this.pixelFormat === trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_RGBA32 || this.pixelFormat === trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32) { return new RGBACanvas3DRenderer_1.default(this.canvas); } else if (this.pixelFormat === trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420) { return new I420Canvas3DRenderer_1.default(this.canvas); } else { throw new Error(`pixel format '${this.pixelFormat}' not supported`); } } catch (err) { logger_1.default.warn('create WebGL context failed.', err); throw new Error('create and initialize WebGL context failed'); } } return null; } setContentMode(mode) { this.contentMode = mode; } bind(viewContainer) { this.viewContainer = viewContainer; if (this.viewWrapper && this.viewContainer) { this.canvas = document.createElement('canvas'); this.viewWrapper.appendChild(this.canvas); this.viewContainer.appendChild(this.viewWrapper); this.canvas.addEventListener("webglcontextlost", this._handleContextLost); try { // I420 WebGL 渲染有些特殊,视频宽高发生变化时,需要重新创建 canvas if (this.pixelFormat === trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420) { if (this.i420Width || this.i420Height) { this.canvas.width = this.i420Width; this.canvas.height = this.i420Height; this.canvas3DRenderer = this._createCanvas3DRenderer(); } } else { this.canvas3DRenderer = this._createCanvas3DRenderer(); } } catch (e) { this.canvas.removeEventListener("webglcontextlost", this._handleContextLost); throw e; } } } unbind() { var _a, _b, _c; (_a = this.canvas3DRenderer) === null || _a === void 0 ? void 0 : _a.destroy(); this.canvas3DRenderer = null; if (this.canvas && this.viewWrapper && this.canvas.parentElement === this.viewWrapper) { this.viewWrapper.removeChild(this.canvas); } else { logger_1.default.warn("Canvas3DRenderer unbind error: remove canvas error", this.canvas, this.viewWrapper); } (_b = this.canvas) === null || _b === void 0 ? void 0 : _b.removeEventListener("webglcontextlost", this._handleContextLost); this.canvas = null; if (this.viewWrapper && this.viewContainer && this.viewWrapper.parentElement === this.viewContainer) { this.viewContainer.removeChild(this.viewWrapper); } else { logger_1.default.warn("Canvas3DRenderer unbind error: remove viewWrapper error", this.viewWrapper, this.viewContainer, (_c = this.viewContainer) === null || _c === void 0 ? void 0 : _c.parentElement); } this.viewContainer = null; } drawFrame(frameData) { switch (this.pixelFormat) { case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420: this._drawFrameI420(frameData); break; case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_RGBA32: this._drawFrameRGBA(frameData); break; case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32: this._drawFrameBGRA(frameData); break; default: logger_1.default.warn('Canvas2dRenderer.drawFrame error. Not support video format:', this.pixelFormat); } } _drawFrameI420(frameData) { var _a, _b, _c; try { const { data, width, height, timestamp, rotation, isNeedRotate } = frameData; if (width <= 0 || height <= 0) { throw new Error(`wrong video parameter width:${width} or height:${height}`); } try { // I420 WebGL 渲染有些特殊,视频宽高发生变化时,需要重新创建 canvas if (width !== this.i420Width || height !== this.i420Height || rotation !== this.i420Rotation) { const tempViewContainer = this.viewContainer; this.unbind(); this.i420Width = width; this.i420Height = height; this.i420Rotation = rotation; this.bind(tempViewContainer); } } catch (e) { this.onContextLost && this.onContextLost(); this.destroy(); throw new Error("re-create WebGL context failed"); } if (this.viewWrapper && this.canvas3DRenderer) { this._updateCanvasStyle({ contentWidth: width, contentHeight: height, containerWidth: (_a = this.viewWrapper) === null || _a === void 0 ? void 0 : _a.clientWidth, containerHeight: (_b = this.viewWrapper) === null || _b === void 0 ? void 0 : _b.clientHeight, contentMode: this.contentMode, rotation, isNeedMirror: false, isNeedRotate, }); (_c = this.canvas3DRenderer) === null || _c === void 0 ? void 0 : _c.draw(data, width, height); } else { throw new Error('renderer container element is null'); } } catch (err) { logger_1.default.error('Canvas3dRenderer._drawFrameI420 error:', err); } } _drawFrameRGBA(frameData) { var _a, _b; try { const { data, width, height, timestamp, rotation, isNeedRotate } = frameData; if (width <= 0 || height <= 0) { throw new Error(`wrong video parameter width:${width} or height:${height}`); } if (this.viewWrapper && this.canvas3DRenderer) { this._updateCanvasStyle({ contentWidth: width, contentHeight: height, containerWidth: (_a = this.viewWrapper) === null || _a === void 0 ? void 0 : _a.clientWidth, containerHeight: (_b = this.viewWrapper) === null || _b === void 0 ? void 0 : _b.clientHeight, contentMode: this.contentMode, rotation, isNeedMirror: false, isNeedRotate, }); this.canvas3DRenderer.draw(data, width, height); } else { throw new Error('renderer container element is null'); } } catch (err) { logger_1.default.error('Canvas3dRenderer._drawFrameRGBA error:', err); } } _drawFrameBGRA(frameData) { this._drawFrameRGBA(Object.assign(Object.assign({}, frameData), { data: (0, util_1.transferBGRA2RGBA)(frameData.data, frameData.width, frameData.height) })); } _updateCanvasStyle(options) { if (this.canvas) { if ((0, lodash_isequal_1.default)(this.cacheCanvasOptions, options)) { return; } this.cacheCanvasOptions = Object.assign({}, options); const { width, height, zoom, transform } = (0, util_1.calcCanvasStyle)(options); this.canvas.width = width; this.canvas.height = height; // @ts-ignore this.canvas.style.zoom = zoom; if (transform) { this.canvas.style.transform = transform; } } else { throw new Error('canvas element not exist'); } } isValid(viewContainer) { var _a; return viewContainer === this.viewContainer && this.viewContainer === ((_a = this.viewWrapper) === null || _a === void 0 ? void 0 : _a.parentElement); } destroy() { if (this.viewWrapper) { this.unbind(); this.viewWrapper = null; currentCreatedCount--; this.onContextLost = null; } } } exports.default = Canvas3dRenderer;