import {BufferNode, BufferQueue, ImagePool} from './BufferNode.js'; import YUVWebGLCanvas from './WebGLCanvas.js'; let Uniformity = true; let channelId = 0; let canvas = null; let drawer = null; let preWidth = null; let preHeight = null; let drawingStrategy = null; let frameInterval = null; let prevCodecType = null; let resizeCallback = null; let startTimestamp = 0; let frameTimestamp = null; let preTimestamp = 0; let progressTime = 0; let curTime = 0; let imagePool = new ImagePool; let bufferNode = null; let fileName = ""; let captureFlag = false; let isRendering = false; let defaultInterval = 16.7; let defaultMaxDelay = 20; let milisecond = 1e3; let maxDelay = null; let videoBufferQueue = null; let canvasElem = null; class VideoBufferNode extends BufferNode{ constructor(data, width, height, codecType, frameType, timeStamp){ super(); //console.log(data) this.buffer = data; this.width = width; this.height = height; this.codecType = codecType; this.frameType = frameType; this.timeStamp = timeStamp } } class VideoBufferQueue extends BufferQueue{ constructor() { super(); this.MAX_LENGTH = 30; } enqueue(data, width, height, codecType, frameType, timeStamp) { //console.log(arguments) if(this.size >= this.MAX_LENGTH) { this.clear(); } let node = new VideoBufferNode(data, width, height, codecType, frameType, timeStamp); if (this.first === null) { this.first = node } else { let tempNode = this.first; while (tempNode.next !== null) { tempNode = tempNode.next } tempNode.next = node } this.size += 1; return node } } class Size { constructor(width, height) { this.w = width; this.h = height; } toString() { return "(" + this.w + ", " + this.h + ")" } getHalfSize() { return new Size(this.w >>> 1, this.h >>> 1) } length() { return this.w * this.h } } class YUVPlayer { constructor(canvas){ drawingStrategy = "YUVWebGL"; prevCodecType = null; videoBufferQueue = new VideoBufferQueue; frameInterval = defaultInterval; isRendering = false canvasElem = canvas; } draw(data, width, height, codecType, frameType, timeStamp) { if (videoBufferQueue !== null) { videoBufferQueue.enqueue(data, width, height, codecType, frameType, timeStamp) } } startRendering() { if (startTimestamp === 0 && Uniformity !== false) { isRendering = true; window.requestAnimationFrame(drawingInTime) } } stopRendering() { isRendering = false; startTimestamp = 0 } setFPS(fps) { if (typeof fps === "undefined") { frameInterval = defaultInterval; maxDelay = defaultMaxDelay } else if (fps === 0) { frameInterval = defaultInterval; maxDelay = defaultMaxDelay } else { frameInterval = milisecond / fps; maxDelay = fps * 1 } } terminate() { startTimestamp = 0; frameTimestamp = null; if (videoBufferQueue !== null) { videoBufferQueue.clear(); videoBufferQueue = null } drawer = null } } function resize(width, height) { let size = new Size(width, height); canvas = canvasElem; switch (drawingStrategy) { case"YUVWebGL": drawer = new YUVWebGLCanvas(canvas, size); break; default: break } } function drawFrame(stepValue) { bufferNode = videoBufferQueue.dequeue(); if (bufferNode !== null && bufferNode.buffer !== null && (bufferNode.codecType === "mjpeg" || bufferNode.buffer.length > 0)) { if (typeof preWidth === "undefined" || typeof preHeight === "undefined" || preWidth !== bufferNode.width || preHeight !== bufferNode.height || prevCodecType !== bufferNode.codecType) { drawingStrategy = bufferNode.codecType === "h264" || bufferNode.codecType === "h265" ? "YUVWebGL" : "ImageWebGL"; resize(bufferNode.width, bufferNode.height); preWidth = bufferNode.width; preHeight = bufferNode.height; prevCodecType = bufferNode.codecType; if (typeof resizeCallback !== "undefined" && resizeCallback !== null) { resizeCallback("resize") } } frameTimestamp = bufferNode.timeStamp; //workerManager.timeStamp(frameTimestamp); if (typeof drawer !== "undefined") { drawer.drawCanvas(bufferNode.buffer); canvas.updatedCanvas = true; // if (captureFlag) { // captureFlag = false; // doCapture(canvas.toDataURL(), fileName) // } if (bufferNode.codecType === "mjpeg") { imagePool.free(bufferNode.buffer) } else { delete bufferNode.buffer; bufferNode.buffer = null } bufferNode.previous = null; bufferNode.next = null; bufferNode = null; return true } else { console.log("drawer is undefined in StreamDrawer!") } } else { } return false } function drawingInTime(timestamp) { let stampCheckTime = 200; if (isRendering === true) { if (startTimestamp === 0 || timestamp - startTimestamp < stampCheckTime) { if (startTimestamp === 0) { startTimestamp = timestamp } if (videoBufferQueue !== null) { window.requestAnimationFrame(drawingInTime) } return } curTime += timestamp - preTimestamp; if (curTime > progressTime) { if(drawFrame()) { progressTime += frameInterval } } if (curTime > milisecond) { progressTime = 0; curTime = 0 } preTimestamp = timestamp; window.requestAnimationFrame(drawingInTime) } } function drawImage(data) { if (typeof preWidth === "undefined" || typeof preHeight === "undefined" || preWidth !== data.width || preHeight !== data.height) { drawingStrategy = "ImageWebGL"; resize(data.width, data.height); preWidth = data.width; preHeight = data.height; resizeCallback("resize") } frameTimestamp = data.time; if (frameTimestamp !== null) { //workerManager.timeStamp(frameTimestamp) } if (typeof drawer !== "undefined") { drawer.drawCanvas(data); if (captureFlag) { captureFlag = false; //doCapture(canvas.toDataURL(), fileName) } imagePool.free(data); return true } else { console.log("drawer is undefined in StreamDrawer!") } return false } export default YUVPlayer;