Merge master.
[dcpomatic.git] / src / lib / writer.cc
index 9410dd565b4a9ba963cda63af72aea763c489511..b165545c7b23e5f3eb04b085d50020861f135ffd 100644 (file)
@@ -27,6 +27,7 @@
 #include <dcp/reel_mono_picture_asset.h>
 #include <dcp/reel_stereo_picture_asset.h>
 #include <dcp/reel_sound_asset.h>
+#include <dcp/reel_subtitle_asset.h>
 #include <dcp/dcp.h>
 #include <dcp/cpl.h>
 #include "writer.h"
 #include "film.h"
 #include "ratio.h"
 #include "log.h"
-#include "dcp_video_frame.h"
+#include "dcp_video.h"
 #include "dcp_content_type.h"
-#include "player.h"
 #include "audio_mapping.h"
 #include "config.h"
 #include "job.h"
 #include "cross.h"
 #include "audio_buffers.h"
+#include "md5_digester.h"
+#include "encoded_data.h"
 
 #include "i18n.h"
 
@@ -138,6 +140,7 @@ Writer::write (shared_ptr<const EncodedData> encoded, int frame, Eyes eyes)
        boost::mutex::scoped_lock lock (_mutex);
 
        while (_queued_full_in_memory > _maximum_frames_in_memory) {
+               /* The queue is too big; wait until that is sorted out */
                _full_condition.wait (lock);
        }
 
@@ -159,7 +162,8 @@ Writer::write (shared_ptr<const EncodedData> encoded, int frame, Eyes eyes)
                _queue.push_back (qi);
                ++_queued_full_in_memory;
        }
-       
+
+       /* Now there's something to do: wake anything wait()ing on _empty_condition */
        _empty_condition.notify_all ();
 }
 
@@ -169,6 +173,7 @@ Writer::fake_write (int frame, Eyes eyes)
        boost::mutex::scoped_lock lock (_mutex);
 
        while (_queued_full_in_memory > _maximum_frames_in_memory) {
+               /* The queue is too big; wait until that is sorted out */
                _full_condition.wait (lock);
        }
        
@@ -190,6 +195,7 @@ Writer::fake_write (int frame, Eyes eyes)
                _queue.push_back (qi);
        }
 
+       /* Now there's something to do: wake anything wait()ing on _empty_condition */
        _empty_condition.notify_all ();
 }
 
@@ -236,16 +242,18 @@ void
 Writer::thread ()
 try
 {
-       while (1)
+       while (true)
        {
                boost::mutex::scoped_lock lock (_mutex);
 
-               while (1) {
+               while (true) {
                        
                        if (_finish || _queued_full_in_memory > _maximum_frames_in_memory || have_sequenced_image_at_queue_head ()) {
+                               /* We've got something to do: go and do it */
                                break;
                        }
 
+                       /* Nothing to do: wait until something happens which may indicate that we do */
                        LOG_TIMING (N_("writer sleeps with a queue of %1"), _queue.size());
                        _empty_condition.wait (lock);
                        LOG_TIMING (N_("writer wakes with a queue of %1"), _queue.size());
@@ -335,6 +343,7 @@ try
                        --_queued_full_in_memory;
                }
 
+               /* The queue has probably just gone down a bit; notify anything wait()ing on _full_condition */
                _full_condition.notify_all ();
        }
 }
@@ -444,6 +453,20 @@ Writer::finish ()
                reel->add (shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (_sound_mxf, 0)));
                dcp.add (_sound_mxf);
        }
+
+       if (_subtitle_content) {
+               _subtitle_content->write_xml (_film->dir (_film->dcp_name ()) / _film->subtitle_xml_filename ());
+               reel->add (shared_ptr<dcp::ReelSubtitleAsset> (
+                                  new dcp::ReelSubtitleAsset (
+                                          _subtitle_content,
+                                          dcp::Fraction (_film->video_frame_rate(), 1),
+                                          _subtitle_content->latest_subtitle_out().to_seconds() * _film->video_frame_rate(),
+                                          0
+                                          )
+                                  ));
+               
+               dcp.add (_subtitle_content);
+       }
        
        cpl->add (reel);
 
@@ -493,9 +516,10 @@ Writer::check_existing_picture_mxf_frame (FILE* mxf, int f, Eyes eyes)
                LOG_GENERAL ("Existing frame %1 is incomplete", f);
                return false;
        }
-       
-       string const existing_hash = md5_digest (data.data(), data.size());
-       if (existing_hash != info.hash) {
+
+       MD5Digester digester;
+       digester.add (data.data(), data.size());
+       if (digester.get() != info.hash) {
                LOG_GENERAL ("Existing frame %1 failed hash check", f);
                return false;
        }
@@ -521,7 +545,7 @@ Writer::check_existing_picture_mxf ()
                ++N;
        }
 
-       while (1) {
+       while (true) {
 
                shared_ptr<Job> job = _job.lock ();
                assert (job);
@@ -562,6 +586,24 @@ Writer::can_fake_write (int frame) const
        return (frame != 0 && frame < _first_nonexistant_frame);
 }
 
+void
+Writer::write (PlayerSubtitles subs)
+{
+       if (subs.text.empty ()) {
+               return;
+       }
+       
+       if (!_subtitle_content) {
+               _subtitle_content.reset (
+                       new dcp::SubtitleContent (_film->name(), _film->isdcf_metadata().subtitle_language)
+                       );
+       }
+       
+       for (list<dcp::SubtitleString>::const_iterator i = subs.text.begin(); i != subs.text.end(); ++i) {
+               _subtitle_content->add (*i);
+       }
+}
+
 bool
 operator< (QueueItem const & a, QueueItem const & b)
 {