From 42a6003535d3153224da33b973bb79662d296e02 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 29 Sep 2020 14:16:56 +0200 Subject: [PATCH] Basic handling of overlapping video (#1848). --- cscript | 4 +- src/lib/piece.h | 11 +++- src/lib/player.cc | 20 +++++++ src/lib/player.h | 2 + test/overlap_video_test.cc | 111 +++++++++++++++++++++++++++++++++++++ test/wscript | 1 + 6 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 test/overlap_video_test.cc diff --git a/cscript b/cscript index 7b593c8cb..18b9b71ae 100644 --- a/cscript +++ b/cscript @@ -370,8 +370,8 @@ def dependencies(target, options): # Use distro-provided FFmpeg on Arch deps = [] - deps.append(('libdcp', 'bed820d')) - deps.append(('libsub', '2ac27e6')) + deps.append(('libdcp', '9b6997a')) + deps.append(('libsub', '3d2a513')) deps.append(('leqm-nrt', '131f971')) deps.append(('rtaudio', 'f619b76')) # We get our OpenSSL libraries from the environment, but we diff --git a/src/lib/piece.h b/src/lib/piece.h index a2e62d366..688242c06 100644 --- a/src/lib/piece.h +++ b/src/lib/piece.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,15 +18,20 @@ */ + #ifndef DCPOMATIC_PIECE_H #define DCPOMATIC_PIECE_H -#include "types.h" + +#include "dcpomatic_time.h" #include "frame_rate_change.h" +#include "types.h" + class Content; class Decoder; + class Piece { public: @@ -39,8 +44,10 @@ public: std::shared_ptr content; std::shared_ptr decoder; + boost::optional ignore_video; FrameRateChange frc; bool done; }; + #endif diff --git a/src/lib/player.cc b/src/lib/player.cc index 465fcad6d..36d3fde67 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -266,6 +266,22 @@ Player::setup_pieces_unlocked () } } + for (auto i = _pieces.begin(); i != _pieces.end(); ++i) { + if (auto video = (*i)->content->video) { + if (video->use() && video->frame_type() != VideoFrameType::THREE_D_LEFT && video->frame_type() != VideoFrameType::THREE_D_RIGHT) { + /* Look for content later in the content list with in-use video that overlaps this */ + auto period = DCPTimePeriod((*i)->content->position(), (*i)->content->end(_film)); + auto j = i; + ++j; + for (; j != _pieces.end(); ++j) { + if ((*j)->content->video && (*j)->content->video->use()) { + (*i)->ignore_video = DCPTimePeriod((*j)->content->position(), (*j)->content->end(_film)).overlap(period); + } + } + } + } + } + _black = Empty (_film, playlist(), bind(&have_video, _1), _playback_length); _silent = Empty (_film, playlist(), bind(&have_audio, _1), _playback_length); @@ -851,6 +867,10 @@ Player::video (weak_ptr wp, ContentVideo video) return; } + if (piece->ignore_video && piece->ignore_video->contains(time)) { + return; + } + /* Fill gaps that we discover now that we have some video which needs to be emitted. This is where we need to fill to. */ diff --git a/src/lib/player.h b/src/lib/player.h index ce49af148..be8d556af 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -76,6 +76,7 @@ public: Player (Player const& Player) = delete; Player& operator= (Player const& Player) = delete; + bool pass (); void seek (dcpomatic::DCPTime time, bool accurate); @@ -118,6 +119,7 @@ private: friend struct empty_test1; friend struct empty_test2; friend struct check_reuse_old_data_test; + friend struct overlap_video_test1; void construct (); void setup_pieces (); diff --git a/test/overlap_video_test.cc b/test/overlap_video_test.cc new file mode 100644 index 000000000..246a75834 --- /dev/null +++ b/test/overlap_video_test.cc @@ -0,0 +1,111 @@ +/* + Copyright (C) 2020-2021 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + + +#include "lib/content.h" +#include "lib/content_factory.h" +#include "lib/dcpomatic_time.h" +#include "lib/film.h" +#include "lib/player.h" +#include "lib/video_content.h" +#include "test.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using std::dynamic_pointer_cast; +using std::make_shared; +using std::shared_ptr; + + +BOOST_AUTO_TEST_CASE (overlap_video_test1) +{ + auto film = new_test_film2 ("overlap_video_test1"); + film->set_sequence (false); + auto A = content_factory("test/data/flat_red.png").front(); + film->examine_and_add_content (A); + auto B = content_factory("test/data/flat_green.png").front(); + film->examine_and_add_content (B); + BOOST_REQUIRE (!wait_for_jobs()); + + A->video->set_length (72); + B->video->set_length (24); + B->set_position (film, dcpomatic::DCPTime::from_seconds(1)); + + auto player = make_shared(film); + auto pieces = player->_pieces; + BOOST_REQUIRE_EQUAL (pieces.size(), 2U); + BOOST_CHECK_EQUAL (pieces.front()->content, A); + BOOST_CHECK_EQUAL (pieces.back()->content, B); + BOOST_CHECK (pieces.front()->ignore_video); + BOOST_CHECK (pieces.front()->ignore_video.get() == dcpomatic::DCPTimePeriod(dcpomatic::DCPTime::from_seconds(1), dcpomatic::DCPTime::from_seconds(1) + B->length_after_trim(film))); + + BOOST_CHECK (player->_black.done()); + + film->make_dcp (); + BOOST_REQUIRE (!wait_for_jobs()); + + dcp::DCP back (film->dir(film->dcp_name())); + back.read (); + BOOST_REQUIRE_EQUAL (back.cpls().size(), 1U); + auto cpl = back.cpls()[0]; + BOOST_REQUIRE_EQUAL (cpl->reels().size(), 1U); + auto reel = cpl->reels()[0]; + BOOST_REQUIRE (reel->main_picture()); + auto mono_picture = dynamic_pointer_cast(reel->main_picture()); + BOOST_REQUIRE (mono_picture); + auto asset = mono_picture->mono_asset(); + BOOST_REQUIRE (asset); + BOOST_CHECK_EQUAL (asset->intrinsic_duration(), 72); + auto reader = asset->start_read (); + + for (int i = 0; i < 24; ++i) { + auto frame = reader->get_frame (i); + auto image = dcp::decompress_j2k(*frame.get(), 0); + BOOST_CHECK_EQUAL (image->data(0)[0], 2808); + BOOST_CHECK_EQUAL (image->data(1)[0], 2176); + BOOST_CHECK_EQUAL (image->data(2)[0], 865); + } + + for (int i = 24; i < 48; ++i) { + auto frame = reader->get_frame (i); + auto image = dcp::decompress_j2k(*frame.get(), 0); + BOOST_CHECK_EQUAL (image->data(0)[0], 2657); + BOOST_CHECK_EQUAL (image->data(1)[0], 3470); + BOOST_CHECK_EQUAL (image->data(2)[0], 1742); + } + + for (int i = 48; i < 72; ++i) { + auto frame = reader->get_frame (i); + auto image = dcp::decompress_j2k(*frame.get(), 0); + BOOST_CHECK_EQUAL (image->data(0)[0], 2808); + BOOST_CHECK_EQUAL (image->data(1)[0], 2176); + BOOST_CHECK_EQUAL (image->data(2)[0], 865); + } +} + diff --git a/test/wscript b/test/wscript index 70aad81a3..cbe2c176c 100644 --- a/test/wscript +++ b/test/wscript @@ -98,6 +98,7 @@ def build(bld): markers_test.cc no_use_video_test.cc optimise_stills_test.cc + overlap_video_test.cc pixel_formats_test.cc player_test.cc pulldown_detect_test.cc -- 2.30.2