From: Carl Hetherington Date: Fri, 30 Aug 2019 22:16:21 +0000 (+0100) Subject: Make player more tolerant of some DCP errors. X-Git-Tag: v2.15.16~1 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=1f88a38a2a607c21988a403e76f315444c4be36b Make player more tolerant of some DCP errors. --- diff --git a/src/lib/dcp.cc b/src/lib/dcp.cc index f506d5c70..0b80a3737 100644 --- a/src/lib/dcp.cc +++ b/src/lib/dcp.cc @@ -46,7 +46,7 @@ DCP::cpls () const LOG_GENERAL ("Reading %1 DCP directories", _dcp_content->directories().size()); BOOST_FOREACH (boost::filesystem::path i, _dcp_content->directories()) { shared_ptr dcp (new dcp::DCP (i)); - dcp->read (false, 0, true); + dcp->read (_tolerant, 0, true); dcps.push_back (dcp); LOG_GENERAL ("Reading DCP %1: %2 CPLs", i.string(), dcp->cpls().size()); BOOST_FOREACH (shared_ptr i, dcp->cpls()) { diff --git a/src/lib/dcp.h b/src/lib/dcp.h index 575bcc803..d449fdb39 100644 --- a/src/lib/dcp.h +++ b/src/lib/dcp.h @@ -24,6 +24,7 @@ #include #include #include +#include class DCPContent; @@ -33,11 +34,15 @@ public: std::list > cpls () const; protected: - explicit DCP (boost::shared_ptr content) + explicit DCP (boost::shared_ptr content, bool tolerant) : _dcp_content (content) + , _tolerant (tolerant) {} boost::shared_ptr _dcp_content; + +private: + bool _tolerant; }; #endif diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc index dc1a463c5..95f293b4d 100644 --- a/src/lib/dcp_content.cc +++ b/src/lib/dcp_content.cc @@ -198,7 +198,7 @@ DCPContent::examine (shared_ptr film, shared_ptr job) } Content::examine (film, job); - shared_ptr examiner (new DCPExaminer (shared_from_this ())); + shared_ptr examiner (new DCPExaminer(shared_from_this(), film->tolerant())); if (examiner->has_video()) { { @@ -478,7 +478,7 @@ DCPContent::reels (shared_ptr film) const if (reel_lengths.empty ()) { /* Old metadata with no reel lengths; get them here instead */ try { - scoped_ptr examiner (new DCPExaminer (shared_from_this())); + scoped_ptr examiner (new DCPExaminer(shared_from_this(), film->tolerant())); reel_lengths = examiner->reel_lengths (); } catch (...) { /* Could not examine the DCP; guess reels */ @@ -625,7 +625,7 @@ DCPContent::can_reference_audio (shared_ptr film, string& why_not) c { shared_ptr decoder; try { - decoder.reset (new DCPDecoder (film, shared_from_this(), false)); + decoder.reset (new DCPDecoder (film, shared_from_this(), false, film->tolerant(), shared_ptr())); } catch (dcp::DCPReadError &) { /* We couldn't read the DCP, so it's probably missing */ return false; @@ -660,7 +660,7 @@ DCPContent::can_reference_text (shared_ptr film, TextType type, stri { shared_ptr decoder; try { - decoder.reset (new DCPDecoder (film, shared_from_this(), false)); + decoder.reset (new DCPDecoder (film, shared_from_this(), false, film->tolerant(), shared_ptr())); } catch (dcp::DCPReadError &) { /* We couldn't read the DCP, so it's probably missing */ return false; diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc index b6947211c..90b730f5b 100644 --- a/src/lib/dcp_decoder.cc +++ b/src/lib/dcp_decoder.cc @@ -56,8 +56,8 @@ using boost::dynamic_pointer_cast; using boost::optional; using namespace dcpomatic; -DCPDecoder::DCPDecoder (shared_ptr film, shared_ptr c, bool fast, shared_ptr old) - : DCP (c) +DCPDecoder::DCPDecoder (shared_ptr film, shared_ptr c, bool fast, bool tolerant, shared_ptr old) + : DCP (c, tolerant) , Decoder (film) , _decode_referenced (false) { diff --git a/src/lib/dcp_decoder.h b/src/lib/dcp_decoder.h index f31d28053..2e63b24a2 100644 --- a/src/lib/dcp_decoder.h +++ b/src/lib/dcp_decoder.h @@ -44,7 +44,8 @@ public: boost::shared_ptr film, boost::shared_ptr, bool fast, - boost::shared_ptr old = boost::shared_ptr() + bool tolerant, + boost::shared_ptr old ); std::list > reels () const { diff --git a/src/lib/dcp_examiner.cc b/src/lib/dcp_examiner.cc index f44db84e1..8866ba721 100644 --- a/src/lib/dcp_examiner.cc +++ b/src/lib/dcp_examiner.cc @@ -52,8 +52,8 @@ using std::runtime_error; using boost::shared_ptr; using boost::dynamic_pointer_cast; -DCPExaminer::DCPExaminer (shared_ptr content) - : DCP (content) +DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) + : DCP (content, tolerant) , _video_length (0) , _audio_length (0) , _has_video (false) diff --git a/src/lib/dcp_examiner.h b/src/lib/dcp_examiner.h index da9092411..e52234e36 100644 --- a/src/lib/dcp_examiner.h +++ b/src/lib/dcp_examiner.h @@ -31,7 +31,7 @@ class DCPContent; class DCPExaminer : public DCP, public VideoExaminer, public AudioExaminer { public: - explicit DCPExaminer (boost::shared_ptr); + explicit DCPExaminer (boost::shared_ptr, bool tolerant); bool has_video () const { return _has_video; diff --git a/src/lib/decoder_factory.cc b/src/lib/decoder_factory.cc index 5d758956d..2ded95fef 100644 --- a/src/lib/decoder_factory.cc +++ b/src/lib/decoder_factory.cc @@ -47,9 +47,12 @@ maybe_cast (shared_ptr d) return dynamic_pointer_cast (d); } -/** @param old_decoder A `used' decoder that has been previously made for this piece of content, or 0 */ +/** + @param tolerant true to proceed in the face of `survivable' errors, otherwise false. + @param old_decoder A `used' decoder that has been previously made for this piece of content, or 0 +*/ shared_ptr -decoder_factory (shared_ptr film, shared_ptr content, bool fast, shared_ptr old_decoder) +decoder_factory (shared_ptr film, shared_ptr content, bool fast, bool tolerant, shared_ptr old_decoder) { shared_ptr fc = dynamic_pointer_cast (content); if (fc) { @@ -59,7 +62,7 @@ decoder_factory (shared_ptr film, shared_ptr content, shared_ptr dc = dynamic_pointer_cast (content); if (dc) { try { - return shared_ptr (new DCPDecoder(film, dc, fast, maybe_cast(old_decoder))); + return shared_ptr (new DCPDecoder(film, dc, fast, tolerant, maybe_cast(old_decoder))); } catch (KDMError& e) { /* This will be found and reported to the user when the content is examined */ return shared_ptr(); diff --git a/src/lib/decoder_factory.h b/src/lib/decoder_factory.h index cb145c8a9..0cd90a585 100644 --- a/src/lib/decoder_factory.h +++ b/src/lib/decoder_factory.h @@ -24,5 +24,6 @@ extern boost::shared_ptr decoder_factory ( boost::shared_ptr film, boost::shared_ptr content, bool fast, + bool tolerant, boost::shared_ptr old_decoder ); diff --git a/src/lib/film.cc b/src/lib/film.cc index 4eed5e3f0..dcaa73754 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -161,6 +161,7 @@ Film::Film (optional dir) , _user_explicit_video_frame_rate (false) , _state_version (current_state_version) , _dirty (false) + , _tolerant (false) { set_isdcf_date_today (); diff --git a/src/lib/film.h b/src/lib/film.h index a28d81b6f..6f1294b29 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -174,6 +174,14 @@ public: bool references_dcp_video () const; bool references_dcp_audio () const; + void set_tolerant (bool t) { + _tolerant = t; + } + + bool tolerant () const { + return _tolerant; + } + /** Identifiers for the parts of our state; used for signalling changes. */ @@ -432,6 +440,11 @@ private: /** film being used as a template, or 0 */ boost::shared_ptr _template_film; + /** Be tolerant of errors in content (currently applies to DCP only). + Not saved as state. + */ + bool _tolerant; + boost::signals2::scoped_connection _playlist_change_connection; boost::signals2::scoped_connection _playlist_order_changed_connection; boost::signals2::scoped_connection _playlist_content_change_connection; diff --git a/src/lib/player.cc b/src/lib/player.cc index bdfa51528..1a88505af 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2018 Carl Hetherington + Copyright (C) 2013-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -93,6 +93,7 @@ Player::Player (shared_ptr film, shared_ptr playlist , _ignore_text (false) , _always_burn_open_subtitles (false) , _fast (false) + , _tolerant (film->tolerant()) , _play_referenced (false) , _audio_merger (_film->audio_frame_rate()) , _shuffler (0) @@ -145,13 +146,17 @@ Player::setup_pieces_unlocked () _shuffler = new Shuffler(); _shuffler->Video.connect(bind(&Player::video, this, _1, _2)); + cout << "SPU " << _playlist->content().size() << ".\n"; + BOOST_FOREACH (shared_ptr i, _playlist->content ()) { if (!i->paths_valid ()) { + cout << "not valid.\n"; continue; } if (_ignore_video && _ignore_audio && i->text.empty()) { + cout << "text only.\n"; /* We're only interested in text and this content has none */ continue; } @@ -164,7 +169,8 @@ Player::setup_pieces_unlocked () } } - shared_ptr decoder = decoder_factory (_film, i, _fast, old_decoder); + cout << " DF " << _tolerant << "\n"; + shared_ptr decoder = decoder_factory (_film, i, _fast, _tolerant, old_decoder); FrameRateChange frc (_film, i); if (!decoder) { @@ -503,7 +509,7 @@ Player::get_reel_assets () scoped_ptr decoder; try { - decoder.reset (new DCPDecoder (_film, j, false)); + decoder.reset (new DCPDecoder (_film, j, false, false, shared_ptr())); } catch (...) { return a; } diff --git a/src/lib/player.h b/src/lib/player.h index 9f3dc7e71..7558f6da0 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2018 Carl Hetherington + Copyright (C) 2013-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -164,6 +164,8 @@ private: bool _always_burn_open_subtitles; /** true if we should try to be fast rather than high quality */ bool _fast; + /** true if we should keep going in the face of `survivable' errors */ + bool _tolerant; /** true if we should `play' (i.e output) referenced DCP data (e.g. for preview) */ bool _play_referenced; diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc index cdacee784..864818845 100644 --- a/src/tools/dcpomatic_player.cc +++ b/src/tools/dcpomatic_player.cc @@ -312,7 +312,7 @@ public: shared_ptr dcp = dynamic_pointer_cast(_film->content().front()); if (dcp) { - DCPExaminer ex (dcp); + DCPExaminer ex (dcp, true); shared_ptr playing_cpl; BOOST_FOREACH (shared_ptr i, ex.cpls()) { if (!dcp->cpl() || i->id() == *dcp->cpl()) { @@ -394,6 +394,7 @@ public: void reset_film (shared_ptr film = shared_ptr(new Film(optional()))) { _film = film; + _film->set_tolerant (true); _viewer->set_film (_film); _controls->set_film (_film); _film->Change.connect (bind(&DOMFrame::film_changed, this, _1, _2)); @@ -448,7 +449,7 @@ public: /* Offer a CPL menu */ shared_ptr first = dynamic_pointer_cast(_film->content().front()); if (first) { - DCPExaminer ex (first); + DCPExaminer ex (first, true); int id = ID_view_cpl; BOOST_FOREACH (shared_ptr i, ex.cpls()) { wxMenuItem* j = _cpl_menu->AppendRadioItem( @@ -701,7 +702,7 @@ private: { shared_ptr dcp = boost::dynamic_pointer_cast(_film->content().front()); DCPOMATIC_ASSERT (dcp); - DCPExaminer ex (dcp); + DCPExaminer ex (dcp, true); int id = ev.GetId() - ID_view_cpl; DCPOMATIC_ASSERT (id >= 0); DCPOMATIC_ASSERT (id < int(ex.cpls().size())); diff --git a/src/wx/content_menu.cc b/src/wx/content_menu.cc index e5cadd794..c5dc1606d 100644 --- a/src/wx/content_menu.cc +++ b/src/wx/content_menu.cc @@ -126,7 +126,7 @@ ContentMenu::popup (weak_ptr film, ContentList c, TimelineContentViewList _kdm->Enable (dcp->encrypted ()); _ov->Enable (dcp->needs_assets ()); try { - DCPExaminer ex (dcp); + DCPExaminer ex (dcp, true); list > cpls = ex.cpls (); _choose_cpl->Enable (cpls.size() > 1); /* We can't have 0 as a menu item ID on OS X */ @@ -433,7 +433,7 @@ ContentMenu::cpl_selected (wxCommandEvent& ev) shared_ptr dcp = dynamic_pointer_cast (_content.front ()); DCPOMATIC_ASSERT (dcp); - DCPExaminer ex (dcp); + DCPExaminer ex (dcp, true); list > cpls = ex.cpls (); DCPOMATIC_ASSERT (ev.GetId() > 0); DCPOMATIC_ASSERT (ev.GetId() <= int (cpls.size())); diff --git a/src/wx/text_panel.cc b/src/wx/text_panel.cc index 98398aaa6..27465ad68 100644 --- a/src/wx/text_panel.cc +++ b/src/wx/text_panel.cc @@ -667,7 +667,7 @@ TextPanel::text_view_clicked () ContentList c = _parent->selected_text (); DCPOMATIC_ASSERT (c.size() == 1); - shared_ptr decoder = decoder_factory (_parent->film(), c.front(), false, shared_ptr()); + shared_ptr decoder = decoder_factory (_parent->film(), c.front(), false, false, shared_ptr()); if (decoder) { _text_view = new TextView (this, _parent->film(), c.front(), c.front()->text_of_original_type(_original_type), decoder, _parent->film_viewer()); diff --git a/test/dcp_subtitle_test.cc b/test/dcp_subtitle_test.cc index 150cd8539..4b3d8fc97 100644 --- a/test/dcp_subtitle_test.cc +++ b/test/dcp_subtitle_test.cc @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE (dcp_subtitle_within_dcp_test) film->examine_and_add_content (content); BOOST_REQUIRE (!wait_for_jobs ()); - shared_ptr decoder (new DCPDecoder (film, content, false)); + shared_ptr decoder (new DCPDecoder (film, content, false, false, shared_ptr())); decoder->only_text()->PlainStart.connect (bind (store, _1)); stored = optional ();