rework video-export dialog, remember settings
authorRobin Gareus <robin@gareus.org>
Sat, 28 Feb 2015 01:31:08 +0000 (02:31 +0100)
committerRobin Gareus <robin@gareus.org>
Sat, 28 Feb 2015 01:38:18 +0000 (02:38 +0100)
gtk2_ardour/export_video_dialog.cc
gtk2_ardour/export_video_dialog.h

index 2bcef77920d555bcc88624847b4fcb46841ae463..0cc0a4d9091e001178204c818ad4c0de02d2dd7c 100644 (file)
@@ -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 (_("<b>Output:</b> (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<AudioGrapher::BroadcastInfo> 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(
 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
 "<ExportFormatSpecification name=\"VTL-WAV-16\" id=\"3094591e-ccb9-4385-a93f-c9955ffeb1f0\">"
@@ -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);
index 16e5cf7486094263e259317c16738e043c94759e..ab6f3223e92c089b08d5e5067c6e743bc60b60b8 100644 (file)
@@ -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<ARDOUR::ExportStatus> 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;