X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Ffilm.cc;h=d2c73c8b5ef5e02269d27c2e11637e601eff7f39;hb=2354c1fd781879d215834ebe54661f125fcb324e;hp=c56cd36df6f0ae9ada472efcb582245c21f636f5;hpb=51dda295b5bd63e6635ae17786e4657c41a3678a;p=dcpomatic.git diff --git a/src/lib/film.cc b/src/lib/film.cc index c56cd36df..d2c73c8b5 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -413,6 +413,9 @@ Film::metadata (bool with_content_paths) const } root->add_child("ReelType")->add_child_text (raw_convert (static_cast (_reel_type))); root->add_child("ReelLength")->add_child_text (raw_convert (_reel_length)); + for (auto boundary: _custom_reel_boundaries) { + root->add_child("CustomReelBoundary")->add_child_text(raw_convert(boundary.get())); + } root->add_child("ReencodeJ2K")->add_child_text (_reencode_j2k ? "1" : "0"); root->add_child("UserExplicitVideoFrameRate")->add_child_text(_user_explicit_video_frame_rate ? "1" : "0"); for (auto const& marker: _markers) { @@ -600,6 +603,9 @@ Film::read_metadata (optional path) _reel_type = static_cast (f.optional_number_child("ReelType").get_value_or (static_cast(ReelType::SINGLE))); _reel_length = f.optional_number_child("ReelLength").get_value_or (2000000000); + for (auto boundary: f.node_children("CustomReelBoundary")) { + _custom_reel_boundaries.push_back(DCPTime(raw_convert(boundary->content()))); + } _reencode_j2k = f.optional_bool_child("ReencodeJ2K").get_value_or(false); _user_explicit_video_frame_rate = f.optional_bool_child("UserExplicitVideoFrameRate").get_value_or(false); @@ -948,10 +954,12 @@ Film::isdcf_name (bool if_created_now) const if (dcp_content_type() && dcp_content_type()->libdcp_kind() != dcp::ContentKind::TRAILER) { auto first_video = std::find_if(content_list.begin(), content_list.end(), [](shared_ptr c) { return static_cast(c->video); }); if (first_video != content_list.end()) { - auto first_ratio = lrintf((*first_video)->video->scaled_size(frame_size()).ratio() * 100); - auto container_ratio = lrintf(container()->ratio() * 100); - if (first_ratio != container_ratio) { - isdcf_name += "-" + dcp::raw_convert(first_ratio); + if (auto scaled_size = (*first_video)->video->scaled_size(frame_size())) { + auto first_ratio = lrintf(scaled_size->ratio() * 100); + auto container_ratio = lrintf(container()->ratio() * 100); + if (first_ratio != container_ratio) { + isdcf_name += "-" + dcp::raw_convert(first_ratio); + } } } } @@ -1231,6 +1239,16 @@ Film::set_reel_length (int64_t r) _reel_length = r; } + +void +Film::set_custom_reel_boundaries(vector boundaries) +{ + FilmChangeSignaller ch(this, FilmProperty::CUSTOM_REEL_BOUNDARIES); + std::sort(boundaries.begin(), boundaries.end()); + _custom_reel_boundaries = std::move(boundaries); +} + + void Film::set_reencode_j2k (bool r) { @@ -1440,13 +1458,13 @@ Film::maybe_set_container_and_resolution () } } - if (video) { + if (video && video->size()) { /* This is the only piece of video content in this Film. Use it to make a guess for * DCP container size and resolution, unless the user has already explicitly set these * things. */ if (!_user_explicit_container) { - if (video->size().ratio() > 2.3) { + if (video->size()->ratio() > 2.3) { set_container (Ratio::from_id("239"), false); } else { set_container (Ratio::from_id("185"), false); @@ -1454,7 +1472,7 @@ Film::maybe_set_container_and_resolution () } if (!_user_explicit_resolution) { - if (video->size_after_crop().width > 2048 || video->size_after_crop().height > 1080) { + if (video->size_after_crop()->width > 2048 || video->size_after_crop()->height > 1080) { set_resolution (Resolution::FOUR_K, false); } else { set_resolution (Resolution::TWO_K, false); @@ -1598,6 +1616,23 @@ Film::check_settings_consistency () if (change_made) { Message (_("DCP-o-matic had to change your settings for referring to DCPs as OV. Please review those settings to make sure they are what you want.")); } + + if (reel_type() == ReelType::CUSTOM) { + auto boundaries = custom_reel_boundaries(); + auto too_late = std::find_if(boundaries.begin(), boundaries.end(), [this](dcpomatic::DCPTime const& time) { + return time >= length(); + }); + + if (too_late != boundaries.end()) { + if (std::distance(too_late, boundaries.end()) > 1) { + Message(_("DCP-o-matic had to remove some of your custom reel boundaries as they no longer lie within the film.")); + } else { + Message(_("DCP-o-matic had to remove one of your custom reel boundaries as it no longer lies within the film.")); + } + boundaries.erase(too_late, boundaries.end()); + set_custom_reel_boundaries(boundaries); + } + } } void @@ -1652,9 +1687,10 @@ Film::active_area () const for (auto 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); + if (auto s = i->video->scaled_size(frame)) { + active.width = max(active.width, s->width); + active.height = max(active.height, s->height); + } } } @@ -1801,15 +1837,16 @@ Film::audio_analysis_finished () /* XXX */ } -list + +vector Film::reels () const { - list p; + vector periods; auto const len = length(); switch (reel_type ()) { case ReelType::SINGLE: - p.push_back (DCPTimePeriod (DCPTime (), len)); + periods.emplace_back(DCPTime(), len); break; case ReelType::BY_VIDEO_CONTENT: { @@ -1834,7 +1871,7 @@ Film::reels () const for (auto t: split_points) { if (last && (t - *last) >= DCPTime::from_seconds(1)) { /* Period from *last to t is long enough; use it and start a new one */ - p.push_back (DCPTimePeriod(*last, t)); + periods.emplace_back(*last, t); last = t; } else if (!last) { /* That was the first time, so start a new period */ @@ -1842,8 +1879,8 @@ Film::reels () const } } - if (!p.empty()) { - p.back().to = split_points.back(); + if (!periods.empty()) { + periods.back().to = split_points.back(); } break; } @@ -1856,16 +1893,29 @@ Film::reels () const Frame const reel_in_frames = max(_reel_length / ((j2k_bandwidth() / video_frame_rate()) / 8), static_cast(video_frame_rate())); while (current < len) { DCPTime end = min (len, current + DCPTime::from_frames (reel_in_frames, video_frame_rate ())); - p.push_back (DCPTimePeriod (current, end)); + periods.emplace_back(current, end); current = end; } break; } + case ReelType::CUSTOM: + { + DCPTimePeriod current; + for (auto boundary: _custom_reel_boundaries) { + current.to = boundary; + periods.push_back(current); + current.from = boundary; + } + current.to = len; + periods.push_back(current); + break; + } } - return p; + return periods; } + /** @param period A period within the DCP * @return Name of the content which most contributes to the given period. */