X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Fwriter.cc;h=3aca2ab89c96328445907dbbd88ae64156b722ac;hp=7208402e45704002fc3f635bd2d3e16755ff47b4;hb=8a8c977c12fc65f1f50ea05099387e0fc8840e7d;hpb=c370c651eba466f5073384de8b304a2625c64b89 diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 7208402e4..3aca2ab89 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -54,13 +54,9 @@ using std::cout; using std::dynamic_pointer_cast; -using std::list; -using std::make_pair; using std::make_shared; -using std::map; using std::max; using std::min; -using std::pair; using std::shared_ptr; using std::string; using std::vector; @@ -74,14 +70,6 @@ using dcp::ArrayData; using namespace dcpomatic; -static -void -ignore_progress (float) -{ - -} - - /** @param j Job to report progress to, or 0. * @param text_only true to enable only the text (subtitle/ccap) parts of the writer. */ @@ -535,36 +523,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( - film()->dcp_name(), - film()->dcp_content_type()->libdcp_kind(), - film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE - ); - - dcp.add (cpl); - - /* Calculate digests for each reel in parallel */ - auto job = _job.lock (); if (job) { job->sub (_("Computing digests")); @@ -575,17 +536,19 @@ Writer::finish (boost::filesystem::path output_dcp) auto work = make_shared(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)); } - boost::function set_progress; + std::function set_progress; if (job) { set_progress = boost::bind (&Writer::set_digest_progress, this, job.get(), _1); } else { - set_progress = &ignore_progress; + set_progress = [](float) { + boost::this_thread::interruption_point(); + }; } for (auto& i: _reels) { @@ -594,8 +557,50 @@ Writer::finish (boost::filesystem::path output_dcp) service.post (boost::bind (&Writer::calculate_referenced_digests, this, set_progress)); work.reset (); - pool.join_all (); + + try { + pool.join_all (); + } catch (boost::thread_interrupted) { + /* join_all was interrupted, so we need to interrupt the threads + * in our pool then try again to join them. + */ + pool.interrupt_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( + film()->dcp_name(), + film()->dcp_content_type()->libdcp_kind(), + film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE + ); + + dcp.add (cpl); + + calculate_digests (); /* Add reels */ @@ -615,12 +620,18 @@ Writer::finish (boost::filesystem::path output_dcp) issuer = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit); } + cpl->set_creator (creator); + cpl->set_issuer (issuer); + cpl->set_ratings (film()->ratings()); vector cv; for (auto i: film()->content_versions()) { cv.push_back (dcp::ContentVersion(i)); } + if (cv.empty()) { + cv = { dcp::ContentVersion("1") }; + } cpl->set_content_versions (cv); cpl->set_full_content_title_text (film()->name()); @@ -642,6 +653,9 @@ Writer::finish (boost::filesystem::path output_dcp) if (film()->luminance()) { cpl->set_luminance (*film()->luminance()); } + if (film()->sign_language_video_language()) { + cpl->set_sign_language_video_language (*film()->sign_language_video_language()); + } auto ac = film()->mapped_audio_channels(); dcp::MCASoundField field = ( @@ -678,14 +692,11 @@ Writer::finish (boost::filesystem::path output_dcp) throw InvalidSignerError (reason); } - dcp.write_xml ( - issuer, - creator, - dcp::LocalTime().as_string(), - film()->dcp_name(), - signer, - Config::instance()->dcp_metadata_filename_format() - ); + dcp.set_issuer(issuer); + dcp.set_creator(creator); + dcp.set_annotation_text(film()->dcp_name()); + + dcp.write_xml (signer, Config::instance()->dcp_metadata_filename_format()); LOG_GENERAL ( N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT, %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk @@ -699,19 +710,23 @@ void Writer::write_cover_sheet (boost::filesystem::path output_dcp) { auto const cover = film()->file("COVER_SHEET.txt"); - auto f = fopen_boost (cover, "w"); + dcp::File f(cover, "w"); if (!f) { throw OpenFileError (cover, errno, OpenFileError::WRITE); } auto text = Config::instance()->cover_sheet (); boost::algorithm::replace_all (text, "$CPL_NAME", film()->name()); + auto cpls = film()->cpls(); + if (!cpls.empty()) { + boost::algorithm::replace_all (text, "$CPL_FILENAME", cpls[0].cpl_file.filename().string()); + } boost::algorithm::replace_all (text, "$TYPE", film()->dcp_content_type()->pretty_name()); boost::algorithm::replace_all (text, "$CONTAINER", film()->container()->container_nickname()); - auto audio_languages = film()->audio_languages(); - if (!audio_languages.empty()) { - boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", audio_languages.front().description()); + auto audio_language = film()->audio_language(); + if (audio_language) { + boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", audio_language->description()); } else { boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", _("None")); } @@ -763,8 +778,7 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp) boost::algorithm::replace_all (text, "$LENGTH", length); - checked_fwrite (text.c_str(), text.length(), f, cover); - fclose (f); + f.checked_write(text.c_str(), text.length()); } @@ -932,12 +946,15 @@ Writer::set_digest_progress (Job* job, float progress) Waker waker; waker.nudge (); + + boost::this_thread::interruption_point(); } /** Calculate hashes for any referenced MXF assets which do not already have one */ void -Writer::calculate_referenced_digests (boost::function set_progress) +Writer::calculate_referenced_digests (std::function set_progress) +try { for (auto const& i: _reel_assets) { auto file = dynamic_pointer_cast(i.asset); @@ -946,6 +963,10 @@ Writer::calculate_referenced_digests (boost::function set_progress file->set_hash (file->asset_ref().asset()->hash()); } } +} 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. + */ }