Another writer deadlock fix.
[dcpomatic.git] / src / lib / writer.cc
index 10e4514fbcc134ef333d333d5086511b6b5660a3..96fb9e179cc30b76ae5815899c4bf2f86187339f 100644 (file)
@@ -74,7 +74,9 @@ Writer::Writer (shared_ptr<const Film> film, weak_ptr<Job> j)
        , _thread (0)
        , _finish (false)
        , _queued_full_in_memory (0)
-       , _maximum_frames_in_memory (0)
+       /* These will be reset to sensible values when J2KEncoder is created */
+       , _maximum_frames_in_memory (8)
+       , _maximum_queue_size (8)
        , _full_written (0)
        , _fake_written (0)
        , _repeat_written (0)
@@ -106,6 +108,9 @@ void
 Writer::start ()
 {
        _thread = new boost::thread (boost::bind (&Writer::thread, this));
+#ifdef DCPOMATIC_LINUX
+       pthread_setname_np (_thread->native_handle(), "writer");
+#endif
 }
 
 Writer::~Writer ()
@@ -125,7 +130,7 @@ Writer::write (Data encoded, Frame frame, Eyes eyes)
        boost::mutex::scoped_lock lock (_state_mutex);
 
        while (_queued_full_in_memory > _maximum_frames_in_memory) {
-               /* The queue is too big; wait until that is sorted out */
+               /* There are too many full frames in memory; wait until that is sorted out */
                _full_condition.wait (lock);
        }
 
@@ -168,8 +173,10 @@ Writer::repeat (Frame frame, Eyes eyes)
 {
        boost::mutex::scoped_lock lock (_state_mutex);
 
-       while (_queued_full_in_memory > _maximum_frames_in_memory) {
-               /* The queue is too big; wait until that is sorted out */
+       while (_queue.size() > _maximum_queue_size && have_sequenced_image_at_queue_head()) {
+               /* The queue is too big, and the main writer thread can run and fix it, so
+                  wait until it has done.
+               */
                _full_condition.wait (lock);
        }
 
@@ -196,8 +203,10 @@ Writer::fake_write (Frame frame, Eyes eyes)
 {
        boost::mutex::scoped_lock lock (_state_mutex);
 
-       while (_queued_full_in_memory > _maximum_frames_in_memory) {
-               /* The queue is too big; wait until that is sorted out */
+       while (_queue.size() > _maximum_queue_size && have_sequenced_image_at_queue_head()) {
+               /* The queue is too big, and the main writer thread can run and fix it, so
+                  wait until it has done.
+               */
                _full_condition.wait (lock);
        }
 
@@ -402,6 +411,7 @@ try
                        }
 
                        lock.lock ();
+                       _full_condition.notify_all ();
                }
 
                while (_queued_full_in_memory > _maximum_frames_in_memory) {
@@ -437,10 +447,8 @@ try
                        lock.lock ();
                        i->encoded.reset ();
                        --_queued_full_in_memory;
+                       _full_condition.notify_all ();
                }
-
-               /* The queue has probably just gone down a bit; notify anything wait()ing on _full_condition */
-               _full_condition.notify_all ();
        }
 }
 catch (...)
@@ -634,6 +642,11 @@ Writer::write_cover_sheet ()
 bool
 Writer::can_fake_write (Frame frame) const
 {
+       if (_film->encrypted()) {
+               /* We need to re-write the frame because the asset ID is embedded in the HMAC... I think... */
+               return false;
+       }
+
        /* We have to do a proper write of the first frame so that we can set up the JPEG2000
           parameters in the asset writer.
        */
@@ -652,10 +665,13 @@ Writer::write (PlayerSubtitles subs, DCPTimePeriod period)
                return;
        }
 
-       if (_subtitle_reel->period().to <= period.from) {
+       while (_subtitle_reel->period().to <= period.from) {
                ++_subtitle_reel;
+               DCPOMATIC_ASSERT (_subtitle_reel != _reels.end());
        }
 
+       DCPOMATIC_ASSERT (_subtitle_reel != _reels.end());
+
        _subtitle_reel->write (subs);
 }
 
@@ -701,7 +717,9 @@ operator== (QueueItem const & a, QueueItem const & b)
 void
 Writer::set_encoder_threads (int threads)
 {
+       boost::mutex::scoped_lock lm (_state_mutex);
        _maximum_frames_in_memory = lrint (threads * Config::instance()->frames_in_memory_multiplier());
+       _maximum_queue_size = threads * 16;
 }
 
 void