diff --git a/applications/gui/src/camera.cpp b/applications/gui/src/camera.cpp index 8686a608097805e60f715b2e16549c658812361d..0c3b587789b8abf744f3591d02abf00a4c1a8a2c 100644 --- a/applications/gui/src/camera.cpp +++ b/applications/gui/src/camera.cpp @@ -834,12 +834,17 @@ void ftl::gui::Camera::snapshot(const std::string &filename) { do_snapshot_ = true; } -void ftl::gui::Camera::startVideoRecording(const std::string &filename) { +void ftl::gui::Camera::startVideoRecording(const std::string &filename, const std::string &uri) { if (!record_stream_) { - record_stream_ = ftl::create<ftl::stream::File>(screen_->root(), "video2d"); - record_stream_->setMode(ftl::stream::File::Mode::Write); + file_stream_ = ftl::create<ftl::stream::File>(screen_->root(), "video2d"); + file_stream_->setMode(ftl::stream::File::Mode::Write); + net_stream_ = ftl::create<ftl::stream::Net>(screen_->root(), "liveStream", screen_->net()); + + record_stream_ = ftl::create<ftl::stream::Broadcast>(screen_->root(), "recordStream"); + //record_stream_->add(file_stream_); + //record_stream_->add(net_stream_); + record_sender_ = ftl::create<ftl::stream::Sender>(screen_->root(), "videoEncode"); - record_sender_->setStream(record_stream_); record_sender_->value("codec", 2); // Default H264 record_sender_->set("iframes", 50); // Add iframes by default record_sender_->value("stereo", true); // If both channels, then default to stereo @@ -847,8 +852,22 @@ void ftl::gui::Camera::startVideoRecording(const std::string &filename) { if (record_stream_->active()) return; - record_stream_->set("filename", filename); - record_stream_->begin(); + record_stream_->clear(); + + if (filename.size() > 0) { + file_stream_->set("filename", filename); + record_stream_->add(file_stream_); + } + + if (uri.size() > 0) { + net_stream_->set("uri", uri); + record_stream_->add(net_stream_); + } + + record_sender_->setStream(record_stream_); + + LOG(INFO) << "About to record"; + if (record_stream_->begin()) LOG(INFO) << "Recording started..."; } void ftl::gui::Camera::stopVideoRecording() { diff --git a/applications/gui/src/camera.hpp b/applications/gui/src/camera.hpp index cb34ff0f7a3046719c438e0e2c81e752090c2294..730ba380dbe8586be61ecf4ceef4ad82ff5588fc 100644 --- a/applications/gui/src/camera.hpp +++ b/applications/gui/src/camera.hpp @@ -8,6 +8,7 @@ #include "gltexture.hpp" #include <ftl/streams/filestream.hpp> +#include <ftl/streams/netstream.hpp> #include <ftl/streams/sender.hpp> #include <ftl/codecs/faces.hpp> @@ -96,7 +97,7 @@ class Camera { void snapshot(const std::string &filename); - void startVideoRecording(const std::string &filename); + void startVideoRecording(const std::string &filename, const std::string &uri); void stopVideoRecording(); @@ -173,7 +174,9 @@ class Camera { ftl::operators::Graph *post_pipe_; ftl::rgbd::Frame frame_; ftl::rgbd::FrameState state_; - ftl::stream::File *record_stream_; + ftl::stream::File *file_stream_; + ftl::stream::Net *net_stream_; + ftl::stream::Broadcast *record_stream_; ftl::stream::Sender *record_sender_; std::string name_; diff --git a/applications/gui/src/media_panel.cpp b/applications/gui/src/media_panel.cpp index 182324deb9d628f716bac0d515a41d2c9c30c0ed..2801e2dc896d0861aa0b890cffa2e11405ef3e44 100644 --- a/applications/gui/src/media_panel.cpp +++ b/applications/gui/src/media_panel.cpp @@ -54,6 +54,12 @@ MediaPanel::MediaPanel(ftl::gui::Screen *screen, ftl::gui::SourceWindow *sourceW recordbutton_->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); recordbutton_->setPushed(false); }); + itembutton = new Button(recordpopup, "Virtual camera Live"); + itembutton->setCallback([this]() { + _startRecording(RecordMode::Live2D); + recordbutton_->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); + recordbutton_->setPushed(false); + }); itembutton = new Button(recordpopup, "3D scene snapshot (.ftl)"); itembutton->setCallback([this]() { _startRecording(RecordMode::Snapshot3D); @@ -208,6 +214,7 @@ void MediaPanel::_startRecording(MediaPanel::RecordMode mode) { case RecordMode::Snapshot3D : case RecordMode::Video3D : filename += ".ftl"; break; case RecordMode::Video2D : filename += ".ftl"; break; + case RecordMode::Live2D : break; default: return; } @@ -218,14 +225,16 @@ void MediaPanel::_startRecording(MediaPanel::RecordMode mode) { screen_->activeCamera()->snapshot(filename); } else if (mode == RecordMode::Video2D) { record_mode_ = mode; - screen_->activeCamera()->startVideoRecording(filename); + screen_->activeCamera()->startVideoRecording(filename, ""); + } else if (mode == RecordMode::Live2D) { + screen_->activeCamera()->startVideoRecording("", "ftl://live.utu.fi"); } } void MediaPanel::_stopRecording() { if (record_mode_ == RecordMode::Video3D) { sourceWindow_->stopRecordingVideo(); - } else if (record_mode_ == RecordMode::Video2D) { + } else if (record_mode_ == RecordMode::Video2D || record_mode_ == RecordMode::Live2D) { screen_->activeCamera()->stopVideoRecording(); } record_mode_ = RecordMode::None; diff --git a/applications/gui/src/media_panel.hpp b/applications/gui/src/media_panel.hpp index 94700cad073c00fec51bfd5135476938d510de06..f615be1f6079808fcce71500840f6fc8c6652ac9 100644 --- a/applications/gui/src/media_panel.hpp +++ b/applications/gui/src/media_panel.hpp @@ -56,7 +56,9 @@ class MediaPanel : public nanogui::Window { Snapshot2D, Snapshot3D, Video2D, - Video3D + Video3D, + Live2D, + Live3D }; RecordMode record_mode_; diff --git a/components/net/cpp/src/ws_internal.cpp b/components/net/cpp/src/ws_internal.cpp index c0cf9630bdb21e2bb23810335d6d44fa5391047a..db9393d2a5350f07c69b5ce514f59f6ccdfe68b5 100644 --- a/components/net/cpp/src/ws_internal.cpp +++ b/components/net/cpp/src/ws_internal.cpp @@ -203,7 +203,7 @@ bool ftl::net::ws_connect(SOCKET sockfd, const URI &uri) { http += "\r\n"; int rc = ::send(sockfd, http.c_str(), (int)http.length(), 0); if (rc != (int)http.length()) { - LOG(ERROR) << "Could not send Websocket http request..."; + LOG(ERROR) << "Could not send Websocket http request... (" << rc << ", " << errno << ")"; std::cout << http; return false; } diff --git a/components/streams/include/ftl/streams/stream.hpp b/components/streams/include/ftl/streams/stream.hpp index 75aa9ab806baaf8ab7cf863188c3119856959a79..4baa178a97c7abd8fec3d7d3a2777dd81751cac4 100644 --- a/components/streams/include/ftl/streams/stream.hpp +++ b/components/streams/include/ftl/streams/stream.hpp @@ -155,6 +155,8 @@ class Broadcast : public Stream { virtual ~Broadcast(); void add(Stream *); + void remove(Stream *); + void clear(); bool onPacket(const std::function<void(const ftl::codecs::StreamPacket &, const ftl::codecs::Packet &)> &) override; diff --git a/components/streams/src/netstream.cpp b/components/streams/src/netstream.cpp index 0cba3f4dc533a3cfd71b116e0da9709718fbe3da..0484ed2e70ac13a4289d5b8af93c9f05bf25b0a8 100644 --- a/components/streams/src/netstream.cpp +++ b/components/streams/src/netstream.cpp @@ -231,6 +231,9 @@ bool Net::begin() { LOG(INFO) << "Hosting stream: " << uri_; // TODO: Register URI as available. host_ = true; + + net_->broadcast("add_stream", uri_); + return true; } else { //LOG(INFO) << "Net cfg: " << net_->call<std::string>(*p, "get_cfg", uri_); @@ -275,7 +278,7 @@ bool Net::_sendRequest(Channel c, uint8_t frameset, uint8_t frames, uint8_t coun StreamPacket spkt = { 4, ftl::timer::get_time(), - frameset, + 0, frames, c, 0, diff --git a/components/streams/src/stream.cpp b/components/streams/src/stream.cpp index 22d8768d473074b26a62d12d029349562180c287..43c53eae64c7ace22ef9026d2a4148c8889f5628 100644 --- a/components/streams/src/stream.cpp +++ b/components/streams/src/stream.cpp @@ -180,12 +180,29 @@ void Broadcast::add(Stream *s) { UNIQUE_LOCK(mutex_,lk); streams_.push_back(s); - s->onPacket([this](const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { + s->onPacket([this,s](const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { + LOG(INFO) << "BCAST Request: " << (int)spkt.streamID << " " << (int)spkt.channel << " " << spkt.timestamp; SHARED_LOCK(mutex_, lk); + if (spkt.frameSetID() < 255) available(spkt.frameSetID()) += spkt.channel; if (cb_) cb_(spkt, pkt); + if (spkt.streamID < 255) s->select(spkt.streamID, selected(spkt.streamID)); }); } +void Broadcast::remove(Stream *s) { + UNIQUE_LOCK(mutex_,lk); + s->onPacket(nullptr); + streams_.remove(s); +} + +void Broadcast::clear() { + UNIQUE_LOCK(mutex_,lk); + for (auto s : streams_) { + s->onPacket(nullptr); + } + streams_.clear(); +} + bool Broadcast::onPacket(const std::function<void(const ftl::codecs::StreamPacket &, const ftl::codecs::Packet &)> &cb) { UNIQUE_LOCK(mutex_,lk); cb_ = cb; @@ -194,9 +211,11 @@ bool Broadcast::onPacket(const std::function<void(const ftl::codecs::StreamPacke bool Broadcast::post(const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { SHARED_LOCK(mutex_, lk); - + if (spkt.frameSetID() < 255) available(spkt.frameSetID()) += spkt.channel; + bool status = true; for (auto s : streams_) { + //s->select(spkt.frameSetID(), selected(spkt.frameSetID())); status = status && s->post(spkt, pkt); } return status; @@ -219,6 +238,7 @@ bool Broadcast::end() { } bool Broadcast::active() { + if (streams_.size() == 0) return false; bool r = true; for (auto &s : streams_) { r = r && s->active(); diff --git a/web-service/public/js/bundle.js b/web-service/public/js/bundle.js index df7eec769a1efa2850c96cdede4cd698835a6c56..65d67c028e8ae6ee0975fe14e9bc9326a94de0e1 100644 --- a/web-service/public/js/bundle.js +++ b/web-service/public/js/bundle.js @@ -1,4 +1,5 @@ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ +(function (Buffer){ const Peer = require('../../server/src/peer') const VideoConverter = require('./lib/dist/video-converter'); @@ -108,8 +109,8 @@ createCard = (url, viewers) => { createPeer = () => { // FOR PRODUCTION - const ws = new WebSocket("ws://" + location.host + ":" + (location.port == "" ? "80" : location.port) + location.pathname); - // const ws = new WebSocket("ws://localhost:8080") + //const ws = new WebSocket("ws://" + location.host + ":" + (location.port == "" ? "80" : location.port) + location.pathname); + const ws = new WebSocket("ws://localhost:8080") ws.binaryType = "arraybuffer"; peer = new Peer(ws) } @@ -121,20 +122,45 @@ webSocketTest = () => { connectToStream = () => { const element = document.getElementById('ftlab-stream-video'); - const converter = new VideoConverter.default(element, 20, 6); + let converter = null; + + let rxcount = 0; + let ts = 0; + let dts = 0; peer.bind(current_data.uri, (latency, streampckg, pckg) => { if(pckg[0] === 2){ - function decode(value){ - converter.appendRawData(value); + rxcount++; + if (rxcount >= 25) { + rxcount = 0; + peer.send(current_data.uri, 0, [1,0,255,0],[255,7,35,0,0,Buffer.alloc(0)]); + //peer.send(current_data.uri, 0, [255,7,35,0,0,Buffer.alloc(0)], [1,0,255,0]); + } + + if (converter) { + function decode(value){ + converter.appendRawData(value); + } + decode(pckg[5]); + converter.play(); + } else { + if (ts > 0) { + dts = streampckg[0] - ts; + console.log("Framerate = ", 1000/dts); + converter = new VideoConverter.default(element, 1000/dts, 6); + } + ts = streampckg[0]; } - decode(pckg[5]); - converter.play(); }; }) // Start the transaction - peer.send("get_stream", (current_data.uri, 30, 0, current_data.uri)); + //peer.send("get_stream", (current_data.uri, 30, 0, current_data.uri)); + + peer.rpc("find_stream", (res) => { + peer.send(current_data.uri, 0, [1,0,255,0],[255,7,35,0,0,Buffer.alloc(0)]); + //peer.send(current_data.uri, [255,7,35,0,0,Buffer.alloc(0)], [1,0,255,0]); + }, current_data.uri); } closeStream = () => { @@ -194,7 +220,8 @@ saveConfigs = async () => { }); const content = await rawResp.json(); } -},{"../../server/src/peer":36,"./lib/dist/video-converter":9}],2:[function(require,module,exports){ +}).call(this,require("buffer").Buffer) +},{"../../server/src/peer":36,"./lib/dist/video-converter":9,"buffer":44}],2:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var bit_stream_1 = require("./util/bit-stream"); @@ -1914,7 +1941,7 @@ BufferList.prototype._match = function(offset, search) { module.exports = BufferList -},{"readable-stream":28,"safe-buffer":29,"util":53}],11:[function(require,module,exports){ +},{"readable-stream":27,"safe-buffer":28,"util":53}],11:[function(require,module,exports){ (function (Buffer){ // Copyright Joyent, Inc. and other Node contributors. // @@ -2144,7 +2171,7 @@ function msgpack (options) { module.exports = msgpack -},{"./lib/decoder":15,"./lib/encoder":16,"./lib/streams":17,"assert":38,"bl":10,"safe-buffer":29}],15:[function(require,module,exports){ +},{"./lib/decoder":15,"./lib/encoder":16,"./lib/streams":17,"assert":38,"bl":10,"safe-buffer":28}],15:[function(require,module,exports){ 'use strict' var bl = require('bl') @@ -2927,7 +2954,7 @@ function encodeFloat (obj, forceFloat64) { return buf } -},{"bl":10,"safe-buffer":29}],17:[function(require,module,exports){ +},{"bl":10,"safe-buffer":28}],17:[function(require,module,exports){ 'use strict' var Transform = require('readable-stream').Transform @@ -3019,7 +3046,7 @@ Decoder.prototype._transform = function (buf, enc, done) { module.exports.decoder = Decoder module.exports.encoder = Encoder -},{"bl":10,"inherits":12,"readable-stream":28}],18:[function(require,module,exports){ +},{"bl":10,"inherits":12,"readable-stream":27}],18:[function(require,module,exports){ (function (process){ 'use strict'; @@ -3114,7 +3141,7 @@ var objectKeys = Object.keys || function (obj) { module.exports = Duplex; /*<replacement>*/ -var util = require('core-util-is'); +var util = Object.create(require('core-util-is')); util.inherits = require('inherits'); /*</replacement>*/ @@ -3233,7 +3260,7 @@ module.exports = PassThrough; var Transform = require('./_stream_transform'); /*<replacement>*/ -var util = require('core-util-is'); +var util = Object.create(require('core-util-is')); util.inherits = require('inherits'); /*</replacement>*/ @@ -3316,7 +3343,7 @@ function _isUint8Array(obj) { /*</replacement>*/ /*<replacement>*/ -var util = require('core-util-is'); +var util = Object.create(require('core-util-is')); util.inherits = require('inherits'); /*</replacement>*/ @@ -4270,7 +4297,7 @@ function indexOf(xs, x) { return -1; } }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./_stream_duplex":19,"./internal/streams/BufferList":24,"./internal/streams/destroy":25,"./internal/streams/stream":26,"_process":49,"core-util-is":11,"events":45,"inherits":12,"isarray":13,"process-nextick-args":18,"safe-buffer":29,"string_decoder/":27,"util":43}],22:[function(require,module,exports){ +},{"./_stream_duplex":19,"./internal/streams/BufferList":24,"./internal/streams/destroy":25,"./internal/streams/stream":26,"_process":49,"core-util-is":11,"events":45,"inherits":12,"isarray":13,"process-nextick-args":18,"safe-buffer":28,"string_decoder/":29,"util":43}],22:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -4341,7 +4368,7 @@ module.exports = Transform; var Duplex = require('./_stream_duplex'); /*<replacement>*/ -var util = require('core-util-is'); +var util = Object.create(require('core-util-is')); util.inherits = require('inherits'); /*</replacement>*/ @@ -4553,7 +4580,7 @@ var Duplex; Writable.WritableState = WritableState; /*<replacement>*/ -var util = require('core-util-is'); +var util = Object.create(require('core-util-is')); util.inherits = require('inherits'); /*</replacement>*/ @@ -5175,7 +5202,7 @@ Writable.prototype._destroy = function (err, cb) { cb(err); }; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate) -},{"./_stream_duplex":19,"./internal/streams/destroy":25,"./internal/streams/stream":26,"_process":49,"core-util-is":11,"inherits":12,"process-nextick-args":18,"safe-buffer":29,"timers":50,"util-deprecate":30}],24:[function(require,module,exports){ +},{"./_stream_duplex":19,"./internal/streams/destroy":25,"./internal/streams/stream":26,"_process":49,"core-util-is":11,"inherits":12,"process-nextick-args":18,"safe-buffer":28,"timers":50,"util-deprecate":30}],24:[function(require,module,exports){ 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -5255,7 +5282,7 @@ if (util && util.inspect && util.inspect.custom) { return this.constructor.name + ' ' + obj; }; } -},{"safe-buffer":29,"util":43}],25:[function(require,module,exports){ +},{"safe-buffer":28,"util":43}],25:[function(require,module,exports){ 'use strict'; /*<replacement>*/ @@ -5334,6 +5361,79 @@ module.exports = { module.exports = require('events').EventEmitter; },{"events":45}],27:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":19,"./lib/_stream_passthrough.js":20,"./lib/_stream_readable.js":21,"./lib/_stream_transform.js":22,"./lib/_stream_writable.js":23}],28:[function(require,module,exports){ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"buffer":44}],29:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -5630,80 +5730,7 @@ function simpleWrite(buf) { function simpleEnd(buf) { return buf && buf.length ? this.write(buf) : ''; } -},{"safe-buffer":29}],28:[function(require,module,exports){ -exports = module.exports = require('./lib/_stream_readable.js'); -exports.Stream = exports; -exports.Readable = exports; -exports.Writable = require('./lib/_stream_writable.js'); -exports.Duplex = require('./lib/_stream_duplex.js'); -exports.Transform = require('./lib/_stream_transform.js'); -exports.PassThrough = require('./lib/_stream_passthrough.js'); - -},{"./lib/_stream_duplex.js":19,"./lib/_stream_passthrough.js":20,"./lib/_stream_readable.js":21,"./lib/_stream_transform.js":22,"./lib/_stream_writable.js":23}],29:[function(require,module,exports){ -/* eslint-disable node/no-deprecated-api */ -var buffer = require('buffer') -var Buffer = buffer.Buffer - -// alternative to using Object.keys for old browsers -function copyProps (src, dst) { - for (var key in src) { - dst[key] = src[key] - } -} -if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { - module.exports = buffer -} else { - // Copy properties from require('buffer') - copyProps(buffer, exports) - exports.Buffer = SafeBuffer -} - -function SafeBuffer (arg, encodingOrOffset, length) { - return Buffer(arg, encodingOrOffset, length) -} - -// Copy static methods from Buffer -copyProps(Buffer, SafeBuffer) - -SafeBuffer.from = function (arg, encodingOrOffset, length) { - if (typeof arg === 'number') { - throw new TypeError('Argument must not be a number') - } - return Buffer(arg, encodingOrOffset, length) -} - -SafeBuffer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - var buf = Buffer(size) - if (fill !== undefined) { - if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) - } - } else { - buf.fill(0) - } - return buf -} - -SafeBuffer.allocUnsafe = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return Buffer(size) -} - -SafeBuffer.allocUnsafeSlow = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return buffer.SlowBuffer(size) -} - -},{"buffer":44}],30:[function(require,module,exports){ +},{"safe-buffer":28}],30:[function(require,module,exports){ (function (global){ /** @@ -5798,14 +5825,16 @@ function bytesToUuid(buf, offset) { var i = offset || 0; var bth = byteToHex; // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4 - return ([bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]]]).join(''); + return ([ + bth[buf[i++]], bth[buf[i++]], + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], '-', + bth[buf[i++]], bth[buf[i++]], + bth[buf[i++]], bth[buf[i++]], + bth[buf[i++]], bth[buf[i++]] + ]).join(''); } module.exports = bytesToUuid; @@ -5862,7 +5891,7 @@ var _clockseq; var _lastMSecs = 0; var _lastNSecs = 0; -// See https://github.com/broofa/node-uuid for API details +// See https://github.com/uuidjs/uuid for API details function v1(options, buf, offset) { var i = buf && offset || 0; var b = buf || []; @@ -6032,7 +6061,6 @@ function Peer(ws) { this.master = false; let message = (raw) => { - // console.log(raw) //Gets right data for client if(this.sock.on === undefined){ raw = raw.data; @@ -6177,6 +6205,10 @@ Peer.prototype.bind = function(name, f) { } } +Peer.prototype.isBound = function(name) { + return this.bindings.hasOwnProperty(name) || this.proxies.hasOwnProperty(name); +} + /** * Allow an RPC call to pass through to another machine with minimal local * processing. diff --git a/web-service/public/js/index.js b/web-service/public/js/index.js index 8ea42a108eefed4a1bcf9a3bddddb2a6c4fa628b..b48e75333e3cc10afc4830bc2349a8f0ca65e74c 100644 --- a/web-service/public/js/index.js +++ b/web-service/public/js/index.js @@ -107,8 +107,8 @@ createCard = (url, viewers) => { createPeer = () => { // FOR PRODUCTION - const ws = new WebSocket("ws://" + location.host + ":" + (location.port == "" ? "80" : location.port) + location.pathname); - // const ws = new WebSocket("ws://localhost:8080") + //const ws = new WebSocket("ws://" + location.host + ":" + (location.port == "" ? "80" : location.port) + location.pathname); + const ws = new WebSocket("ws://localhost:8080") ws.binaryType = "arraybuffer"; peer = new Peer(ws) } @@ -120,20 +120,45 @@ webSocketTest = () => { connectToStream = () => { const element = document.getElementById('ftlab-stream-video'); - const converter = new VideoConverter.default(element, 20, 6); + let converter = null; + + let rxcount = 0; + let ts = 0; + let dts = 0; peer.bind(current_data.uri, (latency, streampckg, pckg) => { if(pckg[0] === 2){ - function decode(value){ - converter.appendRawData(value); + rxcount++; + if (rxcount >= 25) { + rxcount = 0; + peer.send(current_data.uri, 0, [1,0,255,0],[255,7,35,0,0,Buffer.alloc(0)]); + //peer.send(current_data.uri, 0, [255,7,35,0,0,Buffer.alloc(0)], [1,0,255,0]); + } + + if (converter) { + function decode(value){ + converter.appendRawData(value); + } + decode(pckg[5]); + converter.play(); + } else { + if (ts > 0) { + dts = streampckg[0] - ts; + console.log("Framerate = ", 1000/dts); + converter = new VideoConverter.default(element, 1000/dts, 6); + } + ts = streampckg[0]; } - decode(pckg[5]); - converter.play(); }; }) // Start the transaction - peer.send("get_stream", (current_data.uri, 30, 0, current_data.uri)); + //peer.send("get_stream", (current_data.uri, 30, 0, current_data.uri)); + + peer.rpc("find_stream", (res) => { + peer.send(current_data.uri, 0, [1,0,255,0],[255,7,35,0,0,Buffer.alloc(0)]); + //peer.send(current_data.uri, [255,7,35,0,0,Buffer.alloc(0)], [1,0,255,0]); + }, current_data.uri); } closeStream = () => { diff --git a/web-service/server/src/index.js b/web-service/server/src/index.js index 339be2b6862219f605c50fa6200709db1fbf76f9..37a0683d2015eef0cdb256f16f5fbcea95dacb42 100644 --- a/web-service/server/src/index.js +++ b/web-service/server/src/index.js @@ -114,7 +114,7 @@ RGBDStream.prototype.subscribe = function() { //console.log("Subscribe to ", this.uri); // TODO: Don't hard code 9 here, instead use 9 for thumbnails and 0 for // the video... - this.peer.send("get_stream", this.uri, 10, 0, [Peer.uuid], this.uri); + //this.peer.send("get_stream", this.uri, 10, 0, [Peer.uuid], this.uri); } RGBDStream.prototype.pushFrames = function(latency, spacket, packet) { @@ -158,7 +158,7 @@ app.get('/streams', (req, res) => { app.get('/stream/rgb', (req, res) => { let uri = req.query.uri; if (uri_data.hasOwnProperty(uri)) { - uri_data[uri].peer.send("get_stream", uri, 3, 9, [Peer.uuid], uri); + //uri_data[uri].peer.send("get_stream", uri, 3, 9, [Peer.uuid], uri); res.writeHead(200, {'Content-Type': 'image/jpeg'}); res.end(uri_data[uri].rgb); } @@ -298,8 +298,9 @@ app.ws('/', (ws, req) => { if (puris) { for (let i=0; i<puris.length; i++) { console.log("Removing stream: ", puris[i]); - //delete uri_to_peer[puris[i]]; + delete uri_to_peer[puris[i]]; delete uri_data[puris[i]]; + //p.unbind(pu) } delete peer_uris[peer.string_id]; } @@ -331,11 +332,15 @@ app.ws('/', (ws, req) => { if (!p.isBound(uri)) { console.log("Adding local stream binding"); p.bind(uri, (ttimeoff, spkt, pkt) => { - console.log("STREAM: ", spkt); + console.log("STREAM: ", ttimeoff, spkt, pkt); let speer = uri_to_peer[parsedURI]; if (speer) { + try { uri_data[parsedURI].addClient(p); speer.send(parsedURI, ttimeoff, spkt, pkt); + } catch(e) { + console.error("EXCEPTION", e); + } } else if (speer) console.log("Stream response"); else console.error("No stream peer"); }); @@ -393,7 +398,7 @@ app.ws('/', (ws, req) => { }); // Request from frames from a source - p.bind("get_stream", (uri, N, rate, /*pid,*/ dest) => { + /*p.bind("get_stream", (uri, N, rate, dest) => { console.log(uri) const parsedURI = stringSplitter(uri); if(uri_data[uri]){ @@ -409,7 +414,7 @@ app.ws('/', (ws, req) => { console.log("Couldn't get stream for ", uri) return "{}"; } - }); + });*/ /** * Get JSON values for stream configuration