#include "dcpomatic_log.h"
#include "digester.h"
#include "film.h"
+#include "film_util.h"
#include "image.h"
#include "image_png.h"
#include "job.h"
#include <dcp/certificate_chain.h>
#include <dcp/cpl.h>
#include <dcp/dcp.h>
+#include <dcp/filesystem.h>
#include <dcp/interop_subtitle_asset.h>
#include <dcp/mono_picture_asset.h>
#include <dcp/raw_convert.h>
to change its contents (if only by changing the IDs); see
#1126.
*/
- if (boost::filesystem::exists(asset) && boost::filesystem::hard_link_count(asset) > 1) {
+ if (dcp::filesystem::exists(asset) && dcp::filesystem::hard_link_count(asset) > 1) {
if (job) {
job->sub (_("Copying old video file"));
copy_in_bits (asset, asset.string() + ".tmp", bind(&Job::set_progress, job.get(), _1, false));
} else {
- boost::filesystem::copy_file (asset, asset.string() + ".tmp");
+ dcp::filesystem::copy_file(asset, asset.string() + ".tmp");
}
- boost::filesystem::remove (asset);
- boost::filesystem::rename (asset.string() + ".tmp", asset);
+ dcp::filesystem::remove(asset);
+ dcp::filesystem::rename(asset.string() + ".tmp", asset);
}
_sound_asset = make_shared<dcp::SoundAsset> (
dcp::Fraction(film()->video_frame_rate(), 1),
film()->audio_frame_rate(),
- /* Always make 16-channel sound assets for SMPTE; libdcp will pad unused channels for us */
- standard == dcp::Standard::SMPTE ? MAX_DCP_AUDIO_CHANNELS : film()->audio_channels(),
+ film()->audio_channels(),
lang ? *lang : dcp::LanguageTag("en-US"),
standard
);
DCPOMATIC_ASSERT (film()->directory());
- auto mapped = film()->mapped_audio_channels();
std::vector<dcp::Channel> extra_active_channels;
- auto add_if_mapped = [mapped, &extra_active_channels](dcp::Channel channel) {
- if (std::find(mapped.begin(), mapped.end(), static_cast<int>(channel)) != mapped.end()) {
+ for (auto channel: std::vector<dcp::Channel>{dcp::Channel::HI, dcp::Channel::VI, dcp::Channel::BSL, dcp::Channel::BSR}) {
+ if (channel_is_mapped(film(), channel)) {
extra_active_channels.push_back(channel);
}
- };
-
- add_if_mapped(dcp::Channel::HI);
- add_if_mapped(dcp::Channel::VI);
- add_if_mapped(dcp::Channel::BSL);
- add_if_mapped(dcp::Channel::BSR);
+ }
/* Write the sound asset into the film directory so that we leave the creation
of the DCP directory until the last minute.
}
/* Offset of the last dcp::FrameInfo in the info file */
- int const n = (boost::filesystem::file_size(info_file->get().path()) / _info_size) - 1;
- LOG_GENERAL ("The last FI is %1; info file is %2, info size %3", n, boost::filesystem::file_size(info_file->get().path()), _info_size);
+ int const n = (dcp::filesystem::file_size(info_file->get().path()) / _info_size) - 1;
+ LOG_GENERAL ("The last FI is %1; info file is %2, info size %3", n, dcp::filesystem::file_size(info_file->get().path()), _info_size);
Frame first_nonexistent_frame;
if (film()->three_d()) {
changing any video.
*/
boost::system::error_code ec;
- boost::filesystem::remove (video_to, ec);
+ dcp::filesystem::remove(video_to, ec);
- boost::filesystem::create_hard_link (video_from, video_to, ec);
+ dcp::filesystem::create_hard_link(video_from, video_to, ec);
if (ec) {
LOG_WARNING("Hard-link failed (%1); copying instead", error_details(ec));
auto job = _job.lock ();
throw FileError (e.what(), video_from);
}
} else {
- boost::filesystem::copy_file (video_from, video_to, ec);
+ dcp::filesystem::copy_file(video_from, video_to, ec);
if (ec) {
LOG_ERROR("Failed to copy video file from %1 to %2 (%3)", video_from.string(), video_to.string(), error_details(ec));
throw FileError (ec.message(), video_from);
audio_to /= aaf;
boost::system::error_code ec;
- boost::filesystem::rename (film()->file(aaf), audio_to, ec);
+ dcp::filesystem::rename(film()->file(aaf), audio_to, ec);
if (ec) {
throw FileError (
String::compose(_("could not move audio asset into the DCP (%1)"), error_details(ec)), aaf
atmos_to /= aaf;
boost::system::error_code ec;
- boost::filesystem::rename (film()->file(aaf), atmos_to, ec);
+ dcp::filesystem::rename(film()->file(aaf), atmos_to, ec);
if (ec) {
throw FileError (
String::compose(_("could not move atmos asset into the DCP (%1)"), error_details(ec)), aaf
int reel_count,
optional<string> content_summary,
list<ReferencedReelAsset> const & refs,
- FontIdMap const& fonts,
- shared_ptr<dcpomatic::Font> chosen_interop_font,
- dcp::ArrayData default_font,
shared_ptr<const Film> film,
DCPTimePeriod period,
boost::filesystem::path output_dcp,
shared_ptr<Result> reel_asset;
if (asset) {
- if (film->interop()) {
- if (chosen_interop_font) {
- /* We only add one font, as Interop will ignore subsequent ones (and some validators will
- * complain if they are even present)
- */
- asset->add_font(fonts.get(chosen_interop_font), chosen_interop_font->data().get_value_or(default_font));
- } else {
- }
- } else {
- for (auto const& font: fonts.map()) {
- asset->add_font(font.second, font.first->data().get_value_or(default_font));
- }
- }
-
if (auto interop = dynamic_pointer_cast<dcp::InteropSubtitleAsset>(asset)) {
auto directory = output_dcp / interop->id ();
- boost::filesystem::create_directories (directory);
+ dcp::filesystem::create_directories(directory);
interop->write (directory / subtitle_asset_filename(asset, reel_index, reel_count, content_summary, ".xml"));
reel_asset = make_shared<Interop> (
interop,
ReelWriter::create_reel_text (
shared_ptr<dcp::Reel> reel,
list<ReferencedReelAsset> const & refs,
- FontIdMap const& fonts,
- shared_ptr<dcpomatic::Font> chosen_interop_font,
int64_t duration,
boost::filesystem::path output_dcp,
bool ensure_subtitles,
) const
{
auto subtitle = maybe_add_text<dcp::ReelInteropSubtitleAsset, dcp::ReelSMPTESubtitleAsset, dcp::ReelSubtitleAsset> (
- _subtitle_asset, duration, reel, _reel_index, _reel_count, _content_summary, refs, fonts, chosen_interop_font, _default_font, film(), _period, output_dcp, _text_only
+ _subtitle_asset, duration, reel, _reel_index, _reel_count, _content_summary, refs, film(), _period, output_dcp, _text_only
);
- if (subtitle) {
- /* We have a subtitle asset that we either made or are referencing */
- if (auto main_language = film()->subtitle_languages().first) {
- subtitle->set_language (*main_language);
- }
- } else if (ensure_subtitles) {
+ if (!subtitle && ensure_subtitles) {
/* We had no subtitle asset, but we've been asked to make sure there is one */
subtitle = maybe_add_text<dcp::ReelInteropSubtitleAsset, dcp::ReelSMPTESubtitleAsset, dcp::ReelSubtitleAsset> (
empty_text_asset(TextType::OPEN_SUBTITLE, optional<DCPTextTrack>(), true),
_reel_count,
_content_summary,
refs,
- fonts,
- chosen_interop_font,
- _default_font,
film(),
_period,
output_dcp,
);
}
+ if (subtitle) {
+ /* We have a subtitle asset that we either made or are referencing */
+ if (auto main_language = film()->subtitle_languages().first) {
+ subtitle->set_language (*main_language);
+ }
+ }
+
for (auto const& i: _closed_caption_assets) {
auto a = maybe_add_text<dcp::ReelInteropClosedCaptionAsset, dcp::ReelSMPTEClosedCaptionAsset, dcp::ReelClosedCaptionAsset> (
- i.second, duration, reel, _reel_index, _reel_count, _content_summary, refs, fonts, chosen_interop_font, _default_font, film(), _period, output_dcp, _text_only
+ i.second, duration, reel, _reel_index, _reel_count, _content_summary, refs, film(), _period, output_dcp, _text_only
);
DCPOMATIC_ASSERT (a);
a->set_annotation_text (i.first.name);
_reel_count,
_content_summary,
refs,
- fonts,
- chosen_interop_font,
- _default_font,
film(),
_period,
output_dcp,
shared_ptr<dcp::Reel>
ReelWriter::create_reel (
list<ReferencedReelAsset> const & refs,
- FontIdMap const & fonts,
- shared_ptr<dcpomatic::Font> chosen_interop_font,
boost::filesystem::path output_dcp,
bool ensure_subtitles,
set<DCPTextTrack> ensure_closed_captions
auto reel_picture_asset = create_reel_picture (reel, refs);
duration = reel_picture_asset->actual_duration ();
create_reel_sound (reel, refs);
- create_reel_markers (reel);
+ if (!film()->interop()) {
+ create_reel_markers(reel);
+ }
}
- create_reel_text (reel, refs, fonts, chosen_interop_font, duration, output_dcp, ensure_subtitles, ensure_closed_captions);
+ create_reel_text(reel, refs, duration, output_dcp, ensure_subtitles, ensure_closed_captions);
if (_atmos_asset) {
reel->add (make_shared<dcp::ReelAtmosAsset>(_atmos_asset, 0));
return reel;
}
+
+/** @param set_progress Method to call with progress; first parameter is the number of bytes
+ * done, second parameter is the number of bytes in total.
+ */
void
-ReelWriter::calculate_digests (std::function<void (float)> set_progress)
+ReelWriter::calculate_digests(std::function<void (int64_t, int64_t)> set_progress)
try
{
+ vector<shared_ptr<const dcp::Asset>> assets;
+
if (_picture_asset) {
- _picture_asset->hash (set_progress);
+ assets.push_back(_picture_asset);
}
-
if (_sound_asset) {
- _sound_asset->hash (set_progress);
+ assets.push_back(_sound_asset);
}
-
if (_atmos_asset) {
- _atmos_asset->hash (set_progress);
+ assets.push_back(_atmos_asset);
}
+
+ int64_t total_size = 0;
+ for (auto asset: assets) {
+ total_size += asset->file() ? boost::filesystem::file_size(*asset->file()) : 0;
+ }
+
+ int64_t total_done = 0;
+ for (auto asset: assets) {
+ asset->hash([&total_done, total_size, set_progress](int64_t done, int64_t) {
+ set_progress(total_done + done, total_size);
+ });
+ total_done += asset->file() ? boost::filesystem::file_size(*asset->file()) : 0;
+ }
+
} catch (boost::thread_interrupted) {
/* set_progress contains an interruption_point, so any of these methods
* may throw thread_interrupted, at which point we just give up.
ReelWriter::empty_text_asset (TextType type, optional<DCPTextTrack> track, bool with_dummy) const
{
shared_ptr<dcp::SubtitleAsset> asset;
+ optional<string> font;
auto lang = film()->subtitle_languages();
if (film()->interop()) {
if (with_dummy) {
asset->add(
std::make_shared<dcp::SubtitleString>(
- optional<std::string>(),
+ font,
false,
false,
false,
dcp::Colour(),
dcp::Time(),
dcp::Time(),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
+
+ if (!film()->interop()) {
+ /* We must have a LoadFont since we have a Text */
+ font = "font";
+ asset->ensure_font(*font, _default_font);
+ }
}
return asset;
void
-ReelWriter::write (PlayerText subs, TextType type, optional<DCPTextTrack> track, DCPTimePeriod period, FontIdMap const& fonts)
+ReelWriter::write(PlayerText subs, TextType type, optional<DCPTextTrack> track, DCPTimePeriod period, FontIdMap const& fonts, shared_ptr<dcpomatic::Font> chosen_interop_font)
{
shared_ptr<dcp::SubtitleAsset> asset;
i.set_out (dcp::Time(period.to.seconds() - _period.from.seconds(), tcr));
i.set_v_position(convert_vertical_position(i, film()->interop() ? dcp::SubtitleStandard::INTEROP : dcp::SubtitleStandard::SMPTE_2014));
auto sub = make_shared<dcp::SubtitleString>(i);
- sub->set_font(fonts.get(i.font));
+ /* i.font is a shared_ptr<Font> which uniquely identifies the font we want,
+ * though if we are Interop we can only have one font, so we'll use the chosen
+ * one instead.
+ */
+ auto font = film()->interop() ? chosen_interop_font : i.font;
+ /* We can get the corresponding ID from fonts */
+ auto const font_id_to_use = fonts.get(font);
+ /* Give this subtitle the correct font ID */
+ sub->set_font(font_id_to_use);
asset->add(sub);
+ /* Make sure the asset LoadFonts the font we just asked for */
+ asset->ensure_font(font_id_to_use, font->data().get_value_or(_default_font));
}
for (auto i: subs.bitmap) {