+ TIMING ("encoder thread %1 wakes with queue of %2", boost::this_thread::get_id(), _queue.size());
+ boost::shared_ptr<DCPVideoFrame> vf = _queue.front ();
+ _film->log()->log (String::compose (N_("Encoder thread %1 pops frame %2 from queue"), boost::this_thread::get_id(), vf->frame()), Log::VERBOSE);
+ _queue.pop_front ();
+
+ lock.unlock ();
+
+ shared_ptr<EncodedData> encoded;
+
+ if (server) {
+ try {
+ encoded = vf->encode_remotely (server);
+
+ if (remote_backoff > 0) {
+ _film->log()->log (String::compose (N_("%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;
+ }
+ _film->log()->log (
+ String::compose (
+ N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"),
+ vf->frame(), server->host_name(), e.what(), remote_backoff)
+ );
+ }
+
+ } else {
+ try {
+ TIMING ("encoder thread %1 begins local encode of %2", boost::this_thread::get_id(), vf->frame());
+ encoded = vf->encode_locally ();
+ TIMING ("encoder thread %1 finishes local encode of %2", boost::this_thread::get_id(), vf->frame());
+ } catch (std::exception& e) {
+ _film->log()->log (String::compose (N_("Local encode failed (%1)"), e.what ()));
+ }
+ }
+
+ if (encoded) {
+ _writer->write (encoded, vf->frame ());
+ frame_done ();
+ } else {
+ lock.lock ();
+ _film->log()->log (
+ String::compose (N_("Encoder thread %1 pushes frame %2 back onto queue after failure"), boost::this_thread::get_id(), vf->frame())
+ );
+ _queue.push_front (vf);
+ lock.unlock ();
+ }
+
+ if (remote_backoff > 0) {
+ dvdomatic_sleep (remote_backoff);
+ }
+
+ lock.lock ();
+ _condition.notify_all ();