From acfb59c6b4c30f71089f6d160a25f5c7ca72b302 Mon Sep 17 00:00:00 2001 From: Iiro Rastas <iitara@utu.fi> Date: Tue, 10 Dec 2019 17:27:23 +0200 Subject: [PATCH] Fix reconstruction snapshots Reconstruction snapshots are now fixed. The snapshot is taken from the next complete IFrame, so reconstruction snapshots cannot be taken while the reconstruction is paused. --- applications/reconstruct/src/main.cpp | 87 +++++++++++-------- .../codecs/include/ftl/codecs/writer.hpp | 1 + components/codecs/src/writer.cpp | 4 + 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp index 0f45f363e..e1e7adcd8 100644 --- a/applications/reconstruct/src/main.cpp +++ b/applications/reconstruct/src/main.cpp @@ -45,6 +45,9 @@ #include <ftl/cuda/normals.hpp> #include <ftl/registration.hpp> +#include <ftl/codecs/h264.hpp> +#include <ftl/codecs/hevc.hpp> + #include <cuda_profiler_api.h> #ifdef WIN32 @@ -269,25 +272,55 @@ static void run(ftl::Configurable *root) { std::ofstream fileout; ftl::codecs::Writer writer(fileout); + std::ofstream snapshotout; + ftl::codecs::Writer snapshotwriter(snapshotout); + root->set("record", false); - int64_t timestamp = 0; - std::vector<std::pair<ftl::codecs::StreamPacket, ftl::codecs::Packet>> currentFrame, completeFrame; + int64_t timestamp = -1; + bool writingSnapshot = false; + std::unordered_set<int64_t> precedingFrames, followingFrames; // Add a recording callback to all reconstruction scenes for (size_t i=0; i<sources.size(); ++i) { - sources[i]->addRawCallback([&writer,&groups,×tamp,¤tFrame,&completeFrame,i](ftl::rgbd::Source *src, const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { + sources[i]->addRawCallback([&writer,&groups,&snapshotout,&snapshotwriter,×tamp,&writingSnapshot,&precedingFrames,&followingFrames,i](ftl::rgbd::Source *src, const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { ftl::codecs::StreamPacket s = spkt; // Patch stream ID to match order in group s.streamID = i; writer.write(s, pkt); - if (s.timestamp > timestamp) { - timestamp = s.timestamp; - completeFrame = currentFrame; - currentFrame = std::vector<std::pair<ftl::codecs::StreamPacket, ftl::codecs::Packet>>({ std::make_pair(s, pkt) }); - } else if (s.timestamp == timestamp) { - currentFrame.push_back(std::make_pair(s, pkt)); + if (snapshotwriter.active()) { + // The frame that is captured is the next IFrame, unless that + // IFrame is one of the first two frames seen. In this case a + // part of the frame might already have been missed, so the + // IFrame after that one is captured instead. + if (precedingFrames.size() >= 2) { + bool isIFrame = false; + switch (pkt.codec) { + case ftl::codecs::codec_t::H264: + isIFrame = ftl::codecs::h264::isIFrame(pkt.data); + break; + case ftl::codecs::codec_t::HEVC: + isIFrame = ftl::codecs::hevc::isIFrame(pkt.data); + } + + if (isIFrame && precedingFrames.count(s.timestamp) == 0) { + timestamp = s.timestamp; + writingSnapshot = true; + snapshotwriter.write(s, pkt); + } else if (writingSnapshot && s.timestamp > timestamp) { + followingFrames.insert(s.timestamp); + } + + // Keep looking for packets of the captured frame until + // packets from two following frames have been seen. + if (followingFrames.size() >= 2) { + snapshotwriter.end(); + snapshotout.close(); + } + } else { + precedingFrames.insert(s.timestamp); + } } }); } @@ -315,33 +348,17 @@ static void run(ftl::Configurable *root) { } }); - std::ofstream snapshotout; - ftl::codecs::Writer snapshotwriter(snapshotout); - - root->on("3D-snapshot", [&snapshotout,&snapshotwriter,&sources,¤tFrame](const ftl::config::Event &e) { - char timestamp[18]; - std::time_t t=std::time(NULL); - std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); - snapshotout.open(e.entity->value<std::string>("3D-snapshot", std::string(timestamp) + ".ftl")); - - snapshotwriter.begin(); - - for (size_t i=0; i<sources.size(); ++i) { - auto packet_pair = sources[i]->make_packet(Channel::Calibration, sources[i]->parameters(), Channel::Left, sources[i]->getCapabilities()); - packet_pair.first.streamID = i; - snapshotwriter.write(packet_pair.first, packet_pair.second); - - packet_pair = sources[i]->make_packet(sources[i]->getPose()); - packet_pair.first.streamID = i; - snapshotwriter.write(packet_pair.first, packet_pair.second); - } - - for (auto &p : currentFrame) { - snapshotwriter.write(p.first, p.second); + root->on("3D-snapshot", [&snapshotout,&snapshotwriter,&writingSnapshot,&precedingFrames,&followingFrames](const ftl::config::Event &e) { + if (!snapshotwriter.active()) { + char timestamp[18]; + std::time_t t=std::time(NULL); + std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); + snapshotout.open(e.entity->value<std::string>("3D-snapshot", std::string(timestamp) + ".ftl")); + writingSnapshot = false; + precedingFrames.clear(); + followingFrames.clear(); + snapshotwriter.begin(); } - - snapshotwriter.end(); - snapshotout.close(); }); // ------------------------------------------------------------------------- diff --git a/components/codecs/include/ftl/codecs/writer.hpp b/components/codecs/include/ftl/codecs/writer.hpp index 94d82f1ec..c1a0ba6c3 100644 --- a/components/codecs/include/ftl/codecs/writer.hpp +++ b/components/codecs/include/ftl/codecs/writer.hpp @@ -19,6 +19,7 @@ class Writer { bool begin(); bool write(const ftl::codecs::StreamPacket &, const ftl::codecs::Packet &); bool end(); + bool active(); private: std::ostream *stream_; diff --git a/components/codecs/src/writer.cpp b/components/codecs/src/writer.cpp index 1e3841a8e..dba5853ac 100644 --- a/components/codecs/src/writer.cpp +++ b/components/codecs/src/writer.cpp @@ -46,3 +46,7 @@ bool Writer::write(const ftl::codecs::StreamPacket &s, const ftl::codecs::Packet (*stream_).write(buffer.data(), buffer.size()); return true; } + +bool Writer::active() { + return active_; +} \ No newline at end of file -- GitLab