]> git.sesse.net Git - nageru/commitdiff
Add cue point padding, where a clip is elongated (in both directions) by some given...
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 21 Dec 2018 14:17:47 +0000 (15:17 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 21 Dec 2018 14:17:51 +0000 (15:17 +0100)
futatabi/flags.cpp
futatabi/flags.h
futatabi/mainwindow.cpp
futatabi/mainwindow.h
futatabi/mainwindow.ui
futatabi/state.proto

index 9e15399aa40189789c67f9e15d1ae49eb4cf8fd7..aefde273aa64fdbc32504ff2658e743faa6a09d9 100644 (file)
@@ -17,7 +17,8 @@ enum LongOption {
        OPTION_HELP = 1000,
        OPTION_SLOW_DOWN_INPUT = 1001,
        OPTION_HTTP_PORT = 1002,
-       OPTION_TALLY_URL = 1003
+       OPTION_TALLY_URL = 1003,
+       OPTION_CUE_POINT_PADDING = 1004
 };
 
 void usage()
@@ -36,6 +37,7 @@ void usage()
        fprintf(stderr, "                                  2 = default (realtime 720p on fast embedded GPUs)\n");
        fprintf(stderr, "                                  3 = good (realtime 720p on GTX 970 or so)\n");
        fprintf(stderr, "                                  4 = best (not realtime on any current GPU)\n");
+       fprintf(stderr, "      --cue-point-padding SECS    move cue-in/cue-out N seconds earlier/later on set\n");
        fprintf(stderr, "  -d, --working-directory DIR     where to store frames and database\n");
        fprintf(stderr, "      --http-port PORT            which port to listen on for output\n");
        fprintf(stderr, "      --tally-url URL             URL to get tally color from (polled every 100 ms)\n");
@@ -53,6 +55,7 @@ void parse_flags(int argc, char * const argv[])
                { "working-directory", required_argument, 0, 'd' },
                { "http-port", required_argument, 0, OPTION_HTTP_PORT },
                { "tally-url", required_argument, 0, OPTION_TALLY_URL },
+               { "cue-point-padding", required_argument, 0, OPTION_CUE_POINT_PADDING },
                { 0, 0, 0, 0 }
        };
        for ( ;; ) {
@@ -97,6 +100,10 @@ void parse_flags(int argc, char * const argv[])
                case OPTION_TALLY_URL:
                        global_flags.tally_url = optarg;
                        break;
+               case OPTION_CUE_POINT_PADDING:
+                       global_flags.cue_point_padding_seconds = atof(optarg);
+                       global_flags.cue_point_padding_set = true;
+                       break;
                case OPTION_HELP:
                        usage();
                        exit(0);
@@ -113,4 +120,9 @@ void parse_flags(int argc, char * const argv[])
                usage();
                exit(1);
        }
+       if (global_flags.cue_point_padding_seconds < 0.0) {
+               fprintf(stderr, "Cue point padding cannot be negative.\n");
+               usage();
+               exit(1);
+       }
 }
index 5b7d32e729374f304823063e7aa0e0d29a580a95..6796c147bc2b65da3f3047b43b563844b316c846 100644 (file)
@@ -15,6 +15,8 @@ struct Flags {
        uint16_t http_port = DEFAULT_HTTPD_PORT;
        double output_framerate = 60000.0 / 1001.0;
        std::string tally_url;
+       double cue_point_padding_seconds = 0.0;  // Can be changed in the menus.
+       bool cue_point_padding_set = false;
 };
 extern Flags global_flags;
 
index 38a50df371886d4045a31993e5fa93ae19699061..152358b3e1da023160d8ced72e7a75990a6dfcc2 100644 (file)
@@ -40,13 +40,16 @@ MainWindow::MainWindow()
        global_mainwindow = this;
        ui->setupUi(this);
 
-       // Load settings from database if needed.
+       // Load settings from database.
+       SettingsProto settings = db.get_settings();
        if (!global_flags.interpolation_quality_set) {
-               SettingsProto settings = db.get_settings();
                if (settings.interpolation_quality() != 0) {
                        global_flags.interpolation_quality = settings.interpolation_quality() - 1;
                }
        }
+       if (!global_flags.cue_point_padding_set) {
+               global_flags.cue_point_padding_seconds = settings.cue_point_padding_seconds();  // Default 0 is fine.
+       }
        if (global_flags.interpolation_quality == 0) {
                // Allocate something just for simplicity; we won't be using it
                // unless the user changes runtime, in which case 1 is fine.
@@ -93,6 +96,28 @@ MainWindow::MainWindow()
        connect(ui->quality_3_action, &QAction::toggled, bind(&MainWindow::quality_toggled, this, 3, _1));
        connect(ui->quality_4_action, &QAction::toggled, bind(&MainWindow::quality_toggled, this, 4, _1));
 
+       // The cue point padding group.
+       QActionGroup *padding_group = new QActionGroup(ui->interpolation_menu);
+       padding_group->addAction(ui->padding_0_action);
+       padding_group->addAction(ui->padding_1_action);
+       padding_group->addAction(ui->padding_2_action);
+       padding_group->addAction(ui->padding_5_action);
+       if (global_flags.cue_point_padding_seconds <= 1e-3) {
+               ui->padding_0_action->setChecked(true);
+       } else if (fabs(global_flags.cue_point_padding_seconds - 1.0) < 1e-3) {
+               ui->padding_1_action->setChecked(true);
+       } else if (fabs(global_flags.cue_point_padding_seconds - 2.0) < 1e-3) {
+               ui->padding_2_action->setChecked(true);
+       } else if (fabs(global_flags.cue_point_padding_seconds - 5.0) < 1e-3) {
+               ui->padding_5_action->setChecked(true);
+       } else {
+               // Nothing to check, which is fine.
+       }
+       connect(ui->padding_0_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 0.0, _1));
+       connect(ui->padding_1_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 1.0, _1));
+       connect(ui->padding_2_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 2.0, _1));
+       connect(ui->padding_5_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 5.0, _1));
+
        global_disk_space_estimator = new DiskSpaceEstimator(bind(&MainWindow::report_disk_space, this, _1, _2));
        disk_free_label = new QLabel(this);
        disk_free_label->setStyleSheet("QLabel {padding-right: 5px;}");
@@ -252,7 +277,7 @@ void MainWindow::cue_in_clicked()
                return;
        }
        Clip clip;
-       clip.pts_in = current_pts;
+       clip.pts_in = max<int64_t>(current_pts - lrint(global_flags.cue_point_padding_seconds * TIMEBASE), 0);
        cliplist_clips->add_clip(clip);
        playlist_selection_changed();
        ui->clip_list->scrollToBottom();
@@ -261,7 +286,7 @@ void MainWindow::cue_in_clicked()
 void MainWindow::cue_out_clicked()
 {
        if (!cliplist_clips->empty()) {
-               cliplist_clips->mutable_back()->pts_out = current_pts;
+               cliplist_clips->mutable_back()->pts_out = current_pts + lrint(global_flags.cue_point_padding_seconds * TIMEBASE);
                // TODO: select the row in the clip list?
        }
 }
@@ -446,6 +471,7 @@ void MainWindow::save_settings()
 {
        SettingsProto settings;
        settings.set_interpolation_quality(global_flags.interpolation_quality + 1);
+       settings.set_cue_point_padding_seconds(global_flags.cue_point_padding_seconds);
        db.store_settings(settings);
 }
 
@@ -1009,6 +1035,15 @@ void MainWindow::quality_toggled(int quality, bool checked)
        save_settings();
 }
 
+void MainWindow::padding_toggled(double seconds, bool checked)
+{
+       if (!checked) {
+               return;
+       }
+       global_flags.cue_point_padding_seconds = seconds;
+       save_settings();
+}
+
 void MainWindow::highlight_camera_input(int stream_idx)
 {
        for (unsigned i = 0; i < num_cameras; ++i) {
index 5d7104ab3210745770fc603d9db7eea1ea3680f5..2bb880d5ba80e4de3e985b349d61d3d5d997c61c 100644 (file)
@@ -134,6 +134,7 @@ private:
        void undo_triggered();
        void redo_triggered();
        void quality_toggled(int quality, bool checked);
+       void padding_toggled(double seconds, bool checked);
 
        void highlight_camera_input(int stream_idx);
 
index 0f471e00d4b5526a115191940c52b85af71c729c..36d8a5ec9ffb0340b843591d15fa8ce655a6461a 100644 (file)
      <addaction name="quality_3_action"/>
      <addaction name="quality_4_action"/>
     </widget>
+    <widget class="QMenu" name="padding_menu">
+     <property name="title">
+      <string>Cue point &amp;padding</string>
+     </property>
+     <addaction name="padding_0_action"/>
+     <addaction name="padding_1_action"/>
+     <addaction name="padding_2_action"/>
+     <addaction name="padding_5_action"/>
+    </widget>
     <addaction name="interpolation_menu"/>
+    <addaction name="padding_menu"/>
     <addaction name="menu_Export"/>
     <addaction name="exit_action"/>
+    <addaction name="separator"/>
    </widget>
    <widget class="QMenu" name="menu_Help">
     <property name="title">
     <string>Best (&amp;4) (not realtime on any current GPU)</string>
    </property>
   </action>
+  <action name="padding_0_action">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&amp;0 seconds</string>
+   </property>
+  </action>
+  <action name="padding_1_action">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&amp;1 second</string>
+   </property>
+  </action>
+  <action name="padding_2_action">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&amp;2 seconds</string>
+   </property>
+  </action>
+  <action name="padding_5_action">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>&amp;5 seconds</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>
index c64555bd39b9389e57e6ef2b1b19145028509dd5..36a9fa0e896d92370ca781c141412fed07e140b3 100644 (file)
@@ -21,4 +21,5 @@ message StateProto {
 
 message SettingsProto {
        int32 interpolation_quality = 1;  // 0 = unset, 1 = quality 0, 2 = quality 1, etc.
+       double cue_point_padding_seconds = 2;
 }