From e47e76962bdec7886931f345ef6f00f9406ab59b Mon Sep 17 00:00:00 2001 From: Bruno Date: Sat, 7 Aug 2021 12:34:05 +0200 Subject: [PATCH] Fixed Recording (timing and UI) Improved frame grabber timing and fixed UserInterface to show the "saving file" info. --- FrameGrabber.cpp | 37 +++++++++++++++++++++---------------- Recorder.cpp | 9 +++++---- UserInterfaceManager.cpp | 6 ++---- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/FrameGrabber.cpp b/FrameGrabber.cpp index 2a61e60..7fba468 100644 --- a/FrameGrabber.cpp +++ b/FrameGrabber.cpp @@ -285,16 +285,17 @@ void FrameGrabber::callback_enough_data (GstAppSrc *, gpointer p) FrameGrabber *grabber = static_cast(p); if (grabber) grabber->accept_buffer_ = false; + } -GstPadProbeReturn FrameGrabber::callback_event_probe(GstPad *, GstPadProbeInfo * info, gpointer user_data) +GstPadProbeReturn FrameGrabber::callback_event_probe(GstPad *, GstPadProbeInfo * info, gpointer p) { GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { - FrameGrabber *g = static_cast(user_data); - if (g) - g->finished_ = true; + FrameGrabber *grabber = static_cast(p); + if (grabber) + grabber->finished_ = true; } return GST_PAD_PROBE_OK; @@ -310,16 +311,15 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps, float dt) if (pipeline_ == nullptr) { // type specific initialisation init(caps); - // generic EOS detector + // attach EOS detector GstPad *pad = gst_element_get_static_pad (gst_bin_get_by_name (GST_BIN (pipeline_), "sink"), "sink"); gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, FrameGrabber::callback_event_probe, this, NULL); gst_object_unref (pad); } // terminate properly if finished - if (finished_) { + if (finished_) terminate(); - } // stop if an incompatilble frame buffer given else if ( !gst_caps_is_equal( caps_, caps )) @@ -329,21 +329,26 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps, float dt) } // store a frame if recording is active - else if (active_) + // and if the encoder accepts data + else if (active_ && accept_buffer_) { - // initialize timer + GstClockTime t = 0; + + // initialize timer on first occurence if (timer_ == nullptr) { timer_ = gst_pipeline_get_clock ( GST_PIPELINE(pipeline_) ); timer_firstframe_ = gst_clock_get_time(timer_); } + else + // time since timer starts (first frame registered) + t = gst_clock_get_time(timer_) - timer_firstframe_; - // time since begin - GstClockTime t = gst_clock_get_time(timer_) - timer_firstframe_; - t = (t / frame_duration_) * frame_duration_; + // if time is zero (first frame) + // of if delta time is passed one frame duration (with a margin) + if ( t == 0 || (t - timestamp_) > (frame_duration_ - 3000) ) { - // if delta time is passed one frame duration (with a margin) - // and if the encoder accepts data - if ( (t - timestamp_) > (frame_duration_ - 3000) && accept_buffer_) { + // round t to multiple of frame duration + t = ( t / frame_duration_) * frame_duration_; // set timing of buffer buffer->pts = t; @@ -356,7 +361,7 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps, float dt) gst_app_src_push_buffer (src_, buffer); // NB: buffer will be unrefed by the appsrc - // keep timestamp + // keep timestamp for next addFrame timestamp_ = t; } } diff --git a/Recorder.cpp b/Recorder.cpp index 1bdd23d..5c02eb0 100644 --- a/Recorder.cpp +++ b/Recorder.cpp @@ -301,10 +301,11 @@ void VideoRecorder::init(GstCaps *caps) void VideoRecorder::terminate() { active_ = false; - if (expecting_finished_) - Log::Notify("Video Recording %s is ready.", filename_.c_str()); - else - Log::Warning("Recording interrupted (no more disk space?)."); + + if (!expecting_finished_) + Log::Warning("Video Recording interrupted (no more disk space?)."); + + Log::Notify("Video Recording %s is ready.", filename_.c_str()); } std::string VideoRecorder::info() const diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index dc4912b..fa1db56 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -272,7 +272,7 @@ void UserInterface::handleKeyboard() // toggle recording if (video_recorder_) { video_recorder_->stop(); - video_recorder_ = nullptr; +// video_recorder_ = nullptr; } else { _video_recorders.emplace_back( std::async(std::launch::async, delayTrigger, new VideoRecorder, std::chrono::seconds(Settings::application.record.delay)) ); @@ -726,14 +726,13 @@ void UserInterface::Render() _video_recorders.pop_back(); } } - // verify the video recorder is valid + // verify the video recorder is valid (change to nullptr if invalid) FrameGrabbing::manager().verify(&video_recorder_); if (video_recorder_ // if there is an ongoing recorder && Settings::application.record.timeout < RECORD_MAX_TIMEOUT // and if the timeout is valid && video_recorder_->duration() > Settings::application.record.timeout ) // and the timeout is reached { video_recorder_->stop(); - video_recorder_ = nullptr; } #if defined(LINUX) @@ -1088,7 +1087,6 @@ void UserInterface::RenderPreview() ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.8f)); if ( ImGui::MenuItem( ICON_FA_SQUARE " Stop Record", CTRL_MOD "R") ) { video_recorder_->stop(); - video_recorder_ = nullptr; } ImGui::PopStyleColor(1); static char dummy_str[512];