]> git.sesse.net Git - pkanalytics/blobdiff - video_widget.cpp
Make it possible to have separate videos per match, instead of hardcoding one specifi...
[pkanalytics] / video_widget.cpp
index b50ea1c404a0494b8297180e8fc0f7c671c4bad6..e6708a9257cb8f4c5834fae55d720b94b1d826ae 100644 (file)
@@ -194,9 +194,10 @@ bool VideoWidget::process_queued_commands(AVFormatContext *format_ctx, AVCodecCo
                                                queue.pop_front();
                                                queued_frames = std::move(queue);
                                        }
+                                       Frame *new_frame = new Frame(make_video_frame(frame.get()));
                                        {
                                                lock_guard lock(current_frame_mu);
-                                               current_frame.reset(new Frame(make_video_frame(frame.get())));
+                                               current_frame.reset(new_frame);
                                        }
                                        update();
                                        store_pts(frame->pts);
@@ -228,9 +229,10 @@ bool VideoWidget::process_queued_commands(AVFormatContext *format_ctx, AVCodecCo
                if (frame == nullptr || error) {
                        return true;
                }
+               Frame *new_frame = new Frame(make_video_frame(frame.get()));
                {
                        lock_guard lock(current_frame_mu);
-                       current_frame.reset(new Frame(make_video_frame(frame.get())));
+                       current_frame.reset(new_frame);
                }
                update();
                store_pts(frame->pts);
@@ -592,30 +594,40 @@ void VideoWidget::fixup_zoom_matrix()
        zoom_matrix[7] = std::max(zoom_matrix[7], 1.0 - zoom_matrix[4]);  // Top side (y=1).
 }
 
-void VideoWidget::open(const string &filename)
+bool VideoWidget::open(const string &filename)
 {
        stop();
        internal_rewind();
        pathname = filename;
        play();
+
+       while (running == STARTING) {
+               // Poor man's condition variable...
+               usleep(10000);
+               sched_yield();
+       }
+       return (running != VIDEO_FILE_ERROR);   
 }
 
 void VideoWidget::play()
 {
-       if (running) {
+       if (running != NOT_RUNNING && running != VIDEO_FILE_ERROR) {
                std::lock_guard<std::mutex> lock(queue_mu);
                command_queue.push_back(QueuedCommand { QueuedCommand::RESUME });
                producer_thread_should_quit.wakeup();
                return;
        }
-       running = true;
+       running = STARTING;
        producer_thread_should_quit.unquit();
+       if (producer_thread.joinable()) {
+               producer_thread.join();
+       }
        producer_thread = std::thread(&VideoWidget::producer_thread_func, this);
 }
 
 void VideoWidget::pause()
 {
-       if (!running) {
+       if (running == NOT_RUNNING || running == VIDEO_FILE_ERROR) {
                return;
        }
        std::lock_guard<std::mutex> lock(queue_mu);
@@ -625,7 +637,7 @@ void VideoWidget::pause()
 
 void VideoWidget::seek(int64_t relative_seek_ms)
 {
-       if (!running) {
+       if (running == NOT_RUNNING || running == VIDEO_FILE_ERROR) {
                return;
        }
        std::lock_guard<std::mutex> lock(queue_mu);
@@ -635,7 +647,7 @@ void VideoWidget::seek(int64_t relative_seek_ms)
 
 void VideoWidget::seek_frames(int64_t relative_seek_frames)
 {
-       if (!running) {
+       if (running == NOT_RUNNING || running == VIDEO_FILE_ERROR) {
                return;
        }
        std::lock_guard<std::mutex> lock(queue_mu);
@@ -645,7 +657,7 @@ void VideoWidget::seek_frames(int64_t relative_seek_frames)
 
 void VideoWidget::seek_absolute(int64_t position_ms)
 {
-       if (!running) {
+       if (running == NOT_RUNNING || running == VIDEO_FILE_ERROR) {
                return;
        }
        std::lock_guard<std::mutex> lock(queue_mu);
@@ -655,10 +667,9 @@ void VideoWidget::seek_absolute(int64_t position_ms)
 
 void VideoWidget::stop()
 {
-       if (!running) {
+       if (running == NOT_RUNNING || running == VIDEO_FILE_ERROR) {
                return;
        }
-       running = false;
        producer_thread_should_quit.quit();
        producer_thread.join();
 }
@@ -667,7 +678,9 @@ void VideoWidget::producer_thread_func()
 {
        if (!producer_thread_should_quit.should_quit()) {
                if (!play_video(pathname)) {
-                       // TODO: Send the error back to the UI somehow.
+                       running = VIDEO_FILE_ERROR;
+               } else {
+                       running = NOT_RUNNING;
                }
        }
 }
@@ -873,6 +886,8 @@ bool VideoWidget::play_video(const string &pathname)
 
        internal_rewind();
 
+       running = RUNNING;
+
        // Main loop.
        int consecutive_errors = 0;
        double rate = 1.0;
@@ -923,9 +938,10 @@ bool VideoWidget::play_video(const string &pathname)
                        bool finished_wakeup;
                        finished_wakeup = producer_thread_should_quit.sleep_until(next_frame_start);
                        if (finished_wakeup) {
+                               Frame *new_frame = new Frame(make_video_frame(frame.get()));
                                {
                                        lock_guard lock(current_frame_mu);
-                                       current_frame.reset(new Frame(make_video_frame(frame.get())));
+                                       current_frame.reset(new_frame);
                                }
                                last_frame = steady_clock::now();
                                update();
@@ -940,9 +956,10 @@ bool VideoWidget::play_video(const string &pathname)
 
                                if (paused) {
                                        // Just paused, so present the frame immediately and then go into deep sleep.
+                                       Frame *new_frame = new Frame(make_video_frame(frame.get()));
                                        {
                                                lock_guard lock(current_frame_mu);
-                                               current_frame.reset(new Frame(make_video_frame(frame.get())));
+                                               current_frame.reset(new_frame);
                                        }
                                        last_frame = steady_clock::now();
                                        update();