Improve transcode job progress reporting.
[dcpomatic.git] / src / lib / j2k_wav_encoder.cc
index e6a1b285e1ba4d4e01af731f115b28bf043c7f60..ef1e8edc1b1728285276163c0f4f2c129769387c 100644 (file)
@@ -38,6 +38,7 @@
 #include "server.h"
 #include "filter.h"
 #include "log.h"
+#include "cross.h"
 
 using namespace std;
 using namespace boost;
@@ -53,7 +54,7 @@ J2KWAVEncoder::J2KWAVEncoder (shared_ptr<const FilmState> s, shared_ptr<const Op
        */
        for (int i = 0; i < _fs->audio_channels; ++i) {
                SF_INFO sf_info;
-               sf_info.samplerate = _fs->audio_sample_rate;
+               sf_info.samplerate = dcp_audio_sample_rate (_fs->audio_sample_rate);
                /* We write mono files */
                sf_info.channels = 1;
                sf_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
@@ -125,11 +126,13 @@ J2KWAVEncoder::process_video (shared_ptr<Image> yuv, int frame)
                                          ));
                
                _worker_condition.notify_all ();
+       } else {
+               frame_skipped ();
        }
 }
 
 void
-J2KWAVEncoder::encoder_thread (Server* server)
+J2KWAVEncoder::encoder_thread (ServerDescription* server)
 {
        /* Number of seconds that we currently wait between attempts
           to connect to the server; not relevant for localhost
@@ -173,7 +176,7 @@ J2KWAVEncoder::encoder_thread (Server* server)
                                        remote_backoff += 10;
                                }
                                stringstream s;
-                               s << "Remote encode on " << server->host_name() << " failed (" << e.what() << "); thread sleeping for " << remote_backoff << "s.";
+                               s << "Remote encode of " << vf->frame() << " on " << server->host_name() << " failed (" << e.what() << "); thread sleeping for " << remote_backoff << "s.";
                                _log->log (s.str ());
                        }
                                
@@ -189,7 +192,7 @@ J2KWAVEncoder::encoder_thread (Server* server)
 
                if (encoded) {
                        encoded->write (_opt, vf->frame ());
-                       frame_done ();
+                       frame_done (vf->frame ());
                } else {
                        lock.lock ();
                        _queue.push_front (vf);
@@ -197,7 +200,7 @@ J2KWAVEncoder::encoder_thread (Server* server)
                }
 
                if (remote_backoff > 0) {
-                       sleep (remote_backoff);
+                       dvdomatic_sleep (remote_backoff);
                }
 
                lock.lock ();
@@ -209,12 +212,12 @@ void
 J2KWAVEncoder::process_begin ()
 {
        for (int i = 0; i < Config::instance()->num_local_encoding_threads (); ++i) {
-               _worker_threads.push_back (new boost::thread (boost::bind (&J2KWAVEncoder::encoder_thread, this, (Server *) 0)));
+               _worker_threads.push_back (new boost::thread (boost::bind (&J2KWAVEncoder::encoder_thread, this, (ServerDescription *) 0)));
        }
 
-       vector<Server*> servers = Config::instance()->servers ();
+       vector<ServerDescription*> servers = Config::instance()->servers ();
 
-       for (vector<Server*>::iterator i = servers.begin(); i != servers.end(); ++i) {
+       for (vector<ServerDescription*>::iterator i = servers.begin(); i != servers.end(); ++i) {
                for (int j = 0; j < (*i)->threads (); ++j) {
                        _worker_threads.push_back (new boost::thread (boost::bind (&J2KWAVEncoder::encoder_thread, this, *i)));
                }
@@ -235,6 +238,31 @@ J2KWAVEncoder::process_end ()
        lock.unlock ();
        
        terminate_worker_threads ();
+
+       /* The following sequence of events can occur in the above code:
+            1. a remote worker takes the last image off the queue
+            2. the loop above terminates
+            3. the remote worker fails to encode the image and puts it back on the queue
+            4. the remote worker is then terminated by terminate_worker_threads
+
+            So just mop up anything left in the queue here.
+       */
+
+       for (list<shared_ptr<DCPVideoFrame> >::iterator i = _queue.begin(); i != _queue.end(); ++i) {
+               stringstream s;
+               s << "Encode left-over frame " << (*i)->frame();
+               _log->log (s.str ());
+               try {
+                       shared_ptr<EncodedData> e = (*i)->encode_locally ();
+                       e->write (_opt, (*i)->frame ());
+                       frame_done ((*i)->frame ());
+               } catch (std::exception& e) {
+                       stringstream s;
+                       s << "Local encode failed " << e.what() << ".";
+                       _log->log (s.str ());
+               }
+       }
+       
        close_sound_files ();
 
        /* Rename .wav.tmp files to .wav */