X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fj2k_encoder.cc;h=d2e840f85f2a87ce647789321525fb5a14782bad;hb=bfd6bd32b5e20c479170452a66cb44eff59feacd;hp=7c6e2347733f361c7054f3bd862b7bf1e2d19357;hpb=9b946fc5250eff5a5dd4a661896916fcd5d9bd4b;p=dcpomatic.git diff --git a/src/lib/j2k_encoder.cc b/src/lib/j2k_encoder.cc index 7c6e23477..d2e840f85 100644 --- a/src/lib/j2k_encoder.cc +++ b/src/lib/j2k_encoder.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,43 +18,46 @@ */ + /** @file src/j2k_encoder.cc * @brief J2K encoder class. */ -#include "j2k_encoder.h" -#include "util.h" -#include "film.h" -#include "log.h" -#include "dcpomatic_log.h" + +#include "compose.hpp" #include "config.h" -#include "dcp_video.h" #include "cross.h" -#include "writer.h" +#include "dcp_video.h" +#include "dcpomatic_log.h" +#include "encode_server_description.h" #include "encode_server_finder.h" -#include "player.h" +#include "film.h" +#include "j2k_encoder.h" +#include "log.h" #include "player_video.h" -#include "encode_server_description.h" -#include "compose.hpp" +#include "util.h" +#include "writer.h" #include #include #include "i18n.h" -using std::list; + using std::cout; using std::exception; +using std::list; +using std::make_shared; using std::shared_ptr; using std::weak_ptr; -using std::make_shared; using boost::optional; using dcp::Data; using namespace dcpomatic; + /** @param film Film that we are encoding. * @param writer Writer that we are using. */ -J2KEncoder::J2KEncoder (shared_ptr film, shared_ptr writer) +J2KEncoder::J2KEncoder(shared_ptr film, Writer& writer) : _film (film) , _history (200) , _writer (writer) @@ -62,33 +65,24 @@ J2KEncoder::J2KEncoder (shared_ptr film, shared_ptr writer) servers_list_changed (); } + J2KEncoder::~J2KEncoder () { + _server_found_connection.disconnect(); + boost::mutex::scoped_lock lm (_threads_mutex); terminate_threads (); } + void J2KEncoder::begin () { - weak_ptr wp = shared_from_this (); - _server_found_connection = EncodeServerFinder::instance()->ServersListChanged.connect ( - boost::bind (&J2KEncoder::call_servers_list_changed, wp) + _server_found_connection = EncodeServerFinder::instance()->ServersListChanged.connect( + boost::bind(&J2KEncoder::servers_list_changed, this) ); } -/* We don't want the servers-list-changed callback trying to do things - during destruction of J2KEncoder, and I think this is the neatest way - to achieve that. -*/ -void -J2KEncoder::call_servers_list_changed (weak_ptr encoder) -{ - auto e = encoder.lock (); - if (e) { - e->servers_list_changed (); - } -} void J2KEncoder::end () @@ -127,13 +121,13 @@ J2KEncoder::end () So just mop up anything left in the queue here. */ - for (auto i: _queue) { - LOG_GENERAL(N_("Encode left-over frame %1"), i->index()); + for (auto const& i: _queue) { + LOG_GENERAL(N_("Encode left-over frame %1"), i.index()); try { - _writer->write ( - make_shared(i->encode_locally()), - i->index(), - i->eyes() + _writer.write( + make_shared(i.encode_locally()), + i.index(), + i.eyes() ); frame_done (); } catch (std::exception& e) { @@ -142,6 +136,7 @@ J2KEncoder::end () } } + /** @return an estimate of the current number of frames we are encoding per second, * if known. */ @@ -151,6 +146,7 @@ J2KEncoder::current_encoding_rate () const return _history.rate (); } + /** @return Number of video frames that have been queued for encoding */ int J2KEncoder::video_frames_enqueued () const @@ -162,6 +158,7 @@ J2KEncoder::video_frames_enqueued () const return _last_player_video_time->frames_floor (_film->video_frame_rate ()); } + /** Should be called when a frame has been encoded successfully */ void J2KEncoder::frame_done () @@ -169,6 +166,7 @@ J2KEncoder::frame_done () _history.event (); } + /** Called to request encoding of the next video frame in the DCP. This is called in order, * so each time the supplied frame is the one after the previous one. * pv represents one video frame, and could be empty if there is nothing to encode @@ -199,7 +197,7 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) LOG_TIMING ("decoder-wake queue=%1 threads=%2", _queue.size(), threads); } - _writer->rethrow (); + _writer.rethrow(); /* Re-throw any exception raised by one of our threads. If more than one has thrown an exception, only one will be rethrown, I think; but then, if that happens something has gone badly wrong. @@ -208,24 +206,24 @@ J2KEncoder::encode (shared_ptr pv, DCPTime time) auto const position = time.frames_floor(_film->video_frame_rate()); - if (_writer->can_fake_write (position)) { + if (_writer.can_fake_write(position)) { /* We can fake-write this frame */ LOG_DEBUG_ENCODE("Frame @ %1 FAKE", to_string(time)); - _writer->fake_write (position, pv->eyes ()); + _writer.fake_write(position, pv->eyes ()); frame_done (); } 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 ()); + _writer.write(pv->j2k(), position, pv->eyes ()); frame_done (); - } else if (_last_player_video[pv->eyes()] && _writer->can_repeat(position) && pv->same (_last_player_video[pv->eyes()])) { + } else if (_last_player_video[pv->eyes()] && _writer.can_repeat(position) && pv->same(_last_player_video[pv->eyes()])) { LOG_DEBUG_ENCODE("Frame @ %1 REPEAT", to_string(time)); - _writer->repeat (position, pv->eyes ()); + _writer.repeat(position, pv->eyes()); } else { LOG_DEBUG_ENCODE("Frame @ %1 ENCODE", to_string(time)); /* Queue this new frame for encoding */ LOG_TIMING ("add-frame-to-queue queue=%1", _queue.size ()); - _queue.push_back (make_shared( + _queue.push_back (DCPVideo( pv, position, _film->video_frame_rate(), @@ -266,10 +264,13 @@ J2KEncoder::terminate_threads () _threads.reset (); } + void J2KEncoder::encoder_thread (optional server) try { + start_of_thread ("J2KEncoder"); + if (server) { LOG_TIMING ("start-encoder-thread thread=%1 server=%2", thread_id (), server->host_name ()); } else { @@ -300,7 +301,7 @@ try { boost::this_thread::disable_interruption dis; - LOG_TIMING ("encoder-pop thread=%1 frame=%2 eyes=%3", thread_id(), vf->index(), (int) vf->eyes ()); + LOG_TIMING ("encoder-pop thread=%1 frame=%2 eyes=%3", thread_id(), vf.index(), static_cast(vf.eyes())); _queue.pop_front (); lock.unlock (); @@ -310,7 +311,7 @@ try /* We need to encode this input */ if (server) { try { - encoded = make_shared(vf->encode_remotely(server.get())); + encoded = make_shared(vf.encode_remotely(server.get())); if (remote_backoff > 0) { LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", server->host_name ()); @@ -326,15 +327,15 @@ try } LOG_ERROR ( N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"), - vf->index(), server->host_name(), e.what(), remote_backoff + vf.index(), server->host_name(), e.what(), remote_backoff ); } } else { try { - LOG_TIMING ("start-local-encode thread=%1 frame=%2", thread_id(), vf->index()); - encoded = make_shared(vf->encode_locally()); - LOG_TIMING ("finish-local-encode thread=%1 frame=%2", thread_id(), vf->index()); + LOG_TIMING ("start-local-encode thread=%1 frame=%2", thread_id(), vf.index()); + encoded = make_shared(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 */ LOG_ERROR (N_("Local encode failed (%1)"), e.what ()); @@ -343,11 +344,11 @@ try } if (encoded) { - _writer->write (encoded, vf->index(), vf->eyes()); + _writer.write(encoded, vf.index(), vf.eyes()); frame_done (); } else { lock.lock (); - LOG_GENERAL (N_("[%1] J2KEncoder thread pushes frame %2 back onto queue after failure"), thread_id(), vf->index()); + LOG_GENERAL (N_("[%1] J2KEncoder thread pushes frame %2 back onto queue after failure"), thread_id(), vf.index()); _queue.push_front (vf); lock.unlock (); } @@ -373,6 +374,7 @@ catch (...) _full_condition.notify_all (); } + void J2KEncoder::servers_list_changed () { @@ -405,5 +407,5 @@ J2KEncoder::servers_list_changed () } } - _writer->set_encoder_threads (_threads->size()); + _writer.set_encoder_threads(_threads->size()); }