summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2024-03-12 23:42:45 +0100
committerCarl Hetherington <cth@carlh.net>2024-03-12 23:42:45 +0100
commit2354c1fd781879d215834ebe54661f125fcb324e (patch)
tree936e6ae61f3f1eac565e48babf169de1833f9ac8 /src/lib
parenta7be213f1063e3c5cb4dcba37aa0443d1f28f9d5 (diff)
parentda46a695431d3b573924e53ac1a0163056a1a5b5 (diff)
Merge branch '2678-reel-break' into v2.17.x
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/constants.h1
-rw-r--r--src/lib/dcpomatic_time.cc19
-rw-r--r--src/lib/dcpomatic_time.h3
-rw-r--r--src/lib/film.cc63
-rw-r--r--src/lib/film.h11
-rw-r--r--src/lib/film_property.h1
-rw-r--r--src/lib/types.h3
7 files changed, 90 insertions, 11 deletions
diff --git a/src/lib/constants.h b/src/lib/constants.h
index 3b1871554..bfe144420 100644
--- a/src/lib/constants.h
+++ b/src/lib/constants.h
@@ -47,6 +47,7 @@
#define MAX_CLOSED_CAPTION_XML_SIZE (256 * 1024)
#define MAX_CLOSED_CAPTION_XML_SIZE_TEXT "256KB"
#define CERTIFICATE_VALIDITY_PERIOD (10 * 365)
+#define SNAP_SUBDIVISION 64
#endif
diff --git a/src/lib/dcpomatic_time.cc b/src/lib/dcpomatic_time.cc
index ac797f8f4..60fc5342a 100644
--- a/src/lib/dcpomatic_time.cc
+++ b/src/lib/dcpomatic_time.cc
@@ -27,6 +27,25 @@ using std::string;
using namespace dcpomatic;
+bool
+dcpomatic::operator<=(HMSF const& a, HMSF const& b)
+{
+ if (a.h != b.h) {
+ return a.h <= b.h;
+ }
+
+ if (a.m != b.m) {
+ return a.m <= b.m;
+ }
+
+ if (a.s != b.s) {
+ return a.s <= b.s;
+ }
+
+ return a.f <= b.f;
+}
+
+
template <>
Time<ContentTimeDifferentiator, DCPTimeDifferentiator>::Time (DCPTime d, FrameRateChange f)
: _t (llrint(d.get() * f.speed_up))
diff --git a/src/lib/dcpomatic_time.h b/src/lib/dcpomatic_time.h
index 9ebb334fe..63bb86549 100644
--- a/src/lib/dcpomatic_time.h
+++ b/src/lib/dcpomatic_time.h
@@ -64,6 +64,9 @@ public:
};
+bool operator<=(HMSF const& a, HMSF const& b);
+
+
/** A time in seconds, expressed as a number scaled up by Time::HZ. We want two different
* versions of this class, dcpomatic::ContentTime and dcpomatic::DCPTime, and we want it to be impossible to
* convert implicitly between the two. Hence there's this template hack. I'm not
diff --git a/src/lib/film.cc b/src/lib/film.cc
index d747efb0e..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<string> (static_cast<int> (_reel_type)));
root->add_child("ReelLength")->add_child_text (raw_convert<string> (_reel_length));
+ for (auto boundary: _custom_reel_boundaries) {
+ root->add_child("CustomReelBoundary")->add_child_text(raw_convert<string>(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<boost::filesystem::path> path)
_reel_type = static_cast<ReelType> (f.optional_number_child<int>("ReelType").get_value_or (static_cast<int>(ReelType::SINGLE)));
_reel_length = f.optional_number_child<int64_t>("ReelLength").get_value_or (2000000000);
+ for (auto boundary: f.node_children("CustomReelBoundary")) {
+ _custom_reel_boundaries.push_back(DCPTime(raw_convert<int64_t>(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);
@@ -1233,6 +1239,16 @@ Film::set_reel_length (int64_t r)
_reel_length = r;
}
+
+void
+Film::set_custom_reel_boundaries(vector<DCPTime> 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)
{
@@ -1600,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
@@ -1804,15 +1837,16 @@ Film::audio_analysis_finished ()
/* XXX */
}
-list<DCPTimePeriod>
+
+vector<DCPTimePeriod>
Film::reels () const
{
- list<DCPTimePeriod> p;
+ vector<DCPTimePeriod> 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:
{
@@ -1837,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 */
@@ -1845,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;
}
@@ -1859,16 +1893,29 @@ Film::reels () const
Frame const reel_in_frames = max(_reel_length / ((j2k_bandwidth() / video_frame_rate()) / 8), static_cast<Frame>(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.
*/
diff --git a/src/lib/film.h b/src/lib/film.h
index 036bbed7e..0a0c5a4e1 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -186,7 +186,7 @@ public:
return _playlist;
}
- std::list<dcpomatic::DCPTimePeriod> reels () const;
+ std::vector<dcpomatic::DCPTimePeriod> reels() const;
std::list<int> mapped_audio_channels () const;
boost::optional<dcp::LanguageTag> audio_language () const {
@@ -291,6 +291,10 @@ public:
return _reel_length;
}
+ std::vector<dcpomatic::DCPTime> custom_reel_boundaries() const {
+ return _custom_reel_boundaries;
+ }
+
std::string context_id () const {
return _context_id;
}
@@ -408,6 +412,7 @@ public:
void set_audio_processor (AudioProcessor const * processor);
void set_reel_type (ReelType);
void set_reel_length (int64_t);
+ void set_custom_reel_boundaries(std::vector<dcpomatic::DCPTime> boundaries);
void set_reencode_j2k (bool);
void set_marker (dcp::Marker type, dcpomatic::DCPTime time);
void unset_marker (dcp::Marker type);
@@ -527,8 +532,10 @@ private:
bool _limit_to_smpte_bv20;
AudioProcessor const * _audio_processor;
ReelType _reel_type;
- /** Desired reel length in bytes, if _reel_type == REELTYPE_BY_LENGTH */
+ /** Desired reel length in bytes, if _reel_type == BY_LENGTH */
int64_t _reel_length;
+ /** Reel boundaries (excluding those at the start and end, sorted in ascending order) if _reel_type == CUSTOM */
+ std::vector<dcpomatic::DCPTime> _custom_reel_boundaries;
bool _reencode_j2k;
/** true if the user has ever explicitly set the video frame rate of this film */
bool _user_explicit_video_frame_rate;
diff --git a/src/lib/film_property.h b/src/lib/film_property.h
index c23297965..0841caa5c 100644
--- a/src/lib/film_property.h
+++ b/src/lib/film_property.h
@@ -51,6 +51,7 @@ enum class FilmProperty {
AUDIO_PROCESSOR,
REEL_TYPE,
REEL_LENGTH,
+ CUSTOM_REEL_BOUNDARIES,
REENCODE_J2K,
MARKERS,
RATINGS,
diff --git a/src/lib/types.h b/src/lib/types.h
index 36059401e..c9c87bae5 100644
--- a/src/lib/types.h
+++ b/src/lib/types.h
@@ -107,7 +107,8 @@ enum class ReelType
{
SINGLE,
BY_VIDEO_CONTENT,
- BY_LENGTH
+ BY_LENGTH,
+ CUSTOM
};