X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fencoder.cc;h=da6c969052f4a4d8e59f37043263b2c3fa258851;hb=09d7c1aeab76040e1dcbd829fbf734c4f4706180;hp=8caa0190c38726121d182b1f81e27ebf99b85295;hpb=39029279954b1f346d3ba28ec12c58211bfa7436;p=dcpomatic.git diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 8caa0190c..da6c96905 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -21,9 +21,6 @@ * @brief Parent class for classes which can encode video and audio frames. */ -#include -#include -#include #include "encoder.h" #include "util.h" #include "film.h" @@ -36,6 +33,9 @@ #include "server_finder.h" #include "player.h" #include "player_video.h" +#include +#include +#include #include "i18n.h" @@ -80,7 +80,7 @@ Encoder::~Encoder () void Encoder::add_worker_threads (ServerDescription d) { - LOG_GENERAL (N_("Adding %1 worker threads for remote %2"), d.host_name ()); + LOG_GENERAL (N_("Adding %1 worker threads for remote %2"), d.threads(), d.host_name ()); for (int i = 0; i < d.threads(); ++i) { _threads.push_back (new boost::thread (boost::bind (&Encoder::encoder_thread, this, d))); } @@ -176,8 +176,11 @@ Encoder::frame_done () } } +/** Called in order, so each time this is called the supplied frame is the one + * after the previous one. + */ void -Encoder::enqueue (shared_ptr pvf) +Encoder::enqueue (shared_ptr pv) { _waker.nudge (); @@ -204,16 +207,18 @@ Encoder::enqueue (shared_ptr pvf) rethrow (); if (_writer->can_fake_write (_video_frames_out)) { - _writer->fake_write (_video_frames_out, pvf->eyes ()); + /* We can fake-write this frame */ + _writer->fake_write (_video_frames_out, pv->eyes ()); frame_done (); - } else if (pvf->has_j2k ()) { - _writer->write (pvf->j2k(), _video_frames_out, pvf->eyes ()); + } else if (pv->has_j2k ()) { + /* This frame already has JPEG2000 data, so just write it */ + _writer->write (pv->j2k(), _video_frames_out, pv->eyes ()); } else { /* Queue this new frame for encoding */ LOG_TIMING ("adding to queue of %1", _queue.size ()); _queue.push_back (shared_ptr ( new DCPVideo ( - pvf, + pv, _video_frames_out, _film->video_frame_rate(), _film->j2k_bandwidth(), @@ -229,7 +234,7 @@ Encoder::enqueue (shared_ptr pvf) _empty_condition.notify_all (); } - if (pvf->eyes() != EYES_LEFT) { + if (pv->eyes() != EYES_LEFT) { ++_video_frames_out; } } @@ -263,6 +268,8 @@ try encodings. */ int remote_backoff = 0; + shared_ptr last_dcp_video; + shared_ptr last_encoded; while (true) { @@ -285,38 +292,47 @@ try shared_ptr encoded; - if (server) { - try { - encoded = vf->encode_remotely (server.get ()); - - if (remote_backoff > 0) { - LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", server->host_name ()); + if (last_dcp_video && vf->same (last_dcp_video)) { + /* We already have encoded data for the same input as this one, so take a short-cut */ + encoded = last_encoded; + } else { + /* We need to encode this input */ + if (server) { + try { + encoded = vf->encode_remotely (server.get ()); + + if (remote_backoff > 0) { + LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", server->host_name ()); + } + + /* This job succeeded, so remove any backoff */ + remote_backoff = 0; + + } catch (std::exception& e) { + if (remote_backoff < 60) { + /* back off more */ + remote_backoff += 10; + } + LOG_ERROR ( + N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"), + vf->index(), server->host_name(), e.what(), remote_backoff + ); } - /* This job succeeded, so remove any backoff */ - remote_backoff = 0; - - } catch (std::exception& e) { - if (remote_backoff < 60) { - /* back off more */ - remote_backoff += 10; + } else { + try { + LOG_TIMING ("[%1] encoder thread begins local encode of %2", boost::this_thread::get_id(), vf->index()); + encoded = vf->encode_locally (); + LOG_TIMING ("[%1] encoder thread finishes local encode of %2", boost::this_thread::get_id(), vf->index()); + } catch (std::exception& e) { + LOG_ERROR (N_("Local encode failed (%1)"), e.what ()); } - LOG_ERROR ( - N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"), - vf->index(), server->host_name(), e.what(), remote_backoff - ); - } - - } else { - try { - LOG_TIMING ("[%1] encoder thread begins local encode of %2", boost::this_thread::get_id(), vf->index()); - encoded = vf->encode_locally (); - LOG_TIMING ("[%1] encoder thread finishes local encode of %2", boost::this_thread::get_id(), vf->index()); - } catch (std::exception& e) { - LOG_ERROR (N_("Local encode failed (%1)"), e.what ()); } } + last_dcp_video = vf; + last_encoded = encoded; + if (encoded) { _writer->write (encoded, vf->index (), vf->eyes ()); frame_done ();