Move digest calculation to a separate method.
[dcpomatic.git] / src / lib / writer.cc
index 4386b8e26264dea29a1e4cc41dce74212e915465..8fa9fbbca8b76893e913f63ac866ec5964095e42 100644 (file)
@@ -393,6 +393,8 @@ void
 Writer::thread ()
 try
 {
+       start_of_thread ("Writer");
+
        while (true)
        {
                boost::mutex::scoped_lock lock (_state_mutex);
@@ -533,35 +535,9 @@ Writer::terminate_thread (bool can_throw)
 }
 
 
-/** @param output_dcp Path to DCP folder to write */
 void
-Writer::finish (boost::filesystem::path output_dcp)
+Writer::calculate_digests ()
 {
-       if (_thread.joinable()) {
-               LOG_GENERAL_NC ("Terminating writer thread");
-               terminate_thread (true);
-       }
-
-       LOG_GENERAL_NC ("Finishing ReelWriters");
-
-       for (auto& i: _reels) {
-               write_hanging_text (i);
-               i.finish (output_dcp);
-       }
-
-       LOG_GENERAL_NC ("Writing XML");
-
-       dcp::DCP dcp (output_dcp);
-
-       auto cpl = make_shared<dcp::CPL>(
-               film()->dcp_name(),
-               film()->dcp_content_type()->libdcp_kind()
-               );
-
-       dcp.add (cpl);
-
-       /* Calculate digests for each reel in parallel */
-
        auto job = _job.lock ();
        if (job) {
                job->sub (_("Computing digests"));
@@ -572,7 +548,7 @@ Writer::finish (boost::filesystem::path output_dcp)
 
        auto work = make_shared<boost::asio::io_service::work>(service);
 
-       int const threads = max (1, Config::instance()->master_encoding_threads ());
+       int const threads = max (1, Config::instance()->master_encoding_threads());
 
        for (int i = 0; i < threads; ++i) {
                pool.create_thread (boost::bind (&boost::asio::io_service::run, &service));
@@ -591,8 +567,44 @@ Writer::finish (boost::filesystem::path output_dcp)
        service.post (boost::bind (&Writer::calculate_referenced_digests, this, set_progress));
 
        work.reset ();
-       pool.join_all ();
+
+       {
+               pool.join_all ();
+       }
+
        service.stop ();
+}
+
+
+/** @param output_dcp Path to DCP folder to write */
+void
+Writer::finish (boost::filesystem::path output_dcp)
+{
+       if (_thread.joinable()) {
+               LOG_GENERAL_NC ("Terminating writer thread");
+               terminate_thread (true);
+       }
+
+       LOG_GENERAL_NC ("Finishing ReelWriters");
+
+       for (auto& i: _reels) {
+               write_hanging_text (i);
+               i.finish (output_dcp);
+       }
+
+       LOG_GENERAL_NC ("Writing XML");
+
+       dcp::DCP dcp (output_dcp);
+
+       auto cpl = make_shared<dcp::CPL>(
+               film()->dcp_name(),
+               film()->dcp_content_type()->libdcp_kind(),
+               film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE
+               );
+
+       dcp.add (cpl);
+
+       calculate_digests ();
 
        /* Add reels */
 
@@ -622,13 +634,23 @@ Writer::finish (boost::filesystem::path output_dcp)
 
        cpl->set_full_content_title_text (film()->name());
        cpl->set_full_content_title_text_language (film()->name_language());
-       cpl->set_release_territory (film()->release_territory());
+       if (film()->release_territory()) {
+               cpl->set_release_territory (*film()->release_territory());
+       }
        cpl->set_version_number (film()->version_number());
        cpl->set_status (film()->status());
-       cpl->set_chain (film()->chain());
-       cpl->set_distributor (film()->distributor());
-       cpl->set_facility (film()->facility());
-       cpl->set_luminance (film()->luminance());
+       if (film()->chain()) {
+               cpl->set_chain (*film()->chain());
+       }
+       if (film()->distributor()) {
+               cpl->set_distributor (*film()->distributor());
+       }
+       if (film()->facility()) {
+               cpl->set_facility (*film()->facility());
+       }
+       if (film()->luminance()) {
+               cpl->set_luminance (*film()->luminance());
+       }
 
        auto ac = film()->mapped_audio_channels();
        dcp::MCASoundField field = (
@@ -653,9 +675,9 @@ Writer::finish (boost::filesystem::path output_dcp)
                cpl->set_main_picture_active_area (active_area);
        }
 
-       vector<dcp::LanguageTag> sl = film()->subtitle_languages();
-       if (sl.size() > 1) {
-               cpl->set_additional_subtitle_languages(std::vector<dcp::LanguageTag>(sl.begin() + 1, sl.end()));
+       auto sl = film()->subtitle_languages().second;
+       if (!sl.empty()) {
+               cpl->set_additional_subtitle_languages(sl);
        }
 
        auto signer = Config::instance()->signer_chain();
@@ -666,7 +688,6 @@ Writer::finish (boost::filesystem::path output_dcp)
        }
 
        dcp.write_xml (
-               film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE,
                issuer,
                creator,
                dcp::LocalTime().as_string(),
@@ -696,13 +717,19 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp)
        boost::algorithm::replace_all (text, "$CPL_NAME", film()->name());
        boost::algorithm::replace_all (text, "$TYPE", film()->dcp_content_type()->pretty_name());
        boost::algorithm::replace_all (text, "$CONTAINER", film()->container()->container_nickname());
-       boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", film()->isdcf_metadata().audio_language);
+
+       auto audio_languages = film()->audio_languages();
+       if (!audio_languages.empty()) {
+               boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", audio_languages.front().description());
+       } else {
+               boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", _("None"));
+       }
 
        auto subtitle_languages = film()->subtitle_languages();
-       if (subtitle_languages.empty()) {
-               boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", "None");
+       if (subtitle_languages.first) {
+               boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", subtitle_languages.first->description());
        } else {
-               boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", subtitle_languages.front().description());
+               boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", _("None"));
        }
 
        boost::uintmax_t size = 0;
@@ -733,15 +760,14 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp)
        }
        boost::algorithm::replace_all (text, "$AUDIO", description);
 
-       int h, m, s, fr;
-       film()->length().split(film()->video_frame_rate(), h, m, s, fr);
+       auto const hmsf = film()->length().split(film()->video_frame_rate());
        string length;
-       if (h == 0 && m == 0) {
-               length = String::compose("%1s", s);
-       } else if (h == 0 && m > 0) {
-               length = String::compose("%1m%2s", m, s);
-       } else if (h > 0 && m > 0) {
-               length = String::compose("%1h%2m%3s", h, m, s);
+       if (hmsf.h == 0 && hmsf.m == 0) {
+               length = String::compose("%1s", hmsf.s);
+       } else if (hmsf.h == 0 && hmsf.m > 0) {
+               length = String::compose("%1m%2s", hmsf.m, hmsf.s);
+       } else if (hmsf.h > 0 && hmsf.m > 0) {
+               length = String::compose("%1h%2m%3s", hmsf.h, hmsf.m, hmsf.s);
        }
 
        boost::algorithm::replace_all (text, "$LENGTH", length);
@@ -802,6 +828,11 @@ Writer::write (PlayerText text, TextType type, optional<DCPTextTrack> track, DCP
                write_hanging_text (**reel);
        }
 
+       auto back_off = [this](DCPTimePeriod period) {
+               period.to -= DCPTime::from_frames(2, film()->video_frame_rate());
+               return period;
+       };
+
        if (period.to > (*reel)->period().to) {
                /* This text goes off the end of the reel.  Store parts of it that should go into
                 * other reels.
@@ -809,13 +840,14 @@ Writer::write (PlayerText text, TextType type, optional<DCPTextTrack> track, DCP
                for (auto i = std::next(*reel); i != _reels.end(); ++i) {
                        auto overlap = i->period().overlap(period);
                        if (overlap) {
-                               _hanging_texts.push_back (HangingText{text, type, track, *overlap});
+                               _hanging_texts.push_back (HangingText{text, type, track, back_off(*overlap)});
                        }
                }
                /* Back off from the reel boundary by a couple of frames to avoid tripping checks
                 * for subtitles being too close together.
                 */
-               period.to = (*reel)->period().to - DCPTime::from_frames(2, film()->video_frame_rate());
+               period.to = (*reel)->period().to;
+               period = back_off(period);
        }
 
        (*reel)->write (text, type, track, period);