diff --git a/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp b/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp index 7557fecb3da30af7a818823904a9b71bba3bc057..b76dd27fac1a7f09a07612629c9d6aae8ef47eb3 100644 --- a/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp @@ -49,10 +49,22 @@ class Source { virtual ~Source() {} /** + * Perform hardware data capture. + */ + virtual bool capture() { return true; }; + + /** + * Do any processing from previously captured frames... * @param n Number of frames to request in batch. Default -1 means automatic (10) * @param b Bit rate setting. -1 = automatic, 0 = best quality, 9 = lowest quality */ - virtual bool grab(int n, int b)=0; + virtual bool compute(int n, int b)=0; + + /** + * Between frames, or before next frame, do any buffer swapping operations. + */ + virtual void swap() {} + virtual bool isReady() { return false; }; virtual void setPose(const Eigen::Matrix4d &pose) { }; diff --git a/components/rgbd-sources/include/ftl/rgbd/source.hpp b/components/rgbd-sources/include/ftl/rgbd/source.hpp index 4efb97175e886ba821f752f7f154eddde0aa1f8f..55cb8554e9eded1b661a89cdf917025369467ad2 100644 --- a/components/rgbd-sources/include/ftl/rgbd/source.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/source.hpp @@ -71,19 +71,34 @@ class Source : public ftl::Configurable { /** * Perform the hardware or virtual frame grab operation. */ - bool grab(int N=-1, int B=-1); + bool capture(); + + /** + * Between frames, do any required buffer swaps. + */ + void swap() { if (impl_) impl_->swap(); } /** * Do any post-grab processing. This function * may take considerable time to return, especially for sources requiring - * software stereo correspondance. If `process` is not called manually - * after a `grab` and before a `get`, then it will be called automatically - * on first `get`. + * software stereo correspondance. */ - //void process(); + bool compute(int N=-1, int B=-1); + + /** + * Wrapper grab that performs capture, swap and computation steps in one. + * It is more optimal to perform capture and compute in parallel. + */ + bool grab(int N=-1, int B=-1) { + bool c = capture(); + swap(); + return c && compute(N,B); + } /** - * Get a copy of both colour and depth frames. + * Get a copy of both colour and depth frames. Note that this does a buffer + * swap rather than a copy, so the parameters should be persistent buffers for + * best performance. */ void getFrames(cv::Mat &c, cv::Mat &d); diff --git a/components/rgbd-sources/src/group.cpp b/components/rgbd-sources/src/group.cpp index f548806d5b78b00428269f1f4c7d7c5bced8a197..88b9afcdca48fd141ca6487637dc7c78f9181d87 100644 --- a/components/rgbd-sources/src/group.cpp +++ b/components/rgbd-sources/src/group.cpp @@ -60,7 +60,9 @@ void Group::addSource(ftl::rgbd::Source *src) { // Callback returns true if it wishes to continue receiving frames. void Group::sync(int N, int B) { for (auto s : sources_) { - s->grab(N,B); + s->capture(); + s->swap(); + s->compute(N,B); } } diff --git a/components/rgbd-sources/src/image.hpp b/components/rgbd-sources/src/image.hpp index b389fd176ec246db3ca51180589673817897eb03..ccb6ede5c93ed32213a89cc65fe90ab5d1cfbc78 100644 --- a/components/rgbd-sources/src/image.hpp +++ b/components/rgbd-sources/src/image.hpp @@ -14,7 +14,7 @@ class ImageSource : public ftl::rgbd::detail::Source { } - bool grab(int n, int b) { return false; }; + bool compute(int n, int b) { return false; }; bool isReady() { return false; }; }; diff --git a/components/rgbd-sources/src/middlebury_source.cpp b/components/rgbd-sources/src/middlebury_source.cpp index d41d4e77b85d8320ef01572dcd6707af68b5b705..a707bf9fab06a212b4146065b414999d21bc9adb 100644 --- a/components/rgbd-sources/src/middlebury_source.cpp +++ b/components/rgbd-sources/src/middlebury_source.cpp @@ -160,7 +160,7 @@ void MiddleburySource::_performDisparity() { //disparityToDepthTRUE(depth_, depth_, params_); } -bool MiddleburySource::grab(int n, int b) { +bool MiddleburySource::compute(int n, int b) { //_performDisparity(); return true; } diff --git a/components/rgbd-sources/src/middlebury_source.hpp b/components/rgbd-sources/src/middlebury_source.hpp index 5f0e2be538a069747d633e3e4b9483eb8a7a75b2..25f58b05e7888ded29eed71454eb591fd30babed 100644 --- a/components/rgbd-sources/src/middlebury_source.hpp +++ b/components/rgbd-sources/src/middlebury_source.hpp @@ -19,7 +19,7 @@ class MiddleburySource : public detail::Source { MiddleburySource(ftl::rgbd::Source *, const std::string &dir); ~MiddleburySource() {}; - bool grab(int n, int b); + bool compute(int n, int b); bool isReady() { return ready_; } private: diff --git a/components/rgbd-sources/src/net.cpp b/components/rgbd-sources/src/net.cpp index 9a2fdf2af5b667630d9720102549e767b144c36d..135395c57a1bc1f9983308719e88f7f49d5df8cf 100644 --- a/components/rgbd-sources/src/net.cpp +++ b/components/rgbd-sources/src/net.cpp @@ -302,7 +302,7 @@ void NetSource::_updateURI() { } } -bool NetSource::grab(int n, int b) { +bool NetSource::compute(int n, int b) { // Choose highest requested number of frames maxN_ = std::max(maxN_,(n == -1) ? ftl::rgbd::detail::kDefaultFrameCount : n); diff --git a/components/rgbd-sources/src/net.hpp b/components/rgbd-sources/src/net.hpp index b99dc3487a6f4ab1949779935e2ed41699e9f4b0..b3411f12cce2f1e0236475ca75f667429ac5e35d 100644 --- a/components/rgbd-sources/src/net.hpp +++ b/components/rgbd-sources/src/net.hpp @@ -24,7 +24,7 @@ class NetSource : public detail::Source { explicit NetSource(ftl::rgbd::Source *); ~NetSource(); - bool grab(int n, int b); + bool compute(int n, int b); bool isReady(); void setPose(const Eigen::Matrix4d &pose); diff --git a/components/rgbd-sources/src/realsense_source.cpp b/components/rgbd-sources/src/realsense_source.cpp index d6c6f487be89c3eafd4e3e8e6020272dd93e8e9d..df4c0fe2535426ac52808ea985911968efb74e15 100644 --- a/components/rgbd-sources/src/realsense_source.cpp +++ b/components/rgbd-sources/src/realsense_source.cpp @@ -41,7 +41,7 @@ RealsenseSource::~RealsenseSource() { } -bool RealsenseSource::grab(int n, int b) { +bool RealsenseSource::compute(int n, int b) { rs2::frameset frames; if (!pipe_.poll_for_frames(&frames)) return false; //wait_for_frames(); diff --git a/components/rgbd-sources/src/realsense_source.hpp b/components/rgbd-sources/src/realsense_source.hpp index 2af26bbaffb99081e3311a70cb2c715c8fca5cee..3b2d70c76c28608a3faa96af7c927bc0011804f3 100644 --- a/components/rgbd-sources/src/realsense_source.hpp +++ b/components/rgbd-sources/src/realsense_source.hpp @@ -17,7 +17,7 @@ class RealsenseSource : public ftl::rgbd::detail::Source { RealsenseSource(ftl::rgbd::Source *host); ~RealsenseSource(); - bool grab(int n=-1, int b=-1); + bool compute(int n=-1, int b=-1); bool isReady(); private: diff --git a/components/rgbd-sources/src/snapshot_source.hpp b/components/rgbd-sources/src/snapshot_source.hpp index 38b9d875ad9e9846d0c83e42d6b84668cfe7dd18..abc8fd76bb56d9790bb7af6e5098fab80120b8b7 100644 --- a/components/rgbd-sources/src/snapshot_source.hpp +++ b/components/rgbd-sources/src/snapshot_source.hpp @@ -17,7 +17,7 @@ class SnapshotSource : public detail::Source { SnapshotSource(ftl::rgbd::Source *, ftl::rgbd::SnapshotReader &reader, const std::string &id); ~SnapshotSource() {}; - bool grab(int n, int b) override { return true; }; + bool compute(int n, int b) override { return true; }; bool isReady() { return true; } //void reset(); diff --git a/components/rgbd-sources/src/source.cpp b/components/rgbd-sources/src/source.cpp index 1014e24401b4d2dccdc361de3d4331ff2815eacb..4a3b7093ba8a4a5863c67dc51693cdbe1276c1b4 100644 --- a/components/rgbd-sources/src/source.cpp +++ b/components/rgbd-sources/src/source.cpp @@ -167,8 +167,16 @@ void Source::getFrames(cv::Mat &rgb, cv::Mat &depth) { SHARED_LOCK(mutex_,lk); //rgb_.copyTo(rgb); //depth_.copyTo(depth); + //rgb = rgb_; + //depth = depth_; + + cv::Mat tmp; + tmp = rgb; rgb = rgb_; + rgb_ = tmp; + tmp = depth; depth = depth_; + depth_ = tmp; } Eigen::Vector4d Source::point(uint ux, uint uy) { @@ -222,16 +230,21 @@ void Source::reset() { impl_ = _createImplementation(); } -bool Source::grab(int N, int B) { +bool Source::capture() { + if (impl_) return impl_->capture(); + else return true; +} + +bool Source::compute(int N, int B) { UNIQUE_LOCK(mutex_,lk); if (!impl_ && stream_ != 0) { cudaSafeCall(cudaStreamSynchronize(stream_)); if (depth_.type() == CV_32SC1) depth_.convertTo(depth_, CV_32F, 1.0f / 1000.0f); stream_ = 0; return true; - } else if (impl_ && impl_->grab(N,B)) { + } else if (impl_ && impl_->compute(N,B)) { timestamp_ = impl_->timestamp_; - /*cv::Mat tmp; + cv::Mat tmp; rgb_.create(impl_->rgb_.size(), impl_->rgb_.type()); depth_.create(impl_->depth_.size(), impl_->depth_.type()); tmp = rgb_; @@ -239,9 +252,10 @@ bool Source::grab(int N, int B) { impl_->rgb_ = tmp; tmp = depth_; depth_ = impl_->depth_; - impl_->depth_ = tmp;*/ - impl_->rgb_.copyTo(rgb_); - impl_->depth_.copyTo(depth_); + impl_->depth_ = tmp; + + //impl_->rgb_.copyTo(rgb_); + //impl_->depth_.copyTo(depth_); return true; } return false; @@ -314,7 +328,9 @@ bool Source::thumbnail(cv::Mat &t) { return true; } else if (impl_) { UNIQUE_LOCK(mutex_,lk); - impl_->grab(1, 9); + impl_->capture(); + impl_->swap(); + impl_->compute(1, 9); impl_->rgb_.copyTo(rgb_); impl_->depth_.copyTo(depth_); } diff --git a/components/rgbd-sources/src/stereovideo.cpp b/components/rgbd-sources/src/stereovideo.cpp index d7e24de78c41e5b126de3bea44efa176abf062ad..0d20780c275a43a2338fd9d81a6a98f13619c3a2 100644 --- a/components/rgbd-sources/src/stereovideo.cpp +++ b/components/rgbd-sources/src/stereovideo.cpp @@ -153,11 +153,29 @@ static void disparityToDepth(const cv::cuda::GpuMat &disparity, cv::cuda::GpuMat cv::cuda::divide(val, disparity, depth, 1.0f / 1000.0f, -1, stream); } -bool StereoVideoSource::grab(int n, int b) { +bool StereoVideoSource::capture() { + lsrc_->get(cap_left_, cap_right_, stream2_); + stream2_.waitForCompletion(); + return true; +} + +void StereoVideoSource::swap() { + cv::cuda::GpuMat tmp; + tmp = left_; + left_ = cap_left_; + cap_left_ = tmp; + tmp = right_; + right_ = cap_right_; + cap_right_ = tmp; +} + +bool StereoVideoSource::compute(int n, int b) { const ftl::rgbd::channel_t chan = host_->getChannel(); + if (left_.empty() || right_.empty()) return false; + if (chan == ftl::rgbd::kChanDepth) { - lsrc_->get(left_, right_, stream_); + //lsrc_->get(left_, right_, stream_); if (depth_tmp_.empty()) depth_tmp_ = cv::cuda::GpuMat(left_.size(), CV_32FC1); if (disp_tmp_.empty()) disp_tmp_ = cv::cuda::GpuMat(left_.size(), CV_32FC1); calib_->rectifyStereo(left_, right_, stream_); @@ -169,13 +187,13 @@ bool StereoVideoSource::grab(int n, int b) { stream_.waitForCompletion(); // TODO:(Nick) Move to getFrames } else if (chan == ftl::rgbd::kChanRight) { - lsrc_->get(left_, right_, stream_); + //lsrc_->get(left_, right_, stream_); calib_->rectifyStereo(left_, right_, stream_); left_.download(rgb_, stream_); right_.download(depth_, stream_); stream_.waitForCompletion(); // TODO:(Nick) Move to getFrames } else { - lsrc_->get(left_, right_, stream_); + //lsrc_->get(left_, right_, stream_); calib_->rectifyStereo(left_, right_, stream_); //rgb_ = lsrc_->cachedLeft(); left_.download(rgb_, stream_); diff --git a/components/rgbd-sources/src/stereovideo.hpp b/components/rgbd-sources/src/stereovideo.hpp index 7835742389330046a33b7f22289ac36e8cdab4d5..9d01da4cdebe0ca2bb2a1e91832ca016f7116645 100644 --- a/components/rgbd-sources/src/stereovideo.hpp +++ b/components/rgbd-sources/src/stereovideo.hpp @@ -26,7 +26,9 @@ class StereoVideoSource : public detail::Source { StereoVideoSource(ftl::rgbd::Source*, const std::string &); ~StereoVideoSource(); - bool grab(int n, int b); + void swap(); + bool capture(); + bool compute(int n, int b); bool isReady(); Camera parameters(channel_t chan); @@ -40,9 +42,12 @@ class StereoVideoSource : public detail::Source { bool ready_; cv::cuda::Stream stream_; + cv::cuda::Stream stream2_; cv::cuda::GpuMat left_; cv::cuda::GpuMat right_; + cv::cuda::GpuMat cap_left_; + cv::cuda::GpuMat cap_right_; cv::cuda::GpuMat disp_tmp_; cv::cuda::GpuMat depth_tmp_; diff --git a/components/rgbd-sources/src/streamer.cpp b/components/rgbd-sources/src/streamer.cpp index 1d46ad7fd3c6ab9f35aa435bf6775927994eaceb..3fd69afe3fd6568f16ed9a9c9b489fde36bdc64a 100644 --- a/components/rgbd-sources/src/streamer.cpp +++ b/components/rgbd-sources/src/streamer.cpp @@ -274,6 +274,7 @@ void Streamer::_swap(StreamSource *src) { } src->src->getFrames(src->rgb, src->depth); + src->src->swap(); //if (!src->rgb.empty() && src->prev_depth.empty()) { //src->prev_depth = cv::Mat(src->rgb.size(), CV_16UC1, cv::Scalar(0)); @@ -325,14 +326,14 @@ void Streamer::_schedule() { // There will be two jobs for this source... //UNIQUE_LOCK(job_mtx_,lk); - jobs_ += 1 + kChunkCount; + jobs_ += 2 + kChunkCount; //lk.unlock(); StreamSource *src = sources_[uri]; if (src == nullptr || src->jobs != 0) continue; - src->jobs = 1 + kChunkCount; + src->jobs = 2 + kChunkCount; - // Grab job + // Grab / capture job ftl::pool.push([this,src](int id) { //auto start = std::chrono::high_resolution_clock::now(); @@ -362,7 +363,7 @@ void Streamer::_schedule() { last_frame_ = now/40; try { - src->src->grab(); + src->src->capture(); } catch (std::exception &ex) { LOG(ERROR) << "Exception when grabbing frame"; LOG(ERROR) << ex.what(); @@ -387,6 +388,27 @@ void Streamer::_schedule() { job_cv_.notify_one(); }); + // Compute job + ftl::pool.push([this,src](int id) { + try { + src->src->compute(); + } catch (std::exception &ex) { + LOG(ERROR) << "Exception when computing frame"; + LOG(ERROR) << ex.what(); + } + catch (...) { + LOG(ERROR) << "Unknown exception when computing frame"; + } + + src->jobs--; + _swap(src); + + // Mark job as finished + std::unique_lock<std::mutex> lk(job_mtx_); + --jobs_; + job_cv_.notify_one(); + }); + // Create jobs for each chunk for (int i=0; i<kChunkCount; ++i) { // Add chunk job to thread pool diff --git a/components/rgbd-sources/test/source_unit.cpp b/components/rgbd-sources/test/source_unit.cpp index b27b72e070f6e2116632b967699243a9e80926d8..1c80e8292ff27e3c2652e7453dff59a1acea7bda 100644 --- a/components/rgbd-sources/test/source_unit.cpp +++ b/components/rgbd-sources/test/source_unit.cpp @@ -26,7 +26,7 @@ class ImageSource : public ftl::rgbd::detail::Source { last_type = "image"; } - bool grab(int n, int b) { return true; }; + bool compute(int n, int b) { return true; }; bool isReady() { return true; }; }; @@ -39,7 +39,7 @@ class StereoVideoSource : public ftl::rgbd::detail::Source { last_type = "video"; } - bool grab(int n, int b) { return true; }; + bool compute(int n, int b) { return true; }; bool isReady() { return true; }; }; @@ -49,7 +49,7 @@ class NetSource : public ftl::rgbd::detail::Source { last_type = "net"; } - bool grab(int n, int b) { return true; }; + bool compute(int n, int b) { return true; }; bool isReady() { return true; }; }; @@ -59,7 +59,7 @@ class SnapshotSource : public ftl::rgbd::detail::Source { last_type = "snapshot"; } - bool grab(int n, int b) { return true; }; + bool compute(int n, int b) { return true; }; bool isReady() { return true; }; }; @@ -69,7 +69,7 @@ class RealsenseSource : public ftl::rgbd::detail::Source { last_type = "realsense"; } - bool grab(int n, int b) { return true; }; + bool compute(int n, int b) { return true; }; bool isReady() { return true; }; }; @@ -79,7 +79,7 @@ class MiddleburySource : public ftl::rgbd::detail::Source { last_type = "middlebury"; } - bool grab(int n, int b) { return true; }; + bool compute(int n, int b) { return true; }; bool isReady() { return true; }; };