Bugfix generation image sequence

Fixed pb with non-power of two height of video, added more informative error messages, fixed UI issue.
This commit is contained in:
Bruno Herbelin
2022-10-15 15:19:17 +02:00
parent 7e13c1b22a
commit 3c32f1da6e
2 changed files with 32 additions and 20 deletions

View File

@@ -9,6 +9,7 @@
#include "Log.h" #include "Log.h"
#include "GstToolkit.h" #include "GstToolkit.h"
#include "BaseToolkit.h" #include "BaseToolkit.h"
#include "SystemToolkit.h"
#include "Settings.h" #include "Settings.h"
#include "MediaPlayer.h" #include "MediaPlayer.h"
@@ -130,7 +131,7 @@ bool MultiFileRecorder::start_record (const std::string &video_filename)
} }
// create a gstreamer pipeline // create a gstreamer pipeline
std::string description = "appsrc name=src ! queue ! videoconvert ! "; std::string description = "appsrc name=src ! queue ! videoconvert ! videoscale ! ";
description += VideoRecorder::profile_description[ profile_ ]; description += VideoRecorder::profile_description[ profile_ ];
description += "qtmux ! filesink name=sink"; description += "qtmux ! filesink name=sink";
@@ -179,8 +180,8 @@ bool MultiFileRecorder::start_record (const std::string &video_filename)
// specify recorder resolution and framerate in the source caps // specify recorder resolution and framerate in the source caps
GstCaps *caps = gst_caps_new_simple ("video/x-raw", GstCaps *caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, bpp_ < 4 ? "RGB" : "RGBA", "format", G_TYPE_STRING, bpp_ < 4 ? "RGB" : "RGBA",
"width", G_TYPE_INT, width_, "width", G_TYPE_INT, width_ - width_%2,
"height", G_TYPE_INT, height_, "height", G_TYPE_INT, height_ - height_%2,
"framerate", GST_TYPE_FRACTION, fps_, 1, "framerate", GST_TYPE_FRACTION, fps_, 1,
NULL); NULL);
gst_app_src_set_caps (src_, caps ); gst_app_src_set_caps (src_, caps );
@@ -251,7 +252,7 @@ bool MultiFileRecorder::end_record ()
// wait to receive end of stream // wait to receive end of stream
GstMessage *msg = gst_bus_timed_pop_filtered(bus, GST_SECOND, GST_MESSAGE_EOS); GstMessage *msg = gst_bus_timed_pop_filtered(bus, GST_SECOND, GST_MESSAGE_EOS);
if ( msg == NULL ) { if ( msg == NULL ) {
Log::Warning("MultiFileRecorder: Failed to close recording."); Log::Warning("MultiFileRecorder: could not close.");
ret = false; ret = false;
} }
@@ -259,10 +260,16 @@ bool MultiFileRecorder::end_record ()
GstStateChangeReturn r = gst_element_set_state (pipeline_, GST_STATE_NULL); GstStateChangeReturn r = gst_element_set_state (pipeline_, GST_STATE_NULL);
if (r == GST_STATE_CHANGE_ASYNC) { if (r == GST_STATE_CHANGE_ASYNC) {
gst_element_get_state (pipeline_, NULL, NULL, GST_SECOND); gst_element_get_state (pipeline_, NULL, NULL, GST_SECOND);
g_print("... ASYNC END !\n"); // g_print("... ASYNC END !\n");
} }
else if (r == GST_STATE_CHANGE_FAILURE) { else if (r == GST_STATE_CHANGE_FAILURE) {
Log::Warning("MultiFileRecorder: Failed to end recording."); Log::Warning("MultiFileRecorder: could not end properly.");
ret = false;
}
// invalidate if single frame
if (frame_count_ < 2) {
Log::Warning("MultiFileRecorder: a single image does not make a sequence.");
ret = false; ret = false;
} }
@@ -311,7 +318,7 @@ bool MultiFileRecorder::finished ()
std::string MultiFileRecorder::assemble (MultiFileRecorder *rec) std::string MultiFileRecorder::assemble (MultiFileRecorder *rec)
{ {
std::string filename; std::string filename = std::string();
// reset // reset
rec->progress_ = 0.f; rec->progress_ = 0.f;
@@ -329,20 +336,22 @@ std::string MultiFileRecorder::assemble (MultiFileRecorder *rec)
stbi_info( rec->files_.front().c_str(), &rec->width_, &rec->height_, &rec->bpp_); stbi_info( rec->files_.front().c_str(), &rec->width_, &rec->height_, &rec->bpp_);
if ( rec->width_ < 10 || rec->height_ < 10 || rec->bpp_ < 3 ) { if ( rec->width_ < 10 || rec->height_ < 10 || rec->bpp_ < 3 ) {
Log::Warning("MultiFileRecorder: invalid image."); Log::Warning("MultiFileRecorder: Invalid image %s.", rec->files_.front());
return filename; return filename;
} }
Log::Info("MultiFileRecorder creating video %d x %d : %d.", rec->width_, rec->height_, rec->bpp_);
// progress increment // progress increment
float inc_ = 1.f / ( (float) rec->files_.size() + 2.f); float inc_ = 1.f / ( (float) rec->files_.size() + 2.f);
// initialize // initialize
rec->frame_count_ = 0; rec->frame_count_ = 0;
filename = BaseToolkit::common_prefix (rec->files_); filename = BaseToolkit::common_prefix (rec->files_);
if (!SystemToolkit::path_directory(filename).empty())
filename += "image";
filename += "_sequence.mov"; filename += "_sequence.mov";
Log::Info("MultiFileRecorder creating %s, %d x %d px.", filename.c_str(), rec->width_, rec->height_);
if ( rec->start_record( filename ) ) if ( rec->start_record( filename ) )
{ {
// progressing // progressing
@@ -354,14 +363,11 @@ std::string MultiFileRecorder::assemble (MultiFileRecorder *rec)
if ( rec->cancel_ ) if ( rec->cancel_ )
break; break;
if ( rec->add_image( *file ) ) { if ( rec->add_image( *file ) )
// validate file // validate file
rec->frame_count_++; rec->frame_count_++;
} else
else { Log::Info("MultiFileRecorder could not add %s.", file->c_str());
Log::Info("MultiFileRecorder could not include images %s.", file->c_str());
}
// pause in case appsrc buffer is full // pause in case appsrc buffer is full
int max = 100; int max = 100;
@@ -372,10 +378,15 @@ std::string MultiFileRecorder::assemble (MultiFileRecorder *rec)
rec->progress_ += inc_; rec->progress_ += inc_;
} }
// Give more explanation for possible errors
if ( rec->frame_count_ < rec->files_.size())
Log::Info("MultiFileRecorder not fully successful; are all images %d x %d px?",rec->width_, rec->height_);
// close file properly // close file properly
if ( rec->end_record() ) { if ( rec->end_record() )
Log::Info("MultiFileRecorder %d images encoded (%ld s), saved in %s.", rec->frame_count_, rec->timestamp_, filename.c_str()); Log::Info("MultiFileRecorder %d images encoded (%s).", rec->frame_count_, GstToolkit::time_to_string(rec->timestamp_, GstToolkit::TIME_STRING_READABLE).c_str());
} else
filename = std::string();
} }
else else
filename = std::string(); filename = std::string();

View File

@@ -6654,6 +6654,7 @@ void Navigator::RenderNewPannel()
// clic button to load file // clic button to load file
if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) { if ( ImGui::Button( ICON_FA_FOLDER_OPEN " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
sourceSequenceFiles.clear(); sourceSequenceFiles.clear();
new_source_preview_.setSource();
_selectImagesDialog.open(); _selectImagesDialog.open();
} }
@@ -6737,7 +6738,7 @@ void Navigator::RenderNewPannel()
if ( _video_recorder.finished() ) { if ( _video_recorder.finished() ) {
// video recorder failed if it does not return a valid filename // video recorder failed if it does not return a valid filename
if ( _video_recorder.filename().empty() ) if ( _video_recorder.filename().empty() )
Log::Warning("Failed to gemerate image sequence."); Log::Warning("Failed to generate an image sequence.");
else { else {
Log::Notify("Image sequence saved to %s.", _video_recorder.filename().c_str()); Log::Notify("Image sequence saved to %s.", _video_recorder.filename().c_str());
// open the file as new recording // open the file as new recording