From 60bb5986e2c705434d7f6e319332efe2a0be7c30 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 28 Feb 2015 02:31:08 +0100 Subject: [PATCH] rework video-export dialog, remember settings --- gtk2_ardour/export_video_dialog.cc | 368 ++++++++++++++++++++++------- gtk2_ardour/export_video_dialog.h | 23 +- 2 files changed, 304 insertions(+), 87 deletions(-) diff --git a/gtk2_ardour/export_video_dialog.cc b/gtk2_ardour/export_video_dialog.cc index 2bcef77920..0cc0a4d909 100644 --- a/gtk2_ardour/export_video_dialog.cc +++ b/gtk2_ardour/export_video_dialog.cc @@ -65,6 +65,14 @@ using namespace VideoUtils; ExportVideoDialog::ExportVideoDialog () : ArdourDialog (_("Export Video File ")) + , _aborted(false) + , _twopass(false) + , _firstpass(false) + , _normalize(false) + , _previous_progress(0) + , _transcoder(0) + , _video_source_aspect_ratio(-1) + , _suspend_signals(false) , outfn_path_label (_("File:"), Gtk::ALIGN_LEFT) , outfn_browse_button (_("Browse")) , invid_path_label (_("Video:"), Gtk::ALIGN_LEFT) @@ -72,6 +80,7 @@ ExportVideoDialog::ExportVideoDialog () , transcode_button (_("Export")) , abort_button (_("Abort")) , scale_checkbox (_("Scale Video (W x H):")) + , scale_aspect (_("Retain Aspect")) , width_adjustment (768, 128, 1920, 1, 16, 0) , width_spinner (width_adjustment) , height_adjustment (576, 128, 1920, 1, 16, 0) @@ -100,8 +109,8 @@ ExportVideoDialog::ExportVideoDialog () HBox* path_hbox; /* check if ffmpeg can be found */ - transcoder = new TranscodeFfmpeg(""); - if (!transcoder->ffexec_ok()) { + _transcoder = new TranscodeFfmpeg(""); + if (!_transcoder->ffexec_ok()) { l = manage (new Label (_("No ffprobe or ffmpeg executables could be found on this system. Video Export is not possible until you install those tools. See the Log window for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false)); l->set_line_wrap(); vbox->pack_start (*l, false, false, 8); @@ -110,7 +119,7 @@ ExportVideoDialog::ExportVideoDialog () show_all_children (); return; } - delete transcoder; transcoder = 0; + delete _transcoder; _transcoder = 0; l = manage (new Label (_("Output: (file extension defines format)"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false)); l->set_use_markup (); @@ -173,7 +182,8 @@ ExportVideoDialog::ExportVideoDialog () t->attach (*l, 0, 1, ty, ty+1); t->attach (audio_samplerate_combo, 1, 2, ty, ty+1); t->attach (normalize_checkbox, 2, 4, ty, ty+1); ty++; - t->attach (scale_checkbox, 0, 2, ty, ty+1); + t->attach (scale_checkbox, 0, 1, ty, ty+1); + t->attach (scale_aspect, 1, 2, ty, ty+1); t->attach (width_spinner, 2, 3, ty, ty+1); t->attach (height_spinner, 3, 4, ty, ty+1); ty++; t->attach (fps_checkbox, 0, 3, ty, ty+1); @@ -197,9 +207,10 @@ ExportVideoDialog::ExportVideoDialog () preset_combo.append_text("dvd-PAL"); preset_combo.append_text("flv"); preset_combo.append_text("mpeg4"); + preset_combo.append_text("mp4/h264/aac"); preset_combo.append_text("ogg"); + preset_combo.append_text("webm"); preset_combo.append_text("you-tube"); - preset_combo.set_active(0); audio_codec_combo.set_name ("PaddedButton"); audio_codec_combo.append_text(_("(default for format)")); @@ -209,7 +220,6 @@ ExportVideoDialog::ExportVideoDialog () audio_codec_combo.append_text("libvorbis"); audio_codec_combo.append_text("mp2"); audio_codec_combo.append_text("pcm_s16le"); - audio_codec_combo.set_active(0); video_codec_combo.set_name ("PaddedButton"); video_codec_combo.append_text(_("(default for format)")); @@ -221,7 +231,6 @@ ExportVideoDialog::ExportVideoDialog () video_codec_combo.append_text("h264"); video_codec_combo.append_text("vpx (webm)"); video_codec_combo.append_text("copy"); - video_codec_combo.set_active(0); audio_bitrate_combo.set_name ("PaddedButton"); audio_bitrate_combo.append_text(_("(default)")); @@ -230,13 +239,11 @@ ExportVideoDialog::ExportVideoDialog () audio_bitrate_combo.append_text("192k"); audio_bitrate_combo.append_text("256k"); audio_bitrate_combo.append_text("320k"); - audio_bitrate_combo.set_active(0); audio_samplerate_combo.set_name ("PaddedButton"); audio_samplerate_combo.append_text("22050"); audio_samplerate_combo.append_text("44100"); audio_samplerate_combo.append_text("48000"); - audio_samplerate_combo.set_active(2); video_bitrate_combo.set_name ("PaddedButton"); video_bitrate_combo.append_text(_("(default)")); @@ -246,7 +253,6 @@ ExportVideoDialog::ExportVideoDialog () video_bitrate_combo.append_text("2000k"); video_bitrate_combo.append_text("5000k"); video_bitrate_combo.append_text("8000k"); - video_bitrate_combo.set_active(0); fps_combo.set_name ("PaddedButton"); fps_combo.append_text("23.976"); @@ -261,13 +267,6 @@ ExportVideoDialog::ExportVideoDialog () aspect_combo.set_name ("PaddedButton"); aspect_combo.append_text("4:3"); aspect_combo.append_text("16:9"); - aspect_combo.set_active(1); - - optimizations_checkbox.set_sensitive(false); - scale_checkbox_toggled(); - aspect_checkbox_toggled(); - fps_checkbox_toggled(); - video_codec_combo_changed(); vbox->pack_start (*options_box, false, true, 4); get_vbox()->set_spacing (4); @@ -288,6 +287,10 @@ ExportVideoDialog::ExportVideoDialog () transcode_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportVideoDialog::launch_export)); abort_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportVideoDialog::abort_clicked)); + invid_path_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportVideoDialog::set_original_file_information)); + width_spinner.signal_value_changed().connect (sigc::mem_fun (*this, &ExportVideoDialog::width_value_changed)); + height_spinner.signal_value_changed().connect (sigc::mem_fun (*this, &ExportVideoDialog::height_value_changed)); + cancel_button = add_button (Stock::CANCEL, RESPONSE_CANCEL); get_action_area()->pack_start (transcode_button, false, false); show_all_children (); @@ -296,16 +299,44 @@ ExportVideoDialog::ExportVideoDialog () ExportVideoDialog::~ExportVideoDialog () { - if (transcoder) { delete transcoder; transcoder = 0;} + if (_transcoder) { delete _transcoder; _transcoder = 0;} } +void +ExportVideoDialog::set_original_file_information() +{ + assert(_transcoder == 0); + std::string infile = invid_path_entry.get_text(); + + if (scale_checkbox.get_active()) { + // user may have set custom values already, don't touch. + return; + } + if (infile == "" || !Glib::file_test(infile, Glib::FILE_TEST_EXISTS)) { + return; + } + + _transcoder = new TranscodeFfmpeg(infile); + if (_transcoder->probe_ok()) { + _video_source_aspect_ratio = -1; + width_spinner.set_value(_transcoder->get_width()); + height_spinner.set_value(_transcoder->get_height()); + _video_source_aspect_ratio = _transcoder->get_aspect(); + } + delete _transcoder; _transcoder = 0; +} void ExportVideoDialog::apply_state (TimeSelection &tme, bool range) { + _suspend_dirty = true; // TODO really just queue 'dirty' and mark session dirty on "Export" + export_range = tme; + _video_source_aspect_ratio = -1; + outfn_path_entry.set_text (_session->session_directory().export_path() + G_DIR_SEPARATOR +"export.avi"); + // TODO remember setting for export-range.. somehow, (let explicit range override) frameoffset_t av_offset = ARDOUR_UI::instance()->video_timeline->get_offset(); if (av_offset < 0 ) { insnd_combo.append_text (_("from 00:00:00:00 to the video's end")); @@ -321,16 +352,28 @@ ExportVideoDialog::apply_state (TimeSelection &tme, bool range) insnd_combo.set_active(0); } + preset_combo.set_active(0); + audio_codec_combo.set_active(0); + video_codec_combo.set_active(0); + audio_bitrate_combo.set_active(0); + audio_samplerate_combo.set_active(2); + video_bitrate_combo.set_active(0); + aspect_combo.set_active(1); + + scale_checkbox.set_active(false); + scale_aspect.set_active(true); + aspect_checkbox.set_active(false); + normalize_checkbox.set_active(false); + twopass_checkbox.set_active(false); + optimizations_checkbox.set_active(false); + deinterlace_checkbox.set_active(false); + bframes_checkbox.set_active(false); + fps_checkbox.set_active(false); + meta_checkbox.set_active(false); + float tcfps = _session->timecode_frames_per_second(); - if (fabs(tcfps - 23.976) < 0.01) { fps_combo.set_active(0); } - else if (fabs(tcfps - 24.0 ) < 0.01) { fps_combo.set_active(1); } - else if (fabs(tcfps - 24.976) < 0.01) { fps_combo.set_active(2); } - else if (fabs(tcfps - 25.0 ) < 0.01) { fps_combo.set_active(3); } - else if (fabs(tcfps - 29.97 ) < 0.01) { fps_combo.set_active(4); } - else if (fabs(tcfps - 30.0 ) < 0.01) { fps_combo.set_active(5); } - else if (fabs(tcfps - 59.94 ) < 0.01) { fps_combo.set_active(6); } - else if (fabs(tcfps - 60.0 ) < 0.01) { fps_combo.set_active(7); } - else { fps_combo.set_active(5); } + + LocaleGuard lg (X_("C")); XMLNode* node = _session->extra_xml (X_("Videotimeline")); if (node) { @@ -366,15 +409,111 @@ ExportVideoDialog::apply_state (TimeSelection &tme, bool range) node = _session->extra_xml (X_("Videoexport")); if (node) { - if (node->property(X_("OriginalVideoFile"))) { - } + const XMLProperty* prop; + prop = node->property (X_("ChangeGeometry")); + if (prop) { scale_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("KeepAspect")); + if (prop) { scale_aspect.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("ChangeAspect")); + if (prop) { aspect_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("NormalizeAudio")); + if (prop) { normalize_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("TwoPassEncode")); + if (prop) { twopass_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("CodecOptimzations")); + if (prop) { optimizations_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("Deinterlace")); + if (prop) { deinterlace_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("BFrames")); + if (prop) { bframes_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("ChangeFPS")); + if (prop) { fps_checkbox.set_active(atoi(prop->value())?true:false); } + prop = node->property (X_("Metadata")); + if (prop) { meta_checkbox.set_active(atoi(prop->value())?true:false); } + + prop = node->property (X_("Format")); + if (prop && !prop->value().empty()) { change_file_extension( "." + prop->value()); } + + _suspend_signals = true; + prop = node->property (X_("Width")); + if (prop) { width_spinner.set_value(atoi(prop->value())); } + prop = node->property (X_("Height")); + if (prop) { height_spinner.set_value(atoi(prop->value())); } + _suspend_signals = false; + + prop = node->property (X_("FPS")); + if (prop && fps_checkbox.get_active()) { tcfps = atof(prop->value()); } + + prop = node->property (X_("Preset")); + if (prop) { preset_combo.set_active_text(prop->value()); } + prop = node->property (X_("VCodec")); + if (prop) { video_codec_combo.set_active_text(prop->value()); } + prop = node->property (X_("ACodec")); + if (prop) { audio_codec_combo.set_active_text(prop->value()); } + prop = node->property (X_("VBitrate")); + if (prop) { video_bitrate_combo.set_active_text(prop->value()); } + prop = node->property (X_("ABitrate")); + if (prop) { audio_bitrate_combo.set_active_text(prop->value()); } + prop = node->property (X_("AspectRatio")); + if (prop) { aspect_combo.set_active_text(prop->value()); } + prop = node->property (X_("SampleRate")); + if (prop) { audio_samplerate_combo.set_active_text(prop->value()); } } + + if (fabs(tcfps - 23.976) < 0.01) { fps_combo.set_active(0); } + else if (fabs(tcfps - 24.0 ) < 0.01) { fps_combo.set_active(1); } + else if (fabs(tcfps - 24.976) < 0.01) { fps_combo.set_active(2); } + else if (fabs(tcfps - 25.0 ) < 0.01) { fps_combo.set_active(3); } + else if (fabs(tcfps - 29.97 ) < 0.01) { fps_combo.set_active(4); } + else if (fabs(tcfps - 30.0 ) < 0.01) { fps_combo.set_active(5); } + else if (fabs(tcfps - 59.94 ) < 0.01) { fps_combo.set_active(6); } + else if (fabs(tcfps - 60.0 ) < 0.01) { fps_combo.set_active(7); } + else { fps_combo.set_active(5); } + + set_original_file_information(); + + /* update sensitivity */ + scale_checkbox_toggled(); + aspect_checkbox_toggled(); + fps_checkbox_toggled(); + video_codec_combo_changed(); + + _suspend_dirty = false; + + show_all_children (); + progress_box->hide(); } XMLNode& ExportVideoDialog::get_state () { + LocaleGuard lg (X_("C")); XMLNode* node = new XMLNode (X_("Videoexport")); + node->add_property (X_("ChangeGeometry"), scale_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("KeepAspect"), scale_aspect.get_active() ? X_("1") : X_("0")); + node->add_property (X_("ChangeAspect"), aspect_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("NormalizeAudio"), normalize_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("TwoPassEncode"), twopass_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("CodecOptimzations"), optimizations_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("Deinterlace"), deinterlace_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("BFrames"), bframes_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("ChangeFPS"), fps_checkbox.get_active() ? X_("1") : X_("0")); + node->add_property (X_("Metadata"), meta_checkbox.get_active() ? X_("1") : X_("0")); + + node->add_property (X_("Format"), get_file_extension(outfn_path_entry.get_text())); + + node->add_property (X_("Width"), width_spinner.get_value()); + node->add_property (X_("Height"), height_spinner.get_value()); + + node->add_property (X_("Preset"), preset_combo.get_active_text()); + node->add_property (X_("VCodec"), video_codec_combo.get_active_text()); + node->add_property (X_("ACodec"), audio_codec_combo.get_active_text()); + node->add_property (X_("VBitrate"), video_bitrate_combo.get_active_text()); + node->add_property (X_("ABitrate"), audio_bitrate_combo.get_active_text()); + node->add_property (X_("AspectRatio"), aspect_combo.get_active_text()); + node->add_property (X_("SampleRate"), audio_samplerate_combo.get_active_text()); + node->add_property (X_("FPS"), fps_combo.get_active_text()); + return *node; } @@ -408,9 +547,9 @@ ExportVideoDialog::on_focus_out_event (GdkEventFocus *ev) void ExportVideoDialog::abort_clicked () { - aborted = true; - if (transcoder) { - transcoder->cancel(); + _aborted = true; + if (_transcoder) { + _transcoder->cancel(); } } @@ -422,10 +561,10 @@ ExportVideoDialog::update_progress (framecnt_t c, framecnt_t a) pbar.pulse(); } else { double progress = (double)c / (double) a; - progress = progress / ((twopass ? 2.0 : 1.0) + (normalize ? 2.0 : 1.0)); - if (normalize && twopass) progress += (firstpass ? .5 : .75); - else if (normalize) progress += 2.0/3.0; - else if (twopass) progress += (firstpass ? 1.0/3.0 : 2.0/3.0); + progress = progress / ((_twopass ? 2.0 : 1.0) + (_normalize ? 2.0 : 1.0)); + if (_normalize && _twopass) progress += (_firstpass ? .5 : .75); + else if (_normalize) progress += 2.0/3.0; + else if (_twopass) progress += (_firstpass ? 1.0/3.0 : 2.0/3.0); else progress += .5; pbar.set_fraction (progress); @@ -441,18 +580,18 @@ ExportVideoDialog::audio_progress_display () if (status->normalizing) { pbar.set_text (_("Normalizing audio")); progress = ((float) status->current_normalize_cycle) / status->total_normalize_cycles; - progress = progress / (twopass ? 4.0 : 3.0) + (twopass ? .25 : 1.0/3.0); + progress = progress / (_twopass ? 4.0 : 3.0) + (_twopass ? .25 : 1.0/3.0); } else { pbar.set_text (_("Exporting audio")); progress = ((float) status->processed_frames_current_timespan) / status->total_frames_current_timespan; - progress = progress / ((twopass ? 2.0 : 1.0) + (normalize ? 2.0 : 1.0)); + progress = progress / ((_twopass ? 2.0 : 1.0) + (_normalize ? 2.0 : 1.0)); } - if (progress < previous_progress) { + if (progress < _previous_progress) { // Work around gtk bug pbar.hide(); pbar.show(); } - previous_progress = progress; + _previous_progress = progress; pbar.set_fraction (progress); return TRUE; } @@ -460,13 +599,14 @@ ExportVideoDialog::audio_progress_display () void ExportVideoDialog::finished () { - if (aborted) { + if (_aborted) { ::g_unlink(outfn_path_entry.get_text().c_str()); - ::g_unlink (insnd.c_str()); + ::g_unlink (_insnd.c_str()); + delete _transcoder; _transcoder = 0; Gtk::Dialog::response(RESPONSE_CANCEL); - } else if (twopass && firstpass) { - firstpass = false; - if (transcoder) { delete transcoder; transcoder = 0;} + } else if (_twopass && _firstpass) { + _firstpass = false; + if (_transcoder) { delete _transcoder; _transcoder = 0;} encode_pass(2); } else { if (twopass_checkbox.get_active()) { @@ -474,7 +614,8 @@ ExportVideoDialog::finished () std::string p2log = Glib::path_get_dirname (outfn) + G_DIR_SEPARATOR + "ffmpeg2pass"; ::g_unlink (p2log.c_str()); } - ::g_unlink (insnd.c_str()); + ::g_unlink (_insnd.c_str()); + delete _transcoder; _transcoder = 0; Gtk::Dialog::response(RESPONSE_ACCEPT); } } @@ -482,6 +623,13 @@ ExportVideoDialog::finished () void ExportVideoDialog::launch_export () { + /* remember current settings. + * needed because apply_state() acts on both: + * "Videotimeline" and "Video Export" extra XML + * as well as current _session settings + */ + _session->add_extra_xml (get_state()); + std::string outfn = outfn_path_entry.get_text(); if (!confirm_video_outfn(outfn)) { return; } @@ -491,10 +639,10 @@ ExportVideoDialog::launch_export () pbar.set_size_request(300,-1); pbar.set_text(_("Exporting Audio...")); progress_box->show(); - aborted = false; - twopass = twopass_checkbox.get_active(); - firstpass = true; - normalize = normalize_checkbox.get_active(); + _aborted = false; + _twopass = twopass_checkbox.get_active(); + _firstpass = true; + _normalize = normalize_checkbox.get_active(); /* export audio track */ ExportTimespanPtr tsp = _session->get_export_handler()->add_timespan(); @@ -503,7 +651,7 @@ ExportVideoDialog::launch_export () boost::shared_ptr b; XMLTree tree; std::string vtl_samplerate = audio_samplerate_combo.get_active_text(); - std::string vtl_normalize = normalize ? "true" : "false"; + std::string vtl_normalize = _normalize ? "true" : "false"; tree.read_buffer(std::string( "" "" @@ -542,14 +690,14 @@ ExportVideoDialog::launch_export () framepos_t start, end; start = end = 0; if (insnd_combo.get_active_row_number() == 1) { - transcoder = new TranscodeFfmpeg(invid_path_entry.get_text()); - if (transcoder->probe_ok() && transcoder->get_fps() > 0) { - end = transcoder->get_duration() * _session->nominal_frame_rate() / transcoder->get_fps(); + _transcoder = new TranscodeFfmpeg(invid_path_entry.get_text()); + if (_transcoder->probe_ok() && _transcoder->get_fps() > 0) { + end = _transcoder->get_duration() * _session->nominal_frame_rate() / _transcoder->get_fps(); } else { warning << _("Export Video: Cannot query duration of video-file, using duration from timeline instead.") << endmsg; end = ARDOUR_UI::instance()->video_timeline->get_duration(); } - if (transcoder) {delete transcoder; transcoder = 0;} + if (_transcoder) {delete _transcoder; _transcoder = 0;} frameoffset_t av_offset = ARDOUR_UI::instance()->video_timeline->get_offset(); #if 0 /* DEBUG */ @@ -577,6 +725,7 @@ ExportVideoDialog::launch_export () if ( (start >= end) || (end < vstart) || (start > vend)) { warning << _("Export Video: export-range does not include video.") << endmsg; + delete _transcoder; _transcoder = 0; Gtk::Dialog::response(RESPONSE_CANCEL); return; } @@ -589,6 +738,7 @@ ExportVideoDialog::launch_export () IO* master_out = _session->master_out()->output().get(); if (!master_out) { warning << _("Export Video: No Master Out Ports to Connect for Audio Export") << endmsg; + delete _transcoder; _transcoder = 0; Gtk::Dialog::response(RESPONSE_CANCEL); return; } @@ -603,7 +753,7 @@ ExportVideoDialog::launch_export () fnp->set_timespan(tsp); fnp->set_label("vtl"); fnp->include_label = true; - insnd = fnp->get_path(fmp); + _insnd = fnp->get_path(fmp); /* do sound export */ fmp->set_soundcloud_upload(false); @@ -612,9 +762,9 @@ ExportVideoDialog::launch_export () status = _session->get_export_status (); audio_progress_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ExportVideoDialog::audio_progress_display), 100); - previous_progress = 0.0; + _previous_progress = 0.0; while (status->running) { - if (aborted) { status->abort(); } + if (_aborted) { status->abort(); } if (gtk_events_pending()) { gtk_main_iteration (); } else { @@ -624,7 +774,8 @@ ExportVideoDialog::launch_export () audio_progress_connection.disconnect(); status->finish (); if (status->aborted()) { - ::g_unlink (insnd.c_str()); + ::g_unlink (_insnd.c_str()); + delete _transcoder; _transcoder = 0; Gtk::Dialog::response(RESPONSE_CANCEL); return; } @@ -638,19 +789,21 @@ ExportVideoDialog::encode_pass (int pass) std::string outfn = outfn_path_entry.get_text(); std::string invid = invid_path_entry.get_text(); - transcoder = new TranscodeFfmpeg(invid); - if (!transcoder->ffexec_ok()) { + _transcoder = new TranscodeFfmpeg(invid); + if (!_transcoder->ffexec_ok()) { /* ffmpeg binary was not found. TranscodeFfmpeg prints a warning */ - ::g_unlink (insnd.c_str()); + ::g_unlink (_insnd.c_str()); + delete _transcoder; _transcoder = 0; Gtk::Dialog::response(RESPONSE_CANCEL); return; } - if (!transcoder->probe_ok()) { + if (!_transcoder->probe_ok()) { /* video input file can not be read */ warning << _("Export Video: Video input file cannot be read.") << endmsg; - ::g_unlink (insnd.c_str()); - Gtk::Dialog::response(RESPONSE_CANCEL); - return; + ::g_unlink (_insnd.c_str()); + delete _transcoder; _transcoder = 0; + Gtk::Dialog::response(RESPONSE_CANCEL); + return; } std::string preset = preset_combo.get_active_text(); @@ -659,7 +812,7 @@ ExportVideoDialog::encode_pass (int pass) if (fps_checkbox.get_active()) { ffs["-r"] = fps_combo.get_active_text(); - transcoder->set_fps(atof(fps_combo.get_active_text())); + _transcoder->set_fps(atof(fps_combo.get_active_text())); } if (scale_checkbox.get_active()) { @@ -751,7 +904,7 @@ ExportVideoDialog::encode_pass (int pass) } bool map = true; - if (pass == 1 && twopass) { + if (pass == 1 && _twopass) { pbar.set_text (_("Encoding Video.. Pass 1/2")); map = false; ffs["-pass"] = "1"; @@ -790,7 +943,7 @@ ExportVideoDialog::encode_pass (int pass) std::ostringstream osstream; osstream << duration_s; ffs["-t"] = osstream.str(); - transcoder->set_duration(duration_s * transcoder->get_fps()); + _transcoder->set_duration(duration_s * _transcoder->get_fps()); if (insnd_combo.get_active_row_number() == 0 || insnd_combo.get_active_row_number() == 2) { framepos_t start, snend; @@ -809,13 +962,13 @@ ExportVideoDialog::encode_pass (int pass) #endif if (av_offset > start && av_offset + vid_duration < snend) { - transcoder->set_leadinout((av_offset - start) / (double)_session->nominal_frame_rate(), + _transcoder->set_leadinout((av_offset - start) / (double)_session->nominal_frame_rate(), (snend - (av_offset + vid_duration)) / (double)_session->nominal_frame_rate()); } else if (av_offset > start) { - transcoder->set_leadinout((av_offset - start) / (double)_session->nominal_frame_rate(), 0); + _transcoder->set_leadinout((av_offset - start) / (double)_session->nominal_frame_rate(), 0); } else if (av_offset + vid_duration < snend) { - transcoder->set_leadinout(0, (snend - (av_offset + vid_duration)) / (double)_session->nominal_frame_rate()); - transcoder->set_avoffset((av_offset - start) / (double)_session->nominal_frame_rate()); + _transcoder->set_leadinout(0, (snend - (av_offset + vid_duration)) / (double)_session->nominal_frame_rate()); + _transcoder->set_avoffset((av_offset - start) / (double)_session->nominal_frame_rate()); } #if 0 else if (start > av_offset) { @@ -824,15 +977,15 @@ ExportVideoDialog::encode_pass (int pass) } #endif else { - transcoder->set_avoffset((av_offset - start) / (double)_session->nominal_frame_rate()); + _transcoder->set_avoffset((av_offset - start) / (double)_session->nominal_frame_rate()); } } else if (av_offset < 0) { /* from 00:00:00:00 to video-end */ - transcoder->set_avoffset(av_offset / (double)_session->nominal_frame_rate()); + _transcoder->set_avoffset(av_offset / (double)_session->nominal_frame_rate()); } - TranscodeFfmpeg::FFSettings meta = transcoder->default_meta_data(); + TranscodeFfmpeg::FFSettings meta = _transcoder->default_meta_data(); if (meta_checkbox.get_active()) { ARDOUR::SessionMetadata * session_data = ARDOUR::SessionMetadata::Metadata(); if (session_data->year() > 0 ) { @@ -860,14 +1013,15 @@ ExportVideoDialog::encode_pass (int pass) #if 1 /* tentative debug mode */ if (debug_checkbox.get_active()) { - transcoder->set_debug(true); + _transcoder->set_debug(true); } #endif - transcoder->Progress.connect(*this, invalidator (*this), boost::bind (&ExportVideoDialog::update_progress , this, _1, _2), gui_context()); - transcoder->Finished.connect(*this, invalidator (*this), boost::bind (&ExportVideoDialog::finished, this), gui_context()); - if (!transcoder->encode(outfn, insnd, invid, ffs, meta, map)) { + _transcoder->Progress.connect(*this, invalidator (*this), boost::bind (&ExportVideoDialog::update_progress , this, _1, _2), gui_context()); + _transcoder->Finished.connect(*this, invalidator (*this), boost::bind (&ExportVideoDialog::finished, this), gui_context()); + if (!_transcoder->encode(outfn, _insnd, invid, ffs, meta, map)) { ARDOUR_UI::instance()->popup_error(_("Transcoding failed.")); + delete _transcoder; _transcoder = 0; Gtk::Dialog::response(RESPONSE_CANCEL); return; } @@ -876,28 +1030,69 @@ ExportVideoDialog::encode_pass (int pass) void ExportVideoDialog::change_file_extension (std::string ext) { + if (ext == "") return; outfn_path_entry.set_text ( strip_file_extension(outfn_path_entry.get_text()) + ext ); } +void +ExportVideoDialog::width_value_changed () +{ + if (_suspend_signals) { + return; + } + if (_session && !_suspend_dirty) _session->set_dirty (); + if (!scale_checkbox.get_active() || !scale_aspect.get_active()) { + return; + } + if (_video_source_aspect_ratio <= 0) { + return; + } + _suspend_signals = true; + height_spinner.set_value(rintf(width_spinner.get_value() / _video_source_aspect_ratio)); + _suspend_signals = false; +} + +void +ExportVideoDialog::height_value_changed () +{ + if (_suspend_signals) { + return; + } + if (_session && !_suspend_dirty) _session->set_dirty (); + if (!scale_checkbox.get_active() || !scale_aspect.get_active()) { + return; + } + if (_video_source_aspect_ratio <= 0) { + return; + } + _suspend_signals = true; + width_spinner.set_value(rintf(height_spinner.get_value() * _video_source_aspect_ratio)); + _suspend_signals = false; +} + void ExportVideoDialog::scale_checkbox_toggled () { + scale_aspect.set_sensitive(scale_checkbox.get_active()); width_spinner.set_sensitive(scale_checkbox.get_active()); height_spinner.set_sensitive(scale_checkbox.get_active()); + if (_session && !_suspend_dirty) _session->set_dirty (); } void ExportVideoDialog::fps_checkbox_toggled () { fps_combo.set_sensitive(fps_checkbox.get_active()); + if (_session && !_suspend_dirty) _session->set_dirty (); } void ExportVideoDialog::aspect_checkbox_toggled () { aspect_combo.set_sensitive(aspect_checkbox.get_active()); + if (_session && !_suspend_dirty) _session->set_dirty (); } void @@ -925,6 +1120,7 @@ ExportVideoDialog::video_codec_combo_changed () optimizations_checkbox.set_active(false); optimizations_label.set_text("-"); } + if (_session && !_suspend_dirty) _session->set_dirty (); } void @@ -1008,6 +1204,18 @@ ExportVideoDialog::preset_combo_changed () audio_samplerate_combo.set_active(1); } } + else if (p == "mp4/h264/aac") { + change_file_extension(".mp4"); + audio_codec_combo.set_active(2); + video_codec_combo.set_active(6); + audio_bitrate_combo.set_active(0); + video_bitrate_combo.set_active(0); + if (_session->nominal_frame_rate() == 48000 || _session->nominal_frame_rate() == 96000) { + audio_samplerate_combo.set_active(2); + } else { + audio_samplerate_combo.set_active(1); + } + } if (p == "none") { audio_codec_combo.set_sensitive(true); diff --git a/gtk2_ardour/export_video_dialog.h b/gtk2_ardour/export_video_dialog.h index 16e5cf7486..ab6f3223e9 100644 --- a/gtk2_ardour/export_video_dialog.h +++ b/gtk2_ardour/export_video_dialog.h @@ -59,6 +59,10 @@ class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList void launch_export (); void encode_pass (int); void change_file_extension (std::string); + void width_value_changed (); + void height_value_changed (); + + void set_original_file_information (); bool on_focus_in_event (GdkEventFocus*); bool on_focus_out_event (GdkEventFocus*); @@ -71,10 +75,10 @@ class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList void aspect_checkbox_toggled (); void fps_checkbox_toggled (); - bool aborted; - bool twopass; - bool firstpass; - bool normalize; + bool _aborted; + bool _twopass; + bool _firstpass; + bool _normalize; void finished (); void update_progress (ARDOUR::framecnt_t, ARDOUR::framecnt_t); @@ -82,10 +86,14 @@ class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList boost::shared_ptr status; sigc::connection audio_progress_connection; gint audio_progress_display (); - float previous_progress; + float _previous_progress; + + TranscodeFfmpeg *_transcoder; + std::string _insnd; - TranscodeFfmpeg *transcoder; - std::string insnd; + float _video_source_aspect_ratio; + bool _suspend_signals; + bool _suspend_dirty; Gtk::Label outfn_path_label; Gtk::Entry outfn_path_entry; @@ -111,6 +119,7 @@ class ExportVideoDialog : public ArdourDialog , public PBD::ScopedConnectionList Gtk::ComboBoxText preset_combo; Gtk::CheckButton scale_checkbox; + Gtk::CheckButton scale_aspect; Gtk::Adjustment width_adjustment; Gtk::SpinButton width_spinner; Gtk::Adjustment height_adjustment; -- 2.30.2