Merge branch 'v2.15.x' of ssh://localhost:2222/home/carl/git/dcpomatic into v2.15.x
authorCarl Hetherington <cth@carlh.net>
Mon, 14 Oct 2019 09:24:48 +0000 (11:24 +0200)
committerCarl Hetherington <cth@carlh.net>
Mon, 14 Oct 2019 09:24:48 +0000 (11:24 +0200)
14 files changed:
src/lib/audio_processor.cc
src/lib/audio_processor.h
src/lib/config.cc
src/lib/config.h
src/lib/dcp_decoder.cc
src/lib/dcp_decoder.h
src/lib/film.cc
src/lib/hints.cc
src/lib/player.h
src/wx/dcp_panel.cc
src/wx/dcp_panel.h
src/wx/full_config_dialog.cc
test/dcp_decoder_test.cc [new file with mode: 0644]
test/wscript

index 0d3f2b6d7ecc2b0a0259a8018e2964c1f19ae9fa..6cccbdc80f5842fef0f1cfb4597ac78d00ba0aa0 100644 (file)
 #include "mid_side_decoder.h"
 #include "upmixer_a.h"
 #include "upmixer_b.h"
+#include "config.h"
 
 using std::string;
 using std::list;
 
 list<AudioProcessor const *> AudioProcessor::_all;
+list<AudioProcessor const *> AudioProcessor::_non_experimental;
 
 void
 AudioProcessor::setup_audio_processors ()
 {
-       _all.push_back (new MidSideDecoder ());
+       AudioProcessor* mid_side = new MidSideDecoder ();
+       _all.push_back (mid_side);
+       _non_experimental.push_back (mid_side);
+
        _all.push_back (new UpmixerA (48000));
        _all.push_back (new UpmixerB (48000));
 }
@@ -48,6 +53,16 @@ AudioProcessor::from_id (string id)
        return 0;
 }
 
+list<AudioProcessor const *>
+AudioProcessor::visible ()
+{
+       if (Config::instance()->show_experimental_audio_processors()) {
+               return _all;
+       }
+
+       return _non_experimental;
+}
+
 list<AudioProcessor const *>
 AudioProcessor::all ()
 {
index e10df254cbd18fc7c2a09d73796502f5ebb2fb16..78a3efb58fd6ec0d745b747d7d835628a78e5a25 100644 (file)
@@ -61,11 +61,13 @@ public:
        virtual std::vector<std::string> input_names () const = 0;
 
        static std::list<AudioProcessor const *> all ();
+       static std::list<AudioProcessor const *> visible ();
        static void setup_audio_processors ();
        static AudioProcessor const * from_id (std::string);
 
 private:
        static std::list<AudioProcessor const *> _all;
+       static std::list<AudioProcessor const *> _non_experimental;
 };
 
 #endif
index 1d2ef1e40d25f343c8135cfc88f7eb915f7c9f3e..581620f832846f8a2f8e7418478fb43666dbc5ab 100644 (file)
@@ -94,6 +94,7 @@ Config::set_defaults ()
        _tms_password = "";
        _allow_any_dcp_frame_rate = false;
        _allow_any_container = false;
+       _show_experimental_audio_processors = false;
        _language = optional<string> ();
        _default_still_length = 10;
        _default_container = Ratio::from_id ("185");
@@ -384,6 +385,7 @@ try
        _maximum_j2k_bandwidth = f.optional_number_child<int> ("MaximumJ2KBandwidth").get_value_or (250000000);
        _allow_any_dcp_frame_rate = f.optional_bool_child ("AllowAnyDCPFrameRate").get_value_or (false);
        _allow_any_container = f.optional_bool_child ("AllowAnyContainer").get_value_or (false);
+       _show_experimental_audio_processors = f.optional_bool_child ("ShowExperimentalAudioProcessors").get_value_or (false);
 
        _log_types = f.optional_number_child<int> ("LogTypes").get_value_or (LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING | LogEntry::TYPE_ERROR);
        _analyse_ebur128 = f.optional_bool_child("AnalyseEBUR128").get_value_or (true);
@@ -801,6 +803,8 @@ Config::write_config () const
        root->add_child("AllowAnyDCPFrameRate")->add_child_text (_allow_any_dcp_frame_rate ? "1" : "0");
        /* [XML] AllowAnyContainer 1 to allow users to user any container ratio for their DCP, 0 to limit the GUI to standard containers. */
        root->add_child("AllowAnyContainer")->add_child_text (_allow_any_container ? "1" : "0");
+       /* [XML] ShowExperimentalAudioProcessors 1 to offer users the (experimental) audio upmixer processors, 0 to hide them */
+       root->add_child("ShowExperimentalAudioProcessors")->add_child_text (_show_experimental_audio_processors ? "1" : "0");
        /* [XML] LogTypes Types of logging to write; a bitfield where 1 is general notes, 2 warnings, 4 errors, 8 debug information related
           to encoding, 16 debug information related to encoding, 32 debug information for timing purposes, 64 debug information related
           to sending email.
index 9a57b1b484624b36a73055911944e1ae374a78d1..ff7a0fe396f9af9ac7e91d914d692ab870ff8381 100644 (file)
@@ -82,6 +82,7 @@ public:
                PLAYER_PLAYLIST_DIRECTORY,
                PLAYER_DEBUG_LOG,
                HISTORY,
+               SHOW_EXPERIMENTAL_AUDIO_PROCESSORS,
 #ifdef DCPOMATIC_VARIANT_SWAROOP
                PLAYER_BACKGROUND_IMAGE,
 #endif
@@ -157,6 +158,10 @@ public:
                return _allow_any_container;
        }
 
+       bool show_experimental_audio_processors () const {
+               return _show_experimental_audio_processors;
+       }
+
        ISDCFMetadata default_isdcf_metadata () const {
                return _default_isdcf_metadata;
        }
@@ -620,6 +625,10 @@ public:
                maybe_set (_allow_any_container, a);
        }
 
+       void set_show_experimental_audio_processors (bool e) {
+               maybe_set (_show_experimental_audio_processors, e, SHOW_EXPERIMENTAL_AUDIO_PROCESSORS);
+       }
+
        void set_default_isdcf_metadata (ISDCFMetadata d) {
                maybe_set (_default_isdcf_metadata, d);
        }
@@ -1177,6 +1186,8 @@ private:
            https://www.dcpomatic.com/forum/viewtopic.php?f=2&t=1119&p=4468
        */
        bool _allow_any_container;
+       /** Offer the upmixers in the audio processor settings */
+       bool _show_experimental_audio_processors;
        /** Default ISDCF metadata for newly-created Films */
        ISDCFMetadata _default_isdcf_metadata;
        boost::optional<std::string> _language;
index 95cad926620ad9a4824b40e8ff1914331d3e776e..4b189189e0b61fc395e83658968a1b34cf44947b 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014-2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2019 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -28,6 +28,7 @@
 #include "ffmpeg_image_proxy.h"
 #include "image.h"
 #include "config.h"
+#include "digester.h"
 #include <dcp/dcp.h>
 #include <dcp/cpl.h>
 #include <dcp/reel.h>
@@ -52,6 +53,7 @@
 
 using std::list;
 using std::cout;
+using std::string;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using boost::optional;
@@ -75,16 +77,18 @@ DCPDecoder::DCPDecoder (shared_ptr<const Film> film, shared_ptr<const DCPContent
                }
        }
 
-       if (old) {
-               _reels = old->_reels;
+       /* We try to avoid re-scanning the DCP's files every time we make a new DCPDecoder; we do this
+          by re-using the _reels list.  Before we do this we need to check that nothing too serious
+          has changed in the DCPContent.
 
-               /* We might have gained a KDM since we made the Reel objects */
-               if (_dcp_content->kdm ()) {
-                       dcp::DecryptedKDM k = decrypted_kdm ();
-                       BOOST_FOREACH (shared_ptr<dcp::Reel> i, _reels) {
-                               i->add (k);
-                       }
-               }
+          We do this by storing a digest of the important bits of the DCPContent and then checking that's
+          the same before we re-use _reels.
+       */
+
+       _lazy_digest = calculate_lazy_digest (c);
+
+       if (old && old->lazy_digest() == _lazy_digest) {
+               _reels = old->_reels;
        } else {
 
                list<shared_ptr<dcp::CPL> > cpl_list = cpls ();
@@ -425,3 +429,18 @@ DCPDecoder::set_forced_reduction (optional<int> reduction)
 {
        _forced_reduction = reduction;
 }
+
+string
+DCPDecoder::calculate_lazy_digest (shared_ptr<const DCPContent> c) const
+{
+       Digester d;
+       BOOST_FOREACH (boost::filesystem::path i, c->paths()) {
+               d.add (i.string());
+       }
+       d.add (static_cast<bool>(_dcp_content->kdm()));
+       d.add (static_cast<bool>(c->cpl()));
+       if (c->cpl()) {
+               d.add (c->cpl().get());
+       }
+       return d.get ();
+}
index 2e63b24a296ca488079150378a8942982cada924..496d95740d63cf26e9c74024dd43f506416cbf7b 100644 (file)
@@ -58,6 +58,10 @@ public:
        bool pass ();
        void seek (dcpomatic::ContentTime t, bool accurate);
 
+       std::string lazy_digest () const {
+               return _lazy_digest;
+       }
+
 private:
        friend struct dcp_subtitle_within_dcp_test;
 
@@ -72,6 +76,7 @@ private:
                boost::shared_ptr<TextDecoder> decoder,
                dcp::Size size
                );
+       std::string calculate_lazy_digest (boost::shared_ptr<const DCPContent>) const;
 
        /** Time of next thing to return from pass relative to the start of _reel */
        dcpomatic::ContentTime _next;
@@ -89,4 +94,6 @@ private:
 
        bool _decode_referenced;
        boost::optional<int> _forced_reduction;
+
+       std::string _lazy_digest;
 };
index e85543b807e9f4165fbfbafc53a7ed2bde40e8b9..93459661be39463c8cd257ee3ac3611ea85e33f1 100644 (file)
@@ -93,6 +93,7 @@ using std::copy;
 using std::back_inserter;
 using std::map;
 using std::exception;
+using std::find;
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
@@ -542,6 +543,13 @@ Film::read_metadata (optional<boost::filesystem::path> path)
                _audio_processor = 0;
        }
 
+       if (_audio_processor && !Config::instance()->show_experimental_audio_processors()) {
+               list<AudioProcessor const *> ap = AudioProcessor::visible();
+               if (find(ap.begin(), ap.end(), _audio_processor) == ap.end()) {
+                       Config::instance()->set_show_experimental_audio_processors(true);
+               }
+       }
+
        _reel_type = static_cast<ReelType> (f.optional_number_child<int>("ReelType").get_value_or (static_cast<int>(REELTYPE_SINGLE)));
        _reel_length = f.optional_number_child<int64_t>("ReelLength").get_value_or (2000000000);
        _upload_after_make_dcp = f.optional_bool_child("UploadAfterMakeDCP").get_value_or (false);
index a9b9d6f54b34562b8bd6858edeac8c12ce8e66c5..ad81e8d59eee1e7499e151c091e184c5d1f56331 100644 (file)
@@ -117,7 +117,7 @@ Hints::thread ()
        }
 
        if (film->audio_channels() < 6) {
-               hint (_("Your DCP has fewer than 6 audio channels.  This may cause problems on some projectors."));
+               hint (_("Your DCP has fewer than 6 audio channels.  This may cause problems on some projectors.  You may want to set the DCP to have 6 channels.  It does not matter if your content has fewer channels, as DCP-o-matic will fill the extras with silence."));
        }
 
        AudioProcessor const * ap = film->audio_processor();
index 7558f6da0bd2fd62376ae2e666623239cefd1729..e99c345bb211ea99d683fcb5b3d32513305ad4c9 100644 (file)
@@ -110,6 +110,7 @@ private:
        friend struct player_subframe_test;
        friend struct empty_test1;
        friend struct empty_test2;
+       friend struct check_reuse_old_data_test;
 
        void setup_pieces ();
        void setup_pieces_unlocked ();
index a7f4f45e9f88b6e68055aecfa3c55fbcc9dc443a..c4a14a58b3a118bec1c36c4356aea4a1d1c84632 100644 (file)
@@ -783,6 +783,12 @@ DCPPanel::config_changed (Config::Property p)
                _audio_grid->Clear ();
                add_audio_panel_to_grid ();
                _audio_grid->Layout ();
+       } else if (p == Config::SHOW_EXPERIMENTAL_AUDIO_PROCESSORS) {
+               _audio_processor->Clear ();
+               add_audio_processors ();
+               if (_film) {
+                       film_changed (Film::AUDIO_PROCESSOR);
+               }
        }
 }
 
@@ -931,10 +937,10 @@ wxPanel *
 DCPPanel::make_audio_panel ()
 {
        wxPanel* panel = new wxPanel (_notebook);
-       wxSizer* sizer = new wxBoxSizer (wxVERTICAL);
+       _audio_panel_sizer = new wxBoxSizer (wxVERTICAL);
        _audio_grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
-       sizer->Add (_audio_grid, 0, wxALL, 8);
-       panel->SetSizer (sizer);
+       _audio_panel_sizer->Add (_audio_grid, 0, wxALL, 8);
+       panel->SetSizer (_audio_panel_sizer);
 
        _channels_label = create_label (panel, _("Channels"), true);
        _audio_channels = new wxChoice (panel, wxID_ANY);
@@ -942,10 +948,7 @@ DCPPanel::make_audio_panel ()
 
        _processor_label = create_label (panel, _("Processor"), true);
        _audio_processor = new wxChoice (panel, wxID_ANY);
-       _audio_processor->Append (_("None"), new wxStringClientData (N_("none")));
-       BOOST_FOREACH (AudioProcessor const * ap, AudioProcessor::all ()) {
-               _audio_processor->Append (std_to_wx (ap->name ()), new wxStringClientData (std_to_wx (ap->id ())));
-       }
+       add_audio_processors ();
 
        _show_audio = new Button (panel, _("Show audio..."));
 
@@ -1040,3 +1043,13 @@ DCPPanel::reel_length_changed ()
 
        _film->set_reel_length (_reel_length->GetValue() * 1000000000LL);
 }
+
+void
+DCPPanel::add_audio_processors ()
+{
+       _audio_processor->Append (_("None"), new wxStringClientData (N_("none")));
+       BOOST_FOREACH (AudioProcessor const * ap, AudioProcessor::visible()) {
+               _audio_processor->Append (std_to_wx(ap->name()), new wxStringClientData(std_to_wx(ap->id())));
+       }
+       _audio_panel_sizer->Layout();
+}
index f717e83273c2219285ecfbc8b10441004ceb3bb6..887ae7c77e552c81aad307deb7a963f58fbbca08 100644 (file)
@@ -90,6 +90,7 @@ private:
        void add_to_grid ();
        void add_video_panel_to_grid ();
        void add_audio_panel_to_grid ();
+       void add_audio_processors ();
 
        int minimum_allowed_audio_channels () const;
 
@@ -151,6 +152,7 @@ private:
        wxCheckBox* _upload_after_make_dcp;
        wxButton* _markers;
        wxButton* _metadata;
+       wxSizer* _audio_panel_sizer;
 
        AudioDialog* _audio_dialog;
        MarkersDialog* _markers_dialog;
index ffe7b4749c67c22a9fce59281c8ff8fceb3e7c5c..f6dd783bd9f5baaff64d40107c93cdd0a48b2426 100644 (file)
@@ -1368,6 +1368,7 @@ public:
                , _maximum_j2k_bandwidth (0)
                , _allow_any_dcp_frame_rate (0)
                , _allow_any_container (0)
+               , _show_experimental_audio_processors (0)
                , _only_servers_encode (0)
                , _log_general (0)
                , _log_warning (0)
@@ -1428,6 +1429,10 @@ private:
                restart->SetFont (font);
                table->AddSpacer (0);
 
+               _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
+               table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxALL);
+               table->AddSpacer (0);
+
                _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
                table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
                table->AddSpacer (0);
@@ -1504,6 +1509,7 @@ private:
                _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
                _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
                _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
+               _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
                _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
                _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
                _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
@@ -1535,6 +1541,7 @@ private:
                }
                checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
                checked_set (_allow_any_container, config->allow_any_container ());
+               checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
                checked_set (_only_servers_encode, config->only_servers_encode ());
                checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
                checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
@@ -1578,6 +1585,11 @@ private:
                Config::instance()->set_allow_any_container (_allow_any_container->GetValue ());
        }
 
+       void show_experimental_audio_processors_changed ()
+       {
+               Config::instance()->set_show_experimental_audio_processors (_show_experimental_audio_processors->GetValue ());
+       }
+
        void only_servers_encode_changed ()
        {
                Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
@@ -1632,6 +1644,7 @@ private:
        wxSpinCtrl* _frames_in_memory_multiplier;
        wxCheckBox* _allow_any_dcp_frame_rate;
        wxCheckBox* _allow_any_container;
+       wxCheckBox* _show_experimental_audio_processors;
        wxCheckBox* _only_servers_encode;
        NameFormatEditor* _dcp_metadata_filename_format;
        NameFormatEditor* _dcp_asset_filename_format;
diff --git a/test/dcp_decoder_test.cc b/test/dcp_decoder_test.cc
new file mode 100644 (file)
index 0000000..64d35a2
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+    Copyright (C) 2019 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/>.
+
+*/
+
+/** @file  test/dcp_decoder_test.cc
+ *  @brief Test DCPDecoder class.
+ *  @ingroup selfcontained
+ */
+
+#include "lib/film.h"
+#include "lib/dcp_content.h"
+#include "lib/dcp_decoder.h"
+#include "lib/content_factory.h"
+#include "lib/player.h"
+#include "lib/examine_content_job.h"
+#include "lib/job_manager.h"
+#include "lib/config.h"
+#include "test.h"
+#include <dcp/dcp.h>
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+
+using std::list;
+using std::string;
+using std::vector;
+using boost::shared_ptr;
+
+/* Check that DCPDecoder reuses old data when it should */
+BOOST_AUTO_TEST_CASE (check_reuse_old_data_test)
+{
+       /* Make some DCPs */
+
+       shared_ptr<Film> ov = new_test_film2 ("check_reuse_old_data_ov");
+       ov->examine_and_add_content (content_factory("test/data/flat_red.png").front());
+       BOOST_REQUIRE (!wait_for_jobs());
+       ov->make_dcp ();
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       shared_ptr<Film> vf = new_test_film2 ("check_reuse_old_data_vf");
+       shared_ptr<DCPContent> ov_content(new DCPContent(ov->dir(ov->dcp_name(false))));
+       vf->examine_and_add_content (ov_content);
+       vf->examine_and_add_content (content_factory("test/data/L.wav").front());
+       BOOST_REQUIRE (!wait_for_jobs());
+       ov_content->set_reference_video (true);
+       vf->make_dcp ();
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       shared_ptr<Film> encrypted = new_test_film2 ("check_reuse_old_data_decrypted");
+       encrypted->examine_and_add_content (content_factory("test/data/flat_red.png").front());
+       BOOST_REQUIRE (!wait_for_jobs());
+       encrypted->set_encrypted (true);
+       encrypted->make_dcp ();
+       BOOST_REQUIRE (!wait_for_jobs());
+
+       dcp::DCP encrypted_dcp (encrypted->dir(encrypted->dcp_name()));
+       encrypted_dcp.read ();
+
+       dcp::EncryptedKDM kdm = encrypted->make_kdm (
+               Config::instance()->decryption_chain()->leaf(),
+               vector<string>(),
+               encrypted_dcp.cpls().front()->file().get(),
+               dcp::LocalTime ("2014-07-21T00:00:00+00:00"),
+               dcp::LocalTime ("2024-07-21T00:00:00+00:00"),
+               dcp::MODIFIED_TRANSITIONAL_1,
+               true, 0
+               );
+
+
+       /* Add just the OV to a new project, move it around a bit and check that
+          the _reels get reused.
+       */
+       shared_ptr<Film> test = new_test_film2 ("check_reuse_old_data_test1");
+       ov_content.reset (new DCPContent(ov->dir(ov->dcp_name(false))));
+       test->examine_and_add_content (ov_content);
+       BOOST_REQUIRE (!wait_for_jobs());
+       shared_ptr<Player> player (new Player(test, test->playlist()));
+
+       shared_ptr<DCPDecoder> decoder = boost::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
+       BOOST_REQUIRE (decoder);
+       list<shared_ptr<dcp::Reel> > reels = decoder->reels();
+
+       ov_content->set_position (test, dcpomatic::DCPTime(96000));
+       decoder = boost::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
+       BOOST_REQUIRE (decoder);
+       BOOST_REQUIRE (reels == decoder->reels());
+
+       /* Add the VF to a new project, then add the OV and check that the
+          _reels did not get reused.
+       */
+       test = new_test_film2 ("check_reuse_old_data_test2");
+       shared_ptr<DCPContent> vf_content (new DCPContent(vf->dir(vf->dcp_name(false))));
+       test->examine_and_add_content (vf_content);
+       BOOST_REQUIRE (!wait_for_jobs());
+       player.reset (new Player(test, test->playlist()));
+
+       decoder = boost::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
+       BOOST_REQUIRE (decoder);
+       reels = decoder->reels();
+
+       vf_content->add_ov (ov->dir(ov->dcp_name(false)));
+       JobManager::instance()->add (shared_ptr<Job>(new ExamineContentJob(test, vf_content)));
+       BOOST_REQUIRE (!wait_for_jobs());
+       decoder = boost::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
+       BOOST_REQUIRE (decoder);
+       BOOST_REQUIRE (reels != decoder->reels());
+
+       /* Add a KDM to an encrypted DCP and check that the _reels did not get reused */
+       test = new_test_film2 ("check_reuse_old_data_test3");
+       shared_ptr<DCPContent> encrypted_content (new DCPContent(encrypted->dir(encrypted->dcp_name(false))));
+       test->examine_and_add_content (encrypted_content);
+       BOOST_REQUIRE (!wait_for_jobs());
+       player.reset (new Player(test, test->playlist()));
+
+       decoder = boost::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
+       BOOST_REQUIRE (decoder);
+       reels = decoder->reels();
+
+       encrypted_content->add_kdm (kdm);
+       JobManager::instance()->add (shared_ptr<Job>(new ExamineContentJob(test, encrypted_content)));
+       BOOST_REQUIRE (!wait_for_jobs());
+       decoder = boost::dynamic_pointer_cast<DCPDecoder>(player->_pieces.front()->decoder);
+       BOOST_REQUIRE (decoder);
+       BOOST_REQUIRE (reels != decoder->reels());
+}
index 1d2fafc02627c96a53a331d342c167fbaa4bec1c..3c6170dcf3ef2e4f9c4190b786e562544e68f4d4 100644 (file)
@@ -61,6 +61,7 @@ def build(bld):
                  create_cli_test.cc
                  crypto_test.cc
                  dcpomatic_time_test.cc
+                 dcp_decoder_test.cc
                  dcp_playback_test.cc
                  dcp_subtitle_test.cc
                  digest_test.cc