diff --git a/applications/gui2/src/modules/camera.cpp b/applications/gui2/src/modules/camera.cpp index bc6839a356204d179d0b53b546b1c22435b333c4..a1d2e352ec062a4aa958b58903eba6cad2ecfc1e 100644 --- a/applications/gui2/src/modules/camera.cpp +++ b/applications/gui2/src/modules/camera.cpp @@ -1,9 +1,11 @@ #include "camera.hpp" #include "../views/camera3d.hpp" +#include <ftl/rgbd/capabilities.hpp> using ftl::gui2::Camera; using ftl::codecs::Channel; +using ftl::rgbd::Capability; void Camera::init() { @@ -31,11 +33,38 @@ void Camera::activate(ftl::data::FrameID id) { speaker->setVolume(v); }); + has_seen_frame_ = false; + filter = io->feed()->filter(std::unordered_set<unsigned int>{id.frameset()}, {Channel::Left, Channel::Depth}); filter->on( [this, speaker = io->speaker(), panel = this->panel](ftl::data::FrameSetPtr fs){ if (paused || !view) { return true; } - std::atomic_store(¤t_fs_, fs); + + // For first data, extract useful things + if (!has_seen_frame_) { + has_seen_frame_ = true; + + // TODO: Create the view here... + + if (fs->frames[frame_idx].has(Channel::Capabilities)) { + const auto &cap = fs->frames[frame_idx].get<std::unordered_set<Capability>>(Channel::Capabilities); + LOG(INFO) << "Camera Capabilities:"; + for (auto c : cap) { + LOG(INFO) << " -- " << (int)c; + } + } + + if (fs->frames[frame_idx].has(Channel::MetaData)) { + const auto &meta = fs->frames[frame_idx].get<std::map<std::string,std::string>>(Channel::MetaData); + LOG(INFO) << "Camera Frame Meta Data:"; + for (auto m : meta) { + LOG(INFO) << " -- " << m.first << " = " << m.second; + } + } + } + + //std::atomic_store(¤t_fs_, fs); // Not needed and deprecated in C++20 + current_fs_ = fs; // Deal with audio if (fs->frames[frame_idx].hasOwn(Channel::AudioStereo)) { diff --git a/applications/gui2/src/modules/camera.hpp b/applications/gui2/src/modules/camera.hpp index 4a17f749d06b12dc4ab4940157ac2dd11c3eeac0..e2d5439e8cb7dbb4a65de187b3dabeb6c7309900 100644 --- a/applications/gui2/src/modules/camera.hpp +++ b/applications/gui2/src/modules/camera.hpp @@ -38,6 +38,7 @@ private: ftl::codecs::Channel channel = ftl::codecs::Channel::Colour; ftl::stream::Feed::Filter *filter = nullptr; std::atomic_bool paused = false; // TODO: implement in InputOutput + bool has_seen_frame_ = false; ftl::data::FrameSetPtr current_fs_; ftl::cuda::TextureObject<uchar4> current_frame_; diff --git a/components/codecs/include/ftl/codecs/channels.hpp b/components/codecs/include/ftl/codecs/channels.hpp index 417de06051f1458f30ee75e309a2b078a79740f7..bcbaad4b8e5ac234d51c9099d7b4d11820f94a45 100644 --- a/components/codecs/include/ftl/codecs/channels.hpp +++ b/components/codecs/include/ftl/codecs/channels.hpp @@ -53,7 +53,7 @@ enum struct Channel : int { Index = 68, Control = 69, // For stream and encoder control Settings3 = 70, - Name = 71, + MetaData = 71, // Map of string pairs (key, value) Capabilities = 72, // Unordered set of int capabilities Data = 2048, // Custom data, any codec. diff --git a/components/renderers/cpp/src/overlay.cpp b/components/renderers/cpp/src/overlay.cpp index 2472ade58f32eb832677c265dece1cb5424fdf74..947662acd1d3c315b0d69f23cfacf0680fea7ac8 100644 --- a/components/renderers/cpp/src/overlay.cpp +++ b/components/renderers/cpp/src/overlay.cpp @@ -299,7 +299,8 @@ void Overlay::draw(ftl::data::FrameSet &fs, ftl::rgbd::Frame &frame, const Eigen auto pose = f.getPose(); //.inverse() * state.getPose(); - auto name = fs.frames[i].get<std::string>(Channel::Name); + auto meta = fs.frames[i].get<std::map<std::string,std::string>>(Channel::MetaData); + std::string name = (meta.count("name")) ? meta["name"] : "NoName"; _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)); diff --git a/components/rgbd-sources/include/ftl/rgbd/capabilities.hpp b/components/rgbd-sources/include/ftl/rgbd/capabilities.hpp index c43b47e042adb9396067a66bbaae28fb748cddec..9f8ba139963d938c96ca0d9ad8192e39c8756fff 100644 --- a/components/rgbd-sources/include/ftl/rgbd/capabilities.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/capabilities.hpp @@ -10,18 +10,20 @@ namespace rgbd { * To be added to the capabilities channel to indicate what the source device * is capable of. */ -enum class Capabilities : int { +enum class Capability : int { DEPTH = 0, // Has depth data MOVABLE, // Is a pose controllable camera STEREO, // Has right colour ACTIVE, // An active depth sensor VIDEO, // Is video and not just static - FEEDBACK // Can respond to feedback data (not just movable) + FEEDBACK, // Can respond to feedback data (not just movable) + ADJUSTABLE, // Camera properties can be changed (exposure etc) + VIRTUAL // Is not a physical camera }; } } -MSGPACK_ADD_ENUM(ftl::rgbd::Capabilities); +MSGPACK_ADD_ENUM(ftl::rgbd::Capability); #endif \ No newline at end of file diff --git a/components/rgbd-sources/src/init.cpp b/components/rgbd-sources/src/init.cpp index 4633d3e937a5e04371d691250083fe3b843d7066..712b933cae220e3a88e1ddada193b263fbb03d9e 100644 --- a/components/rgbd-sources/src/init.cpp +++ b/components/rgbd-sources/src/init.cpp @@ -8,8 +8,8 @@ using ftl::data::StorageMode; bool ftl_video_init = ftl::data::make_channel<ftl::rgbd::Camera>(Channel::Calibration, "calibration", ftl::data::StorageMode::PERSISTENT) && ftl::data::make_channel<ftl::rgbd::Camera>(Channel::Pose, "pose", ftl::data::StorageMode::PERSISTENT) && - ftl::data::make_channel<ftl::rgbd::Camera>(Channel::Calibration2, "calibration_right", ftl::data::StorageMode::PERSISTENT) && - ftl::data::make_channel<ftl::rgbd::Camera>(Channel::Name, "name", ftl::data::StorageMode::PERSISTENT); + ftl::data::make_channel<ftl::rgbd::Camera>(Channel::Calibration2, "calibration_right", ftl::data::StorageMode::PERSISTENT); // && + //ftl::data::make_channel<ftl::rgbd::Camera>(Channel::Name, "name", ftl::data::StorageMode::PERSISTENT); bool ftl_video_initialised() { return ftl_video_init; diff --git a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp index 191c5ed83e0d97d8b90683bca7336e74ea79148a..56ad3b08831bdce80b8dcf2e060bc30ad9f7aad6 100644 --- a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp +++ b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp @@ -22,9 +22,12 @@ #include "ftl/operators/disparity.hpp" #include "ftl/operators/mask.hpp" +#include <ftl/rgbd/capabilities.hpp> + #include "ftl/threads.hpp" #include "calibrate.hpp" #include "opencv.hpp" +#include <unordered_set> #ifdef HAVE_PYLON #include "pylon.hpp" @@ -34,6 +37,7 @@ using ftl::rgbd::detail::Calibrate; using ftl::rgbd::detail::StereoVideoSource; using ftl::codecs::Channel; using std::string; +using ftl::rgbd::Capability; ftl::rgbd::detail::Device::Device(nlohmann::json &config) : Configurable(config) { @@ -248,7 +252,19 @@ void StereoVideoSource::updateParameters(ftl::rgbd::Frame &frame) { frame.setPose() = pose; - frame.create<std::string>(Channel::Name) = host_->value("name", host_->getID()); + auto &meta = frame.create<std::map<std::string,std::string>>(Channel::MetaData); + meta["name"] = host_->value("name", host_->getID()); + meta["uri"] = host_->value("uri", std::string("")); + + if (!frame.has(Channel::Capabilities)) { + auto &cap = frame.create<std::unordered_set<Capability>>(Channel::Capabilities); + cap.emplace(Capability::VIDEO); + + if (lsrc_->isStereo()) { + cap.emplace(Capability::STEREO); + cap.emplace(Capability::DEPTH); + } + } cv::Mat K; diff --git a/components/streams/src/builder.cpp b/components/streams/src/builder.cpp index f8e8c9df1fc74777cfccc4e5ecc0275de16c69bc..4575ce3c9a073ae25a1be13604db5af1dace6d7b 100644 --- a/components/streams/src/builder.cpp +++ b/components/streams/src/builder.cpp @@ -356,7 +356,7 @@ void ForeignBuilder::_schedule() { // Calling onFrameset but without all frames so mark as partial if (static_cast<size_t>(fs->count) < fs->frames.size()) fs->set(ftl::data::FSFlag::PARTIAL); - for (auto &f : fs->frames) f.store(); + //for (auto &f : fs->frames) f.store(); fs->store(); //UNIQUE_LOCK(fs->mutex(), lk2); diff --git a/components/structures/include/ftl/data/new_frame.hpp b/components/structures/include/ftl/data/new_frame.hpp index 1641423fea374bef21495de98672665a042c0c02..59f9b5781045a8a0ae3530c914109dae083b1e39 100644 --- a/components/structures/include/ftl/data/new_frame.hpp +++ b/components/structures/include/ftl/data/new_frame.hpp @@ -509,9 +509,9 @@ template <typename T> const T &ftl::data::Frame::get(ftl::codecs::Channel c) const { const auto &d = _getData(c); - if (d.status == ftl::data::ChannelStatus::ENCODED) { + if (d.status != ftl::data::ChannelStatus::INVALID && !d.data.has_value() && d.encoded.size() > 0) { UNIQUE_LOCK(parent_->mutex(), lk); - if (d.status == ftl::data::ChannelStatus::ENCODED) { + if (!d.data.has_value()) { // Do a decode now and change the status d.status = ftl::data::ChannelStatus::DISPATCHED; decode_type<T>(d.data, d.encoded.front().data); @@ -519,6 +519,7 @@ const T &ftl::data::Frame::get(ftl::codecs::Channel c) const { } if (d.status != ftl::data::ChannelStatus::INVALID) { + if (!d.data.has_value()) throw FTL_Error("'get' does not have value (" << static_cast<unsigned int>(c) << ")"); auto *p = std::any_cast<T>(&d.data); if (!p) throw FTL_Error("'get' wrong type for channel (" << static_cast<unsigned int>(c) << ")"); return *p; diff --git a/components/structures/src/new_frame.cpp b/components/structures/src/new_frame.cpp index bcbc96d21feaf71823e5d5b26f21856a74134b9b..7872f2d823d907b409ab88fd3a1d5b5f584fff80 100644 --- a/components/structures/src/new_frame.cpp +++ b/components/structures/src/new_frame.cpp @@ -243,10 +243,12 @@ void Frame::store() { if (ftl::data::isPersistent(c.first) && hasOwn(c.first)) { auto &d = data_[c.first]; auto &pd = parent_->data_[c.first]; - pd.data = d.data; - //pd.encoded = std::move(d.encoded); + pd.data = std::move(d.data); + pd.encoded = std::move(d.encoded); + //if (d.status == ChannelStatus::ENCODED) LOG(INFO) << "STORE ENCODED: " << (int)c.first; pd.status = ChannelStatus::VALID; //data_.erase(c.first); + d.status = ChannelStatus::INVALID; } parent_->change_.trigger(*this, c.first);