X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Ffilm.cc;h=0be1ddd7b71a19161c44f6957f63c5a3aae23213;hp=8637085af9a7090251f5684d4c3a1572a1c2f335;hb=d7ac100c0eb1b5efdcfbec59be870fd869252840;hpb=bb6b53bdb63754fe0cea1368f69f39a3c3cbbdfd diff --git a/src/lib/film.cc b/src/lib/film.cc index 8637085af..0be1ddd7b 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington + Copyright (C) 2012-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -27,7 +27,7 @@ #include "job.h" #include "util.h" #include "job_manager.h" -#include "dcp_transcoder.h" +#include "dcp_encoder.h" #include "transcode_job.h" #include "upload_job.h" #include "null_log.h" @@ -46,7 +46,7 @@ #include "screen.h" #include "audio_content.h" #include "video_content.h" -#include "subtitle_content.h" +#include "text_content.h" #include "ffmpeg_content.h" #include "dcp_content.h" #include "screen_kdm.h" @@ -151,7 +151,7 @@ Film::Film (optional dir) , _audio_processor (0) , _reel_type (REELTYPE_SINGLE) , _reel_length (2000000000) - , _upload_after_make_dcp (false) + , _upload_after_make_dcp (Config::instance()->default_upload_after_make_dcp()) , _state_version (current_state_version) , _dirty (false) { @@ -293,7 +293,7 @@ void Film::make_dcp () { if (dcp_name().find ("/") != string::npos) { - throw BadSettingError (_("name"), _("cannot contain slashes")); + throw BadSettingError (_("name"), _("Cannot contain slashes")); } if (container() == 0) { @@ -301,7 +301,7 @@ Film::make_dcp () } if (content().empty()) { - throw runtime_error (_("you must add some content to the DCP before creating it")); + throw runtime_error (_("You must add some content to the DCP before creating it")); } if (dcp_content_type() == 0) { @@ -309,7 +309,7 @@ Film::make_dcp () } if (name().empty()) { - throw MissingSettingError (_("name")); + set_name ("DCP"); } BOOST_FOREACH (shared_ptr i, content ()) { @@ -318,10 +318,10 @@ Film::make_dcp () } shared_ptr dcp = dynamic_pointer_cast (i); if (dcp && dcp->needs_kdm()) { - throw runtime_error (_("some of your content needs a KDM")); + throw runtime_error (_("Some of your content needs a KDM")); } if (dcp && dcp->needs_assets()) { - throw runtime_error (_("some of your content needs an OV")); + throw runtime_error (_("Some of your content needs an OV")); } } @@ -343,7 +343,7 @@ Film::make_dcp () LOG_GENERAL ("J2K bandwidth %1", j2k_bandwidth()); shared_ptr tj (new TranscodeJob (shared_from_this())); - tj->set_transcoder (shared_ptr (new DCPTranscoder (shared_from_this(), tj))); + tj->set_encoder (shared_ptr (new DCPEncoder (shared_from_this(), tj))); JobManager::instance()->add (tj); } @@ -514,7 +514,7 @@ Film::read_metadata (optional path) } /** Given a directory name, return its full path within the Film's directory. - * @param d directory name within the Filn's directory. + * @param d directory name within the Film's directory. * @param create true to create the directory (and its parents) if they do not exist. */ boost::filesystem::path @@ -669,7 +669,7 @@ Film::isdcf_name (bool if_created_now) const /* XXX: this uses the first bit of content only */ - /* The standard says we don't do this for trailers, for some strange reason */ + /* Interior aspect ratio. The standard says we don't do this for trailers, for some strange reason */ if (dcp_content_type() && dcp_content_type()->libdcp_kind() != dcp::TRAILER) { Ratio const * content_ratio = 0; BOOST_FOREACH (shared_ptr i, content ()) { @@ -685,7 +685,8 @@ Film::isdcf_name (bool if_created_now) const } if (content_ratio && content_ratio != container()) { - d += "-" + content_ratio->isdcf_name(); + /* This needs to be the numeric version of the ratio, and ::id() is close enough */ + d += "-" + content_ratio->id(); } } @@ -729,7 +730,9 @@ Film::isdcf_name (bool if_created_now) const /* Count mapped audio channels */ pair ch = audio_channel_types (mapped_audio_channels(), audio_channels()); - if (ch.first) { + if (!ch.first && !ch.second) { + d += "_MOS"; + } else if (ch.first) { d += String::compose("_%1%2", ch.first, ch.second); } @@ -1027,24 +1030,27 @@ Film::content () const return _playlist->content (); } +/** @param content Content to add. + * @param disable_audio_analysis true to never do automatic audio analysis, even if it is enabled in configuration. + */ void -Film::examine_and_add_content (shared_ptr c) +Film::examine_and_add_content (shared_ptr content, bool disable_audio_analysis) { - if (dynamic_pointer_cast (c) && _directory) { - run_ffprobe (c->path(0), file ("ffprobe.log"), _log); + if (dynamic_pointer_cast (content) && _directory) { + run_ffprobe (content->path(0), file ("ffprobe.log"), _log); } - shared_ptr j (new ExamineContentJob (shared_from_this(), c)); + shared_ptr j (new ExamineContentJob (shared_from_this(), content)); _job_connections.push_back ( - j->Finished.connect (bind (&Film::maybe_add_content, this, weak_ptr (j), weak_ptr (c))) + j->Finished.connect (bind (&Film::maybe_add_content, this, weak_ptr(j), weak_ptr(content), disable_audio_analysis)) ); JobManager::instance()->add (j); } void -Film::maybe_add_content (weak_ptr j, weak_ptr c) +Film::maybe_add_content (weak_ptr j, weak_ptr c, bool disable_audio_analysis) { shared_ptr job = j.lock (); if (!job || !job->finished_ok ()) { @@ -1058,12 +1064,12 @@ Film::maybe_add_content (weak_ptr j, weak_ptr c) add_content (content); - if (Config::instance()->automatic_audio_analysis() && content->audio) { + if (Config::instance()->automatic_audio_analysis() && content->audio && !disable_audio_analysis) { shared_ptr playlist (new Playlist); playlist->add (content); boost::signals2::connection c; JobManager::instance()->analyse_audio ( - shared_from_this (), playlist, c, bind (&Film::audio_analysis_finished, this) + shared_from_this(), playlist, false, c, bind (&Film::audio_analysis_finished, this) ); _audio_analysis_connections.push_back (c); } @@ -1082,9 +1088,7 @@ Film::add_content (shared_ptr c) if (_template_film) { /* Take settings from the first piece of content of c's type in _template */ BOOST_FOREACH (shared_ptr i, _template_film->content()) { - if (typeid(i.get()) == typeid(c.get())) { - c->use_template (i); - } + c->take_settings_from (i); } } @@ -1113,7 +1117,7 @@ Film::move_content_later (shared_ptr c) DCPTime Film::length () const { - return _playlist->length (); + return _playlist->length().ceil(video_frame_rate()); } int @@ -1170,6 +1174,10 @@ Film::audio_frame_rate () const void Film::set_sequence (bool s) { + if (s == _sequence) { + return; + } + _sequence = s; _playlist->set_sequence (s); signal_changed (SEQUENCE); @@ -1203,6 +1211,9 @@ Film::frame_size () const * @param from KDM from time expressed as a local time with an offset from UTC. * @param until KDM to time expressed as a local time with an offset from UTC. * @param formulation KDM formulation to use. + * @param disable_forensic_marking_picture true to disable forensic marking of picture. + * @param disable_forensic_marking_audio if not set, don't disable forensic marking of audio. If set to 0, + * disable all forensic marking; if set above 0, disable forensic marking above that channel. */ dcp::EncryptedKDM Film::make_kdm ( @@ -1211,9 +1222,15 @@ Film::make_kdm ( boost::filesystem::path cpl_file, dcp::LocalTime from, dcp::LocalTime until, - dcp::Formulation formulation + dcp::Formulation formulation, + bool disable_forensic_marking_picture, + optional disable_forensic_marking_audio ) const { + if (!_encrypted) { + throw runtime_error (_("Cannot make a KDM as this project is not encrypted.")); + } + shared_ptr cpl (new dcp::CPL (cpl_file)); shared_ptr signer = Config::instance()->signer_chain (); if (!signer->valid ()) { @@ -1258,7 +1275,7 @@ Film::make_kdm ( return dcp::DecryptedKDM ( cpl->id(), keys, from, until, cpl->content_title_text(), cpl->content_title_text(), dcp::LocalTime().as_string() - ).encrypt (signer, recipient, trusted_devices, formulation); + ).encrypt (signer, recipient, trusted_devices, formulation, disable_forensic_marking_picture, disable_forensic_marking_audio); } /** @param screens Screens to make KDMs for. @@ -1266,6 +1283,9 @@ Film::make_kdm ( * @param from KDM from time expressed as a local time in the time zone of the Screen's Cinema. * @param until KDM to time expressed as a local time in the time zone of the Screen's Cinema. * @param formulation KDM formulation to use. + * @param disable_forensic_marking_picture true to disable forensic marking of picture. + * @param disable_forensic_marking_audio if not set, don't disable forensic marking of audio. If set to 0, + * disable all forensic marking; if set above 0, disable forensic marking above that channel. */ list Film::make_kdms ( @@ -1273,7 +1293,9 @@ Film::make_kdms ( boost::filesystem::path cpl_file, boost::posix_time::ptime from, boost::posix_time::ptime until, - dcp::Formulation formulation + dcp::Formulation formulation, + bool disable_forensic_marking_picture, + optional disable_forensic_marking_audio ) const { list kdms; @@ -1286,7 +1308,9 @@ Film::make_kdms ( cpl_file, dcp::LocalTime (from, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()), dcp::LocalTime (until, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()), - formulation + formulation, + disable_forensic_marking_picture, + disable_forensic_marking_audio ); kdms.push_back (ScreenKDM (i, kdm)); @@ -1456,7 +1480,7 @@ list Film::reels () const { list p; - DCPTime const len = length().ceil (video_frame_rate ()); + DCPTime const len = length(); switch (reel_type ()) { case REELTYPE_SINGLE: @@ -1516,42 +1540,6 @@ Film::content_summary (DCPTimePeriod period) const return _playlist->content_summary (period); } -list -Film::fix_conflicting_settings () -{ - list notes; - - list was_referencing; - BOOST_FOREACH (shared_ptr i, content()) { - shared_ptr d = dynamic_pointer_cast (i); - if (d) { - list reasons; - bool was = false; - if (!d->can_reference_video(reasons) && d->reference_video()) { - d->set_reference_video (false); - was = true; - } - if (!d->can_reference_audio(reasons) && d->reference_audio()) { - d->set_reference_audio (false); - was = true; - } - if (!d->can_reference_subtitle(reasons) && d->reference_subtitle()) { - d->set_reference_subtitle (false); - was = true; - } - if (was) { - was_referencing.push_back (d->path(0).parent_path().filename()); - } - } - } - - BOOST_FOREACH (boost::filesystem::path d, was_referencing) { - notes.push_back (String::compose (_("The DCP %1 was being referred to by this film. This not now possible because the reel sizes in the film no longer agree with those in the imported DCP.\n\nSetting the 'Reel type' to 'split by video content' will probably help.\n\nAfter doing that you would need to re-tick the appropriate 'refer to existing DCP' checkboxes."), d.string())); - } - - return notes; -} - void Film::use_template (string name) { @@ -1573,6 +1561,7 @@ Film::use_template (string name) _reel_type = _template_film->_reel_type; _reel_length = _template_film->_reel_length; _upload_after_make_dcp = _template_film->_upload_after_make_dcp; + _isdcf_metadata = _template_film->_isdcf_metadata; } pair @@ -1586,3 +1575,29 @@ Film::copy_from (shared_ptr film) { read_metadata (film->file (metadata_file)); } + +bool +Film::references_dcp_video () const +{ + BOOST_FOREACH (shared_ptr i, _playlist->content()) { + shared_ptr d = dynamic_pointer_cast(i); + if (d && d->reference_video()) { + return true; + } + } + + return false; +} + +bool +Film::references_dcp_audio () const +{ + BOOST_FOREACH (shared_ptr i, _playlist->content()) { + shared_ptr d = dynamic_pointer_cast(i); + if (d && d->reference_audio()) { + return true; + } + } + + return false; +}