diff --git a/components/codecs/include/ftl/codecs/channels.hpp b/components/codecs/include/ftl/codecs/channels.hpp index b6aba67dd9e142c90ed3bb45fce31a2775c1be62..17197c31b126e5e8bf373b139c8efd7e56e5d9b6 100644 --- a/components/codecs/include/ftl/codecs/channels.hpp +++ b/components/codecs/include/ftl/codecs/channels.hpp @@ -56,6 +56,7 @@ enum struct Channel : int { MetaData = 71, // Map of string pairs (key, value) Capabilities = 72, // Unordered set of int capabilities CalibrationData = 73, // Just for stereo intrinsics/extrinsics etc + Thumbnail = 74, // Small JPG thumbnail, sometimes updated Data = 2048, // Custom data, any codec. Faces = 2049, // Data about detected faces diff --git a/components/rgbd-sources/src/sources/stereovideo/device.hpp b/components/rgbd-sources/src/sources/stereovideo/device.hpp index 40f526c0adfe53f83f2191ee400bf53c8a16d3e9..f575ea3aec6b23ccbfe755690e3e6bc4a94e7b6d 100644 --- a/components/rgbd-sources/src/sources/stereovideo/device.hpp +++ b/components/rgbd-sources/src/sources/stereovideo/device.hpp @@ -7,6 +7,8 @@ namespace ftl { namespace rgbd { +class Frame; + namespace detail { class StereoRectification; @@ -33,7 +35,7 @@ class Device : public Configurable { //virtual const std::vector<DeviceDetails> &listDevices()=0; virtual bool grab()=0; - virtual bool get(cv::cuda::GpuMat &l, cv::cuda::GpuMat &r, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream)=0; + virtual bool get(ftl::rgbd::Frame &frame, cv::cuda::GpuMat &l, cv::cuda::GpuMat &r, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream)=0; virtual unsigned int width() const =0; virtual unsigned int height() const =0; diff --git a/components/rgbd-sources/src/sources/stereovideo/opencv.cpp b/components/rgbd-sources/src/sources/stereovideo/opencv.cpp index aefae673e1cc320308e47da6cb65b08faae0e070..ba48e7b262dfc45c646ef66baeb9a62750531b84 100644 --- a/components/rgbd-sources/src/sources/stereovideo/opencv.cpp +++ b/components/rgbd-sources/src/sources/stereovideo/opencv.cpp @@ -8,12 +8,14 @@ #include <chrono> #include <ftl/threads.hpp> #include <ftl/profiler.hpp> +#include <ftl/rgbd/frame.hpp> #include "opencv.hpp" #include "rectification.hpp" #include <opencv2/core.hpp> #include <opencv2/opencv.hpp> #include <opencv2/xphoto.hpp> +#include <opencv2/imgcodecs.hpp> #include <ftl/timer.hpp> @@ -323,7 +325,7 @@ bool OpenCVDevice::grab() { return true; } -bool OpenCVDevice::get(cv::cuda::GpuMat &l_out, cv::cuda::GpuMat &r_out, +bool OpenCVDevice::get(ftl::rgbd::Frame &frame, cv::cuda::GpuMat &l_out, cv::cuda::GpuMat &r_out, cv::cuda::GpuMat &l_hres_out, cv::Mat &r_hres_out, StereoRectification *c, cv::cuda::Stream &stream) { Mat l, r ,hres; @@ -413,6 +415,14 @@ bool OpenCVDevice::get(cv::cuda::GpuMat &l_out, cv::cuda::GpuMat &r_out, } //r_out.upload(r, stream); + if (!frame.hasChannel(Channel::Thumbnail)) { + cv::Mat thumb; + cv::resize(l, thumb, cv::Size(320,240)); + auto &thumbdata = frame.create<std::vector<uint8_t>>(Channel::Thumbnail); + std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 70}; + cv::imencode(".jpg", thumb, thumbdata, params); + } + if (camera_b_) { //FTL_Profile("WaitCamB", 0.05); future_b.wait(); diff --git a/components/rgbd-sources/src/sources/stereovideo/opencv.hpp b/components/rgbd-sources/src/sources/stereovideo/opencv.hpp index 1ea18d8f3a3492290c68b89bbe963769567b34d1..e0f10ca1e5329cff94545d00a97e20e638ae1b78 100644 --- a/components/rgbd-sources/src/sources/stereovideo/opencv.hpp +++ b/components/rgbd-sources/src/sources/stereovideo/opencv.hpp @@ -20,7 +20,7 @@ class OpenCVDevice : public ftl::rgbd::detail::Device { static std::vector<DeviceDetails> listDevices(); bool grab() override; - bool get(cv::cuda::GpuMat &l, cv::cuda::GpuMat &r, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream) override; + bool get(ftl::rgbd::Frame &frame, cv::cuda::GpuMat &l, cv::cuda::GpuMat &r, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream) override; unsigned int width() const override { return dwidth_; } unsigned int height() const override { return dheight_; } diff --git a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp index f479014475a0366efcfe6cd822fa52a54191e2e2..160c389e10a8ae59a529a3dc7a4ac2b9fee8ee28 100644 --- a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp +++ b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp @@ -6,6 +6,7 @@ #include <ftl/threads.hpp> #include <ftl/rgbd/source.hpp> #include <ftl/profiler.hpp> +#include <ftl/rgbd/frame.hpp> #include <pylon/PylonIncludes.h> #include <pylon/BaslerUniversalInstantCamera.h> @@ -215,7 +216,7 @@ bool PylonDevice::_retrieveFrames(Pylon::CGrabResultPtr &result, Pylon::CBaslerU return true; } -bool PylonDevice::get(cv::cuda::GpuMat &l_out, cv::cuda::GpuMat &r_out, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream) { +bool PylonDevice::get(ftl::rgbd::Frame &frame, cv::cuda::GpuMat &l_out, cv::cuda::GpuMat &r_out, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream) { if (!isReady()) return false; Mat l, r ,hres; diff --git a/components/rgbd-sources/src/sources/stereovideo/pylon.hpp b/components/rgbd-sources/src/sources/stereovideo/pylon.hpp index 6331b418deb50297f3106c55543ecce076c63fa4..70c82a3da316fa7b7f21bab45830b8880f363768 100644 --- a/components/rgbd-sources/src/sources/stereovideo/pylon.hpp +++ b/components/rgbd-sources/src/sources/stereovideo/pylon.hpp @@ -22,7 +22,7 @@ class PylonDevice : public ftl::rgbd::detail::Device { static std::vector<DeviceDetails> listDevices(); bool grab() override; - bool get(cv::cuda::GpuMat &l, cv::cuda::GpuMat &r, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream) override; + bool get(ftl::rgbd::Frame &frame, cv::cuda::GpuMat &l, cv::cuda::GpuMat &r, cv::cuda::GpuMat &h_l, cv::Mat &h_r, StereoRectification *c, cv::cuda::Stream &stream) override; unsigned int width() const override { return width_; } unsigned int height() const override { return height_; }; diff --git a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp index 93883e5aafed354f24b311fa54842e2a43c59262..547e84382260ba3f2eb27c8937b95511427d6d6c 100644 --- a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp +++ b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp @@ -341,7 +341,7 @@ bool StereoVideoSource::retrieve(ftl::rgbd::Frame &frame) { if (lsrc_->isStereo()) { cv::cuda::GpuMat &left = frame.create<cv::cuda::GpuMat>(Channel::Left); cv::cuda::GpuMat &right = frame.create<cv::cuda::GpuMat>(Channel::Right); - if (!lsrc_->get(left, right, hres, hres_r, rectification_.get(), stream2_)) { + if (!lsrc_->get(frame, left, right, hres, hres_r, rectification_.get(), stream2_)) { frame.remove(Channel::Left); frame.remove(Channel::Right); } @@ -349,7 +349,7 @@ bool StereoVideoSource::retrieve(ftl::rgbd::Frame &frame) { else { cv::cuda::GpuMat &left = frame.create<cv::cuda::GpuMat>(Channel::Left); cv::cuda::GpuMat right; - if (!lsrc_->get(left, right, hres, hres_r, rectification_.get(), stream2_)) { + if (!lsrc_->get(frame, left, right, hres, hres_r, rectification_.get(), stream2_)) { frame.remove(Channel::Left); } } diff --git a/components/streams/src/feed.cpp b/components/streams/src/feed.cpp index a4bea0efeff283f61d59647417caa35bd9b33eb6..9a5974093b496d43897da9e57f7d9fcc077652dd 100644 --- a/components/streams/src/feed.cpp +++ b/components/streams/src/feed.cpp @@ -182,6 +182,10 @@ Feed::Feed(nlohmann::json &config, ftl::net::Universe*net) : std::atomic_store(&latest_.at(fs->frameset()), fs); + if (fs->hasAnyChanged(Channel::Thumbnail)) { + _saveThumbnail(fs); + } + for (auto* filter : filters_) { // TODO: smarter update (update only when changed) instead of // filter->channels_available_ = fs->channels(); @@ -253,6 +257,9 @@ Feed::~Feed() { } } +void Feed::_saveThumbnail(const ftl::data::FrameSetPtr& fs) { + // TODO: Put thumb somewhere here... +} uint32_t Feed::allocateFrameSetId(const std::string &group) { if (group.size() == 0) {