Merge remote-tracking branch 'remotes/origin/cairocanvas' into windows
[ardour.git] / gtk2_ardour / export_video_dialog.cc
index 309e3af48f1c0ad10ac1ce08686dee40d51d9605..7f6fcc2a8ad80088010e60f392479b48d1f322a4 100644 (file)
@@ -30,6 +30,8 @@
 #include <sigc++/bind.h>
 #include <libgen.h>
 
+#include <glib/gstdio.h>
+
 #include "pbd/error.h"
 #include "pbd/convert.h"
 #include "gtkmm2ext/utils.h"
@@ -60,10 +62,11 @@ using namespace Gtk;
 using namespace std;
 using namespace PBD;
 using namespace ARDOUR;
+using namespace VideoUtils;
 
-ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
+ExportVideoDialog::ExportVideoDialog (Session* s, TimeSelection &tme)
        : ArdourDialog (_("Export Video File "))
-       , editor (ed)
+       , export_range (tme)
        , outfn_path_label (_("File:"), Gtk::ALIGN_LEFT)
        , outfn_browse_button (_("Browse"))
        , invid_path_label (_("Video:"), Gtk::ALIGN_LEFT)
@@ -85,7 +88,7 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
        , fps_checkbox (_("Override FPS (Default is to retain FPS from the input video file):"))
        , meta_checkbox (_("Include Session Metadata"))
 #if 1 /* tentative debug mode */
-       , debug_checkbox (_("Enable Debug Mode: Print ffmpeg Command & Output to stdout."))
+       , debug_checkbox (_("Debug Mode: Print ffmpeg command and output to stdout."))
 #endif
 {
        set_session (s);
@@ -103,7 +106,7 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
        /* check if ffmpeg can be found */
        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 widow for more information."), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
+               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);
                get_vbox()->pack_start (*vbox, false, false);
@@ -141,13 +144,16 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
        vbox->pack_start (*path_hbox, false, false, 2);
 
        insnd_combo.set_name ("PaddedButton");
-       insnd_combo.append_text("from ardour session-start to session-end");
+       insnd_combo.append_text (string_compose (_("from the %1 session's start to the session's end"), PROGRAM_NAME));
 
        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 video-end");
+               insnd_combo.append_text (_("from 00:00:00:00 to the video's end"));
        } else {
-               insnd_combo.append_text("from video-start to video-end");
+               insnd_combo.append_text (_("from the video's start to the video's end"));
+       }
+       if (!export_range.empty()) {
+               insnd_combo.append_text (_("Selected range"));  // TODO show export_range.start() -> export_range.end_frame()
        }
        insnd_combo.set_active(0);
 
@@ -155,12 +161,32 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
        outfn_path_entry.set_text (_session->session_directory().export_path() + G_DIR_SEPARATOR +"export.avi");
 
        XMLNode* node = _session->extra_xml (X_("Videotimeline"));
-       if (node && node->property(X_("Filename"))) {
-               std::string filename = node->property(X_("Filename"))->value();
-               if (filename.at(0) != G_DIR_SEPARATOR) {
-                       filename = Glib::build_filename (_session->session_directory().video_path(), filename);
+       if (node) {
+               bool filenameset = false;
+               if (node->property(X_("OriginalVideoFile"))) {
+                       std::string filename = node->property(X_("OriginalVideoFile"))->value();
+                       if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) {
+                               invid_path_entry.set_text (filename);
+                               filenameset = true;
+                       }
+               }
+               if (!filenameset
+                               && node->property(X_("Filename"))
+                               && node->property(X_("LocalFile"))
+                               && node->property(X_("LocalFile"))->value() == X_("1")
+                               ) {
+                       std::string filename = node->property(X_("Filename"))->value();
+                       if (filename.at(0) != G_DIR_SEPARATOR) {
+                               filename = Glib::build_filename (_session->session_directory().video_path(), filename);
+                       }
+                       if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) {
+                               invid_path_entry.set_text (filename);
+                               filenameset = true;
+                       }
+               }
+               if (!filenameset) {
+                       invid_path_entry.set_text (X_(""));
                }
-               invid_path_entry.set_text (filename);
        }
 
        l = manage (new Label (_("<b>Settings:</b>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false));
@@ -236,8 +262,7 @@ ExportVideoDialog::ExportVideoDialog (PublicEditor& ed, Session* s)
        video_codec_combo.append_text("mjpeg");
        video_codec_combo.append_text("mpeg2video");
        video_codec_combo.append_text("mpeg4");
-       video_codec_combo.append_text("x264 (baseline)");
-       video_codec_combo.append_text("x264 (hq)");
+       video_codec_combo.append_text("h264");
        video_codec_combo.append_text("vpx (webm)");
        video_codec_combo.append_text("copy");
        video_codec_combo.set_active(4);
@@ -388,8 +413,8 @@ void
 ExportVideoDialog::finished ()
 {
        if (aborted) {
-               unlink(outfn_path_entry.get_text().c_str());
-               unlink (insnd.c_str());
+               ::g_unlink(outfn_path_entry.get_text().c_str());
+               ::g_unlink (insnd.c_str());
                Gtk::Dialog::response(RESPONSE_CANCEL);
        } else if (twopass && firstpass) {
                firstpass = false;
@@ -399,9 +424,9 @@ ExportVideoDialog::finished ()
                if (twopass_checkbox.get_active()) {
                        std::string outfn = outfn_path_entry.get_text();
                        std::string p2log = Glib::path_get_dirname (outfn) + G_DIR_SEPARATOR + "ffmpeg2pass";
-                       unlink (p2log.c_str());
+                       ::g_unlink (p2log.c_str());
                }
-               unlink (insnd.c_str());
+               ::g_unlink (insnd.c_str());
                Gtk::Dialog::response(RESPONSE_ACCEPT);
        }
 }
@@ -416,7 +441,7 @@ ExportVideoDialog::launch_export ()
        cancel_button->hide();
        transcode_button.hide();
        pbar.set_size_request(300,-1);
-       pbar.set_text(_("Exporting Audio.."));
+       pbar.set_text(_("Exporting Audio..."));
        progress_box->show();
        aborted = false;
        twopass = twopass_checkbox.get_active();
@@ -487,6 +512,11 @@ ExportVideoDialog::launch_export ()
                }
                end += av_offset;
        }
+       else if (insnd_combo.get_active_row_number() == 2) {
+               // TODO quantize to video-frame ?!
+               start = export_range.start();
+               end   = export_range.end_frame();
+       }
        if (end <= 0) {
                start = _session->current_start_frame();
                end   = _session->current_end_frame();
@@ -537,11 +567,11 @@ ExportVideoDialog::launch_export ()
        audio_progress_connection.disconnect();
        status->finish ();
        if (status->aborted()) {
-               unlink (insnd.c_str());
+               ::g_unlink (insnd.c_str());
                Gtk::Dialog::response(RESPONSE_CANCEL);
                return;
        }
-       pbar.set_text (_("Encoding Video.."));
+       pbar.set_text (_("Encoding Video..."));
        encode_pass(1);
 }
 
@@ -554,20 +584,20 @@ ExportVideoDialog::encode_pass (int pass)
        transcoder = new TranscodeFfmpeg(invid);
        if (!transcoder->ffexec_ok()) {
                /* ffmpeg binary was not found. TranscodeFfmpeg prints a warning */
-               unlink (insnd.c_str());
+               ::g_unlink (insnd.c_str());
                Gtk::Dialog::response(RESPONSE_CANCEL);
                return;
        }
        if (!transcoder->probe_ok()) {
                /* video input file can not be read */
                warning << _("Export Video: Video input file cannot be read.") << endmsg;
-         unlink (insnd.c_str());
+         ::g_unlink (insnd.c_str());
          Gtk::Dialog::response(RESPONSE_CANCEL);
          return;
        }
 
        std::string preset = preset_combo.get_active_text();
-       FFSettings ffs ; /* = transcoder->default_encoder_settings(); */
+       TranscodeFfmpeg::FFSettings ffs ; /* = transcoder->default_encoder_settings(); */
        ffs.clear();
 
        if (fps_checkbox.get_active()) {
@@ -581,7 +611,7 @@ ExportVideoDialog::encode_pass (int pass)
        ffs["-acodec"] = audio_codec_combo.get_active_text();
 
        if (video_bitrate_combo.get_active_text() == "retain" ) {
-               ffs["-sameq"]  = "-y"; // we use '-y' as dummy parameter for non key/value options
+               ffs["-qscale"]  = "0";
        } else {
                ffs["-b:v"]  = video_bitrate_combo.get_active_text();
        }
@@ -591,13 +621,8 @@ ExportVideoDialog::encode_pass (int pass)
                ffs["-strict"] = "-2";
        }
 
-       if (video_codec_combo.get_active_text() == "x264 (hq)" ) {
-               ffs["-vcodec"] = "libx264";
-               ffs["-vprofile"] = "high";
-       }
-       else if (video_codec_combo.get_active_text() == "x264 (baseline)" ) {
+       if (video_codec_combo.get_active_text() == "h264" ) {
                ffs["-vcodec"] = "libx264";
-               ffs["-vpre"] = "baseline";
        }
        else if (video_codec_combo.get_active_text() == "vpx (webm)" ) {
                ffs["-vcodec"] = "libvpx";
@@ -679,9 +704,14 @@ ExportVideoDialog::encode_pass (int pass)
        double duration_s  = 0;
 
        if (insnd_combo.get_active_row_number() == 0) {
+               /* session start to session end */
                framecnt_t duration_f = _session->current_end_frame() - _session->current_start_frame();
                duration_s = (double)duration_f / (double)_session->nominal_frame_rate();
+       } else if (insnd_combo.get_active_row_number() == 2) {
+               /* selected range */
+               duration_s = export_range.length() / (double)_session->nominal_frame_rate();
        } else {
+               /* video start to end */
                framecnt_t duration_f = ARDOUR_UI::instance()->video_timeline->get_duration();
                if (av_offset < 0 ) {
                        duration_f += av_offset;
@@ -697,10 +727,16 @@ ExportVideoDialog::encode_pass (int pass)
                transcoder->set_duration(duration_s * transcoder->get_fps());
        }
 
-       if (insnd_combo.get_active_row_number() == 0) {
-               const framepos_t start = _session->current_start_frame();
-               const framepos_t snend = _session->current_end_frame();
+       if (insnd_combo.get_active_row_number() == 0 || insnd_combo.get_active_row_number() == 2) {
+               framepos_t start, snend;
                const frameoffset_t vid_duration = ARDOUR_UI::instance()->video_timeline->get_duration();
+               if (insnd_combo.get_active_row_number() == 0) {
+                       start = _session->current_start_frame();
+                       snend = _session->current_end_frame();
+               } else {
+                       start = export_range.start();
+                       snend = export_range.end_frame();
+               }
 
 #if 0 /* DEBUG */
                printf("AV offset: %lld Vid-len: %lld Vid-end: %lld || start:%lld || end:%lld\n",
@@ -715,15 +751,23 @@ ExportVideoDialog::encode_pass (int pass)
                } 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());
-               } else {
+               }
+#if 0
+               else if (start > av_offset) {
+                       std::ostringstream osstream; osstream << ((start - av_offset) / (double)_session->nominal_frame_rate());
+                       ffs["-ss"] = osstream.str();
+               }
+#endif
+               else {
                        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());
        }
 
-       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 ) {