From 1fa1a2d5e33d9f9c7ad3762940516248664ac773 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 3 Jul 2025 15:38:52 +0200 Subject: Insert black for missing 3D eyes in the Shuffler (#3056). --- src/lib/shuffler.cc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/lib/shuffler.cc b/src/lib/shuffler.cc index 57c17ad46..56987a3cf 100644 --- a/src/lib/shuffler.cc +++ b/src/lib/shuffler.cc @@ -22,6 +22,8 @@ #include "content_video.h" #include "dcpomatic_assert.h" #include "dcpomatic_log.h" +#include "image.h" +#include "raw_image_proxy.h" #include "shuffler.h" #include #include @@ -91,13 +93,42 @@ Shuffler::video(weak_ptr weak_piece, ContentVideo video) break; } + optional extra; + if (_store.size() > _max_size) { LOG_WARNING("Shuffler is full after receiving frame at %1; 3D sync may be incorrect.", to_string(video.time)); + /* Now that we've given up waiting for the correct frames to arrive, we may need to insert some extra + * left/right eyes so that the player doesn't wait forever for lefts/rights that will never come. + * Set extra to the extra eye that we should insert based on what we'll emit now and what's coming next. + */ + auto const& this_frame = _store.front(); + auto const& next_frame = *std::next(_store.begin()); + if (this_frame.second.eyes == next_frame.second.eyes) { + extra = this_frame.second.eyes == Eyes::LEFT ? Eyes::RIGHT : Eyes::LEFT; + } + } + + auto emit_black = [this](Eyes eyes) { + LOG_DEBUG_THREE_D("Shuffler emits extra time=%1 eyes=%2 store=%3", to_string(_store.front().second.time), static_cast(eyes), _store.size()); + auto image = std::make_shared(AV_PIX_FMT_RGB24, dcp::Size(64, 64), Image::Alignment::COMPACT); + image->make_black(); + auto proxy = std::make_shared(image); + ContentVideo black(proxy, _store.front().second.time, eyes, _store.front().second.part); + Video(_store.front().first, black); + }; + + if (extra && *extra == Eyes::LEFT) { + emit_black(*extra); } LOG_DEBUG_THREE_D("Shuffler emits time=%1 eyes=%2 store=%3", to_string(_store.front().second.time), static_cast(_store.front().second.eyes), _store.size()); Video(_store.front().first, _store.front().second); _last = _store.front().second; + + if (extra && *extra == Eyes::RIGHT) { + emit_black(*extra); + } + _store.pop_front(); } } -- cgit v1.2.3