summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2019-08-30 23:16:21 +0100
committerCarl Hetherington <cth@carlh.net>2019-08-30 23:16:21 +0100
commit1f88a38a2a607c21988a403e76f315444c4be36b (patch)
tree2b14f959784faf33eec61172552d9c50b72a0f65 /src
parent77d2514fee2919c32e4db92b8f75369754d17fb5 (diff)
Make player more tolerant of some DCP errors.
Diffstat (limited to 'src')
-rw-r--r--src/lib/dcp.cc2
-rw-r--r--src/lib/dcp.h7
-rw-r--r--src/lib/dcp_content.cc8
-rw-r--r--src/lib/dcp_decoder.cc4
-rw-r--r--src/lib/dcp_decoder.h3
-rw-r--r--src/lib/dcp_examiner.cc4
-rw-r--r--src/lib/dcp_examiner.h2
-rw-r--r--src/lib/decoder_factory.cc9
-rw-r--r--src/lib/decoder_factory.h1
-rw-r--r--src/lib/film.cc1
-rw-r--r--src/lib/film.h13
-rw-r--r--src/lib/player.cc12
-rw-r--r--src/lib/player.h4
-rw-r--r--src/tools/dcpomatic_player.cc7
-rw-r--r--src/wx/content_menu.cc4
-rw-r--r--src/wx/text_panel.cc2
16 files changed, 58 insertions, 25 deletions
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::DCP> 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<dcp::CPL> 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 <dcp/cpl.h>
#include <boost/shared_ptr.hpp>
#include <list>
+#include <iostream>
class DCPContent;
@@ -33,11 +34,15 @@ public:
std::list<boost::shared_ptr<dcp::CPL> > cpls () const;
protected:
- explicit DCP (boost::shared_ptr<const DCPContent> content)
+ explicit DCP (boost::shared_ptr<const DCPContent> content, bool tolerant)
: _dcp_content (content)
+ , _tolerant (tolerant)
{}
boost::shared_ptr<const DCPContent> _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<const Film> film, shared_ptr<Job> job)
}
Content::examine (film, job);
- shared_ptr<DCPExaminer> examiner (new DCPExaminer (shared_from_this ()));
+ shared_ptr<DCPExaminer> examiner (new DCPExaminer(shared_from_this(), film->tolerant()));
if (examiner->has_video()) {
{
@@ -478,7 +478,7 @@ DCPContent::reels (shared_ptr<const Film> film) const
if (reel_lengths.empty ()) {
/* Old metadata with no reel lengths; get them here instead */
try {
- scoped_ptr<DCPExaminer> examiner (new DCPExaminer (shared_from_this()));
+ scoped_ptr<DCPExaminer> 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<const Film> film, string& why_not) c
{
shared_ptr<DCPDecoder> decoder;
try {
- decoder.reset (new DCPDecoder (film, shared_from_this(), false));
+ decoder.reset (new DCPDecoder (film, shared_from_this(), false, film->tolerant(), shared_ptr<DCPDecoder>()));
} 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<const Film> film, TextType type, stri
{
shared_ptr<DCPDecoder> decoder;
try {
- decoder.reset (new DCPDecoder (film, shared_from_this(), false));
+ decoder.reset (new DCPDecoder (film, shared_from_this(), false, film->tolerant(), shared_ptr<DCPDecoder>()));
} 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<const Film> film, shared_ptr<const DCPContent> c, bool fast, shared_ptr<DCPDecoder> old)
- : DCP (c)
+DCPDecoder::DCPDecoder (shared_ptr<const Film> film, shared_ptr<const DCPContent> c, bool fast, bool tolerant, shared_ptr<DCPDecoder> 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<const Film> film,
boost::shared_ptr<const DCPContent>,
bool fast,
- boost::shared_ptr<DCPDecoder> old = boost::shared_ptr<DCPDecoder>()
+ bool tolerant,
+ boost::shared_ptr<DCPDecoder> old
);
std::list<boost::shared_ptr<dcp::Reel> > 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<const DCPContent> content)
- : DCP (content)
+DCPExaminer::DCPExaminer (shared_ptr<const DCPContent> 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<const DCPContent>);
+ explicit DCPExaminer (boost::shared_ptr<const DCPContent>, 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<Decoder> d)
return dynamic_pointer_cast<T> (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>
-decoder_factory (shared_ptr<const Film> film, shared_ptr<const Content> content, bool fast, shared_ptr<Decoder> old_decoder)
+decoder_factory (shared_ptr<const Film> film, shared_ptr<const Content> content, bool fast, bool tolerant, shared_ptr<Decoder> old_decoder)
{
shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (content);
if (fc) {
@@ -59,7 +62,7 @@ decoder_factory (shared_ptr<const Film> film, shared_ptr<const Content> content,
shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (content);
if (dc) {
try {
- return shared_ptr<Decoder> (new DCPDecoder(film, dc, fast, maybe_cast<DCPDecoder>(old_decoder)));
+ return shared_ptr<Decoder> (new DCPDecoder(film, dc, fast, tolerant, maybe_cast<DCPDecoder>(old_decoder)));
} catch (KDMError& e) {
/* This will be found and reported to the user when the content is examined */
return shared_ptr<Decoder>();
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> decoder_factory (
boost::shared_ptr<const Film> film,
boost::shared_ptr<const Content> content,
bool fast,
+ bool tolerant,
boost::shared_ptr<Decoder> 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<boost::filesystem::path> 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<Film> _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 <cth@carlh.net>
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -93,6 +93,7 @@ Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> 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<Content> 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 = decoder_factory (_film, i, _fast, old_decoder);
+ cout << " DF " << _tolerant << "\n";
+ shared_ptr<Decoder> 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<DCPDecoder> decoder;
try {
- decoder.reset (new DCPDecoder (_film, j, false));
+ decoder.reset (new DCPDecoder (_film, j, false, false, shared_ptr<DCPDecoder>()));
} 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 <cth@carlh.net>
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
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<DCPContent> dcp = dynamic_pointer_cast<DCPContent>(_film->content().front());
if (dcp) {
- DCPExaminer ex (dcp);
+ DCPExaminer ex (dcp, true);
shared_ptr<dcp::CPL> playing_cpl;
BOOST_FOREACH (shared_ptr<dcp::CPL> i, ex.cpls()) {
if (!dcp->cpl() || i->id() == *dcp->cpl()) {
@@ -394,6 +394,7 @@ public:
void reset_film (shared_ptr<Film> film = shared_ptr<Film>(new Film(optional<boost::filesystem::path>())))
{
_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<DCPContent> first = dynamic_pointer_cast<DCPContent>(_film->content().front());
if (first) {
- DCPExaminer ex (first);
+ DCPExaminer ex (first, true);
int id = ID_view_cpl;
BOOST_FOREACH (shared_ptr<dcp::CPL> i, ex.cpls()) {
wxMenuItem* j = _cpl_menu->AppendRadioItem(
@@ -701,7 +702,7 @@ private:
{
shared_ptr<DCPContent> dcp = boost::dynamic_pointer_cast<DCPContent>(_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> film, ContentList c, TimelineContentViewList
_kdm->Enable (dcp->encrypted ());
_ov->Enable (dcp->needs_assets ());
try {
- DCPExaminer ex (dcp);
+ DCPExaminer ex (dcp, true);
list<shared_ptr<dcp::CPL> > 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<DCPContent> dcp = dynamic_pointer_cast<DCPContent> (_content.front ());
DCPOMATIC_ASSERT (dcp);
- DCPExaminer ex (dcp);
+ DCPExaminer ex (dcp, true);
list<shared_ptr<dcp::CPL> > 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 = decoder_factory (_parent->film(), c.front(), false, shared_ptr<Decoder>());
+ shared_ptr<Decoder> decoder = decoder_factory (_parent->film(), c.front(), false, false, shared_ptr<Decoder>());
if (decoder) {
_text_view = new TextView (this, _parent->film(), c.front(), c.front()->text_of_original_type(_original_type), decoder, _parent->film_viewer());