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()) {
#include <dcp/cpl.h>
#include <boost/shared_ptr.hpp>
#include <list>
+#include <iostream>
class DCPContent;
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
}
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()) {
{
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 */
{
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;
{
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;
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)
{
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 {
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)
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;
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) {
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>();
boost::shared_ptr<const Film> film,
boost::shared_ptr<const Content> content,
bool fast,
+ bool tolerant,
boost::shared_ptr<Decoder> old_decoder
);
, _user_explicit_video_frame_rate (false)
, _state_version (current_state_version)
, _dirty (false)
+ , _tolerant (false)
{
set_isdcf_date_today ();
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.
*/
/** 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;
/*
- 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.
, _ignore_text (false)
, _always_burn_open_subtitles (false)
, _fast (false)
+ , _tolerant (film->tolerant())
, _play_referenced (false)
, _audio_merger (_film->audio_frame_rate())
, _shuffler (0)
_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;
}
}
}
- 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) {
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;
}
/*
- 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.
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;
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()) {
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));
/* 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(
{
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()));
_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 */
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()));
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());
film->examine_and_add_content (content);
BOOST_REQUIRE (!wait_for_jobs ());
- shared_ptr<DCPDecoder> decoder (new DCPDecoder (film, content, false));
+ shared_ptr<DCPDecoder> decoder (new DCPDecoder (film, content, false, false, shared_ptr<DCPDecoder>()));
decoder->only_text()->PlainStart.connect (bind (store, _1));
stored = optional<ContentStringText> ();