/*
- Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
-#include "shuffler.h"
+
#include "content_video.h"
#include "dcpomatic_assert.h"
-#include <boost/foreach.hpp>
+#include "dcpomatic_log.h"
+#include "shuffler.h"
+#include <string>
#include <iostream>
+
using std::make_pair;
-using boost::weak_ptr;
-using boost::shared_ptr;
+using std::shared_ptr;
+using std::string;
+using std::weak_ptr;
using boost::optional;
+
+int const Shuffler::_max_size = 64;
+
+
struct Comparator
{
bool operator()(Shuffler::Store const & a, Shuffler::Store const & b) {
}
};
+
void
Shuffler::video (weak_ptr<Piece> weak_piece, ContentVideo video)
{
- /* Something has gong wrong if our store gets too big */
- DCPOMATIC_ASSERT (_store.size() != 8);
- /* We should only ever see 3D_LEFT / 3D_RIGHT */
- DCPOMATIC_ASSERT (video.eyes == EYES_LEFT || video.eyes == EYES_RIGHT);
+ LOG_DEBUG_THREE_D ("Shuffler::video frame=%1 eyes=%2 part=%3", video.frame, static_cast<int>(video.eyes), static_cast<int>(video.part));
+
+ if (video.eyes != Eyes::LEFT && video.eyes != Eyes::RIGHT) {
+ /* Pass through anything that we don't care about */
+ Video (weak_piece, video);
+ return;
+ }
- shared_ptr<Piece> piece = weak_piece.lock ();
+ auto piece = weak_piece.lock ();
DCPOMATIC_ASSERT (piece);
- if (!_last) {
- /* We haven't seen anything since the last clear() so assume everything is OK */
+ if (!_last && video.eyes == Eyes::LEFT) {
+ LOG_DEBUG_THREE_D_NC ("Shuffler first after clear");
+ /* We haven't seen anything since the last clear() and we have some eyes-left so assume everything is OK */
Video (weak_piece, video);
_last = video;
return;
_store.push_back (make_pair (weak_piece, video));
_store.sort (Comparator());
- while (
- !_store.empty() &&
- (
- (_store.front().second.frame == _last->frame && _store.front().second.eyes == EYES_RIGHT && _last->eyes == EYES_LEFT) ||
- (_store.front().second.frame == (_last->frame + 1) && _store.front().second.eyes == EYES_LEFT && _last->eyes == EYES_RIGHT) ||
- _store.size() > 8
- )
- ) {
+ while (true) {
+
+ bool const store_front_in_sequence =
+ !_store.empty() &&
+ _last &&
+ (
+ (_store.front().second.frame == _last->frame && _store.front().second.eyes == Eyes::RIGHT && _last->eyes == Eyes::LEFT) ||
+ (_store.front().second.frame >= (_last->frame + 1) && _store.front().second.eyes == Eyes::LEFT && _last->eyes == Eyes::RIGHT)
+ );
+ if (!store_front_in_sequence) {
+ string const store = _store.empty() ? "store empty" : String::compose("store front frame=%1 eyes=%2", _store.front().second.frame, static_cast<int>(_store.front().second.eyes));
+ string const last = _last ? String::compose("last frame=%1 eyes=%2", _last->frame, static_cast<int>(_last->eyes)) : "no last";
+ LOG_DEBUG_THREE_D("Shuffler not in sequence: %1 %2", store, last);
+ }
+
+ if (!store_front_in_sequence && _store.size() <= _max_size) {
+ /* store_front_in_sequence means everything is ok; otherwise if the store is getting too big just
+ start emitting things as best we can. This can easily happen if, for example, there is only content
+ for one eye in some part of the timeline.
+ */
+ break;
+ }
+
+ if (_store.size() > _max_size) {
+ LOG_WARNING ("Shuffler is full after receiving frame %1; 3D sync may be incorrect.", video.frame);
+ }
+
+ LOG_DEBUG_THREE_D("Shuffler emits frame=%1 eyes=%2 store=%3", _store.front().second.frame, static_cast<int>(_store.front().second.eyes), _store.size());
Video (_store.front().first, _store.front().second);
_last = _store.front().second;
_store.pop_front ();
}
}
+
void
Shuffler::clear ()
{
- VideoAdjuster::clear ();
+ LOG_DEBUG_THREE_D_NC ("Shuffler::clear");
+ _store.clear ();
_last = optional<ContentVideo>();
}
+
+
+void
+Shuffler::flush ()
+{
+ for (auto i: _store) {
+ Video (i.first, i.second);
+ }
+}