Basic handling of overlapping video (#1848).
authorCarl Hetherington <cth@carlh.net>
Tue, 29 Sep 2020 12:16:56 +0000 (14:16 +0200)
committerCarl Hetherington <cth@carlh.net>
Mon, 15 Feb 2021 02:16:16 +0000 (03:16 +0100)
cscript
src/lib/piece.h
src/lib/player.cc
src/lib/player.h
test/overlap_video_test.cc [new file with mode: 0644]
test/wscript

diff --git a/cscript b/cscript
index 7b593c8cb211f80be86fd54310b4a25f2902a728..18b9b71ae9c1ee44738f57e6eda1559b56b2c635 100644 (file)
--- a/cscript
+++ b/cscript
@@ -370,8 +370,8 @@ def dependencies(target, options):
         # Use distro-provided FFmpeg on Arch
         deps = []
 
         # 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
     deps.append(('leqm-nrt', '131f971'))
     deps.append(('rtaudio', 'f619b76'))
     # We get our OpenSSL libraries from the environment, but we
index a2e62d366004d51a65eec04f330f61e135c9c09d..688242c064d5b54013217fb6c98a942540445817 100644 (file)
@@ -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.
 
 
     This file is part of DCP-o-matic.
 
 
 */
 
 
 */
 
+
 #ifndef DCPOMATIC_PIECE_H
 #define DCPOMATIC_PIECE_H
 
 #ifndef DCPOMATIC_PIECE_H
 #define DCPOMATIC_PIECE_H
 
-#include "types.h"
+
+#include "dcpomatic_time.h"
 #include "frame_rate_change.h"
 #include "frame_rate_change.h"
+#include "types.h"
+
 
 class Content;
 class Decoder;
 
 
 class Content;
 class Decoder;
 
+
 class Piece
 {
 public:
 class Piece
 {
 public:
@@ -39,8 +44,10 @@ public:
 
        std::shared_ptr<Content> content;
        std::shared_ptr<Decoder> decoder;
 
        std::shared_ptr<Content> content;
        std::shared_ptr<Decoder> decoder;
+       boost::optional<dcpomatic::DCPTimePeriod> ignore_video;
        FrameRateChange frc;
        bool done;
 };
 
        FrameRateChange frc;
        bool done;
 };
 
+
 #endif
 #endif
index 465fcad6d7fc342eb66f78dc318b89a550d062fc..36d3fde67109ca51fe59aa8acdac8445a672b65e 100644 (file)
@@ -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);
 
        _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;
        }
 
                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.
        */
        /* Fill gaps that we discover now that we have some video which needs to be emitted.
           This is where we need to fill to.
        */
index ce49af14848e8d5aa8a7be8121ac67a011b08da0..be8d556afae77be2b5c691e0cbdeefefebd089db 100644 (file)
@@ -76,6 +76,7 @@ public:
 
        Player (Player const& Player) = delete;
        Player& operator= (Player const& Player) = delete;
 
        Player (Player const& Player) = delete;
        Player& operator= (Player const& Player) = delete;
+
        bool pass ();
        void seek (dcpomatic::DCPTime time, bool accurate);
 
        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 empty_test1;
        friend struct empty_test2;
        friend struct check_reuse_old_data_test;
+       friend struct overlap_video_test1;
 
        void construct ();
        void setup_pieces ();
 
        void construct ();
        void setup_pieces ();
diff --git a/test/overlap_video_test.cc b/test/overlap_video_test.cc
new file mode 100644 (file)
index 0000000..246a758
--- /dev/null
@@ -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);
+       }
+}
+
index 70aad81a33de3d3c972a6321b3a86fe4c890239f..cbe2c176c09d9e1413e6bbb8149361ad8f931f09 100644 (file)
@@ -98,6 +98,7 @@ def build(bld):
                  markers_test.cc
                  no_use_video_test.cc
                  optimise_stills_test.cc
                  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
                  pixel_formats_test.cc
                  player_test.cc
                  pulldown_detect_test.cc