From 0c1e5ad18823c8ae429902dd48fdbad1d10f3718 Mon Sep 17 00:00:00 2001 From: Nicolas Pope <nwpope@utu.fi> Date: Sun, 14 Jun 2020 13:49:02 +0300 Subject: [PATCH] WIP refactor to use new frame class --- .../codecs/include/ftl/codecs/channels.hpp | 1 + .../include/ftl/operators/smoothing.hpp | 12 +- .../src/disparity/bilateral_filter.cpp | 2 +- .../operators/src/disparity/libstereo.cpp | 2 +- components/operators/src/fusion/mvmls.cpp | 22 +- components/operators/src/mask.cpp | 2 +- components/operators/src/operator.cpp | 2 +- components/operators/src/smoothing.cpp | 60 ++-- .../cpp/include/ftl/render/CUDARender.hpp | 3 +- .../cpp/include/ftl/render/overlay.hpp | 2 +- components/renderers/cpp/src/CUDARender.cpp | 49 +-- components/renderers/cpp/src/colouriser.cpp | 2 +- components/renderers/cpp/src/overlay.cpp | 31 +- components/rgbd-sources/CMakeLists.txt | 6 +- .../rgbd-sources/include/ftl/rgbd/frame.hpp | 287 +++++------------- .../include/ftl/rgbd/frameset.hpp | 173 +---------- .../rgbd-sources/include/ftl/rgbd/source.hpp | 18 +- components/rgbd-sources/src/frame.cpp | 204 ++----------- components/rgbd-sources/src/source.cpp | 20 +- .../structures/include/ftl/data/new_frame.hpp | 23 +- components/structures/src/new_frame.cpp | 21 ++ 21 files changed, 272 insertions(+), 670 deletions(-) diff --git a/components/codecs/include/ftl/codecs/channels.hpp b/components/codecs/include/ftl/codecs/channels.hpp index 43ef166a2..d2c65328f 100644 --- a/components/codecs/include/ftl/codecs/channels.hpp +++ b/components/codecs/include/ftl/codecs/channels.hpp @@ -53,6 +53,7 @@ enum struct Channel : int { Index = 68, Control = 69, // For stream and encoder control Settings3 = 70, + Name = 71, Data = 2048, // Custom data, any codec. Faces = 2049, // Data about detected faces diff --git a/components/operators/include/ftl/operators/smoothing.hpp b/components/operators/include/ftl/operators/smoothing.hpp index 0dc463d2e..c42f801ed 100644 --- a/components/operators/include/ftl/operators/smoothing.hpp +++ b/components/operators/include/ftl/operators/smoothing.hpp @@ -23,7 +23,7 @@ class HFSmoother : public ftl::operators::Operator { private: cv::cuda::GpuMat temp_; - ftl::rgbd::Frame frames_[4]; + //ftl::rgbd::Frame frames_[4]; }; /** @@ -43,7 +43,7 @@ class SmoothChannel : public ftl::operators::Operator { bool apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t stream) override; private: - ftl::rgbd::Frame temp_[6]; + ftl::cuda::TextureObject<uchar4> temp_[6]; }; /** @@ -61,7 +61,7 @@ class SimpleMLS : public ftl::operators::Operator { bool apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t stream) override; private: - ftl::rgbd::Frame temp_; + ftl::data::Frame temp_; }; /** @@ -78,7 +78,7 @@ class ColourMLS : public ftl::operators::Operator { bool apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t stream) override; private: - ftl::rgbd::Frame temp_; + ftl::data::Frame temp_; }; /** @@ -125,7 +125,7 @@ class AggreMLS : public ftl::operators::Operator { ftl::cuda::TextureObject<float4> centroid_vert_; ftl::cuda::TextureObject<half4> normals_horiz_; - ftl::rgbd::Frame temp_; + ftl::data::Frame temp_; }; /** @@ -145,7 +145,7 @@ class AdaptiveMLS : public ftl::operators::Operator { bool apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t stream) override; private: - ftl::rgbd::Frame temp_; + ftl::data::Frame temp_; }; } diff --git a/components/operators/src/disparity/bilateral_filter.cpp b/components/operators/src/disparity/bilateral_filter.cpp index 4b14c3bb5..7ffce560c 100644 --- a/components/operators/src/disparity/bilateral_filter.cpp +++ b/components/operators/src/disparity/bilateral_filter.cpp @@ -56,7 +56,7 @@ bool DisparityBilateralFilter::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out auto cvstream = cv::cuda::StreamAccessor::wrapStream(stream); const GpuMat &rgb = in.get<GpuMat>(Channel::Colour); - GpuMat &disp_in = in.get<GpuMat>(Channel::Disparity); + const GpuMat &disp_in = in.get<GpuMat>(Channel::Disparity); GpuMat &disp_out = out.create<GpuMat>(Channel::Disparity); disp_int_.create(disp_in.size(), disp_in.type()); diff --git a/components/operators/src/disparity/libstereo.cpp b/components/operators/src/disparity/libstereo.cpp index 22aaac630..8531dd98f 100644 --- a/components/operators/src/disparity/libstereo.cpp +++ b/components/operators/src/disparity/libstereo.cpp @@ -56,7 +56,7 @@ bool StereoDisparity::apply(Frame &in, Frame &out, cudaStream_t stream) { disp32f_.create(l.size(), CV_32FC1); bool has_estimate = in.hasChannel(Channel::Disparity); - auto &disp = (!has_estimate) ? out.create<GpuMat>(Channel::Disparity, Format<short>(l.size())) : in.get<GpuMat>(Channel::Disparity); + auto &disp = (!has_estimate) ? out.create<ftl::rgbd::VideoFrame>(Channel::Disparity).createGPU(Format<short>(l.size())) : in.get<GpuMat>(Channel::Disparity); auto cvstream = cv::cuda::StreamAccessor::wrapStream(stream); diff --git a/components/operators/src/fusion/mvmls.cpp b/components/operators/src/fusion/mvmls.cpp index 0dfe26b14..a444d8d1a 100644 --- a/components/operators/src/fusion/mvmls.cpp +++ b/components/operators/src/fusion/mvmls.cpp @@ -62,7 +62,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda for (size_t i=0; i<in.frames.size(); ++i) { if (!in.hasFrame(i)) continue; - auto &f = in.frames[i]; + auto &f = in.frames[i].cast<ftl::rgbd::Frame>(); auto size = f.get<GpuMat>(Channel::Depth).size(); centroid_horiz_[i]->create(size.height, size.width); normals_horiz_[i]->create(size.height, size.width); @@ -77,12 +77,12 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda } // Create required channels - f.create<GpuMat>(Channel::Confidence, Format<float>(size)); + f.create<ftl::rgbd::VideoFrame>(Channel::Confidence).createGPU(Format<float>(size)); f.createTexture<float>(Channel::Confidence); - f.create<GpuMat>(Channel::Screen, Format<short2>(size)); + f.create<ftl::rgbd::VideoFrame>(Channel::Screen).createGPU(Format<short2>(size)); f.createTexture<short2>(Channel::Screen); - f.get<GpuMat>(Channel::Confidence).setTo(cv::Scalar(0.0f), cvstream); + f.set<GpuMat>(Channel::Confidence).setTo(cv::Scalar(0.0f), cvstream); } //for (int iter=0; iter<iters; ++iter) { @@ -95,7 +95,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda for (size_t i=0; i<in.frames.size(); ++i) { if (!in.hasFrame(i)) continue; - auto &f1 = in.frames[i]; + auto &f1 = in.frames[i].cast<ftl::rgbd::Frame>(); //f1.get<GpuMat>(Channel::Depth2).setTo(cv::Scalar(0.0f), cvstream); //f1.get<GpuMat>(Channel::Confidence).setTo(cv::Scalar(0.0f), cvstream); @@ -108,7 +108,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda //LOG(INFO) << "Running phase1"; - auto &f2 = in.frames[j]; + auto &f2 = in.frames[j].cast<ftl::rgbd::Frame>(); //auto s1 = in.sources[i]; //auto s2 = in.sources[j]; @@ -345,7 +345,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda // Redo normals for (size_t i=0; i<in.frames.size(); ++i) { if (!in.hasFrame(i)) continue; - auto &f = in.frames[i]; + auto &f = in.frames[i].cast<ftl::rgbd::Frame>(); ftl::cuda::normals( f.getTexture<half4>(Channel::Normals), f.getTexture<float>(Channel::Depth), @@ -411,7 +411,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda for (size_t i=0; i<in.frames.size(); ++i) { if (!in.hasFrame(i)) continue; - auto &f = in.frames[i]; + auto &f = in.frames[i].cast<ftl::rgbd::Frame>(); //auto *s = in.sources[i]; // Clear data @@ -465,7 +465,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda if (do_aggr) { for (size_t i=0; i<in.frames.size(); ++i) { if (!in.hasFrame(i)) continue; - auto &f1 = in.frames[i]; + auto &f1 = in.frames[i].cast<ftl::rgbd::Frame>(); //f1.get<GpuMat>(Channel::Depth2).setTo(cv::Scalar(0.0f), cvstream); //f1.get<GpuMat>(Channel::Confidence).setTo(cv::Scalar(0.0f), cvstream); @@ -478,7 +478,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda //LOG(INFO) << "Running phase1"; - auto &f2 = in.frames[j]; + auto &f2 = in.frames[j].cast<ftl::rgbd::Frame>(); //auto s1 = in.sources[i]; //auto s2 = in.sources[j]; @@ -520,7 +520,7 @@ bool MultiViewMLS::apply(ftl::rgbd::FrameSet &in, ftl::rgbd::FrameSet &out, cuda // Normalise aggregations and move the points for (size_t i=0; i<in.frames.size(); ++i) { if (!in.hasFrame(i)) continue; - auto &f = in.frames[i]; + auto &f = in.frames[i].cast<ftl::rgbd::Frame>(); //auto *s = in.sources[i]; auto size = f.get<GpuMat>(Channel::Depth).size(); diff --git a/components/operators/src/mask.cpp b/components/operators/src/mask.cpp index e39fcabea..c9f1dad53 100644 --- a/components/operators/src/mask.cpp +++ b/components/operators/src/mask.cpp @@ -99,7 +99,7 @@ bool CullDiscontinuity::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaS unsigned int radius = config()->value("radius", 0); bool inverted = config()->value("invert", false); - out.clearPackets(Channel::Depth); // Force reset + out.set<ftl::rgbd::VideoFrame>(Channel::Depth); // Force reset ftl::cuda::cull_mask( in.createTexture<uint8_t>(Channel::Mask), out.createTexture<float>(Channel::Depth), diff --git a/components/operators/src/operator.cpp b/components/operators/src/operator.cpp index 617514afd..2baf2f41b 100644 --- a/components/operators/src/operator.cpp +++ b/components/operators/src/operator.cpp @@ -71,7 +71,7 @@ bool Graph::apply(FrameSet &in, FrameSet &out, cudaStream_t stream) { if (instance->enabled()) { try { - instance->apply(in.frames[j], out.frames[j], stream_actual); + instance->apply(in.frames[j].cast<ftl::rgbd::Frame>(), out.frames[j].cast<ftl::rgbd::Frame>(), stream_actual); } catch (const std::exception &e) { LOG(ERROR) << "Operator exception for '" << instance->config()->getID() << "': " << e.what(); success = false; diff --git a/components/operators/src/smoothing.cpp b/components/operators/src/smoothing.cpp index 739162622..0ca343057 100644 --- a/components/operators/src/smoothing.cpp +++ b/components/operators/src/smoothing.cpp @@ -89,7 +89,7 @@ bool SmoothChannel::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStrea float scale = 1.0f; // Clear to max smoothing - out.create<GpuMat>(Channel::Smoothing, Format<float>(width, height)).setTo(cv::Scalar(1.0f)); + out.create<ftl::rgbd::VideoFrame>(Channel::Smoothing).createGPU(Format<float>(width, height)).setTo(cv::Scalar(1.0f)); // Reduce to nearest ftl::cuda::smooth_channel( @@ -108,14 +108,16 @@ bool SmoothChannel::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStrea height /= 2; scale *= 2.0f; + temp_[i].create(width,height); + ftl::rgbd::Camera scaledCam = in.getLeftCamera().scaled(width, height); // Downscale images for next pass - cv::cuda::resize(in.get<GpuMat>(Channel::Colour), temp_[i].create<GpuMat>(Channel::Colour), cv::Size(width, height), 0.0, 0.0, cv::INTER_LINEAR); + cv::cuda::resize(in.get<GpuMat>(Channel::Colour), temp_[i].to_gpumat(), cv::Size(width, height), 0.0, 0.0, cv::INTER_LINEAR); //cv::cuda::resize(in.get<GpuMat>(Channel::Depth), temp_[i].create<GpuMat>(Channel::Depth), cv::Size(width, height), 0.0, 0.0, cv::INTER_NEAREST); ftl::cuda::smooth_channel( - temp_[i].createTexture<uchar4>(Channel::Colour), + temp_[i], //temp_[i].createTexture<float>(Channel::Depth), out.getTexture<float>(Channel::Smoothing), scaledCam, @@ -133,7 +135,7 @@ bool SmoothChannel::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStrea // ===== MLS =================================================================== -SimpleMLS::SimpleMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg) { +SimpleMLS::SimpleMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg), temp_(ftl::data::Frame::make_standalone()) { } @@ -146,6 +148,8 @@ bool SimpleMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t int iters = config()->value("mls_iterations", 1); int radius = config()->value("mls_radius",2); + auto &temp = temp_.cast<ftl::rgbd::Frame>(); + if (!in.hasChannel(Channel::Normals)) { /*ftl::cuda::normals( in.createTexture<float4>(Channel::Normals, ftl::rgbd::Format<float4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), @@ -160,9 +164,9 @@ bool SimpleMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t for (int i=0; i<iters; ++i) { ftl::cuda::mls_smooth( in.createTexture<half4>(Channel::Normals), - temp_.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<float>(Channel::Depth), - temp_.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), thresh, radius, in.getLeftCamera(), @@ -171,7 +175,8 @@ bool SimpleMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t //in.swapChannels(Channel::Depth, Channel::Depth2); //in.swapChannels(Channel::Normals, Channel::Points); - temp_.swapChannels(Channel::Normals + Channel::Depth, in); + temp.swapChannel(Channel::Normals, in); + temp.swapChannel(Channel::Depth, in); } return true; @@ -179,7 +184,7 @@ bool SimpleMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t -ColourMLS::ColourMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg) { +ColourMLS::ColourMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg), temp_(ftl::data::Frame::make_standalone()) { } @@ -200,14 +205,16 @@ bool ColourMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t return false; } + auto &temp = temp_.cast<ftl::rgbd::Frame>(); + // FIXME: Assume in and out are the same frame. for (int i=0; i<iters; ++i) { if (!crosssup) { ftl::cuda::colour_mls_smooth( in.createTexture<half4>(Channel::Normals), - temp_.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<float>(Channel::Depth), - temp_.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<uchar4>(Channel::Colour), thresh, col_smooth, @@ -219,9 +226,9 @@ bool ColourMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t ftl::cuda::colour_mls_smooth_csr( in.createTexture<uchar4>(Channel::Support1), in.createTexture<half4>(Channel::Normals), - temp_.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<float>(Channel::Depth), - temp_.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<uchar4>(Channel::Colour), thresh, col_smooth, @@ -233,7 +240,8 @@ bool ColourMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t //in.swapChannels(Channel::Depth, Channel::Depth2); //in.swapChannels(Channel::Normals, Channel::Points); - temp_.swapChannels(Channel::Normals + Channel::Depth, in); + temp_.swapChannel(Channel::Depth, in); + temp_.swapChannel(Channel::Normals, in); } return true; @@ -242,7 +250,7 @@ bool ColourMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t // ====== Aggregating MLS ====================================================== -AggreMLS::AggreMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg) { +AggreMLS::AggreMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg), temp_(ftl::data::Frame::make_standalone()) { } @@ -267,6 +275,8 @@ bool AggreMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t s return false; } + auto &temp = temp_.cast<ftl::rgbd::Frame>(); + auto size = in.get<GpuMat>(Channel::Depth).size(); centroid_horiz_.create(size.height, size.width); normals_horiz_.create(size.height, size.width); @@ -306,7 +316,7 @@ bool AggreMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t s ftl::cuda::mls_adjust_depth( in.createTexture<half4>(Channel::Normals), centroid_vert_, - temp_.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(size)), + temp.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(size)), in.getTexture<float>(Channel::Depth), in.getLeftCamera(), stream @@ -314,15 +324,15 @@ bool AggreMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t s //in.swapChannels(Channel::Depth, Channel::Depth2); //in.swapChannels(Channel::Normals, Channel::Points); - temp_.swapChannels(ftl::codecs::Channels<0>(Channel::Depth), in); + temp_.swapChannel(Channel::Depth, in); } else { ftl::cuda::colour_mls_smooth_csr( in.createTexture<uchar4>(Channel::Support1), in.createTexture<half4>(Channel::Normals), - temp_.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<float>(Channel::Depth), - temp_.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<uchar4>(Channel::Colour), thresh, col_smooth, @@ -331,7 +341,8 @@ bool AggreMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t s stream ); - temp_.swapChannels(Channel::Normals + Channel::Depth, in); + temp_.swapChannel(Channel::Depth, in); + temp_.swapChannel(Channel::Normals, in); } } @@ -341,7 +352,7 @@ bool AggreMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_t s // ====== Adaptive MLS ========================================================= -AdaptiveMLS::AdaptiveMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg) { +AdaptiveMLS::AdaptiveMLS(ftl::Configurable *cfg) : ftl::operators::Operator(cfg), temp_(ftl::data::Frame::make_standalone()) { } @@ -358,20 +369,23 @@ bool AdaptiveMLS::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream_ return false; } + auto &temp = temp_.cast<ftl::rgbd::Frame>(); + // FIXME: Assume in and out are the same frame. for (int i=0; i<iters; ++i) { ftl::cuda::adaptive_mls_smooth( in.createTexture<half4>(Channel::Normals), - temp_.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<float>(Channel::Depth), - temp_.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + temp.createTexture<float>(Channel::Depth, ftl::rgbd::Format<float>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<float>(Channel::Smoothing), radius, in.getLeftCamera(), stream ); - temp_.swapChannels(Channel::Normals + Channel::Depth, in); + temp_.swapChannel(Channel::Depth, in); + temp_.swapChannel(Channel::Normals, in); } diff --git a/components/renderers/cpp/include/ftl/render/CUDARender.hpp b/components/renderers/cpp/include/ftl/render/CUDARender.hpp index cfdb4cf40..8743137c2 100644 --- a/components/renderers/cpp/include/ftl/render/CUDARender.hpp +++ b/components/renderers/cpp/include/ftl/render/CUDARender.hpp @@ -44,7 +44,8 @@ class CUDARender : public ftl::render::FSRenderer { private: int device_; - ftl::rgbd::Frame temp_; + ftl::data::Frame temp_d_; + ftl::rgbd::Frame &temp_; //ftl::rgbd::Frame accum_; ftl::cuda::TextureObject<float4> accum_; // 2 is number of channels can render together ftl::cuda::TextureObject<int> contrib_; diff --git a/components/renderers/cpp/include/ftl/render/overlay.hpp b/components/renderers/cpp/include/ftl/render/overlay.hpp index be4f36d31..1bb8d7703 100644 --- a/components/renderers/cpp/include/ftl/render/overlay.hpp +++ b/components/renderers/cpp/include/ftl/render/overlay.hpp @@ -24,7 +24,7 @@ class Overlay : public ftl::Configurable { //void apply(ftl::rgbd::FrameSet &fs, cv::Mat &out, ftl::rgbd::FrameState &state); - void draw(ftl::rgbd::FrameSet &fs, ftl::rgbd::FrameState &state, const Eigen::Vector2f &); + void draw(ftl::data::FrameSet &fs, ftl::rgbd::Frame &frame, const Eigen::Vector2f &); private: nanogui::GLShader oShader; diff --git a/components/renderers/cpp/src/CUDARender.cpp b/components/renderers/cpp/src/CUDARender.cpp index 03ea37f63..07cc666fd 100644 --- a/components/renderers/cpp/src/CUDARender.cpp +++ b/components/renderers/cpp/src/CUDARender.cpp @@ -25,13 +25,14 @@ using ftl::render::CUDARender; using ftl::codecs::Channel; using ftl::codecs::Channels; using ftl::rgbd::Format; +using ftl::rgbd::VideoFrame; using cv::cuda::GpuMat; using std::stoul; using ftl::cuda::Mask; using ftl::render::parseCUDAColour; using ftl::render::parseCVColour; -CUDARender::CUDARender(nlohmann::json &config) : ftl::render::FSRenderer(config), scene_(nullptr) { +CUDARender::CUDARender(nlohmann::json &config) : ftl::render::FSRenderer(config), temp_d_(ftl::data::Frame::make_standalone()), temp_(temp_d_.cast<ftl::rgbd::Frame>()), scene_(nullptr) { /*if (config["clipping"].is_object()) { auto &c = config["clipping"]; float rx = c.value("pitch", 0.0f); @@ -111,7 +112,7 @@ void CUDARender::_renderChannel(ftl::rgbd::Frame &output, ftl::codecs::Channel i for (size_t i=0; i < scene_->frames.size(); ++i) { if (!scene_->hasFrame(i)) continue; - auto &f = scene_->frames[i]; + auto &f = scene_->frames[i].cast<ftl::rgbd::Frame>(); if (!f.hasChannel(in)) { LOG(ERROR) << "Reprojecting unavailable channel"; @@ -169,14 +170,14 @@ void CUDARender::_renderChannel(ftl::rgbd::Frame &output, ftl::codecs::Channel i void CUDARender::_dibr(ftl::rgbd::Frame &out, const Eigen::Matrix4d &t, cudaStream_t stream) { cv::cuda::Stream cvstream = cv::cuda::StreamAccessor::wrapStream(stream); - temp_.get<GpuMat>(Channel::Depth2).setTo(cv::Scalar(0x7FFFFFFF), cvstream); + temp_.set<GpuMat>(Channel::Depth2).setTo(cv::Scalar(0x7FFFFFFF), cvstream); for (size_t i=0; i < scene_->frames.size(); ++i) { if (!scene_->hasFrame(i)) continue; - auto &f = scene_->frames[i]; + auto &f = scene_->frames[i].cast<ftl::rgbd::Frame>(); //auto *s = scene_->sources[i]; - if (f.empty(Channel::Colour)) { + if (f.has(Channel::Colour)) { LOG(ERROR) << "Missing required channel"; continue; } @@ -233,19 +234,19 @@ void CUDARender::_mesh(ftl::rgbd::Frame &out, const Eigen::Matrix4d &t, cudaStre bool do_blend = value("mesh_blend", false); float blend_alpha = value("blend_alpha", 0.02f); if (do_blend) { - temp_.get<GpuMat>(Channel::Depth).setTo(cv::Scalar(0x7FFFFFFF), cvstream); - temp_.get<GpuMat>(Channel::Weights).setTo(cv::Scalar(0.0f), cvstream); + temp_.set<GpuMat>(Channel::Depth).setTo(cv::Scalar(0x7FFFFFFF), cvstream); + temp_.set<GpuMat>(Channel::Weights).setTo(cv::Scalar(0.0f), cvstream); } else { - temp_.get<GpuMat>(Channel::Depth2).setTo(cv::Scalar(0x7FFFFFFF), cvstream); + temp_.set<GpuMat>(Channel::Depth2).setTo(cv::Scalar(0x7FFFFFFF), cvstream); } // For each source depth map for (size_t i=0; i < scene_->frames.size(); ++i) { if (!scene_->hasFrame(i)) continue; - auto &f = scene_->frames[i]; + auto &f = scene_->frames[i].cast<ftl::rgbd::Frame>(); //auto *s = scene_->sources[i]; - if (f.empty(Channel::Colour)) { + if (f.has(Channel::Colour)) { LOG(ERROR) << "Missing required channel"; continue; } @@ -285,7 +286,7 @@ void CUDARender::_mesh(ftl::rgbd::Frame &out, const Eigen::Matrix4d &t, cudaStre // Must reset depth channel if blending if (do_blend) { - temp_.get<GpuMat>(Channel::Depth).setTo(cv::Scalar(0x7FFFFFFF), cvstream); + temp_.set<GpuMat>(Channel::Depth).setTo(cv::Scalar(0x7FFFFFFF), cvstream); } // Decide on and render triangles around each point @@ -347,27 +348,27 @@ void CUDARender::_allocateChannels(ftl::rgbd::Frame &out, ftl::codecs::Channel c // Allocate left channel buffers and clear them if (chan == Channel::Colour) { //if (!out.hasChannel(Channel::Depth)) { - out.create<GpuMat>(Channel::Depth, Format<float>(camera.width, camera.height)); - out.create<GpuMat>(Channel::Colour, Format<uchar4>(camera.width, camera.height)); - out.create<GpuMat>(Channel::Normals, Format<half4>(camera.width, camera.height)); + out.create<VideoFrame>(Channel::Depth).createGPU(Format<float>(camera.width, camera.height)); + out.create<VideoFrame>(Channel::Colour).createGPU(Format<uchar4>(camera.width, camera.height)); + out.create<VideoFrame>(Channel::Normals).createGPU(Format<half4>(camera.width, camera.height)); out.createTexture<uchar4>(Channel::Colour, true); // Force interpolated colour - out.get<GpuMat>(Channel::Depth).setTo(cv::Scalar(1000.0f), cvstream); + out.set<GpuMat>(Channel::Depth).setTo(cv::Scalar(1000.0f), cvstream); //} // Allocate right channel buffers and clear them } else { if (!out.hasChannel(Channel::Depth2)) { - out.create<GpuMat>(Channel::Depth2, Format<float>(camera.width, camera.height)); - out.create<GpuMat>(Channel::Colour2, Format<uchar4>(camera.width, camera.height)); - out.create<GpuMat>(Channel::Normals2, Format<half4>(camera.width, camera.height)); + out.create<VideoFrame>(Channel::Depth2).createGPU(Format<float>(camera.width, camera.height)); + out.create<VideoFrame>(Channel::Colour2).createGPU(Format<uchar4>(camera.width, camera.height)); + out.create<VideoFrame>(Channel::Normals2).createGPU(Format<half4>(camera.width, camera.height)); out.createTexture<uchar4>(Channel::Colour2, true); // Force interpolated colour - out.get<GpuMat>(Channel::Depth2).setTo(cv::Scalar(1000.0f), cvstream); + out.set<GpuMat>(Channel::Depth2).setTo(cv::Scalar(1000.0f), cvstream); } } - temp_.create<GpuMat>(Channel::Depth, Format<int>(camera.width, camera.height)); - temp_.create<GpuMat>(Channel::Depth2, Format<int>(camera.width, camera.height)); - temp_.create<GpuMat>(Channel::Normals, Format<half4>(camera.width, camera.height)); - temp_.create<GpuMat>(Channel::Weights, Format<float>(camera.width, camera.height)); + temp_.create<VideoFrame>(Channel::Depth).createGPU(Format<int>(camera.width, camera.height)); + temp_.create<VideoFrame>(Channel::Depth2).createGPU(Format<int>(camera.width, camera.height)); + temp_.create<VideoFrame>(Channel::Normals).createGPU(Format<half4>(camera.width, camera.height)); + temp_.create<VideoFrame>(Channel::Weights).createGPU(Format<float>(camera.width, camera.height)); temp_.createTexture<int>(Channel::Depth); accum_.create(camera.width, camera.height); @@ -492,7 +493,7 @@ void CUDARender::begin(ftl::rgbd::Frame &out, ftl::codecs::Channel chan) { // Apply a colour background if (env_image_.empty() || !value("environment_enabled", false)) { - out.get<GpuMat>(chan).setTo(background_, cvstream); + out.set<GpuMat>(chan).setTo(background_, cvstream); } else { auto pose = poseInverse_.getFloat3x3(); ftl::cuda::equirectangular_reproject( diff --git a/components/renderers/cpp/src/colouriser.cpp b/components/renderers/cpp/src/colouriser.cpp index 6341f1a86..c4dfbc19c 100644 --- a/components/renderers/cpp/src/colouriser.cpp +++ b/components/renderers/cpp/src/colouriser.cpp @@ -192,7 +192,7 @@ TextureObject<uchar4> &Colouriser::_processColour(ftl::rgbd::Frame &f, Channel c auto &buf = _getBuffer(size.width, size.height); if (colour_sources) { - auto colour = HSVtoRGB(360 / 8 * f.id, 0.6, 0.85); + auto colour = HSVtoRGB(360 / 8 * f.source(), 0.6, 0.85); buf.to_gpumat().setTo(colour, cvstream); } diff --git a/components/renderers/cpp/src/overlay.cpp b/components/renderers/cpp/src/overlay.cpp index 7054c275a..1513bc36f 100644 --- a/components/renderers/cpp/src/overlay.cpp +++ b/components/renderers/cpp/src/overlay.cpp @@ -241,11 +241,11 @@ void Overlay::_drawAxis(const Eigen::Matrix4d &pose, const Eigen::Vector3f &scal (const void *)(loffset * sizeof(uint32_t))); } -void Overlay::draw(ftl::rgbd::FrameSet &fs, ftl::rgbd::FrameState &state, const Eigen::Vector2f &screenSize) { +void Overlay::draw(ftl::data::FrameSet &fs, ftl::rgbd::Frame &frame, const Eigen::Vector2f &screenSize) { if (!value("enabled", false)) return; double zfar = 8.0f; - auto intrin = state.getLeft(); + auto intrin = frame.getLeft(); intrin = intrin.scaled(screenSize[0], screenSize[1]); if (!init_) { @@ -263,7 +263,7 @@ void Overlay::draw(ftl::rgbd::FrameSet &fs, ftl::rgbd::FrameState &state, const {0.8f, -0.4f, 2.0f} }; - auto pose = MatrixConversion::toCUDA(state.getPose().cast<float>().inverse()); + auto pose = MatrixConversion::toCUDA(frame.getPose().cast<float>().inverse()); tris[0] = pose * tris[0]; tris[1] = pose * tris[1]; @@ -295,11 +295,13 @@ void Overlay::draw(ftl::rgbd::FrameSet &fs, ftl::rgbd::FrameState &state, const if (value("show_poses", false)) { for (size_t i=0; i<fs.frames.size(); ++i) { - auto pose = fs.frames[i].getPose(); //.inverse() * state.getPose(); + auto &f = fs.frames[i].cast<ftl::rgbd::Frame>(); - auto name = fs.frames[i].get<std::string>("name"); - _drawOutlinedShape(Shape::CAMERA, state.getPose().inverse() * pose, Eigen::Vector3f(0.2f,0.2f,0.2f), make_uchar4(255,0,0,80), make_uchar4(255,0,0,255)); - _drawAxis(state.getPose().inverse() * pose, Eigen::Vector3f(0.2f, 0.2f, 0.2f)); + auto pose = f.getPose(); //.inverse() * state.getPose(); + + auto name = fs.frames[i].get<std::string>(Channel::Name); + _drawOutlinedShape(Shape::CAMERA, frame.getPose().inverse() * pose, Eigen::Vector3f(0.2f,0.2f,0.2f), make_uchar4(255,0,0,80), make_uchar4(255,0,0,255)); + _drawAxis(frame.getPose().inverse() * pose, Eigen::Vector3f(0.2f, 0.2f, 0.2f)); //ftl::overlay::drawCamera(state.getLeft(), out, over_depth_, fs.frames[i].getLeftCamera(), pose, cv::Scalar(0,0,255,255), 0.2,value("show_frustrum", false)); //if (name) ftl::overlay::drawText(state.getLeft(), out, over_depth_, *name, pos, 0.5, cv::Scalar(0,0,255,255)); @@ -308,15 +310,15 @@ void Overlay::draw(ftl::rgbd::FrameSet &fs, ftl::rgbd::FrameState &state, const if (value("show_xz_plane", false)) { float gscale = value("grid_scale",0.5f); - _drawOutlinedShape(Shape::XZPLANE, state.getPose().inverse(), Eigen::Vector3f(gscale,gscale,gscale), make_uchar4(200,200,200,50), make_uchar4(255,255,255,100)); + _drawOutlinedShape(Shape::XZPLANE, frame.getPose().inverse(), Eigen::Vector3f(gscale,gscale,gscale), make_uchar4(200,200,200,50), make_uchar4(255,255,255,100)); } if (value("show_axis", true)) { - _drawAxis(state.getPose().inverse(), Eigen::Vector3f(0.5f, 0.5f, 0.5f)); + _drawAxis(frame.getPose().inverse(), Eigen::Vector3f(0.5f, 0.5f, 0.5f)); } if (value("show_shapes", false)) { - if (fs.hasChannel(Channel::Shapes3D)) { + /*if (fs.hasChannel(Channel::Shapes3D)) { std::vector<ftl::codecs::Shape3D> shapes; fs.get(Channel::Shapes3D, shapes); @@ -340,12 +342,11 @@ void Overlay::draw(ftl::rgbd::FrameSet &fs, ftl::rgbd::FrameState &state, const //ftl::overlay::drawBox(state.getLeft(), out, over_depth_, pose, cv::Scalar(0,0,255,255), s.size.cast<double>()); //ftl::overlay::drawText(state.getLeft(), out, over_depth_, s.label, pos, 0.5, cv::Scalar(0,0,255,100)); } - } + }*/ for (size_t i=0; i<fs.frames.size(); ++i) { if (fs.frames[i].hasChannel(Channel::Shapes3D)) { - std::vector<ftl::codecs::Shape3D> shapes; - fs.frames[i].get(Channel::Shapes3D, shapes); + const auto &shapes = fs.frames[i].get<std::vector<ftl::codecs::Shape3D>>(Channel::Shapes3D); for (auto &s : shapes) { auto pose = s.pose.cast<double>(); //.inverse() * state.getPose(); @@ -355,8 +356,8 @@ void Overlay::draw(ftl::rgbd::FrameSet &fs, ftl::rgbd::FrameState &state, const Eigen::Vector3f scale(s.size[0]/2.0f, s.size[1]/2.0f, s.size[2]/2.0f); switch (s.type) { - case ftl::codecs::Shape3DType::CLIPPING: _drawOutlinedShape(Shape::BOX, state.getPose().inverse() * pose, scale, make_uchar4(255,0,255,80), make_uchar4(255,0,255,255)); break; - case ftl::codecs::Shape3DType::ARUCO: _drawAxis(state.getPose().inverse() * pose, Eigen::Vector3f(0.2f, 0.2f, 0.2f)); break; + case ftl::codecs::Shape3DType::CLIPPING: _drawOutlinedShape(Shape::BOX, frame.getPose().inverse() * pose, scale, make_uchar4(255,0,255,80), make_uchar4(255,0,255,255)); break; + case ftl::codecs::Shape3DType::ARUCO: _drawAxis(frame.getPose().inverse() * pose, Eigen::Vector3f(0.2f, 0.2f, 0.2f)); break; default: break; } diff --git a/components/rgbd-sources/CMakeLists.txt b/components/rgbd-sources/CMakeLists.txt index 7e47d77e4..30f9cb3cb 100644 --- a/components/rgbd-sources/CMakeLists.txt +++ b/components/rgbd-sources/CMakeLists.txt @@ -3,11 +3,11 @@ set(RGBDSRC src/sources/stereovideo/opencv.cpp src/source.cpp src/frame.cpp - src/frameset.cpp + #src/frameset.cpp src/sources/stereovideo/stereovideo.cpp #src/colour.cpp - src/group.cpp - src/cb_segmentation.cpp + #src/group.cpp + #src/cb_segmentation.cpp #src/abr.cpp src/sources/screencapture/screencapture.cpp src/camera.cpp diff --git a/components/rgbd-sources/include/ftl/rgbd/frame.hpp b/components/rgbd-sources/include/ftl/rgbd/frame.hpp index 8fc747cd7..2cd518e3d 100644 --- a/components/rgbd-sources/include/ftl/rgbd/frame.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/frame.hpp @@ -8,7 +8,7 @@ #include <opencv2/core/cuda.hpp> #include <opencv2/core/cuda_stream_accessor.hpp> -#include <ftl/data/frame.hpp> +#include <ftl/data/new_frame.hpp> #include <ftl/codecs/channels.hpp> #include <ftl/rgbd/format.hpp> @@ -16,7 +16,6 @@ #include <ftl/codecs/codecs.hpp> #include <ftl/codecs/packet.hpp> #include <ftl/utility/vectorbuffer.hpp> -#include <ftl/data/framestate.hpp> #include <ftl/cuda_common.hpp> #include <type_traits> @@ -28,264 +27,146 @@ namespace ftl { namespace rgbd { -typedef ftl::data::FrameState<ftl::rgbd::Camera,2> FrameState; +//typedef ftl::data::Frame Frame; -struct VideoData { - ftl::cuda::TextureObjectBase tex; - cv::cuda::GpuMat gpu; - cv::Mat host; - bool isgpu; - bool validhost; - std::list<ftl::codecs::Packet> encoded; +/*inline const ftl::rgbd::Camera &getLeftCamera(const Frame &f) { return f.get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration); } +inline const ftl::rgbd::Camera &getRightCamera(const Frame &f) { return f.get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration2); } +inline const ftl::rgbd::Camera &getLeft(const Frame &f) { return f.get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration); } +inline const ftl::rgbd::Camera &getRight(const Frame &f) { return f.get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration2); } +inline const Eigen::Matrix4d &getPose(const Frame &f) { return f.get<Eigen::Matrix4d>(ftl::codecs::Channel::Pose); }*/ - template <typename T> - T &as() { - throw FTL_Error("Unsupported type for Video data channel"); - }; +class VideoFrame { + public: + VideoFrame() {} + + // Manually add copy constructor since default is removed + VideoFrame(const VideoFrame &); + VideoFrame &operator=(const VideoFrame &); template <typename T> - const T &as() const { - throw FTL_Error("Unsupported type for Video data channel"); - }; + ftl::cuda::TextureObject<T> &createTexture(const ftl::rgbd::Format<T> &f, bool interpolated); template <typename T> - T &make() { - throw FTL_Error("Unsupported type for Video data channel"); - }; + ftl::cuda::TextureObject<T> &createTexture(bool interpolated=false) const; - inline void reset() { - validhost = false; - encoded.clear(); - } + cv::cuda::GpuMat &createGPU(); + cv::cuda::GpuMat &createGPU(const ftl::rgbd::FormatBase &f); + + template <typename T> ftl::cuda::TextureObject<T> &getTexture() const; + + cv::Mat &createCPU(); + cv::Mat &createCPU(const ftl::rgbd::FormatBase &f); + + inline bool isGPU() const { return isgpu; }; + + + private: + mutable ftl::cuda::TextureObjectBase tex; + cv::cuda::GpuMat gpu; + cv::Mat host; + bool isgpu=false; + bool validhost=false; }; -// Specialisations for cv mat types -template <> cv::Mat &VideoData::as<cv::Mat>(); -template <> const cv::Mat &VideoData::as<cv::Mat>() const; -template <> cv::cuda::GpuMat &VideoData::as<cv::cuda::GpuMat>(); -template <> const cv::cuda::GpuMat &VideoData::as<cv::cuda::GpuMat>() const; - -template <> cv::Mat &VideoData::make<cv::Mat>(); -template <> cv::cuda::GpuMat &VideoData::make<cv::cuda::GpuMat>(); - -/** - * Manage a set of image channels corresponding to a single camera frame. - */ -class Frame : public ftl::data::Frame<0,32,ftl::rgbd::FrameState,VideoData> { -//class Frame { -public: - using ftl::data::Frame<0,32,ftl::rgbd::FrameState,VideoData>::create; - - Frame(); - Frame(Frame &&f); - ~Frame(); - - Frame &operator=(Frame &&f); - - // Prevent frame copy, instead use a move. - //Frame(const Frame &)=delete; - //Frame &operator=(const Frame &)=delete; - - void download(ftl::codecs::Channel c, cv::cuda::Stream stream); - void upload(ftl::codecs::Channel c, cv::cuda::Stream stream); - void download(ftl::codecs::Channels<0> c, cv::cuda::Stream stream); - void upload(ftl::codecs::Channels<0> c, cv::cuda::Stream stream); - - inline void download(ftl::codecs::Channel c, cudaStream_t stream=0) { download(c, cv::cuda::StreamAccessor::wrapStream(stream)); }; - inline void upload(ftl::codecs::Channel c, cudaStream_t stream=0) { upload(c, cv::cuda::StreamAccessor::wrapStream(stream)); }; - inline void download(const ftl::codecs::Channels<0> &c, cudaStream_t stream=0) { download(c, cv::cuda::StreamAccessor::wrapStream(stream)); }; - inline void upload(const ftl::codecs::Channels<0> &c, cudaStream_t stream=0) { upload(c, cv::cuda::StreamAccessor::wrapStream(stream)); }; - - /** - * Special case optional download. If a host memory version still exists, - * use that. Only download if no host version exists. This assumes that - * the GPU version has not been modified since the host version was created, - * in otherwords that both version are still the same. It also does not - * actually mark the channel as downloaded. - */ - cv::Mat &fastDownload(ftl::codecs::Channel c, cv::cuda::Stream stream); - - /** - * Get an existing CUDA texture object. - */ - template <typename T> const ftl::cuda::TextureObject<T> &getTexture(ftl::codecs::Channel) const; - - /** - * Get an existing CUDA texture object. - */ - template <typename T> ftl::cuda::TextureObject<T> &getTexture(ftl::codecs::Channel); - - /** - * Create a channel with a given format. This will discard any existing - * data associated with the channel and ensure all data structures and - * memory allocations match the new format. - */ - template <typename T> T &create(ftl::codecs::Channel c, const ftl::rgbd::FormatBase &f); - - /** - * Create a CUDA texture object for a channel. This version takes a format - * argument to also create (or recreate) the associated GpuMat. - */ - template <typename T> - ftl::cuda::TextureObject<T> &createTexture(ftl::codecs::Channel c, const ftl::rgbd::Format<T> &f, bool interpolated=false); +class Frame : public ftl::data::Frame { + public: + inline const ftl::rgbd::Camera &getLeftCamera() { return this->get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration); } + inline const ftl::rgbd::Camera &getRightCamera() { return this->get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration2); } + inline const ftl::rgbd::Camera &getLeft() { return this->get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration); } + inline const ftl::rgbd::Camera &getRight() { return this->get<ftl::rgbd::Camera>(ftl::codecs::Channel::Calibration2); } + inline const Eigen::Matrix4d &getPose() { return this->get<Eigen::Matrix4d>(ftl::codecs::Channel::Pose); } - /** - * Create a CUDA texture object for a channel. With this version the GpuMat - * must already exist and be of the correct type. - */ template <typename T> - ftl::cuda::TextureObject<T> &createTexture(ftl::codecs::Channel c, bool interpolated=false); - - /** - * Append encoded data for a channel. This will move the data, invalidating - * the original packet structure. It is to be used to allow data that is - * already encoded to be transmitted or saved again without re-encoding. - * A called to `create` will clear all encoded data for that channel. - */ - void pushPacket(ftl::codecs::Channel c, ftl::codecs::Packet &pkt); - - /** - * Obtain a list of any existing encodings for this channel. - */ - const std::list<ftl::codecs::Packet> &getPackets(ftl::codecs::Channel c) const; - - /** - * Clear any existing encoded packets. Used when the channel data is - * modified and the encodings are therefore out-of-date. - */ - void clearPackets(ftl::codecs::Channel c); - - /** - * Packets from multiple frames are merged together in sequence. An example - * case is if a frame gets dropped but the original encoding is inter-frame - * and hence still requires the dropped frames encoding data. - */ - void mergeEncoding(ftl::rgbd::Frame &f); - - void resetTexture(ftl::codecs::Channel c); - - /** - * Check if any specified channels are empty or missing. - */ - bool empty(ftl::codecs::Channels<0> c); - - /** - * Check if a specific channel is missing or has no memory allocated. - */ - inline bool empty(ftl::codecs::Channel c) { - auto &m = getData(c); - return !hasChannel(c) || (m.host.empty() && m.gpu.empty()); - } - - /** - * Obtain a mask of all available channels in the frame. - */ - inline ftl::codecs::Channels<0> getVideoChannels() const { return getChannels(); } + ftl::cuda::TextureObject<T> &getTexture(ftl::codecs::Channel c) { return this->get<VideoFrame>(c).getTexture<T>(); } - inline const ftl::rgbd::Camera &getLeftCamera() const { return getLeft(); } - inline const ftl::rgbd::Camera &getRightCamera() const { return getRight(); } + template <typename T> + ftl::cuda::TextureObject<T> &createTexture(ftl::codecs::Channel c, bool interpolated=false) { return this->get<VideoFrame>(c).createTexture<T>(interpolated); } - /** - * Is the channel data currently located on GPU. This also returns false if - * the channel does not exist. - */ - inline bool isGPU(ftl::codecs::Channel channel) const { - return hasChannel(channel) && getData(channel).isgpu; - } + template <typename T> + ftl::cuda::TextureObject<T> &createTexture(ftl::codecs::Channel c, const ftl::rgbd::Format<T> &fmt, bool interpolated=false) { return this->create<VideoFrame>(c).createTexture<T>(fmt, interpolated); } - /** - * Is the channel data currently located on CPU memory. This also returns - * false if the channel does not exist. - */ - inline bool isCPU(ftl::codecs::Channel channel) const { - return hasChannel(channel) && !getData(channel).isgpu; - } }; -// Specialisations - -template <> cv::Mat &Frame::create(ftl::codecs::Channel c, const ftl::rgbd::FormatBase &); -template <> cv::cuda::GpuMat &Frame::create(ftl::codecs::Channel c, const ftl::rgbd::FormatBase &); template <typename T> -ftl::cuda::TextureObject<T> &Frame::getTexture(ftl::codecs::Channel c) { - if (!hasChannel(c)) throw FTL_Error("Texture channel does not exist: " << (int)c); - - auto &m = getData(c); - if (!m.isgpu) throw FTL_Error("Texture channel is not on GPU"); +ftl::cuda::TextureObject<T> &VideoFrame::getTexture() const { + if (!isgpu) throw FTL_Error("Texture channel is not on GPU"); - if (m.tex.cvType() != ftl::traits::OpenCVType<T>::value || m.tex.width() != static_cast<size_t>(m.gpu.cols) || m.tex.height() != static_cast<size_t>(m.gpu.rows) || m.gpu.type() != m.tex.cvType()) { - throw FTL_Error("Texture has not been created properly for this channel: " << (int)c); + if (tex.cvType() != ftl::traits::OpenCVType<T>::value || tex.width() != static_cast<size_t>(gpu.cols) || tex.height() != static_cast<size_t>(gpu.rows) || gpu.type() != tex.cvType()) { + throw FTL_Error("Texture has not been created properly"); } - return ftl::cuda::TextureObject<T>::cast(m.tex); + return ftl::cuda::TextureObject<T>::cast(tex); } template <typename T> -ftl::cuda::TextureObject<T> &Frame::createTexture(ftl::codecs::Channel c, const ftl::rgbd::Format<T> &f, bool interpolated) { - //if (!hasChannel(c)) channels_ += c; - //using ftl::data::Frame<0,32,ftl::rgbd::FrameState,VideoData>::create; - - create<cv::cuda::GpuMat>(c); - auto &m = getData(c); +ftl::cuda::TextureObject<T> &VideoFrame::createTexture(const ftl::rgbd::Format<T> &f, bool interpolated) { + createGPU(); if (f.empty()) { throw FTL_Error("createTexture needs a non-empty format"); } else { - m.gpu.create(f.size(), f.cvType); + gpu.create(f.size(), f.cvType); } - if (m.gpu.type() != ftl::traits::OpenCVType<T>::value) { - throw FTL_Error("Texture type mismatch: " << (int)c << " " << m.gpu.type() << " != " << ftl::traits::OpenCVType<T>::value); + if (gpu.type() != ftl::traits::OpenCVType<T>::value) { + throw FTL_Error("Texture type mismatch: " << gpu.type() << " != " << ftl::traits::OpenCVType<T>::value); } // TODO: Check tex cvType - if (m.tex.devicePtr() == nullptr) { + if (tex.devicePtr() == nullptr) { //LOG(INFO) << "Creating texture object"; - m.tex = ftl::cuda::TextureObject<T>(m.gpu, interpolated); - } else if (m.tex.cvType() != ftl::traits::OpenCVType<T>::value || m.tex.width() != static_cast<size_t>(m.gpu.cols) || m.tex.height() != static_cast<size_t>(m.gpu.rows)) { + tex = ftl::cuda::TextureObject<T>(gpu, interpolated); + } else if (tex.cvType() != ftl::traits::OpenCVType<T>::value || tex.width() != static_cast<size_t>(gpu.cols) || tex.height() != static_cast<size_t>(gpu.rows)) { //LOG(INFO) << "Recreating texture object for '" << ftl::codecs::name(c) << "'"; - m.tex.free(); - m.tex = ftl::cuda::TextureObject<T>(m.gpu, interpolated); + tex.free(); + tex = ftl::cuda::TextureObject<T>(gpu, interpolated); } - return ftl::cuda::TextureObject<T>::cast(m.tex); + return ftl::cuda::TextureObject<T>::cast(tex); } template <typename T> -ftl::cuda::TextureObject<T> &Frame::createTexture(ftl::codecs::Channel c, bool interpolated) { - if (!hasChannel(c)) throw FTL_Error("createTexture needs a format if the channel does not exist: " << (int)c); - - auto &m = getData(c); - - if (!m.isgpu && !m.host.empty()) { - m.gpu.create(m.host.size(), m.host.type()); +ftl::cuda::TextureObject<T> &VideoFrame::createTexture(bool interpolated) const { + if (!isgpu && !host.empty()) { + //gpu.create(host.size(), host.type()); // TODO: Should this upload to GPU or not? //gpu_ += c; - } else if (!m.isgpu || (m.isgpu && m.gpu.empty())) { + throw FTL_Error("Cannot create a texture on a host frame"); + } else if (!isgpu || (isgpu && gpu.empty())) { throw FTL_Error("createTexture needs a format if no memory is allocated"); } - if (m.gpu.type() != ftl::traits::OpenCVType<T>::value) { - throw FTL_Error("Texture type mismatch: " << (int)c << " " << m.gpu.type() << " != " << ftl::traits::OpenCVType<T>::value); + if (gpu.type() != ftl::traits::OpenCVType<T>::value) { + throw FTL_Error("Texture type mismatch: " << gpu.type() << " != " << ftl::traits::OpenCVType<T>::value); } // TODO: Check tex cvType - if (m.tex.devicePtr() == nullptr) { + if (tex.devicePtr() == nullptr) { //LOG(INFO) << "Creating texture object"; - m.tex = ftl::cuda::TextureObject<T>(m.gpu, interpolated); - } else if (m.tex.cvType() != ftl::traits::OpenCVType<T>::value || m.tex.width() != static_cast<size_t>(m.gpu.cols) || m.tex.height() != static_cast<size_t>(m.gpu.rows) || m.tex.devicePtr() != m.gpu.data) { + tex = ftl::cuda::TextureObject<T>(gpu, interpolated); + } else if (tex.cvType() != ftl::traits::OpenCVType<T>::value || tex.width() != static_cast<size_t>(gpu.cols) || tex.height() != static_cast<size_t>(gpu.rows) || tex.devicePtr() != gpu.data) { //LOG(INFO) << "Recreating texture object for '" << ftl::codecs::name(c) << "'."; - m.tex.free(); - m.tex = ftl::cuda::TextureObject<T>(m.gpu, interpolated); + tex.free(); + tex = ftl::cuda::TextureObject<T>(gpu, interpolated); } - return ftl::cuda::TextureObject<T>::cast(m.tex); + return ftl::cuda::TextureObject<T>::cast(tex); +} + +} } +template <> +cv::Mat &ftl::data::Frame::create<cv::Mat>(ftl::codecs::Channel c) { + return create<ftl::rgbd::VideoFrame>(c).createCPU(); } + +template <> +cv::cuda::GpuMat &ftl::data::Frame::create<cv::cuda::GpuMat>(ftl::codecs::Channel c) { + return create<ftl::rgbd::VideoFrame>(c).createGPU(); } #endif // _FTL_RGBD_FRAME_HPP_ \ No newline at end of file diff --git a/components/rgbd-sources/include/ftl/rgbd/frameset.hpp b/components/rgbd-sources/include/ftl/rgbd/frameset.hpp index 30ced7b65..02f638e7b 100644 --- a/components/rgbd-sources/include/ftl/rgbd/frameset.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/frameset.hpp @@ -4,7 +4,7 @@ #include <ftl/threads.hpp> #include <ftl/timer.hpp> #include <ftl/rgbd/frame.hpp> -#include <ftl/data/frameset.hpp> +#include <ftl/data/new_frameset.hpp> //#include <opencv2/core.hpp> #include <vector> @@ -16,176 +16,7 @@ namespace rgbd { static const size_t kMaxFramesets = 15; static const size_t kMaxFramesInSet = 32; -class Source; - -typedef ftl::data::FrameSet<ftl::rgbd::Frame> FrameSet; - -/** - * Represents a set of synchronised frames, each with two channels. This is - * used to collect all frames from multiple computers that have the same - * timestamp. - */ -//struct FrameSet { -// int id=0; -// int64_t timestamp; // Millisecond timestamp of all frames -// std::vector<ftl::rgbd::Frame> frames; -// std::atomic<int> count; // Number of valid frames -// std::atomic<unsigned int> mask; // Mask of all sources that contributed -// bool stale; // True if buffers have been invalidated -// SHARED_MUTEX mtx; - - /** - * Upload all specified host memory channels to GPU memory. - */ -// void upload(ftl::codecs::Channels<0>, cudaStream_t stream=0); - - /** - * Download all specified GPU memory channels to host memory. - */ -// void download(ftl::codecs::Channels<0>, cudaStream_t stream=0); - - /** - * Move the entire frameset to another frameset object. This will - * invalidate the current frameset object as all memory buffers will be - * moved. - */ -// void swapTo(ftl::rgbd::FrameSet &); - - /** - * Clear all channels and all memory allocations within those channels. - * This will perform a resetFull on all frames in the frameset. - */ -// void resetFull(); -//}; - -/** - * Callback type for receiving video frames. - */ -typedef std::function<bool(ftl::rgbd::FrameSet &)> VideoCallback; - -/** - * Abstract class for any generator of FrameSet structures. A generator - * produces (decoded) frame sets at regular frame intervals depending on the - * global timer settings. The `onFrameSet` callback may be triggered from any - * thread and also may drop frames and not be called for a given timestamp. - */ -class Generator { - public: - Generator() {} - virtual ~Generator() {} - - /** Number of frames in last frameset. This can change over time. */ - virtual size_t size()=0; - - /** - * Get the persistent state object for a frame. An exception is thrown - * for a bad index. - */ - virtual ftl::rgbd::FrameState &state(size_t ix)=0; - - inline ftl::rgbd::FrameState &operator[](int ix) { return state(ix); } - - /** Register a callback to receive new frame sets. */ - virtual void onFrameSet(const ftl::rgbd::VideoCallback &)=0; -}; - -/** - * Accept frames and generate framesets as they become completed. This can - * directly act as a generator of framesets, each frameset being generated - * by the global timer. Once the expected number of frames have been received, - * a frameset is marked as complete and can then be passed to the callback at - * the appropriate time. If frames are generated faster than consumed then they - * are buffered and merged into a single frameset. The buffer has a limited size - * so a longer delay in a callback will cause buffer failures. If frames are - * generated below framerate then the on frameset callback is just not called. - */ -class Builder : public Generator { - public: - Builder(); - ~Builder(); - - size_t size() override; - - ftl::rgbd::FrameState &state(size_t ix) override; - - inline void setID(int id) { id_ = id; } - - void onFrameSet(const ftl::rgbd::VideoCallback &) override; - - /** - * Add a new frame at a given timestamp. - */ - //void push(int64_t timestamp, size_t ix, ftl::rgbd::Frame &f); - - /** - * Instead of pushing a frame, find or create a direct reference to one. - */ - ftl::rgbd::Frame &get(int64_t timestamp, size_t ix); - - /** - * Get the entire frameset for a given timestamp. - */ - ftl::rgbd::FrameSet *get(int64_t timestamp); - - /** - * Mark a frame as completed. - */ - void completed(int64_t ts, size_t ix); - - void markPartial(int64_t ts); - - void setName(const std::string &name); - - void setBufferSize(size_t n) { bufferSize_ = n; } - - /** - * Retrieve an fps + latency pair, averaged since last call to this - * function. - */ - static std::pair<float,float> getStatistics(); - - private: - std::list<FrameSet*> framesets_; // Active framesets - std::list<FrameSet*> allocated_; // Keep memory allocations - - size_t head_; - ftl::rgbd::VideoCallback cb_; - MUTEX mutex_; - int mspf_; - int64_t last_ts_; - int64_t last_frame_; - int id_; - std::atomic<int> jobs_; - volatile bool skip_; - ftl::Handle main_id_; - size_t size_; - size_t bufferSize_; - std::vector<ftl::rgbd::FrameState*> states_; - - std::string name_; - - static MUTEX msg_mutex__; - static float latency__; - static float fps__; - static int stats_count__; - - /* Insert a new frameset into the buffer, along with all intermediate - * framesets between the last in buffer and the new one. - */ - ftl::rgbd::FrameSet *_addFrameset(int64_t timestamp); - - /* Find a frameset with given latency in frames. */ - ftl::rgbd::FrameSet *_getFrameset(); - ftl::rgbd::FrameSet *_get(int64_t timestamp); - - /* Search for a matching frameset. */ - ftl::rgbd::FrameSet *_findFrameset(int64_t ts); - void _freeFrameset(ftl::rgbd::FrameSet *); - - void _schedule(); - - void _recordStats(float fps, float latency); -}; +typedef ftl::data::FrameSet FrameSet; } } diff --git a/components/rgbd-sources/include/ftl/rgbd/source.hpp b/components/rgbd-sources/include/ftl/rgbd/source.hpp index 868e1a9a0..b7f4441f6 100644 --- a/components/rgbd-sources/include/ftl/rgbd/source.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/source.hpp @@ -13,7 +13,7 @@ #include <map> #include <ftl/cuda_common.hpp> -#include <ftl/rgbd/frame.hpp> +#include <ftl/data/new_frame.hpp> namespace ftl { @@ -24,7 +24,6 @@ class Universe; namespace rgbd { class BaseSourceImpl; -typedef std::function<void(int64_t,ftl::rgbd::Frame&)> FrameCallback; static inline bool isValidDepth(float d) { return (d > 0.01f) && (d < 39.99f); } @@ -80,14 +79,14 @@ class Source : public ftl::Configurable { /** * Download captured frame. This could be a blocking IO operation. */ - bool retrieve(); + bool retrieve(ftl::data::Frame &); /** * Generate a thread job using the provided callback for the most recently * retrieved frame (matching the provided timestamp). If already busy * dispatching, returns false. */ - bool dispatch(int64_t ts); + bool dispatch(ftl::data::Frame &); /** * Between frames, do any required buffer swaps. @@ -139,19 +138,14 @@ class Source : public ftl::Configurable { std::string getURI() { return value("uri", std::string("")); } - ftl::rgbd::FrameState &state(); - SHARED_MUTEX &mutex() { return mutex_; } - const FrameCallback &callback() { return callback_; } - /** * Set the callback that receives decoded frames as they are generated. * There can be only a single such callback as the buffers can be swapped * by the callback. */ - void setCallback(const FrameCallback &cb); - void removeCallback() { callback_ = nullptr; } + ftl::Handle setCallback(const std::function<bool(ftl::data::Frame&)> &cb); /** * Notify of a decoded or available pair of frames. This calls the source @@ -168,8 +162,8 @@ class Source : public ftl::Configurable { SHARED_MUTEX mutex_; ftl::codecs::Channel channel_; cudaStream_t stream_; - FrameCallback callback_; - ftl::rgbd::Frame frames_[2]; + ftl::SingletonHandler<ftl::data::Frame> callback_; + //ftl::rgbd::Frame frames_[2]; bool is_dispatching; bool is_retrieving; diff --git a/components/rgbd-sources/src/frame.cpp b/components/rgbd-sources/src/frame.cpp index 8c809c026..275175dd2 100644 --- a/components/rgbd-sources/src/frame.cpp +++ b/components/rgbd-sources/src/frame.cpp @@ -4,126 +4,27 @@ #define LOGURU_REPLACE_GLOG 1 #include <loguru.hpp> -using ftl::rgbd::Frame; -using ftl::rgbd::FrameState; using ftl::codecs::Channels; using ftl::codecs::Channel; -using ftl::rgbd::VideoData; +using ftl::rgbd::VideoFrame; -static cv::Mat none; -static cv::cuda::GpuMat noneGPU; -static std::atomic<int> frame_count = 0; - -template <> -cv::Mat &VideoData::as<cv::Mat>() { - if (isgpu) throw FTL_Error("Host request for GPU data without download"); - return host; -} - -template <> -const cv::Mat &VideoData::as<cv::Mat>() const { - if (isgpu) throw FTL_Error("Host request for GPU data without download"); - return host; -} - -template <> -cv::cuda::GpuMat &VideoData::as<cv::cuda::GpuMat>() { - if (!isgpu) throw FTL_Error("GPU request for Host data without upload"); - return gpu; -} - -template <> -const cv::cuda::GpuMat &VideoData::as<cv::cuda::GpuMat>() const { - if (!isgpu) throw FTL_Error("GPU request for Host data without upload"); - return gpu; -} - -template <> -cv::Mat &VideoData::make<cv::Mat>() { - validhost = true; - isgpu = false; - encoded.clear(); - return host; -} - -template <> -cv::cuda::GpuMat &VideoData::make<cv::cuda::GpuMat>() { - isgpu = true; - encoded.clear(); - return gpu; -} - -// ============================================================================= - -/*void Frame::reset() { - origin_ = nullptr; - channels_.clear(); - gpu_.clear(); - data_channels_.clear(); - for (size_t i=0u; i<Channels<0>::kMax; ++i) { - data_[i].encoded.clear(); - } -}*/ - -/*void Frame::resetFull() { - origin_ = nullptr; - channels_.clear(); - gpu_.clear(); - for (size_t i=0u; i<Channels<0>::kMax; ++i) { - data_[i].gpu = cv::cuda::GpuMat(); - data_[i].host = cv::Mat(); - data_[i].encoded.clear(); - } -}*/ - -Frame::Frame() { - ++frame_count; - //LOG(INFO) << "Frames: " << frame_count; +VideoFrame::VideoFrame(const VideoFrame &f) { + gpu = f.gpu; + host = f.host; + isgpu = f.isgpu; + validhost = f.validhost; } -Frame::Frame(Frame &&f) : ftl::data::Frame<0,32,ftl::rgbd::FrameState,VideoData>(std::move(f)) { - -} - -Frame &Frame::operator=(Frame &&f) { - ftl::data::Frame<0,32,ftl::rgbd::FrameState,VideoData>::operator=(std::move(f)); +VideoFrame &VideoFrame::operator=(const VideoFrame &f) { + gpu = f.gpu; + host = f.host; + isgpu = f.isgpu; + validhost = f.validhost; return *this; } -Frame::~Frame() { - --frame_count; -} - -void Frame::download(Channel c, cv::cuda::Stream stream) { - download(Channels(c), stream); -} - -void Frame::upload(Channel c, cv::cuda::Stream stream) { - upload(Channels(c), stream); -} - -void Frame::download(Channels<0> c, cv::cuda::Stream stream) { - for (size_t i=0u; i<Channels<0>::kMax; ++i) { - if (c.has(i) && hasChannel(static_cast<Channel>(i)) && isGPU(static_cast<Channel>(i))) { - auto &data = getData(static_cast<Channel>(i)); - data.validhost = true; - data.gpu.download(data.host, stream); - data.isgpu = false; - } - } -} -void Frame::upload(Channels<0> c, cv::cuda::Stream stream) { - for (size_t i=0u; i<Channels<0>::kMax; ++i) { - if (c.has(i) && hasChannel(static_cast<Channel>(i)) && !isGPU(static_cast<Channel>(i))) { - auto &data = getData(static_cast<Channel>(i)); - data.gpu.upload(data.host, stream); - data.isgpu = true; - } - } -} - -cv::Mat &Frame::fastDownload(ftl::codecs::Channel c, cv::cuda::Stream stream) { +/*cv::Mat &Frame::fastDownload(ftl::codecs::Channel c, cv::cuda::Stream stream) { if (hasChannel(c)) { auto &data = getData(static_cast<Channel>(c)); if (!data.isgpu) return data.host; @@ -136,86 +37,23 @@ cv::Mat &Frame::fastDownload(ftl::codecs::Channel c, cv::cuda::Stream stream) { return data.host; } throw FTL_Error("Fast download channel does not exist: " << (int)c); -} - -void Frame::pushPacket(ftl::codecs::Channel c, ftl::codecs::Packet &pkt) { - if (hasChannel(c)) { - auto &m1 = getData(c); - m1.encoded.emplace_back() = std::move(pkt); - } else { - throw FTL_Error("Channel " << (int)c << " doesn't exist for packet push"); - } -} - -const std::list<ftl::codecs::Packet> &Frame::getPackets(ftl::codecs::Channel c) const { - if (!hasChannel(c)) { - throw FTL_Error("Frame channel does not exist: " << (int)c); - } - - auto &m1 = getData(c); - return m1.encoded; -} - -void Frame::mergeEncoding(ftl::rgbd::Frame &f) { - //LOG(INFO) << "MERGE " << (unsigned int)f.channels_; - for (auto c : getChannels()) { - //if (!f.hasChannel(c)) f.create<cv::cuda::GpuMat>(c); - if (f.hasChannel(c)) { - auto &m1 = getData(c); - auto &m2 = f.getData(c); - m1.encoded.splice(m1.encoded.begin(), m2.encoded); - //LOG(INFO) << "SPLICED: " << m1.encoded.size(); - } - } -} - -bool Frame::empty(ftl::codecs::Channels<0> channels) { - for (auto c : channels) { - if (empty(c)) return true; - } - return false; -} - -template <> cv::Mat &Frame::create(ftl::codecs::Channel c, const ftl::rgbd::FormatBase &f) { - if (c == Channel::None) { - throw FTL_Error("Cannot create a None channel"); - } - - create<cv::Mat>(c); - auto &m = getData(c); - - m.encoded.clear(); // Remove all old encoded data +}*/ +cv::Mat &VideoFrame::createCPU(const ftl::rgbd::FormatBase &f) { if (!f.empty()) { - m.host.create(f.size(), f.cvType); + host.create(f.size(), f.cvType); } + isgpu = false; - return m.host; + return host; } -template <> cv::cuda::GpuMat &Frame::create(ftl::codecs::Channel c, const ftl::rgbd::FormatBase &f) { - if (c == Channel::None) { - throw FTL_Error("Cannot create a None channel"); - } - - create<cv::cuda::GpuMat>(c); - auto &m = getData(c); - - m.encoded.clear(); // Remove all old encoded data - +cv::cuda::GpuMat &VideoFrame::create(const ftl::rgbd::FormatBase &f) { if (!f.empty()) { - m.gpu.create(f.size(), f.cvType); + gpu.create(f.size(), f.cvType); } + isgpu = true; - return m.gpu; -} - -void Frame::clearPackets(ftl::codecs::Channel c) { - auto &m = getData(c); - m.encoded.clear(); + return gpu; } -void Frame::resetTexture(ftl::codecs::Channel c) { - auto &m = getData(c); - m.tex.free(); -} diff --git a/components/rgbd-sources/src/source.cpp b/components/rgbd-sources/src/source.cpp index 2a9af5889..0ee4a2f1a 100644 --- a/components/rgbd-sources/src/source.cpp +++ b/components/rgbd-sources/src/source.cpp @@ -30,7 +30,6 @@ using ftl::rgbd::capability_t; using ftl::codecs::Channel; //using ftl::rgbd::detail::FileSource; using ftl::rgbd::Camera; -using ftl::rgbd::FrameCallback; Source::Source(ftl::config::json_t &cfg) : Configurable(cfg), pose_(Eigen::Matrix4d::Identity()), net_(nullptr) { @@ -185,34 +184,34 @@ bool Source::capture(int64_t ts) { else return true; } -bool Source::retrieve() { +bool Source::retrieve(ftl::data::Frame &f) { is_retrieving = true; bool status = false; - if (impl_) status = impl_->retrieve(frames_[0]); + if (impl_) status = impl_->retrieve(f); is_retrieving = false; return status; } -bool Source::dispatch(int64_t ts) { +bool Source::dispatch(ftl::data::Frame &f) { if (!callback_) return false; if (is_dispatching || is_retrieving) { LOG(WARNING) << "Previous distance not completed"; return false; } is_dispatching = true; - _swap(); + //_swap(); ftl::pool.push([this,ts](int id) { - callback_(ts, frames_[1]); + callback_.trigger(f); is_dispatching = false; }); return true; } -void Source::_swap() { +/*void Source::_swap() { auto tmp = std::move(frames_[0]); frames_[0] = std::move(frames_[1]); frames_[1] = std::move(tmp); -} +}*/ bool Source::setChannel(ftl::codecs::Channel c) { channel_ = c; @@ -224,9 +223,8 @@ const ftl::rgbd::Camera Source::parameters(ftl::codecs::Channel chan) const { return (impl_) ? impl_->parameters(chan) : parameters(); } -void Source::setCallback(const FrameCallback &cb) { - if (bool(callback_)) LOG(ERROR) << "Source already has a callback: " << getURI(); - callback_ = cb; +ftl::Handle Source::setCallback(const std::function<bool(ftl::data::Frame&)> &cb) { + return callback_.on(cb); } diff --git a/components/structures/include/ftl/data/new_frame.hpp b/components/structures/include/ftl/data/new_frame.hpp index 84a598b66..25997f5a9 100644 --- a/components/structures/include/ftl/data/new_frame.hpp +++ b/components/structures/include/ftl/data/new_frame.hpp @@ -26,7 +26,8 @@ class Pool; enum FrameMode { PRIMARY, - RESPONSE + RESPONSE, + STANDALONE }; enum FrameStatus { @@ -102,6 +103,8 @@ class Frame { bool has(ftl::codecs::Channel c) const; + inline bool hasChannel(ftl::codecs::Channel c) const { return has(c); } + inline bool hasOwn(ftl::codecs::Channel c) const; inline bool changed(ftl::codecs::Channel c) const; @@ -204,6 +207,8 @@ class Frame { void swapChannel(ftl::codecs::Channel, Frame &); + void swapChannels(ftl::codecs::Channel, ftl::codecs::Channel); + /** * Discard all change status without removing the data. */ @@ -248,6 +253,15 @@ class Frame { */ Frame response(); + template <typename T> + T &cast(); + + /** + * Used to create isolated frame objects for buffer purposes. This is + * deliberately separate from default constructor to force its explicit use. + */ + static Frame make_standalone(); + protected: std::any &createAnyChange(ftl::codecs::Channel c, ftl::data::ChangeType t); @@ -320,6 +334,13 @@ class Session : public Frame { MUTEX &ftl::data::Frame::mutex() { return parent_->mutex(); } +template <typename T> +T &ftl::data::Frame::cast() { + static_assert(std::is_base_of<Frame, T>::value, "Can only cast to type inheriting Frame"); + static_assert(sizeof(T) == sizeof(Frame), "Casting type must not have additional data members"); + return *reinterpret_cast<T*>(this); +} + bool ftl::data::Frame::hasOwn(ftl::codecs::Channel c) const { const auto &i = data_.find(c); return (i != data_.end() && i->second.status != ftl::data::ChannelStatus::INVALID); diff --git a/components/structures/src/new_frame.cpp b/components/structures/src/new_frame.cpp index b33a41424..dc2823c79 100644 --- a/components/structures/src/new_frame.cpp +++ b/components/structures/src/new_frame.cpp @@ -229,6 +229,21 @@ void Frame::swapChannel(ftl::codecs::Channel c, Frame &f) { } } +void Frame::swapChannels(ftl::codecs::Channel c1, ftl::codecs::Channel c2) { + if (hasOwn(c1) && hasOwn(c2)) { + auto &d1 = data_[c1]; + auto &d2 = data_[c2]; + d2.data.swap(d1.data); + + auto status = d1.status; + d1.status = d2.status; + d2.status = status; + + changed_[c1] = (mode_ == FrameMode::PRIMARY) ? ChangeType::PRIMARY : ChangeType::RESPONSE; + changed_[c2] = (mode_ == FrameMode::PRIMARY) ? ChangeType::PRIMARY : ChangeType::RESPONSE; + } +} + void Frame::reset() { for (auto &d : data_) { d.second.status = ChannelStatus::INVALID; @@ -251,6 +266,12 @@ Frame Frame::response() { return f; } +Frame Frame::make_standalone() { + Frame f(nullptr, nullptr, 0, 0); + f.mode_ = FrameMode::STANDALONE; + return f; +} + // ==== Session ================================================================ ftl::Handle Session::onChange(uint32_t pid, ftl::codecs::Channel c, const std::function<bool(Frame&,ftl::codecs::Channel)> &cb) { -- GitLab