]> git.sesse.net Git - nageru/commitdiff
Add some very basic playback.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 11 Jun 2018 18:32:07 +0000 (20:32 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 11 Jun 2018 18:32:07 +0000 (20:32 +0200)
Makefile
clip_list.h
defs.h [new file with mode: 0644]
main.cpp
mainwindow.cpp
player.cpp [new file with mode: 0644]
player.h [new file with mode: 0644]
ui_mainwindow.ui

index fc91d0e8ce5a6bef370e735897e9b29b8ce1bb6a..42b5ea04fff974c5ccc3fbbf2144c94924fc63ae 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ OBJS_WITH_MOC = mainwindow.o jpeg_frame_view.o clip_list.o
 OBJS += $(OBJS_WITH_MOC)
 OBJS += $(OBJS_WITH_MOC:.o=.moc.o) 
 
-OBJS += ffmpeg_raii.o main.o
+OBJS += ffmpeg_raii.o main.o player.o
 
 %.o: %.cpp
        $(CXX) -MMD -MP $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
index cb58564b33a47ea42b818842d022f011b775ddeb..da76f8c5b394f32bde6bcdf6727da5a02ff91f89 100644 (file)
@@ -37,6 +37,7 @@ public:
                        }
                }
                Clip *operator->() { return &clip; }
+               Clip &operator*() { return clip; }
 
        private:
                Clip &clip;
diff --git a/defs.h b/defs.h
new file mode 100644 (file)
index 0000000..798e5f1
--- /dev/null
+++ b/defs.h
@@ -0,0 +1,6 @@
+#ifndef _DEFS_H
+#define _DEFS_H 1
+
+#define MAX_STREAMS 16
+
+#endif  // !defined(_DEFS_H)
index 865b98b82a3883693eacac6b88dd06b5548073c0..a0e93420688acebd0e742d2632b10b4a6cd2733b 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -3,6 +3,7 @@
 #include <stdint.h>
 
 #include <chrono>
+#include <condition_variable>
 #include <memory>
 #include <mutex>
 #include <string>
@@ -15,13 +16,14 @@ extern "C" {
 
 #include <QApplication>
 
+#include "clip_list.h"
+#include "defs.h"
 #include "mainwindow.h"
 #include "ffmpeg_raii.h"
+#include "player.h"
 #include "post_to_main_thread.h"
 #include "ui_mainwindow.h"
 
-#define MAX_STREAMS 16
-
 using namespace std;
 using namespace std::chrono;
 
@@ -38,7 +40,7 @@ string filename_for_frame(unsigned stream_idx, int64_t pts)
 mutex frame_mu;
 vector<int64_t> frames[MAX_STREAMS];
 
-int thread_func();
+int record_thread_func();
 
 int main(int argc, char **argv)
 {
@@ -49,12 +51,13 @@ int main(int argc, char **argv)
        MainWindow mainWindow;
        mainWindow.show();
 
-       thread(thread_func).detach();
+       thread(record_thread_func).detach();
+       start_player_thread();
 
        return app.exec();
 }
 
-int thread_func()
+int record_thread_func()
 {
        auto format_ctx = avformat_open_input_unique("multiangle.mp4", nullptr, nullptr);
        if (format_ctx == nullptr) {
index 9db4a9bcb8eb29284a83dd3350b1fca24b58c929..bbeeef9f7fa6fe76c927ac552337d03df8e80ef8 100644 (file)
@@ -1,6 +1,7 @@
 #include "mainwindow.h"
 
 #include "clip_list.h"
+#include "player.h"
 #include "ui_mainwindow.h"
 
 #include <string>
@@ -12,6 +13,7 @@ using namespace std;
 
 MainWindow *global_mainwindow = nullptr;
 extern int64_t current_pts;
+ClipList *clips;
 
 MainWindow::MainWindow()
        : ui(new Ui::MainWindow)
@@ -19,13 +21,13 @@ MainWindow::MainWindow()
        global_mainwindow = this;
        ui->setupUi(this);
 
-       ClipList *clips = new ClipList;
+       clips = new ClipList;
        ui->clip_list->setModel(clips);
 
        // TODO: Make these into buttons.
        // TODO: These are too big for lambdas.
        QShortcut *cue_in = new QShortcut(QKeySequence(Qt::Key_A), this);
-       connect(cue_in, &QShortcut::activated, [clips]{
+       connect(cue_in, &QShortcut::activated, []{
                if (!clips->empty() && clips->back()->pts_out < 0) {
                        clips->back()->pts_in = current_pts;
                        return;
@@ -36,7 +38,7 @@ MainWindow::MainWindow()
        });
 
        QShortcut *cue_out = new QShortcut(QKeySequence(Qt::Key_S), this);
-       connect(cue_out, &QShortcut::activated, [clips]{
+       connect(cue_out, &QShortcut::activated, []{
                if (!clips->empty()) {
                        clips->back()->pts_out = current_pts;
                        // TODO: select the row in the clip list?
@@ -49,5 +51,5 @@ MainWindow::MainWindow()
 
 void MainWindow::preview_clicked()
 {
-       printf("preview\n");
+       play_clip(*clips->back(), 0);
 }
diff --git a/player.cpp b/player.cpp
new file mode 100644 (file)
index 0000000..a2c1a93
--- /dev/null
@@ -0,0 +1,109 @@
+#include <algorithm>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include "clip_list.h"
+#include "defs.h"
+#include "mainwindow.h"
+#include "ffmpeg_raii.h"
+#include "post_to_main_thread.h"
+#include "ui_mainwindow.h"
+
+using namespace std;
+using namespace std::chrono;
+
+extern mutex frame_mu;
+extern vector<int64_t> frames[MAX_STREAMS];
+
+struct PlaylistClip {
+       Clip clip;
+       unsigned stream_idx;
+};
+vector<PlaylistClip> current_cue_playlist;
+mutex playlist_mu;
+
+enum { PAUSED, PLAYING } cue_state = PAUSED;
+mutex cue_state_mu;
+condition_variable cue_is_playing;
+//int cue_playlist_index = -1;
+//int64_t cue_playlist_pos = 0;
+
+int preview_thread_func()
+{
+       for ( ;; ) {
+               // Wait until we're supposed to play something.
+               {
+                       unique_lock<mutex> lock(cue_state_mu);
+                       cue_is_playing.wait(lock, []{
+                               return cue_state == PLAYING;
+                               //return current_cue_status.origin != steady_clock::time_point::max();
+                       });
+               }
+
+               PlaylistClip clip;
+               {
+                       lock_guard<mutex> lock2(playlist_mu);
+                       clip = current_cue_playlist[0];
+               }
+               steady_clock::time_point origin = steady_clock::now();
+               int64_t pts_origin = clip.clip.pts_in;
+
+               int64_t next_pts = pts_origin;
+
+               bool eof = false;
+               while (!eof) {  // TODO: check for abort
+                       // FIXME: assumes a given timebase.
+                       double speed = 0.5;
+                       steady_clock::time_point next_frame_start =
+                               origin + microseconds((next_pts - pts_origin) * int(1000000 / speed) / 12800);
+                       this_thread::sleep_until(next_frame_start);
+                       global_mainwindow->ui->preview_display->setFrame(clip.stream_idx, next_pts);
+
+                       // Find the next frame.
+                       {
+                               lock_guard<mutex> lock2(frame_mu);
+                               auto it = upper_bound(frames[clip.stream_idx].begin(),
+                                       frames[clip.stream_idx].end(),
+                                       next_pts);
+                               if (it == frames[clip.stream_idx].end()) {
+                                       eof = true;
+                               } else {
+                                       next_pts = *it;
+                                       if (next_pts >= clip.clip.pts_out) {
+                                               eof = true;
+                                       }
+                               }
+                       }
+                       if (eof) break;
+               }
+
+               // TODO: advance the playlist and look for the next element.
+               {
+                       unique_lock<mutex> lock(cue_state_mu);
+                       cue_state = PAUSED;
+               }
+       }
+}
+
+void start_player_thread()
+{
+       thread(preview_thread_func).detach();
+}
+
+void play_clip(const Clip &clip, unsigned stream_idx)
+{
+       {
+               lock_guard<mutex> lock(playlist_mu);
+               current_cue_playlist.clear();
+               current_cue_playlist.push_back(PlaylistClip{ clip, stream_idx });
+       }
+
+       {
+               lock_guard<mutex> lock(cue_state_mu);
+               cue_state = PLAYING;
+               cue_is_playing.notify_all();
+       }
+}
diff --git a/player.h b/player.h
new file mode 100644 (file)
index 0000000..960bc22
--- /dev/null
+++ b/player.h
@@ -0,0 +1,9 @@
+#ifndef _PLAYER_H
+#define _PLAYER_H 1
+
+#include "clip_list.h"
+
+void start_player_thread();
+void play_clip(const Clip &clip, unsigned stream_idx);
+
+#endif  // !defined(_PLAYER_H)
index d55e00d5fc8aa219533c1cd5d965e3c1008b46ad..9f8fee72fdd37b243197382b0c35c623fd00a327 100644 (file)
@@ -55,7 +55,7 @@
         <item>
          <layout class="QVBoxLayout" name="verticalLayout">
           <item>
-           <widget class="QGraphicsView" name="preview_display"/>
+           <widget class="JPEGFrameView" name="preview_display"/>
           </item>
           <item>
            <widget class="QLabel" name="label_2">
@@ -72,7 +72,7 @@
         <item>
          <layout class="QVBoxLayout" name="verticalLayout_2">
           <item>
-           <widget class="QGraphicsView" name="live_display"/>
+           <widget class="JPEGFrameView" name="live_display"/>
           </item>
           <item>
            <widget class="QLabel" name="label_3">