trtc-electron-sdk
Version:
trtc electron sdk
170 lines (169 loc) • 7.39 kB
JavaScript
"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;