trtc-electron-sdk
Version:
trtc electron sdk
243 lines (242 loc) • 10.9 kB
JavaScript
"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;