Add recording to Shared Memory
This commit is contained in:
1 parent
bb7d08abff
commit
a30643ddc7
24 files changed
+14583
-20
No files matched your search
@@ -0,0 +1,147 @@
|
||||
#include "video_writer.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
#include <filesystem>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
VideoBatchWriter::VideoBatchWriter(const std::string& shm_dir,
|
||||
const std::string& output_dir,
|
||||
int w, int h, int fps,
|
||||
float delay_sec)
|
||||
: shm_dir_(shm_dir), output_dir_(output_dir),
|
||||
w_(w), h_(h), fps_(fps), delay_sec_(delay_sec)
|
||||
{
|
||||
ensure_dir(shm_dir_);
|
||||
ensure_dir(output_dir_);
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(shm_dir_)) {
|
||||
if (entry.path().extension() == ".mp4") {
|
||||
std::filesystem::remove(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VideoBatchWriter::~VideoBatchWriter() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void VideoBatchWriter::ensure_dir(const std::string& dir) {
|
||||
std::filesystem::create_directories(dir);
|
||||
}
|
||||
|
||||
void VideoBatchWriter::on_new_batch(int batch_number) {
|
||||
current_batch_ = batch_number;
|
||||
delaying_ = true;
|
||||
delay_start_ = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
void VideoBatchWriter::on_batch_closed(int batch_number) {
|
||||
if (recording_ && current_batch_ == batch_number) {
|
||||
stop_and_move(batch_number);
|
||||
}
|
||||
delaying_ = false;
|
||||
recording_ = false;
|
||||
current_batch_ = 0;
|
||||
}
|
||||
|
||||
void VideoBatchWriter::feed_frame(const cv::Mat& raw) {
|
||||
if (delaying_) {
|
||||
auto elapsed = std::chrono::duration<float>(
|
||||
std::chrono::steady_clock::now() - delay_start_).count();
|
||||
if (elapsed >= delay_sec_) {
|
||||
delaying_ = false;
|
||||
start_recording(current_batch_);
|
||||
}
|
||||
}
|
||||
if (recording_ && writer_.isOpened()) {
|
||||
writer_.write(raw);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoBatchWriter::start_recording(int batch_number) {
|
||||
if (writer_.isOpened()) writer_.release();
|
||||
|
||||
auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
std::ostringstream name;
|
||||
name << "batch_" << batch_number << "_"
|
||||
<< std::put_time(std::localtime(&t), "%Y%m%d_%H%M%S") << ".mp4";
|
||||
current_path_ = shm_dir_ + "/" + name.str();
|
||||
|
||||
writer_.open(current_path_,
|
||||
cv::VideoWriter::fourcc('a','v','c','1'),
|
||||
fps_, cv::Size(w_, h_));
|
||||
recording_ = writer_.isOpened();
|
||||
|
||||
if (recording_) {
|
||||
std::cout << "[RECORD] Started: " << current_path_ << std::endl;
|
||||
} else {
|
||||
std::cerr << "[RECORD] Failed to open: " << current_path_ << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_and_clean(const std::string& src, const std::string& dst) {
|
||||
if (src.empty() || dst.empty()) return;
|
||||
{
|
||||
std::ifstream ifs(src, std::ios::binary);
|
||||
if (ifs) {
|
||||
std::ofstream ofs(dst, std::ios::binary);
|
||||
ofs << ifs.rdbuf();
|
||||
ofs.flush();
|
||||
}
|
||||
}
|
||||
std::error_code ec;
|
||||
std::filesystem::remove(src, ec);
|
||||
}
|
||||
|
||||
void VideoBatchWriter::stop_and_move(int batch_number) {
|
||||
if (writer_.isOpened()) {
|
||||
writer_.release();
|
||||
std::cout << "[RECORD] Stopped: " << current_path_ << std::endl;
|
||||
}
|
||||
|
||||
std::string src = current_path_;
|
||||
current_path_.clear();
|
||||
|
||||
auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
std::ostringstream name;
|
||||
name << "batch_" << batch_number << "_"
|
||||
<< std::put_time(std::localtime(&t), "%Y%m%d_%H%M%S") << ".mp4";
|
||||
std::string dst = output_dir_ + "/" + name.str();
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
copy_and_clean(src, dst);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoBatchWriter::shutdown() {
|
||||
if (writer_.isOpened()) {
|
||||
writer_.release();
|
||||
}
|
||||
recording_ = false;
|
||||
delaying_ = false;
|
||||
|
||||
if (!current_path_.empty()) {
|
||||
std::string src = current_path_;
|
||||
std::string dst = output_dir_ + "/" +
|
||||
std::filesystem::path(current_path_).filename().string();
|
||||
current_path_.clear();
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
copy_and_clean(src, dst);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user