summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2020-09-29 14:16:56 +0200
committerCarl Hetherington <cth@carlh.net>2021-02-15 03:16:16 +0100
commit42a6003535d3153224da33b973bb79662d296e02 (patch)
treef17b37e110fbd93355c21515614d9ecad5364fdf
parenta632e34e3c9ca94574fcab1b3006227ed2833766 (diff)
Basic handling of overlapping video (#1848).
-rw-r--r--cscript4
-rw-r--r--src/lib/piece.h11
-rw-r--r--src/lib/player.cc20
-rw-r--r--src/lib/player.h2
-rw-r--r--test/overlap_video_test.cc111
-rw-r--r--test/wscript1
6 files changed, 145 insertions, 4 deletions
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 <cth@carlh.net>
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
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> content;
std::shared_ptr<Decoder> decoder;
+ boost::optional<dcpomatic::DCPTimePeriod> 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<Piece> 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 <cth@carlh.net>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#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 <dcp/cpl.h>
+#include <dcp/dcp.h>
+#include <dcp/j2k_transcode.h>
+#include <dcp/mono_picture_asset.h>
+#include <dcp/mono_picture_frame.h>
+#include <dcp/openjpeg_image.h>
+#include <dcp/reel.h>
+#include <dcp/reel_mono_picture_asset.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/test/unit_test.hpp>
+
+
+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<Player>(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<dcp::ReelMonoPictureAsset>(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