25#include <opencv2/core/version.hpp>
27#include <opencv2/videoio.hpp>
28#include <opencv2/imgproc/imgproc.hpp>
31#include <linux/videodev2.h>
40#define PATHPREFIX JEVOIS_ROOT_PATH "/data/savevideo/"
44 PATHPREFIX " will be prepended to it. Name should contain a printf-like directive for "
45 "one int argument, which will start at 0 and be incremented on each streamoff command.",
46 "video%06d.avi", ParamCateg);
50 "as to which codecs are supported. Presumably, the ffmpeg library is used inside OpenCV. "
51 "Hence any video encoder supported by ffmpeg should work. Tested codecs include: MJPG, "
52 "MP4V, AVC1. Make sure you also pick the right filename extension (e.g., .avi for MJPG, "
53 ".mp4 for MP4V, etc)",
59 boost::regex(
"^\\w{4}$"), ParamCateg);
63 "playback. Beware that the video writer will drop frames if you are capturing faster than "
64 "the frame rate specified here. For example, if capturing at 120fps, be sure to set this "
65 "parameter to 120, otherwise by default the saved video will be at 30fps even though capture "
66 "was running at 120fps.",
180 public jevois::Parameter<filename, fourcc, fps>
215 LINFO(
"Writer thread completed. Syncing disk...");
216 if (std::system(
"/bin/sync"))
LERROR(
"Error syncing disk -- IGNORED");
233 inimg.
require(
"input", w,
h, V4L2_PIX_FMT_YUYV);
238 if (
itsBuf.
filled_size() > 1000)
LERROR(
"Image queue too large, video writer cannot keep up - DROPPING FRAME");
244 outimg.
require(
"output", w,
h, V4L2_PIX_FMT_YUYV);
252 std::string txt =
"SaveVideo: ";
if (
itsSaving.load()) txt +=
"RECORDING";
else txt +=
"not recording";
271 if (
itsBuf.
filled_size() > 1000)
LERROR(
"Image queue too large, video writer cannot keep up - DROPPING FRAME");
288 unsigned short winw, winh;
292 int x = 0, y = 0;
unsigned short iw = 0, ih = 0;
297 helper.
itext(std::string(
"JeVois-Pro Save Video: ") + (
itsSaving.load() ?
"RECORDING" :
"not recording"));
300 if (n) helper.
itext(std::to_string(n) +
" queued frames waiting to save...");
303 if (ImGui::Begin(
"SaveVideo Control"))
305 ImGui::Text(
"Click Record to start saving,");
306 ImGui::Text(
"click it again to stop.");
309 if (wassaving && !save)
itsBuf.
push(cv::Mat());
312 if (
itsSaving.load()) ImGui::Text(
"Recording...");
313 else if (n) ImGui::Text(
"Saving queued frames...");
314 else ImGui::Text(
"Ready to record");
324 helper.
reportError(
"Image queue too large, video writer cannot keep up - DROPPING FRAME");
333 std::string
const & fpscpu = timer.
stop();
334 helper.
iinfo(inframe, fpscpu, winw, winh);
344 void parseSerial(std::string
const & str, std::shared_ptr<jevois::UserInterface> )
override
351 else if (str ==
"stop")
364 std::this_thread::sleep_for(std::chrono::milliseconds(200));
366 LINFO(
"Writer thread completed. Syncing disk...");
367 if (std::system(
"/bin/sync"))
LERROR(
"Error syncing disk -- IGNORED");
368 LINFO(
"Video saved.");
371 else throw std::runtime_error(
"Unsupported module command");
379 os <<
"start - start saving video" << std::endl;
380 os <<
"stop - stop saving video and increment video file number" << std::endl;
390 cv::VideoWriter writer;
399 if (im.empty())
break;
402 if (writer.isOpened() ==
false)
405 std::string
const fcc = fourcc::get();
406 int const cvfcc = cv::VideoWriter::fourcc(fcc[0], fcc[1], fcc[2], fcc[3]);
409 std::string fn = filename::get();
410 if (fn.empty())
LFATAL(
"Cannot save to an empty filename");
414 std::string
const cmd =
"/bin/mkdir -p " + fn.substr(0, fn.rfind(
'/'));
415 if (std::system(cmd.c_str()))
LERROR(
"Error running [" << cmd <<
"] -- IGNORED");
421 std::ifstream ifs(tmp);
422 if (ifs.is_open() ==
false) {
itsFilename = tmp;
break; }
427 if (writer.open(
itsFilename, cvfcc, fps::get(), im.size(),
true) ==
false)
437 if ((++frame % 100) == 0)
sendSerial(
"SAVEDNUM " + std::to_string(frame));
JEVOIS_REGISTER_MODULE(ArUcoBlob)
Save captured camera frames into a video file.
virtual void process(jevois::InputFrame &&inframe, jevois::GUIhelper &helper) override
Processing function with zero-copy and GUI on JeVois-Pro.
JEVOIS_DECLARE_PARAMETER(filename, std::string, "Name of the video file to write. If path is not absolute, " PATHPREFIX " will be prepended to it. Name should contain a printf-like directive for " "one int argument, which will start at 0 and be incremented on each streamoff command.", "video%06d.avi", ParamCateg)
Parameter.
void process(jevois::InputFrame &&inframe) override
Processing function, version with no video output.
std::atomic< bool > itsSaving
SaveVideo(std::string const &instance)
Constructor.
void parseSerial(std::string const &str, std::shared_ptr< jevois::UserInterface >) override
Receive a string from a serial port which contains a user command.
void supportedCommands(std::ostream &os) override
Human-readable description of this Module's supported custom commands.
void postInit() override
Get started.
jevois::BoundedBuffer< cv::Mat, jevois::BlockingBehavior::Block, jevois::BlockingBehavior::Block > itsBuf
void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function, version that also shows a debug video output.
JEVOIS_DECLARE_PARAMETER(fourcc, std::string, "FourCC of the codec to use. The OpenCV VideoWriter doc is unclear " "as to which codecs are supported. Presumably, the ffmpeg library is used inside OpenCV. " "Hence any video encoder supported by ffmpeg should work. Tested codecs include: MJPG, " "MP4V, AVC1. Make sure you also pick the right filename extension (e.g., .avi for MJPG, " ".mp4 for MP4V, etc)", "X264", boost::regex("^\\w{4}$"), ParamCateg)
Parameter.
std::future< void > itsRunFut
virtual ~SaveVideo()
Virtual destructor for safe inheritance.
std::atomic< bool > itsRunning
JEVOIS_DECLARE_PARAMETER(fps, double, "Video frames/sec as stored in the file and to be used both for recording and " "playback. Beware that the video writer will drop frames if you are capturing faster than " "the frame rate specified here. For example, if capturing at 120fps, be sure to set this " "parameter to 120, otherwise by default the saved video will be at 30fps even though capture " "was running at 120fps.", 30.0, ParamCateg)
Parameter.
void postUninit() override
Get stopped.
size_t filled_size() const
friend friend class Module
void drawInputFrame(char const *name, InputFrame const &frame, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool casync=false)
bool startFrame(unsigned short &w, unsigned short &h)
void iinfo(jevois::InputFrame const &inframe, std::string const &fpscpu, unsigned short winw=0, unsigned short winh=0)
void reportError(std::string const &err)
void itext(char const *txt, ImU32 const &col=IM_COL32_BLACK_TRANS, int line=-1)
bool toggleButton(char const *name, bool *val)
virtual void sendSerial(std::string const &str)
void require(char const *info, unsigned int w, unsigned int h, unsigned int f) const
std::string const & stop(double *seconds)
std::string warnAndIgnoreException(std::string const &prefix="")
void paste(RawImage const &src, RawImage &dest, int dx, int dy)
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
cv::Mat convertToCvBGR(RawImage const &src)
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async(Function &&f, Args &&... args)
std::string sformat(char const *fmt,...) __attribute__((format(__printf__
unsigned short constexpr White