UNPKG

trtc-electron-sdk

Version:

trtc electron sdk

170 lines (169 loc) 7.39 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; 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 logger_1 = __importDefault(require("../../logger")); class VideoRenderer { constructor(pixelFormat, view) { this.pixelFormat = pixelFormat; this.pixelFormatStr = this._getPixelFormat(); this.viewContainer = view; this.contentMode = trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit; const viewWrapper = document.createElement('div'); viewWrapper.className = 'trtc-video'; Object.assign(viewWrapper.style, { width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' }); this.viewWrapper = viewWrapper; this.track = new window.MediaStreamTrackGenerator({ kind: 'video' }); this.writer = this.track.writable.getWriter(); this.video = document.createElement('video'); this.video.setAttribute('style', 'display: block;'); this.video.setAttribute('autoplay', 'autoplay'); this.video.muted = true; this.video.srcObject = new MediaStream([this.track]); this.viewWrapper.appendChild(this.video); this.cacheCanvasOptions = {}; this.bind(view); } setContentMode(mode = trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit) { this.contentMode = mode; } bind(viewContainer) { this.viewContainer = viewContainer; if (this.viewWrapper) { this.viewContainer.appendChild(this.viewWrapper); } } unbind() { var _a; if (this.viewWrapper && this.viewContainer && this.viewWrapper.parentElement === this.viewContainer) { this.viewContainer.removeChild(this.viewWrapper); } else { logger_1.default.warn("VideoRenderer unbind error: remove viewWrapper error", this.viewWrapper, this.viewContainer, (_a = this.viewContainer) === null || _a === void 0 ? void 0 : _a.parentElement); } this.viewContainer = null; } drawFrame(frameData) { return __awaiter(this, void 0, void 0, function* () { switch (this.pixelFormat) { case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420: case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_RGBA32: case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32: yield this._drawFrameNonH264(frameData); break; case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_H264: yield this._drawFrameH264(frameData); break; default: logger_1.default.warn('VideoRenderer.drawFrame error. Not support video format:', this.pixelFormat); } }); } _drawFrameH264(frameData) { // To-do logger_1.default.warn('H264 renderer not supported right now'); } _drawFrameNonH264(frameData) { return __awaiter(this, void 0, void 0, function* () { 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.writer) { this._updateVideoStyle({ contentWidth: width, contentHeight: height, containerWidth: this.viewWrapper.clientWidth, containerHeight: this.viewWrapper.clientHeight, contentMode: this.contentMode, rotation, isNeedRotate, isNeedMirror: false, }); const vf = new window.VideoFrame(frameData.data, { format: this.pixelFormatStr, codedWidth: frameData.width, codedHeight: frameData.height, timestamp: frameData.timestamp, }); try { yield this.writer.write(vf); } finally { vf.close(); } } else { throw new Error('renderer container element is null'); } } catch (err) { logger_1.default.error('VideoRenderer._drawFrameNonH264 error:', err); } }); } _getPixelFormat() { switch (this.pixelFormat) { case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_I420: return 'I420'; case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_RGBA32: return 'RGBA'; case trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32: return 'BGRA'; default: return ''; } } _updateVideoStyle(options) { if (this.video) { if ((0, lodash_isequal_1.default)(this.cacheCanvasOptions, options)) { return; } this.cacheCanvasOptions = Object.assign({}, options); const style = (0, util_1.calcVideoStyle)(options); Object.keys(style).forEach(key => { // @ts-ignore this.video.style[key] = style[key]; }); } else { throw new Error('video 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() { this.unbind(); this.viewWrapper = null; if (this.video) { this.video.srcObject = null; this.video = null; } this.track = null; this.writer = null; this.cacheCanvasOptions = null; } } exports.default = VideoRenderer;