mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Fixed Recording (timing and UI)
Improved frame grabber timing and fixed UserInterface to show the "saving file" info.
This commit is contained in:
@@ -285,16 +285,17 @@ void FrameGrabber::callback_enough_data (GstAppSrc *, gpointer p)
|
|||||||
FrameGrabber *grabber = static_cast<FrameGrabber *>(p);
|
FrameGrabber *grabber = static_cast<FrameGrabber *>(p);
|
||||||
if (grabber)
|
if (grabber)
|
||||||
grabber->accept_buffer_ = false;
|
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);
|
GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info);
|
||||||
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
|
if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)
|
||||||
{
|
{
|
||||||
FrameGrabber *g = static_cast<FrameGrabber *>(user_data);
|
FrameGrabber *grabber = static_cast<FrameGrabber *>(p);
|
||||||
if (g)
|
if (grabber)
|
||||||
g->finished_ = true;
|
grabber->finished_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_PAD_PROBE_OK;
|
return GST_PAD_PROBE_OK;
|
||||||
@@ -310,16 +311,15 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps, float dt)
|
|||||||
if (pipeline_ == nullptr) {
|
if (pipeline_ == nullptr) {
|
||||||
// type specific initialisation
|
// type specific initialisation
|
||||||
init(caps);
|
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");
|
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_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, FrameGrabber::callback_event_probe, this, NULL);
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminate properly if finished
|
// terminate properly if finished
|
||||||
if (finished_) {
|
if (finished_)
|
||||||
terminate();
|
terminate();
|
||||||
}
|
|
||||||
|
|
||||||
// stop if an incompatilble frame buffer given
|
// stop if an incompatilble frame buffer given
|
||||||
else if ( !gst_caps_is_equal( caps_, caps ))
|
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
|
// 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) {
|
if (timer_ == nullptr) {
|
||||||
timer_ = gst_pipeline_get_clock ( GST_PIPELINE(pipeline_) );
|
timer_ = gst_pipeline_get_clock ( GST_PIPELINE(pipeline_) );
|
||||||
timer_firstframe_ = gst_clock_get_time(timer_);
|
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
|
// if time is zero (first frame)
|
||||||
GstClockTime t = gst_clock_get_time(timer_) - timer_firstframe_;
|
// of if delta time is passed one frame duration (with a margin)
|
||||||
t = (t / frame_duration_) * frame_duration_;
|
if ( t == 0 || (t - timestamp_) > (frame_duration_ - 3000) ) {
|
||||||
|
|
||||||
// if delta time is passed one frame duration (with a margin)
|
// round t to multiple of frame duration
|
||||||
// and if the encoder accepts data
|
t = ( t / frame_duration_) * frame_duration_;
|
||||||
if ( (t - timestamp_) > (frame_duration_ - 3000) && accept_buffer_) {
|
|
||||||
|
|
||||||
// set timing of buffer
|
// set timing of buffer
|
||||||
buffer->pts = t;
|
buffer->pts = t;
|
||||||
@@ -356,7 +361,7 @@ void FrameGrabber::addFrame (GstBuffer *buffer, GstCaps *caps, float dt)
|
|||||||
gst_app_src_push_buffer (src_, buffer);
|
gst_app_src_push_buffer (src_, buffer);
|
||||||
// NB: buffer will be unrefed by the appsrc
|
// NB: buffer will be unrefed by the appsrc
|
||||||
|
|
||||||
// keep timestamp
|
// keep timestamp for next addFrame
|
||||||
timestamp_ = t;
|
timestamp_ = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,10 +301,11 @@ void VideoRecorder::init(GstCaps *caps)
|
|||||||
void VideoRecorder::terminate()
|
void VideoRecorder::terminate()
|
||||||
{
|
{
|
||||||
active_ = false;
|
active_ = false;
|
||||||
if (expecting_finished_)
|
|
||||||
Log::Notify("Video Recording %s is ready.", filename_.c_str());
|
if (!expecting_finished_)
|
||||||
else
|
Log::Warning("Video Recording interrupted (no more disk space?).");
|
||||||
Log::Warning("Recording interrupted (no more disk space?).");
|
|
||||||
|
Log::Notify("Video Recording %s is ready.", filename_.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VideoRecorder::info() const
|
std::string VideoRecorder::info() const
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ void UserInterface::handleKeyboard()
|
|||||||
// toggle recording
|
// toggle recording
|
||||||
if (video_recorder_) {
|
if (video_recorder_) {
|
||||||
video_recorder_->stop();
|
video_recorder_->stop();
|
||||||
video_recorder_ = nullptr;
|
// video_recorder_ = nullptr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_video_recorders.emplace_back( std::async(std::launch::async, delayTrigger, new VideoRecorder, std::chrono::seconds(Settings::application.record.delay)) );
|
_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();
|
_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_);
|
FrameGrabbing::manager().verify(&video_recorder_);
|
||||||
if (video_recorder_ // if there is an ongoing recorder
|
if (video_recorder_ // if there is an ongoing recorder
|
||||||
&& Settings::application.record.timeout < RECORD_MAX_TIMEOUT // and if the timeout is valid
|
&& 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_->duration() > Settings::application.record.timeout ) // and the timeout is reached
|
||||||
{
|
{
|
||||||
video_recorder_->stop();
|
video_recorder_->stop();
|
||||||
video_recorder_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
@@ -1088,7 +1087,6 @@ void UserInterface::RenderPreview()
|
|||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.8f));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_RECORD, 0.8f));
|
||||||
if ( ImGui::MenuItem( ICON_FA_SQUARE " Stop Record", CTRL_MOD "R") ) {
|
if ( ImGui::MenuItem( ICON_FA_SQUARE " Stop Record", CTRL_MOD "R") ) {
|
||||||
video_recorder_->stop();
|
video_recorder_->stop();
|
||||||
video_recorder_ = nullptr;
|
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(1);
|
||||||
static char dummy_str[512];
|
static char dummy_str[512];
|
||||||
|
|||||||
Reference in New Issue
Block a user