Support CPL metadata.
[dcpomatic.git] / src / lib / writer.cc
index 8682437b37888682959a96bf0cd286f9d6ac29f9..0b1d8e06d08d3604ec6848c8ff95e3344c2f577c 100644 (file)
@@ -97,6 +97,7 @@ Writer::Writer (shared_ptr<const Film> film, weak_ptr<Job> j)
        BOOST_FOREACH (DCPTextTrack i, _film->closed_caption_tracks()) {
                _caption_reels[i] = _reels.begin ();
        }
+       _atmos_reel = _reels.begin ();
 
        /* Check that the signer is OK */
        string reason;
@@ -303,6 +304,19 @@ Writer::write (shared_ptr<const AudioBuffers> audio, DCPTime const time)
 }
 
 
+void
+Writer::write (shared_ptr<const dcp::AtmosFrame> atmos, DCPTime time, AtmosMetadata metadata)
+{
+       if (_atmos_reel->period().to == time) {
+               ++_atmos_reel;
+               DCPOMATIC_ASSERT (_atmos_reel != _reels.end());
+       }
+
+       /* We assume that we get a video frame's worth of data here */
+       _atmos_reel->write (atmos, metadata);
+}
+
+
 /** Caller must hold a lock on _state_mutex */
 bool
 Writer::have_sequenced_image_at_queue_head ()
@@ -475,17 +489,18 @@ catch (...)
 void
 Writer::terminate_thread (bool can_throw)
 {
+       boost::this_thread::disable_interruption dis;
+
        boost::mutex::scoped_lock lock (_state_mutex);
-       if (!_thread.joinable()) {
-               return;
-       }
 
        _finish = true;
        _empty_condition.notify_all ();
        _full_condition.notify_all ();
        lock.unlock ();
 
-       _thread.join ();
+       try {
+               _thread.join ();
+       } catch (...) {}
 
        if (can_throw) {
                rethrow ();
@@ -547,27 +562,59 @@ Writer::finish ()
        pool.join_all ();
        service.stop ();
 
-       /* Add reels to CPL */
+       /* Add reels */
 
        BOOST_FOREACH (ReelWriter& i, _reels) {
                cpl->add (i.create_reel (_reel_assets, _fonts));
        }
 
-       dcp::XMLMetadata meta;
-       meta.annotation_text = cpl->annotation_text ();
-       meta.creator = Config::instance()->dcp_creator ();
-       if (meta.creator.empty ()) {
-               meta.creator = String::compose ("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
+       /* Add metadata */
+
+       string creator = Config::instance()->dcp_creator();
+       if (creator.empty()) {
+               creator = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
+       }
+
+       string issuer = Config::instance()->dcp_issuer();
+       if (issuer.empty()) {
+               issuer = String::compose("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
        }
-       meta.issuer = Config::instance()->dcp_issuer ();
-       if (meta.issuer.empty ()) {
-               meta.issuer = String::compose ("DCP-o-matic %1 %2", dcpomatic_version, dcpomatic_git_commit);
+
+       cpl->set_ratings (_film->ratings());
+
+       vector<dcp::ContentVersion> cv;
+       BOOST_FOREACH (string i, _film->content_versions()) {
+               cv.push_back (dcp::ContentVersion(i));
        }
-       meta.set_issue_date_now ();
+       cpl->set_content_versions (cv);
+
+       cpl->set_full_content_title_text (_film->name());
+       cpl->set_full_content_title_text_language (_film->name_language());
+       cpl->set_release_territory (_film->release_territory());
+       cpl->set_version_number (_film->version_number());
+       cpl->set_status (_film->status());
+       cpl->set_chain (_film->chain());
+       cpl->set_distributor (_film->distributor());
+       cpl->set_facility (_film->facility());
+       cpl->set_luminance (_film->luminance());
 
-       cpl->set_metadata (meta);
-       cpl->set_ratings (vector_to_list(_film->ratings()));
-       cpl->set_content_version_label_text (_film->content_version());
+       list<int> ac = _film->mapped_audio_channels ();
+       dcp::MainSoundConfiguration::Field field = (
+               find(ac.begin(), ac.end(), static_cast<int>(dcp::BSL)) != ac.end() ||
+               find(ac.begin(), ac.end(), static_cast<int>(dcp::BSR)) != ac.end()
+               ) ? dcp::MainSoundConfiguration::SEVEN_POINT_ONE : dcp::MainSoundConfiguration::FIVE_POINT_ONE;
+
+       dcp::MainSoundConfiguration msc (field, _film->audio_channels());
+       BOOST_FOREACH (int i, ac) {
+               if (i < _film->audio_channels()) {
+                       msc.set_mapping (i, static_cast<dcp::Channel>(i));
+               }
+       }
+
+       cpl->set_main_sound_configuration (msc.to_string());
+       cpl->set_main_sound_sample_rate (_film->audio_frame_rate());
+       cpl->set_main_picture_stored_area (_film->frame_size());
+       cpl->set_main_picture_active_area (_film->active_area());
 
        shared_ptr<const dcp::CertificateChain> signer;
        signer = Config::instance()->signer_chain ();
@@ -577,7 +624,15 @@ Writer::finish ()
                throw InvalidSignerError (reason);
        }
 
-       dcp.write_xml (_film->interop () ? dcp::INTEROP : dcp::SMPTE, meta, signer, Config::instance()->dcp_metadata_filename_format());
+       dcp.write_xml (
+               _film->interop() ? dcp::INTEROP : dcp::SMPTE,
+               issuer,
+               creator,
+               dcp::LocalTime().as_string(),
+               String::compose("Created by libdcp %1", dcp::version),
+               signer,
+               Config::instance()->dcp_metadata_filename_format()
+               );
 
        LOG_GENERAL (
                N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT, %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk