BugFix Video recorder and image sequence encoder

Improved and simplified UI control of encoding of image sequences into video files. Bugs fixed to prevent problems with video recorder.
This commit is contained in:
Bruno Herbelin
2024-05-01 23:29:08 +02:00
parent a4f8d46d69
commit a46e68f145
5 changed files with 131 additions and 54 deletions

View File

@@ -3859,7 +3859,7 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize)
IMAGES_FILES_PATTERN);
static MultiFileSequence _numbered_sequence;
static MultiFileRecorder _video_recorder;
static int _fps = 25;
static int codec_id = -1;
ImGui::Text("Image sequence");
@@ -3874,8 +3874,7 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize)
ImGui::SameLine();
ImGuiToolkit::HelpToolTip("Create a source displaying a sequence of images;\n"
ICON_FA_CARET_RIGHT " files numbered consecutively\n"
ICON_FA_CARET_RIGHT " create a video from many images\n"
"Supports PNG, JPG or TIF.");
ICON_FA_CARET_RIGHT " create a video from many images");
// return from thread for folder openning
if (_selectImagesDialog.closed()) {
@@ -3891,9 +3890,16 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize)
// automatically create a MultiFile Source if possible
if (_numbered_sequence.valid()) {
// always come back to propose image sequence when possible
codec_id = -1;
// show source preview available if possible
std::string label = BaseToolkit::transliterate( BaseToolkit::common_pattern(sourceSequenceFiles) );
new_source_preview_.setSource( Mixer::manager().createSourceMultifile(sourceSequenceFiles, _fps), label);
}
new_source_preview_
.setSource(Mixer::manager().createSourceMultifile(sourceSequenceFiles,
Settings::application.image_sequence.framerate_mode),
label);
} else
codec_id = Settings::application.image_sequence.profile;
}
// multiple files selected
@@ -3907,44 +3913,84 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize)
info.appendf("%d %s", (int) sourceSequenceFiles.size(), _numbered_sequence.codec.c_str());
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::InputText("Images", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly);
info.clear();
if (_numbered_sequence.location.empty())
info.append("Not consecutively numbered");
else
info.appendf("%s", SystemToolkit::base_filename(_numbered_sequence.location).c_str());
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::InputText("Filenames", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly);
ImGui::PopStyleColor(1);
// offer to open file browser at location
std::string path = SystemToolkit::path_filename(sourceSequenceFiles.front());
std::string label = BaseToolkit::truncated(path, 25);
label = BaseToolkit::transliterate(label);
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
ImGui::SameLine(0, IMGUI_SAME_LINE);
ImGui::Text("Folder");
// set framerate
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::SliderInt("Framerate", &_fps, 1, 30, "%d fps");
ImGui::SliderInt("Framerate", &Settings::application.image_sequence.framerate_mode, 1, 30, "%d fps");
if (ImGui::IsItemDeactivatedAfterEdit()){
if (new_source_preview_.filled()) {
std::string label = BaseToolkit::transliterate( BaseToolkit::common_pattern(sourceSequenceFiles) );
new_source_preview_.setSource( Mixer::manager().createSourceMultifile(sourceSequenceFiles, _fps), label);
new_source_preview_
.setSource(Mixer::manager().createSourceMultifile(
sourceSequenceFiles,
Settings::application.image_sequence.framerate_mode),
label);
}
}
ImGui::Spacing();
// select CODEC: decide for gst sequence (codec_id = -1) or encoding a video
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
std::string codec_current = codec_id < 0 ? ICON_FA_SORT_NUMERIC_DOWN " Numbered images"
: std::string(ICON_FA_FILM " ") + VideoRecorder::profile_name[codec_id];
if (ImGui::BeginCombo("##CodecSequence", codec_current.c_str())) {
// special case; if possible, offer to create an image sequence gst source
if (ImGui::Selectable( ICON_FA_SORT_NUMERIC_DOWN " Numbered images",
codec_id < 0,
_numbered_sequence.valid()
? ImGuiSelectableFlags_None
: ImGuiSelectableFlags_Disabled)) {
// select id of image sequence
codec_id = -1;
// Open source preview for image sequence
if (_numbered_sequence.valid()) {
std::string label = BaseToolkit::transliterate(
BaseToolkit::common_pattern(sourceSequenceFiles));
new_source_preview_
.setSource(Mixer::manager().createSourceMultifile(
sourceSequenceFiles,
Settings::application.image_sequence.framerate_mode),
label);
}
}
// always offer to encode a video
for (int i = VideoRecorder::H264_STANDARD; i < VideoRecorder::VP8; ++i) {
std::string label = std::string(ICON_FA_FILM " ") + VideoRecorder::profile_name[i];
if (ImGui::Selectable(label.c_str(), codec_id == i)) {
// select id of video encoding codec
codec_id = i;
Settings::application.image_sequence.profile = i;
// close source preview (no image sequence)
new_source_preview_.setSource();
}
}
ImGui::EndCombo();
}
// Indication
ImGui::SameLine();
if (_numbered_sequence.valid())
ImGuiToolkit::HelpToolTip(ICON_FA_SORT_NUMERIC_DOWN " Selected images are numbered consecutively; "
"an image sequence source can be created.\n\n"
ICON_FA_FILM " Alternatively, choose a codec to encode a video with the selected images and create a video source.");
else
ImGuiToolkit::HelpToolTip(ICON_FA_SORT_NUMERIC_DOWN " Selected images are NOT numbered consecutively; "
"it is not possible to create a sequence source.\n\n"
ICON_FA_FILM " Instead, choose a codec to encode a video with the selected images and create a video source.");
// Offer to create video from sequence
if ( ImGui::Button( ICON_FA_FILM " Make a video", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
// start video recorder
_video_recorder.setFiles( sourceSequenceFiles );
_video_recorder.setFramerate( _fps );
_video_recorder.setProfile( (VideoRecorder::Profile) Settings::application.record.profile );
_video_recorder.start();
// dialog
ImGui::OpenPopup(LABEL_VIDEO_SEQUENCE);
// if video encoding codec selected
if ( codec_id >= 0 )
{
// Offer to create video from sequence
ImGui::NewLine();
if ( ImGui::Button( ICON_FA_FILM " Encode video", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) {
// start video recorder
_video_recorder.setFiles( sourceSequenceFiles );
_video_recorder.setFramerate( Settings::application.image_sequence.framerate_mode );
_video_recorder.setProfile( (VideoRecorder::Profile) Settings::application.image_sequence.profile );
_video_recorder.start();
// open dialog
ImGui::OpenPopup(LABEL_VIDEO_SEQUENCE);
}
}
// video recorder finished: inform and open pannel to import video source from recent recordings
@@ -3955,7 +4001,7 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize)
else {
Log::Notify("Image sequence saved to %s.", _video_recorder.filename().c_str());
// open the file as new recording
// if (Settings::application.recentRecordings.load_at_start)
// if (Settings::application.recentRecordings.load_at_start)
UserInterface::manager().navigator.setNewMedia(Navigator::MEDIA_RECORDING, _video_recorder.filename());
}
}
@@ -3978,7 +4024,8 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize)
ImGui::ProgressBar(_video_recorder.progress());
ImGui::Spacing();
if (ImGui::Button(ICON_FA_TIMES " Cancel"))
ImGui::Spacing();
if (ImGui::Button(ICON_FA_TIMES " Cancel",ImVec2(ImGui::GetContentRegionAvail().x, 0)))
_video_recorder.cancel();
ImGui::EndPopup();