basic GUI support to auto-align video by LTC.
authorRobin Gareus <robin@gareus.org>
Sun, 20 Sep 2015 16:37:39 +0000 (18:37 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 20 Sep 2015 16:37:39 +0000 (18:37 +0200)
gtk2_ardour/ardour_ui.cc
gtk2_ardour/transcode_video_dialog.cc
gtk2_ardour/transcode_video_dialog.h

index d13a3a2ad5517cfdb1d3333f9631ce3c4af07cf9..3424a105ae844c308709501e3b4bbfab67079d35 100644 (file)
@@ -77,6 +77,7 @@
 #include "ardour/diskstream.h"
 #include "ardour/filename_extensions.h"
 #include "ardour/filesystem_paths.h"
+#include "ardour/ltc_file_reader.h"
 #include "ardour/port.h"
 #include "ardour/plugin_manager.h"
 #include "ardour/process_thread.h"
@@ -3958,6 +3959,9 @@ ARDOUR_UI::add_video (Gtk::Window* float_window)
                return;
        }
 
+       std::string audio_from_video;
+       bool detect_ltc = false;
+
        switch (add_video_dialog->import_option()) {
                case VTL_IMPORT_TRANSCODE:
                        {
@@ -3969,9 +3973,15 @@ ARDOUR_UI::add_video (Gtk::Window* float_window)
                                        delete transcode_video_dialog;
                                        return;
                                }
-                               if (!transcode_video_dialog->get_audiofile().empty()) {
+
+                               audio_from_video = transcode_video_dialog->get_audiofile();
+
+                               if (!audio_from_video.empty() && transcode_video_dialog->detect_ltc()) {
+                                       detect_ltc = true;
+                               }
+                               else if (!audio_from_video.empty()) {
                                        editor->embed_audio_from_video(
-                                                       transcode_video_dialog->get_audiofile(),
+                                                       audio_from_video,
                                                        video_timeline->get_offset(),
                                                        (transcode_video_dialog->import_option() != VTL_IMPORT_NO_VIDEO)
                                                        );
@@ -4004,6 +4014,7 @@ ARDOUR_UI::add_video (Gtk::Window* float_window)
        }
 
        video_timeline->set_update_session_fps(auto_set_session_fps);
+
        if (video_timeline->video_file_info(path, local_file)) {
                XMLNode* node = new XMLNode(X_("Videotimeline"));
                node->add_property (X_("Filename"), path);
@@ -4017,6 +4028,40 @@ ARDOUR_UI::add_video (Gtk::Window* float_window)
                _session->add_extra_xml (*node);
                _session->set_dirty ();
 
+               if (!audio_from_video.empty() && detect_ltc) {
+                       std::vector<LTCFileReader::LTCMap> ltc_seq;
+
+                       try {
+                               /* TODO ask user about TV standard (LTC alignment if any) */
+                               LTCFileReader ltcr (audio_from_video, video_timeline->get_video_file_fps());
+                               /* TODO ASK user which channel:  0 .. ltcr->channels() - 1 */
+
+                               ltc_seq = ltcr.read_ltc (/*channel*/ 0, /*max LTC frames to decode*/ 15);
+
+                               /* TODO seek near end of file, and read LTC until end.
+                                * if it fails to find any LTC frames, scan complete file
+                                *
+                                * calculate drift of LTC compared to video-duration,
+                                * ask user for reference (timecode from start/mid/end)
+                                */
+                       } catch (...) {
+                               // LTCFileReader will have written error messages
+                       }
+
+                       ::g_unlink(audio_from_video.c_str());
+
+                       if (ltc_seq.size() == 0) {
+                               PBD::error << _("No LTC detected, video will not be aligned.") << endmsg;
+                       } else {
+                               /* the very first TC in the file is somteimes not aligned properly */
+                               int i = ltc_seq.size() -1;
+                               ARDOUR::frameoffset_t video_start_offset =
+                                       _session->nominal_frame_rate() * (ltc_seq[i].timecode_sec - ltc_seq[i].framepos_sec);
+                               PBD::info << string_compose (_("Align video-start to %1 [samples]"), video_start_offset) << endmsg;
+                               video_timeline->set_offset(video_start_offset);
+                       }
+               }
+
                _session->maybe_update_session_range(
                        std::max(video_timeline->get_offset(), (ARDOUR::frameoffset_t) 0),
                        std::max(video_timeline->get_offset() + video_timeline->get_duration(), (ARDOUR::frameoffset_t) 0));
index ac3d4808fc10348c2e70d6f108d220575e130af6..3aa35a5c1b648328f6a17b0efb5b242be17ab0af 100644 (file)
@@ -63,6 +63,7 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
        , aspect_checkbox (_("Height = "))
        , height_adjustment (128, 0, 1920, 1, 16, 0)
        , height_spinner (height_adjustment)
+       , ltc_detect (_("Extract LTC from audio and align video"))
        , bitrate_checkbox (_("Manual Override"))
        , bitrate_adjustment (2000, 500, 10000, 10, 100, 0)
        , bitrate_spinner (bitrate_adjustment)
@@ -219,7 +220,7 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
 
        options_box->pack_start (video_combo, false, false, 4);
 
-       Table* t = manage (new Table (4, 3));
+       Table* t = manage (new Table (4, 4));
        t->set_spacings (4);
        options_box->pack_start (*t, true, true, 4);
 
@@ -254,6 +255,7 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
        t->attach (*l, 0, 1, 2, 3);
        audio_combo.set_name ("PaddedButton");
        t->attach (audio_combo, 1, 4, 2, 3);
+       t->attach (ltc_detect, 1, 4, 3, 4);
        if (as.size() == 0) {
                audio_combo.append_text(_("No Audio Track Present"));
                audio_combo.set_sensitive(false);
@@ -264,6 +266,7 @@ TranscodeVideoDialog::TranscodeVideoDialog (Session* s, std::string infile)
                }
        }
        audio_combo.set_active(0);
+       ltc_detect.set_sensitive (false);
 
 #if 1 /* tentative debug mode */
        options_box->pack_start (debug_checkbox, false, true, 4);
@@ -461,6 +464,9 @@ TranscodeVideoDialog::video_combo_changed ()
        }
        if (i == 2 && audio_combo.get_active_row_number() == 0) {
                audio_combo.set_active(1);
+       } else {
+               //update LTC option sensitivity
+               audio_combo_changed ();
        }
 }
 
@@ -471,6 +477,17 @@ TranscodeVideoDialog::audio_combo_changed ()
                        && audio_combo.get_active_row_number() == 0)
        {
                audio_combo.set_active(1);
+               ltc_detect.set_sensitive (false);
+               ltc_detect.set_active (false);
+       }
+
+       if (video_combo.get_active_row_number() != 2
+                       && audio_combo.get_active_row_number() > 0)
+       {
+               ltc_detect.set_sensitive (true);
+       } else {
+               ltc_detect.set_sensitive (false);
+               ltc_detect.set_active (false);
        }
 }
 
index 835b32d82c5da8c74f779e0a090ed7ce13eb2484..9acd1284a566f430ca941c0895b06f41cf68b851 100644 (file)
@@ -48,6 +48,7 @@ class TranscodeVideoDialog : public ArdourDialog , public PBD::ScopedConnectionL
        std::string get_filename () { return path_entry.get_text(); }
        std::string get_audiofile () { return audiofile; }
        VtlTranscodeOption import_option ();
+       bool detect_ltc () { return ltc_detect.get_active (); }
 
   private:
        void on_show ();
@@ -94,6 +95,7 @@ class TranscodeVideoDialog : public ArdourDialog , public PBD::ScopedConnectionL
        Gtk::Adjustment   height_adjustment;
        Gtk::SpinButton   height_spinner;
        Gtk::ComboBoxText audio_combo;
+       Gtk::CheckButton  ltc_detect;
        Gtk::CheckButton  bitrate_checkbox;
        Gtk::Adjustment   bitrate_adjustment;
        Gtk::SpinButton   bitrate_spinner;