X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Ffilm.cc;h=9943711f55cfdc45b3f8a6536a83ffe32447addb;hp=1a9e552fe394f73f14480ad0e18eb8e757866775;hb=e519feaca11005d330e7b8403b948d4ad9cc3ae8;hpb=06454239bd5ed595fe3d5a26c667a6fe15e0d21f diff --git a/src/lib/film.cc b/src/lib/film.cc index 1a9e552fe..9943711f5 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -102,6 +102,9 @@ using boost::weak_ptr; using boost::dynamic_pointer_cast; using boost::optional; using boost::is_any_of; +#if BOOST_VERSION >= 106100 +using namespace boost::placeholders; +#endif using dcp::raw_convert; using namespace dcpomatic; @@ -165,6 +168,12 @@ Film::Film (optional dir) , _user_explicit_video_frame_rate (false) , _user_explicit_container (false) , _user_explicit_resolution (false) + , _name_language (dcp::LanguageTag("en-US")) + , _audio_language (dcp::LanguageTag("en-US")) + , _release_territory (dcp::LanguageTag::RegionSubtag("US")) + , _version_number (1) + , _status (dcp::FINAL) + , _luminance (dcp::Luminance(4.5, dcp::Luminance::FOOT_LAMBERT)) , _state_version (current_state_version) , _dirty (false) , _tolerant (false) @@ -464,9 +473,24 @@ Film::metadata (bool with_content_paths) const BOOST_FOREACH (dcp::Rating i, _ratings) { i.as_xml (root->add_child("Rating")); } - root->add_child("ContentVersion")->add_child_text(_content_version); + BOOST_FOREACH (string i, _content_versions) { + root->add_child("ContentVersion")->add_child_text(i); + } + root->add_child("NameLanguage")->add_child_text(_name_language.to_string()); + root->add_child("AudioLanguage")->add_child_text(_audio_language.to_string()); + root->add_child("ReleaseTerritory")->add_child_text(_release_territory.subtag()); + root->add_child("VersionNumber")->add_child_text(raw_convert(_version_number)); + root->add_child("Status")->add_child_text(dcp::status_to_string(_status)); + root->add_child("Chain")->add_child_text(_chain); + root->add_child("Distributor")->add_child_text(_distributor); + root->add_child("Facility")->add_child_text(_facility); + root->add_child("LuminanceValue")->add_child_text(raw_convert(_luminance.value())); + root->add_child("LuminanceUnit")->add_child_text(dcp::Luminance::unit_to_string(_luminance.unit())); root->add_child("UserExplicitContainer")->add_child_text(_user_explicit_container ? "1" : "0"); root->add_child("UserExplicitResolution")->add_child_text(_user_explicit_resolution ? "1" : "0"); + BOOST_FOREACH (dcp::LanguageTag i, _subtitle_languages) { + root->add_child("SubtitleLanguage")->add_child_text(i.to_string()); + } _playlist->as_xml (root->add_child ("Playlist"), with_content_paths); return doc; @@ -612,12 +636,48 @@ Film::read_metadata (optional path) _ratings.push_back (dcp::Rating(i)); } - _content_version = f.optional_string_child("ContentVersion").get_value_or(""); + BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("ContentVersion")) { + _content_versions.push_back (i->content()); + } + + optional name_language = f.optional_string_child("NameLanguage"); + if (name_language) { + _name_language = dcp::LanguageTag (*name_language); + } + optional audio_language = f.optional_string_child("AudioLanguage"); + if (audio_language) { + _audio_language = dcp::LanguageTag (*audio_language); + } + optional release_territory = f.optional_string_child("ReleaseTerritory"); + if (release_territory) { + _release_territory = dcp::LanguageTag::RegionSubtag (*release_territory); + } + + _version_number = f.optional_number_child("VersionNumber").get_value_or(0); + + optional status = f.optional_string_child("Status"); + if (status) { + _status = dcp::string_to_status (*status); + } + + _chain = f.optional_string_child("Chain").get_value_or(""); + _distributor = f.optional_string_child("Distributor").get_value_or(""); + _facility = f.optional_string_child("Facility").get_value_or(""); + + float value = f.optional_number_child("LuminanceValue").get_value_or(4.5); + optional unit = f.optional_string_child("LuminanceUnit"); + if (unit) { + _luminance = dcp::Luminance (value, dcp::Luminance::string_to_unit(*unit)); + } /* Disable guessing for files made in previous DCP-o-matic versions */ _user_explicit_container = f.optional_bool_child("UserExplicitContainer").get_value_or(true); _user_explicit_resolution = f.optional_bool_child("UserExplicitResolution").get_value_or(true); + BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("SubtitleLanguage")) { + _subtitle_languages.push_back (dcp::LanguageTag(i->content())); + } + list notes; _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes); @@ -810,39 +870,27 @@ Film::isdcf_name (bool if_created_now) const for now I'm just appending -CCAP if we have any closed captions. */ - optional subtitle_language; bool burnt_in = true; bool ccap = false; BOOST_FOREACH (shared_ptr i, content()) { BOOST_FOREACH (shared_ptr j, i->text) { - if (j->type() == TEXT_OPEN_SUBTITLE && j->use()) { - subtitle_language = j->language (); - if (!j->burn()) { - burnt_in = false; - } + if (j->type() == TEXT_OPEN_SUBTITLE && j->use() && !j->burn()) { + burnt_in = false; } else if (j->type() == TEXT_CLOSED_CAPTION && j->use()) { ccap = true; } } } - if (dm.subtitle_language) { - /* Subtitle language is overridden in ISDCF metadata, primarily to handle - content with pre-burnt subtitles. - */ - d += "-" + *dm.subtitle_language; - if (ccap) { - d += "-CCAP"; - } - } else if (subtitle_language) { - /* Language is worked out from the content */ - if (burnt_in && *subtitle_language != "XX") { - transform (subtitle_language->begin(), subtitle_language->end(), subtitle_language->begin(), ::tolower); + if (!_subtitle_languages.empty()) { + string lang = _subtitle_languages.front().language().get_value_or("en").subtag(); + if (burnt_in) { + transform (lang.begin(), lang.end(), lang.begin(), ::tolower); } else { - transform (subtitle_language->begin(), subtitle_language->end(), subtitle_language->begin(), ::toupper); + transform (lang.begin(), lang.end(), lang.begin(), ::toupper); } - d += "-" + *subtitle_language; + d += "-" + lang; if (ccap) { d += "-CCAP"; } @@ -1270,6 +1318,10 @@ Film::add_content (shared_ptr c) _playlist->add (shared_from_this(), c); maybe_set_container_and_resolution (); + if (c->atmos) { + set_audio_channels (14); + set_interop (false); + } } @@ -1373,6 +1425,8 @@ Film::playlist_content_change (ChangeType type, weak_ptr c, int p, bool } else { ContentChange (type, c, p, frequent); } + + _dirty = true; } void @@ -1390,6 +1444,8 @@ Film::playlist_change (ChangeType type) if (type == CHANGE_TYPE_DONE) { check_settings_consistency (); } + + _dirty = true; } /** Check for (and if necessary fix) impossible settings combinations, like @@ -1486,6 +1542,26 @@ Film::frame_size () const return fit_ratio_within (container()->ratio(), full_frame ()); } + +/** @return Area of Film::frame_size() that contains picture rather than pillar/letterboxing */ +dcp::Size +Film::active_area () const +{ + dcp::Size const frame = frame_size (); + dcp::Size active; + + BOOST_FOREACH (shared_ptr i, content()) { + if (i->video) { + dcp::Size s = i->video->scaled_size (frame); + active.width = max(active.width, s.width); + active.height = max(active.height, s.height); + } + } + + return active; +} + + /** @param recipient KDM recipient certificate. * @param trusted_devices Certificate thumbprints of other trusted devices (can be empty). * @param cpl_file CPL filename. @@ -1603,33 +1679,10 @@ Film::should_be_enough_disk_space (double& required, double& available, bool& ca return (available - required) > 1; } -string -Film::subtitle_language () const -{ - set languages; - - BOOST_FOREACH (shared_ptr i, content()) { - BOOST_FOREACH (shared_ptr j, i->text) { - languages.insert (j->language ()); - } - } - - string all; - BOOST_FOREACH (string s, languages) { - if (!all.empty ()) { - all += "/" + s; - } else { - all += s; - } - } - - return all; -} - /** @return The names of the channels that audio contents' outputs are passed into; * this is either the DCP or a AudioProcessor. */ -vector +vector Film::audio_output_names () const { if (audio_processor ()) { @@ -1638,10 +1691,12 @@ Film::audio_output_names () const DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16); - vector n; + vector n; for (int i = 0; i < audio_channels(); ++i) { - n.push_back (short_audio_channel_name (i)); + if (i != 8 && i != 9 && i != 15) { + n.push_back (NamedChannel(short_audio_channel_name(i), i)); + } } return n; @@ -1857,12 +1912,110 @@ Film::set_ratings (vector r) } void -Film::set_content_version (string v) +Film::set_content_versions (vector v) +{ + ChangeSignaller ch (this, CONTENT_VERSIONS); + _content_versions = v; +} + + +void +Film::set_name_language (dcp::LanguageTag lang) +{ + ChangeSignaller ch (this, NAME_LANGUAGE); + _name_language = lang; +} + + +void +Film::set_audio_language (dcp::LanguageTag lang) { - ChangeSignaller ch (this, CONTENT_VERSION); - _content_version = v; + ChangeSignaller ch (this, AUDIO_LANGUAGE); + _audio_language = lang; } + +void +Film::set_release_territory (dcp::LanguageTag::RegionSubtag region) +{ + ChangeSignaller ch (this, RELEASE_TERRITORY); + _release_territory = region; +} + + +void +Film::set_status (dcp::Status s) +{ + ChangeSignaller ch (this, STATUS); + _status = s; +} + + +void +Film::set_version_number (int v) +{ + ChangeSignaller ch (this, VERSION_NUMBER); + _version_number = v; +} + + +void +Film::set_chain (string c) +{ + ChangeSignaller ch (this, CHAIN); + _chain = c; +} + + +void +Film::set_distributor (string d) +{ + ChangeSignaller ch (this, DISTRIBUTOR); + _distributor = d; +} + + +void +Film::set_luminance (dcp::Luminance l) +{ + ChangeSignaller ch (this, LUMINANCE); + _luminance = l; +} + + +void +Film::set_subtitle_language (dcp::LanguageTag language) +{ + vector lang; + lang.push_back (language); + set_subtitle_languages (lang); +} + + +void +Film::unset_subtitle_language () +{ + ChangeSignaller ch (this, SUBTITLE_LANGUAGES); + _subtitle_languages.clear(); +} + + +void +Film::set_subtitle_languages (vector languages) +{ + ChangeSignaller ch (this, SUBTITLE_LANGUAGES); + _subtitle_languages = languages; +} + + +void +Film::set_facility (string f) +{ + ChangeSignaller ch (this, FACILITY); + _facility = f; +} + + optional Film::marker (dcp::Marker type) const { @@ -1906,3 +2059,17 @@ InfoFileHandle::~InfoFileHandle () { fclose (_handle); } + + +/** Add FFOC and LFOC markers to a list if they are not already there */ +void +Film::add_ffoc_lfoc (Markers& markers) const +{ + if (markers.find(dcp::Marker::FFOC) == markers.end()) { + markers[dcp::Marker::FFOC] = dcpomatic::DCPTime(0); + } + + if (markers.find(dcp::Marker::LFOC) == markers.end()) { + markers[dcp::Marker::LFOC] = length() - DCPTime::from_frames(1, video_frame_rate()); + } +}