X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Fj2k_encoder.cc;h=64cd3814784306877628794326fdcec462cd88af;hp=3d1df688c2d718cc2da9a4b2a0c8e00a3a4d6b33;hb=44532cd5f87df3ef10bbbd6b987492e36e4a0eb6;hpb=8e4a2e5ea578ac4f0f41edb6145d5c0040e33ec2 diff --git a/src/lib/j2k_encoder.cc b/src/lib/j2k_encoder.cc index 3d1df688c..64cd38147 100644 --- a/src/lib/j2k_encoder.cc +++ b/src/lib/j2k_encoder.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington + Copyright (C) 2012-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -26,6 +26,7 @@ #include "util.h" #include "film.h" #include "log.h" +#include "dcpomatic_log.h" #include "config.h" #include "dcp_video.h" #include "cross.h" @@ -41,18 +42,14 @@ #include "i18n.h" -#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL); -#define LOG_GENERAL_NC(...) _film->log()->log (__VA_ARGS__, LogEntry::TYPE_GENERAL); -#define LOG_ERROR(...) _film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_ERROR); -#define LOG_TIMING(...) _film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_TIMING); -#define LOG_DEBUG_ENCODE(...) _film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_DEBUG_ENCODE); - using std::list; using std::cout; +using std::exception; using boost::shared_ptr; using boost::weak_ptr; using boost::optional; using dcp::Data; +using namespace dcpomatic; /** @param film Film that we are encoding. * @param writer Writer that we are using. @@ -67,14 +64,7 @@ J2KEncoder::J2KEncoder (shared_ptr film, shared_ptr writer) J2KEncoder::~J2KEncoder () { - try { - terminate_threads (); - } catch (...) { - /* Destructors must not throw exceptions; anything bad - happening now is too late to worry about anyway, - I think. - */ - } + terminate_threads (); } void @@ -119,6 +109,9 @@ J2KEncoder::end () terminate_threads (); + /* Something might have been thrown during terminate_threads */ + rethrow (); + LOG_GENERAL (N_("Mopping up %1"), _queue.size()); /* The following sequence of events can occur in the above code: @@ -134,9 +127,9 @@ J2KEncoder::end () LOG_GENERAL (N_("Encode left-over frame %1"), (*i)->index ()); try { _writer->write ( - (*i)->encode_locally (boost::bind (&Log::dcp_log, _film->log().get(), _1, _2)), - (*i)->index (), - (*i)->eyes () + (*i)->encode_locally(), + (*i)->index(), + (*i)->eyes() ); frame_done (); } catch (std::exception& e) { @@ -146,9 +139,9 @@ J2KEncoder::end () } /** @return an estimate of the current number of frames we are encoding per second, - * or 0 if not known. + * if known. */ -float +optional J2KEncoder::current_encoding_rate () const { return _history.rate (); @@ -185,11 +178,7 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) { _waker.nudge (); - size_t threads = 0; - { - boost::mutex::scoped_lock threads_lock (_threads_mutex); - threads = _threads.size (); - } + size_t threads = _threads->size(); boost::mutex::scoped_lock queue_lock (_queue_mutex); @@ -216,7 +205,7 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) LOG_DEBUG_ENCODE("Frame @ %1 FAKE", to_string(time)); _writer->fake_write (position, pv->eyes ()); frame_done (); - } else if (pv->has_j2k ()) { + } else if (pv->has_j2k() && !_film->reencode_j2k()) { LOG_DEBUG_ENCODE("Frame @ %1 J2K", to_string(time)); /* This frame already has J2K data, so just write it */ _writer->write (pv->j2k(), position, pv->eyes ()); @@ -233,8 +222,7 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) position, _film->video_frame_rate(), _film->j2k_bandwidth(), - _film->resolution(), - _film->log() + _film->resolution() ) )); @@ -251,24 +239,22 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) void J2KEncoder::terminate_threads () { - boost::mutex::scoped_lock threads_lock (_threads_mutex); + boost::this_thread::disable_interruption dis; - int n = 0; - for (list::iterator i = _threads.begin(); i != _threads.end(); ++i) { - LOG_GENERAL ("Terminating thread %1 of %2", n + 1, _threads.size ()); - (*i)->interrupt (); - DCPOMATIC_ASSERT ((*i)->joinable ()); - try { - (*i)->join (); - } catch (boost::thread_interrupted& e) { - /* This is to be expected */ - } - delete *i; - LOG_GENERAL_NC ("Thread terminated"); - ++n; + if (!_threads) { + return; } - _threads.clear (); + _threads->interrupt_all (); + try { + _threads->join_all (); + } catch (exception& e) { + LOG_ERROR ("join() threw an exception: %1", e.what()); + } catch (...) { + LOG_ERROR_NC ("join() threw an exception"); + } + + _threads.reset (); } void @@ -338,7 +324,7 @@ try } else { try { LOG_TIMING ("start-local-encode thread=%1 frame=%2", thread_id(), vf->index()); - encoded = vf->encode_locally (boost::bind (&Log::dcp_log, _film->log().get(), _1, _2)); + encoded = vf->encode_locally (); LOG_TIMING ("finish-local-encode thread=%1 frame=%2", thread_id(), vf->index()); } catch (std::exception& e) { /* This is very bad, so don't cope with it, just pass it on */ @@ -382,42 +368,31 @@ void J2KEncoder::servers_list_changed () { terminate_threads (); + _threads.reset (new boost::thread_group()); /* XXX: could re-use threads */ - boost::mutex::scoped_lock lm (_threads_mutex); - -#ifdef BOOST_THREAD_PLATFORM_WIN32 - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - GetVersionEx (&info); - bool const windows_xp = (info.dwMajorVersion == 5 && info.dwMinorVersion == 1); - if (windows_xp) { - LOG_GENERAL_NC (N_("Setting thread affinity for Windows XP")); - } -#endif - if (!Config::instance()->only_servers_encode ()) { for (int i = 0; i < Config::instance()->master_encoding_threads (); ++i) { - boost::thread* t = new boost::thread (boost::bind (&J2KEncoder::encoder_thread, this, optional ())); #ifdef DCPOMATIC_LINUX + boost::thread* t = _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, optional())); pthread_setname_np (t->native_handle(), "encode-worker"); -#endif - _threads.push_back (t); -#ifdef BOOST_THREAD_PLATFORM_WIN32 - if (windows_xp) { - SetThreadAffinityMask (t->native_handle(), 1 << i); - } +#else + _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, optional())); #endif } } - BOOST_FOREACH (EncodeServerDescription i, EncodeServerFinder::instance()->servers ()) { + BOOST_FOREACH (EncodeServerDescription i, EncodeServerFinder::instance()->servers()) { + if (!i.current_link_version()) { + continue; + } + LOG_GENERAL (N_("Adding %1 worker threads for remote %2"), i.threads(), i.host_name ()); for (int j = 0; j < i.threads(); ++j) { - _threads.push_back (new boost::thread (boost::bind (&J2KEncoder::encoder_thread, this, i))); + _threads->create_thread(boost::bind(&J2KEncoder::encoder_thread, this, i)); } } - _writer->set_encoder_threads (_threads.size ()); + _writer->set_encoder_threads (_threads->size()); }