X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fwriter.cc;h=909b1e4484d1c19b1cbc56b751131a098215534a;hb=68a5daa79ed34bae144de1dc252a4c6539e08fa1;hp=a023d5cd2e1cc28992573e180bc2ccd9cc540cbc;hpb=6de35d058821acc092d2aae75543024a97026b8a;p=dcpomatic.git diff --git a/src/lib/writer.cc b/src/lib/writer.cc index a023d5cd2..909b1e448 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -17,20 +17,6 @@ */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "writer.h" #include "compose.hpp" #include "film.h" @@ -46,12 +32,32 @@ #include "md5_digester.h" #include "encoded_data.h" #include "version.h" +#include "font.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "i18n.h" #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); #define LOG_TIMING(...) _film->log()->microsecond_log (String::compose (__VA_ARGS__), Log::TYPE_TIMING); #define LOG_WARNING_NC(...) _film->log()->log (__VA_ARGS__, Log::TYPE_WARNING); +#define LOG_WARNING(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_WARNING); +#define LOG_ERROR(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_ERROR); +#define LOG_DEBUG(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_DEBUG); +#define LOG_DEBUG_NC(...) _film->log()->log (__VA_ARGS__, Log::TYPE_DEBUG); /* OS X strikes again */ #undef set_key @@ -84,7 +90,7 @@ Writer::Writer (shared_ptr f, weak_ptr j) boost::filesystem::remove_all (_film->dir (_film->dcp_name ())); shared_ptr job = _job.lock (); - assert (job); + DCPOMATIC_ASSERT (job); job->sub (_("Checking existing image data")); check_existing_picture_mxf (); @@ -184,6 +190,9 @@ Writer::fake_write (int frame, Eyes eyes) } FILE* ifi = fopen_boost (_film->info_path (frame, eyes), "r"); + if (!ifi) { + throw ReadFileError (_film->info_path (frame, eyes)); + } dcp::FrameInfo info (ifi); fclose (ifi); @@ -252,6 +261,9 @@ try { boost::mutex::scoped_lock lock (_mutex); + /* This is for debugging only */ + bool done_something = false; + while (true) { if (_finish || _queued_full_in_memory > _maximum_frames_in_memory || have_sequenced_image_at_queue_head ()) { @@ -269,8 +281,30 @@ try return; } + /* We stop here if we have been asked to finish, and if either the queue + is empty or we do not have a sequenced image at its head (if this is the + case we will never terminate as no new frames will be sent once + _finish is true). + */ + if (_finish && (!have_sequenced_image_at_queue_head() || _queue.empty())) { + done_something = true; + /* (Hopefully temporarily) log anything that was not written */ + if (!_queue.empty() && !have_sequenced_image_at_queue_head()) { + LOG_WARNING (N_("Finishing writer with a left-over queue of %1:"), _queue.size()); + for (list::const_iterator i = _queue.begin(); i != _queue.end(); ++i) { + if (i->type == QueueItem::FULL) { + LOG_WARNING (N_("- type FULL, frame %1, eyes %2"), i->frame, i->eyes); + } else { + LOG_WARNING (N_("- type FAKE, size %1, frame %2, eyes %3"), i->size, i->frame, i->eyes); + } + } + LOG_WARNING (N_("Last written frame %1, last written eyes %2"), _last_written_frame, _last_written_eyes); + } + return; + } /* Write any frames that we can write; i.e. those that are in sequence. */ while (have_sequenced_image_at_queue_head ()) { + done_something = true; QueueItem qi = _queue.front (); _queue.pop_front (); if (qi.type == QueueItem::FULL && qi.encoded) { @@ -305,7 +339,7 @@ try _last_written_eyes = qi.eyes; shared_ptr job = _job.lock (); - assert (job); + DCPOMATIC_ASSERT (job); int64_t total = _film->length().frames (_film->video_frame_rate ()); if (_film->three_d ()) { /* _full_written and so on are incremented for each eye, so we need to double the total @@ -319,6 +353,7 @@ try } while (_queued_full_in_memory > _maximum_frames_in_memory) { + done_something = true; /* Too many frames in memory which can't yet be written to the stream. Write some FULL frames to disk. */ @@ -330,7 +365,7 @@ try ++i; } - assert (i != _queue.rend()); + DCPOMATIC_ASSERT (i != _queue.rend()); QueueItem qi = *i; ++_pushed_to_disk; @@ -349,6 +384,14 @@ try --_queued_full_in_memory; } + if (!done_something) { + LOG_DEBUG_NC ("Writer loop ran without doing anything"); + LOG_DEBUG ("_queued_full_in_memory=%1", _queued_full_in_memory); + LOG_DEBUG ("_queue_size=%1", _queue.size ()); + LOG_DEBUG ("_finish=%1", _finish); + LOG_DEBUG ("_last_written_frame=%1", _last_written_frame); + } + /* The queue has probably just gone down a bit; notify anything wait()ing on _full_condition */ _full_condition.notify_all (); } @@ -406,9 +449,12 @@ Writer::finish () boost::system::error_code ec; boost::filesystem::create_hard_link (video_from, video_to, ec); if (ec) { - /* hard link failed; copy instead */ - boost::filesystem::copy_file (video_from, video_to); - LOG_WARNING_NC ("Hard-link failed; fell back to copying"); + LOG_WARNING_NC ("Hard-link failed; copying instead"); + boost::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(), ec.message ()); + throw FileError (ec.message(), video_from); + } } _picture_mxf->set_file (video_to); @@ -477,7 +523,7 @@ Writer::finish () cpl->add (reel); shared_ptr job = _job.lock (); - assert (job); + DCPOMATIC_ASSERT (job); job->sub (_("Computing image digest")); _picture_mxf->hash (boost::bind (&Job::set_progress, job.get(), _1, false)); @@ -565,7 +611,7 @@ Writer::check_existing_picture_mxf () while (true) { shared_ptr job = _job.lock (); - assert (job); + DCPOMATIC_ASSERT (job); if (N > 0) { job->set_progress (float (_first_nonexistant_frame) / N); @@ -609,11 +655,9 @@ Writer::write (PlayerSubtitles subs) if (subs.text.empty ()) { return; } - + if (!_subtitle_content) { - _subtitle_content.reset ( - new dcp::SubtitleContent (_film->name(), _film->isdcf_metadata().subtitle_language) - ); + _subtitle_content.reset (new dcp::InteropSubtitleContent (_film->name(), _film->subtitle_language ())); } for (list::const_iterator i = subs.text.begin(); i != subs.text.end(); ++i) { @@ -621,6 +665,23 @@ Writer::write (PlayerSubtitles subs) } } +void +Writer::write (list > fonts) +{ + if (fonts.empty ()) { + return; + } + + if (!_subtitle_content) { + _subtitle_content.reset (new dcp::InteropSubtitleContent (_film->name(), _film->subtitle_language ())); + } + + for (list >::const_iterator i = fonts.begin(); i != fonts.end(); ++i) { + /* XXX: this LiberationSans-Regular needs to be a path to a DCP-o-matic-distributed copy */ + _subtitle_content->add_font ((*i)->id, (*i)->file.get_value_or ("LiberationSans-Regular.ttf").leaf().string ()); + } +} + bool operator< (QueueItem const & a, QueueItem const & b) {