UNPKG

@deepwaterexploration/dwe-controls

Version:

Web Based UVC Control Driver for the DeepWater Exploration exploreHD and HDCam

155 lines (131 loc) 4.86 kB
const gstreamer = require('gstreamer-superficial'); function buildPipeline(device, host, port, width=1920, height=1080) { // construct the gstreamer streaming pipeline // TODO: support for width and height variability return new gstreamer.Pipeline( `v4l2src device=${device} ! video/x-h264, width=${width},height=${height}! h264parse ! queue ! rtph264pay config-interval=10 pt=96 ! udpsink host=${host} port=${port} sync=false` ); } // simple abstraction representing a gstreamer stream class Stream { constructor(device, host, port, width=1920, height=1080) { this.device = device; this.host = host; this.port = port; this.width = width; this.height = height; this.usingPortSuggestion = false; this.rebuildPipeline(); } rebuildPipeline() { this.pipeline = buildPipeline(this.device, this.host, parseInt(this.port), this.width, this.height); } // setResolution(resolution) { // let [width, height] = resolution.split('x'); // console.log(width, height); // } start() { this.pipeline.play(); } stop() { this.pipeline.stop(); } getSerializable() { return { device: this.device, host: this.host }; } } class StreamManager { static nextPort = 5600; static streams = []; static freePorts = []; static getNextPort() { // if there is an additional free port, utilize that // otherwise, offset from the current stream length if (this.freePorts.length !== 0) { this.nextPort = this.freePorts.pop(); } else { this.nextPort = 5600 + this.streams.length; } return this.nextPort; } static resetAll() { this.nextPort = 5600; // stop all streams for (let stream of this.streams) { stream.stop(); } this.streams = []; this.freePorts = []; } static restartStream(device, host, port, width=undefined, height=undefined) { this.stopStream(device); return this.startStream(device, host, port, width, height); } static serializeStreams() { let result = []; for (let stream of this.streams) { let serialized = { host: stream.host, width: stream.width, height: stream.height }; if (stream.usingPortSuggestion) serialized.port = stream.port; result.push(serialized); } return result; } static addStream(device, host, width=undefined, height=undefined) { // create stream using the specified host and device while computing the port let stream = new Stream(device, host, this.getNextPort(), width, height); console.log(`Created stream for ${device} on port ${stream.port} to ${host}`); this.streams.push(stream); return stream; } static findStreamIndex(device) { return this.streams.findIndex(stream => stream.device === device); } static getStream(device) { return this.streams.find(stream => stream.device === device); } static startStream(device, host, port=null, width=undefined, height=undefined) { // find the index of the stream with the specified device let streamIndex = this.findStreamIndex(device); let stream = null; let usingPortSuggestion = false; if (port != null) { if (this.streams.find((stream) => stream.port == port) == undefined) { this.freePorts.push(port); // suggest the port usingPortSuggestion = true; } else { console.log('Port suggestion is in use, using last used port instead.'); } } // if the stream cannot be found, create one if (streamIndex === -1) { stream = this.addStream(device, host, width, height); } else { stream = this.streams[streamIndex]; } stream.start(); stream.usingPortSuggestion = usingPortSuggestion; return stream; } static stopStream(device) { let streamIndex = this.findStreamIndex(device); if (streamIndex === -1) return; // destroy the found stream let stream = this.streams[streamIndex]; if (stream !== null) { stream.stop(); let freePort = stream.port; this.freePorts.push(freePort); this.streams.splice(streamIndex, 1); console.log(`Deleted stream for ${device} previously running on port ${freePort}`); } else { throw new Error(`The specified stream from '${device}' cannot be found!`); } } } module.exports = StreamManager;