From b6eaf3bbd5005eda6d9853897b2b5667c5fd63a7 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 20 Jul 2023 15:44:51 +0200 Subject: [PATCH] std::shared_ptr is surprisingly not thread-safe, so we need a mutex. --- video_widget.cpp | 26 +++++++++++++++++++++----- video_widget.h | 3 ++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/video_widget.cpp b/video_widget.cpp index 126e874..b50ea1c 100644 --- a/video_widget.cpp +++ b/video_widget.cpp @@ -194,7 +194,10 @@ bool VideoWidget::process_queued_commands(AVFormatContext *format_ctx, AVCodecCo queue.pop_front(); queued_frames = std::move(queue); } - current_frame.reset(new Frame(make_video_frame(frame.get()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } update(); store_pts(frame->pts); break; @@ -225,7 +228,10 @@ bool VideoWidget::process_queued_commands(AVFormatContext *format_ctx, AVCodecCo if (frame == nullptr || error) { return true; } - current_frame.reset(new Frame(make_video_frame(frame.get()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } update(); store_pts(frame->pts); } @@ -375,7 +381,11 @@ int num_levels(GLuint width, GLuint height) void VideoWidget::paintGL() { - std::shared_ptr frame = current_frame; + std::shared_ptr frame; + { + lock_guard lock(current_frame_mu); + frame = current_frame; + } if (frame == nullptr) { glClear(GL_COLOR_BUFFER_BIT); return; @@ -913,7 +923,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) { - current_frame.reset(new Frame(make_video_frame(frame.get()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } last_frame = steady_clock::now(); update(); break; @@ -927,7 +940,10 @@ bool VideoWidget::play_video(const string &pathname) if (paused) { // Just paused, so present the frame immediately and then go into deep sleep. - current_frame.reset(new Frame(make_video_frame(frame.get()))); + { + lock_guard lock(current_frame_mu); + current_frame.reset(new Frame(make_video_frame(frame.get()))); + } last_frame = steady_clock::now(); update(); break; diff --git a/video_widget.h b/video_widget.h index 1f1ffe2..dc7d0ab 100644 --- a/video_widget.h +++ b/video_widget.h @@ -56,7 +56,8 @@ private: unsigned chroma_width, chroma_height; std::unique_ptr data; // Y, followed by Cb, followed by Cr. }; - std::shared_ptr current_frame; + std::mutex current_frame_mu; + std::shared_ptr current_frame; // Protected by current_frame_mu. std::deque queued_frames; // Frames decoded but not displayed. Only used when frame-stepping backwards. GLuint ycbcr_vertex_shader, ycbcr_fragment_shader, ycbcr_program; -- 2.39.2