/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "text_content.h"
#include "ffmpeg_content.h"
#include "dcp_content.h"
-#include "screen_kdm.h"
+#include "kdm_with_metadata.h"
#include "cinema.h"
#include "change_signaller.h"
#include "check_content_change_job.h"
+#include "ffmpeg_subtitle_stream.h"
+#include "font.h"
#include <libcxml/cxml.h>
#include <dcp/cpl.h>
#include <dcp/certificate_chain.h>
* 36 -> 37
* TextContent can be in a Caption tag, and some of the tag names
* have had Subtitle prefixes or suffixes removed.
+ * 37 -> 38
+ * VideoContent scale expressed just as "guess" or "custom"
*/
-int const Film::current_state_version = 37;
+int const Film::current_state_version = 38;
/** Construct a Film object in a given directory.
*
set_isdcf_date_today ();
_playlist_change_connection = _playlist->Change.connect (bind (&Film::playlist_change, this, _1));
- _playlist_order_changed_connection = _playlist->OrderChanged.connect (bind (&Film::playlist_order_changed, this));
+ _playlist_order_changed_connection = _playlist->OrderChange.connect (bind (&Film::playlist_order_changed, this));
_playlist_content_change_connection = _playlist->ContentChange.connect (bind (&Film::playlist_content_change, this, _1, _2, _3, _4));
_playlist_length_change_connection = _playlist->LengthChange.connect (bind(&Film::playlist_length_change, this));
return p;
}
+
+boost::filesystem::path
+Film::subtitle_analysis_path (shared_ptr<const Content> content) const
+{
+ boost::filesystem::path p = dir ("analysis");
+
+ Digester digester;
+ digester.add (content->digest());
+
+ if (!content->text.empty()) {
+ shared_ptr<TextContent> tc = content->text.front();
+ digester.add (tc->x_scale());
+ digester.add (tc->y_scale());
+ BOOST_FOREACH (shared_ptr<dcpomatic::Font> i, tc->fonts()) {
+ digester.add (i->id());
+ }
+ if (tc->effect()) {
+ digester.add (tc->effect().get());
+ }
+ digester.add (tc->line_spacing());
+ digester.add (tc->outline_width());
+ }
+
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent>(content);
+ if (fc) {
+ digester.add (fc->subtitle_stream()->identifier());
+ }
+
+ p /= digester.get ();
+ return p;
+}
+
+
/** Add suitable Jobs to the JobManager to create a DCP for this Film.
* @param gui true if this is being called from a GUI tool.
* @param check true to check the content in the project for changes before making the DCP.
path = file (metadata_file);
}
+ if (!boost::filesystem::exists(*path)) {
+ throw FileNotFoundError(*path);
+ }
+
cxml::Document f ("Metadata");
f.read_file (path.get ());
BOOST_FOREACH (shared_ptr<Content> i, content ()) {
if (i->video) {
/* Here's the first piece of video content */
- if (i->video->scale().ratio ()) {
- content_ratio = i->video->scale().ratio ();
- } else {
- content_ratio = Ratio::from_ratio (i->video->size().ratio ());
- }
+ content_ratio = Ratio::nearest_from_ratio(i->video->scaled_size(frame_size()).ratio());
break;
}
}
_playlist->move_later (shared_from_this(), c);
}
-/** @return length of the film from time 0 to the last thing on the playlist */
+/** @return length of the film from time 0 to the last thing on the playlist,
+ * with a minimum length of 1 second.
+ */
DCPTime
Film::length () const
{
- return _playlist->length(shared_from_this()).ceil(video_frame_rate());
+ return max(DCPTime::from_seconds(1), _playlist->length(shared_from_this()).ceil(video_frame_rate()));
}
int
).encrypt (signer, recipient, trusted_devices, formulation, disable_forensic_marking_picture, disable_forensic_marking_audio);
}
-/** @param screens Screens to make KDMs for.
- * @param cpl_file Path to CPL to make KDMs for.
- * @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<shared_ptr<ScreenKDM> >
-Film::make_kdms (
- list<shared_ptr<Screen> > screens,
- boost::filesystem::path cpl_file,
- boost::posix_time::ptime from,
- boost::posix_time::ptime until,
- dcp::Formulation formulation,
- bool disable_forensic_marking_picture,
- optional<int> disable_forensic_marking_audio
- ) const
-{
- list<shared_ptr<ScreenKDM> > kdms;
-
- BOOST_FOREACH (shared_ptr<Screen> i, screens) {
- if (i->recipient) {
- dcp::EncryptedKDM const kdm = make_kdm (
- i->recipient.get(),
- i->trusted_device_thumbprints(),
- cpl_file,
- dcp::LocalTime (from, i->cinema ? i->cinema->utc_offset_hour() : 0, i->cinema ? i->cinema->utc_offset_minute() : 0),
- dcp::LocalTime (until, i->cinema ? i->cinema->utc_offset_hour() : 0, i->cinema ? i->cinema->utc_offset_minute() : 0),
- formulation,
- disable_forensic_marking_picture,
- disable_forensic_marking_audio
- );
-
- kdms.push_back (shared_ptr<ScreenKDM>(new DCPScreenKDM(i, kdm)));
- }
- }
-
- return kdms;
-}
/** @return The approximate disk space required to encode a DCP of this film with the
* current settings, in bytes.
split_points.sort ();
split_points.unique ();
- /* Make them into periods */
+ /* Make them into periods, coalescing any that are less than 1 second long */
optional<DCPTime> last;
BOOST_FOREACH (DCPTime t, split_points) {
- if (last) {
+ 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));
+ last = t;
+ } else if (!last) {
+ /* That was the first time, so start a new period */
+ last = t;
}
- last = t;
}
break;
}
case REELTYPE_BY_LENGTH:
{
DCPTime current;
- /* Integer-divide reel length by the size of one frame to give the number of frames per reel */
- Frame const reel_in_frames = _reel_length / ((j2k_bandwidth() / video_frame_rate()) / 8);
+ /* Integer-divide reel length by the size of one frame to give the number of frames per reel,
+ * making sure we don't go less than 1s long.
+ */
+ 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));
_markers.erase (type);
}
+
+void
+Film::clear_markers ()
+{
+ ChangeSignaller<Film> ch (this, MARKERS);
+ _markers.clear ();
+}
+
+
void
Film::set_ratings (vector<dcp::Rating> r)
{