diff --git a/FrameGrabber.h b/FrameGrabber.h new file mode 100644 index 0000000..2f967c8 --- /dev/null +++ b/FrameGrabber.h @@ -0,0 +1,43 @@ +#ifndef FRAMEGRABBER_H +#define FRAMEGRABBER_H + +#include +#include + +#include + +class FrameBuffer; +/** + * @brief The FrameGrabber class defines the base class for all recorders + * used to save images or videos from a frame buffer. + * + * The Mixer class calls addFrame() at each newly rendered frame for all of its recorder. + */ +class FrameGrabber +{ +public: + FrameGrabber(): finished_(false), pbo_index_(0), pbo_next_index_(0), size_(0) + { + pbo_[0] = pbo_[1] = 0; + } + + virtual ~FrameGrabber() {} + + virtual void addFrame(FrameBuffer *frame_buffer, float dt) = 0; + virtual void stop() { } + virtual std::string info() { return ""; } + virtual double duration() { return 0.0; } + + inline bool finished() const { return finished_; } + +protected: + // thread-safe testing termination + std::atomic finished_; + + // PBO + guint pbo_[2]; + guint pbo_index_, pbo_next_index_; + guint size_; +}; + +#endif // FRAMEGRABBER_H diff --git a/Mixer.cpp b/Mixer.cpp index 88340f9..c2f50b0 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -801,7 +801,7 @@ void Mixer::swap() back_session_ = tmp; // swap recorders - back_session_->transferRecorders(session_); + back_session_->transferFrameGrabber(session_); // attach new session's nodes to views for (auto source_iter = session_->begin(); source_iter != session_->end(); source_iter++) diff --git a/Recorder.cpp b/Recorder.cpp index a81eef3..896a737 100644 --- a/Recorder.cpp +++ b/Recorder.cpp @@ -25,14 +25,8 @@ // https://stackoverflow.com/questions/38140527/glreadpixels-vs-glgetteximage #define USE_GLREADPIXEL -using namespace std; -Recorder::Recorder() : finished_(false), pbo_index_(0), pbo_next_index_(0), size_(0) -{ - pbo_[0] = pbo_[1] = 0; -} - -PNGRecorder::PNGRecorder() : Recorder() +PNGRecorder::PNGRecorder() : FrameGrabber() { std::string path = SystemToolkit::path_directory(Settings::application.record.path); if (path.empty()) @@ -195,7 +189,7 @@ const std::vector VideoRecorder::profile_description { // "qtmux ! filesink name=sink"; -VideoRecorder::VideoRecorder() : Recorder(), frame_buffer_(nullptr), width_(0), height_(0), +VideoRecorder::VideoRecorder() : FrameGrabber(), frame_buffer_(nullptr), width_(0), height_(0), recording_(false), accept_buffer_(false), pipeline_(nullptr), src_(nullptr), timestamp_(0) { @@ -243,7 +237,7 @@ void VideoRecorder::addFrame (FrameBuffer *frame_buffer, float dt) glBufferData(GL_PIXEL_PACK_BUFFER, size_, NULL, GL_STREAM_READ); // create a gstreamer pipeline - string description = "appsrc name=src ! videoconvert ! "; + std::string description = "appsrc name=src ! videoconvert ! "; if (Settings::application.record.profile < 0 || Settings::application.record.profile >= DEFAULT) Settings::application.record.profile = H264_STANDARD; description += profile_description[Settings::application.record.profile]; diff --git a/Recorder.h b/Recorder.h index cf572d9..e79e4b2 100644 --- a/Recorder.h +++ b/Recorder.h @@ -1,45 +1,14 @@ #ifndef RECORDER_H #define RECORDER_H -#include -#include #include #include #include -class FrameBuffer; +#include "FrameGrabber.h" -/** - * @brief The Recorder class defines the base class for all recorders - * used to save images or videos from a frame buffer. - * - * The Mixer class calls addFrame() at each newly rendered frame for all of its recorder. - */ -class Recorder -{ -public: - Recorder(); - virtual ~Recorder() {} - - virtual void addFrame(FrameBuffer *frame_buffer, float dt) = 0; - virtual void stop() { } - virtual std::string info() { return ""; } - virtual double duration() { return 0.0; } - - inline bool finished() const { return finished_; } - -protected: - // thread-safe testing termination - std::atomic finished_; - - // PBO - guint pbo_[2]; - guint pbo_index_, pbo_next_index_; - guint size_; -}; - -class PNGRecorder : public Recorder +class PNGRecorder : public FrameGrabber { std::string filename_; @@ -51,7 +20,7 @@ public: }; -class VideoRecorder : public Recorder +class VideoRecorder : public FrameGrabber { std::string filename_; diff --git a/Session.cpp b/Session.cpp index f0cc184..a72fc71 100644 --- a/Session.cpp +++ b/Session.cpp @@ -5,7 +5,7 @@ #include "FrameBuffer.h" #include "Session.h" #include "GarbageVisitor.h" -#include "Recorder.h" +#include "FrameGrabber.h" #include "SessionCreator.h" #include "Log.h" @@ -34,7 +34,7 @@ Session::Session() : failedSource_(nullptr), active_(true), fading_target_(0.f) Session::~Session() { // delete all recorders - clearRecorders(); + clearAllFrameGrabbers(); // delete all sources for(auto it = sources_.begin(); it != sources_.end(); ) { @@ -90,15 +90,15 @@ void Session::update(float dt) render_.draw(); // send frame to recorders - std::list::iterator iter; - for (iter=recorders_.begin(); iter != recorders_.end(); ) + std::list::iterator iter; + for (iter=grabbers_.begin(); iter != grabbers_.end(); ) { - Recorder *rec = *iter; + FrameGrabber *rec = *iter; rec->addFrame(render_.frame(), dt); if (rec->finished()) { - iter = recorders_.erase(iter); + iter = grabbers_.erase(iter); delete rec; } else { @@ -295,49 +295,49 @@ int Session::index(SourceList::iterator it) const return index; } -void Session::addRecorder(Recorder *rec) +void Session::addFrameGrabber(FrameGrabber *rec) { - recorders_.push_back(rec); + grabbers_.push_back(rec); } -Recorder *Session::frontRecorder() +FrameGrabber *Session::frontFrameGrabber() { - if (recorders_.empty()) + if (grabbers_.empty()) return nullptr; else - return recorders_.front(); + return grabbers_.front(); } -void Session::stopRecorders() +void Session::stopAllFrameGrabbers() { - std::list::iterator iter; - for (iter=recorders_.begin(); iter != recorders_.end(); ) + std::list::iterator iter; + for (iter=grabbers_.begin(); iter != grabbers_.end(); ) (*iter)->stop(); } -void Session::clearRecorders() +void Session::clearAllFrameGrabbers() { - std::list::iterator iter; - for (iter=recorders_.begin(); iter != recorders_.end(); ) + std::list::iterator iter; + for (iter=grabbers_.begin(); iter != grabbers_.end(); ) { - Recorder *rec = *iter; + FrameGrabber *rec = *iter; rec->stop(); - iter = recorders_.erase(iter); + iter = grabbers_.erase(iter); delete rec; } } -void Session::transferRecorders(Session *dest) +void Session::transferFrameGrabber(Session *dest) { if (dest == nullptr) return; - std::list::iterator iter; - for (iter=recorders_.begin(); iter != recorders_.end(); ) + std::list::iterator iter; + for (iter=grabbers_.begin(); iter != grabbers_.end(); ) { - dest->recorders_.push_back(*iter); - iter = recorders_.erase(iter); + dest->grabbers_.push_back(*iter); + iter = grabbers_.erase(iter); } } diff --git a/Session.h b/Session.h index 5225037..26a9664 100644 --- a/Session.h +++ b/Session.h @@ -6,7 +6,7 @@ #include "View.h" #include "Source.h" -class Recorder; +class FrameGrabber; class Session { @@ -59,11 +59,11 @@ public: inline FrameBuffer *frame () const { return render_.frame(); } // Recorders - void addRecorder(Recorder *rec); - Recorder *frontRecorder(); - void stopRecorders(); - void clearRecorders(); - void transferRecorders(Session *dest); + void addFrameGrabber(FrameGrabber *rec); + FrameGrabber *frontFrameGrabber(); + void stopAllFrameGrabbers(); + void clearAllFrameGrabbers(); + void transferFrameGrabber(Session *dest); // configure rendering resolution void setResolution(glm::vec3 resolution); @@ -90,7 +90,7 @@ protected: SourceList sources_; std::map config_; bool active_; - std::list recorders_; + std::list grabbers_; float fading_target_; std::mutex access_; }; diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index f06bc60..ad24e39 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -294,11 +294,11 @@ void UserInterface::handleKeyboard() } else if (ImGui::IsKeyPressed( GLFW_KEY_R )) { // toggle recording - Recorder *rec = Mixer::manager().session()->frontRecorder(); + FrameGrabber *rec = Mixer::manager().session()->frontFrameGrabber(); if (rec) rec->stop(); else - Mixer::manager().session()->addRecorder(new VideoRecorder); + Mixer::manager().session()->addFrameGrabber(new VideoRecorder); } else if (ImGui::IsKeyPressed( GLFW_KEY_Z )) { if (shift_modifier_active) @@ -774,7 +774,7 @@ void UserInterface::Render() ImGuiToolkit::ShowStats(&Settings::application.widget.stats, &Settings::application.widget.stats_corner); // TODO: better management of main_video_recorder - Recorder *rec = Mixer::manager().session()->frontRecorder(); + FrameGrabber *rec = Mixer::manager().session()->frontFrameGrabber(); if (rec && rec->duration() > Settings::application.record.timeout ){ rec->stop(); } @@ -1089,7 +1089,7 @@ void UserInterface::RenderPreview() } - Recorder *rec = Mixer::manager().session()->frontRecorder(); + FrameGrabber *rec = Mixer::manager().session()->frontFrameGrabber(); // return from thread for folder openning if ( !recordFolderFileDialogs.empty() ) { @@ -1122,7 +1122,7 @@ void UserInterface::RenderPreview() if (ImGui::BeginMenu("Record")) { if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Capture frame (PNG)") ) - Mixer::manager().session()->addRecorder(new PNGRecorder); + Mixer::manager().session()->addFrameGrabber(new PNGRecorder); // Stop recording menu if main recorder already exists if (rec) { @@ -1133,7 +1133,7 @@ void UserInterface::RenderPreview() // start recording else { if ( ImGui::MenuItem( ICON_FA_CIRCLE " Record", CTRL_MOD "R") ) { - Mixer::manager().session()->addRecorder(new VideoRecorder); + Mixer::manager().session()->addFrameGrabber(new VideoRecorder); } // select profile ImGui::SetNextItemWidth(300);