Make Atmos content work more like other content. Now its MXFs
[dcpomatic.git] / src / lib / reel_writer.cc
index 06d20e7c8aeb2876ee67f3496cd0014995a7b085..133bc0adf2e7b2302f9b1e169b8f30271c44b475 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 #include "digester.h"
 #include "font.h"
 #include "compose.hpp"
+#include "config.h"
 #include "audio_buffers.h"
 #include "image.h"
+#include <dcp/atmos_asset.h>
+#include <dcp/atmos_asset_writer.h>
 #include <dcp/mono_picture_asset.h>
 #include <dcp/stereo_picture_asset.h>
 #include <dcp/sound_asset.h>
 #include <dcp/sound_asset_writer.h>
 #include <dcp/reel.h>
+#include <dcp/reel_atmos_asset.h>
 #include <dcp/reel_mono_picture_asset.h>
 #include <dcp/reel_stereo_picture_asset.h>
 #include <dcp/reel_sound_asset.h>
@@ -65,6 +69,23 @@ using namespace dcpomatic;
 
 int const ReelWriter::_info_size = 48;
 
+static dcp::MXFMetadata
+mxf_metadata ()
+{
+       dcp::MXFMetadata meta;
+       Config* config = Config::instance();
+       if (!config->dcp_company_name().empty()) {
+               meta.company_name = config->dcp_company_name ();
+       }
+       if (!config->dcp_product_name().empty()) {
+               meta.product_name = config->dcp_product_name ();
+       }
+       if (!config->dcp_product_version().empty()) {
+               meta.product_version = config->dcp_product_version ();
+       }
+       return meta;
+}
+
 /** @param job Related job, or 0 */
 ReelWriter::ReelWriter (
        shared_ptr<const Film> film, DCPTimePeriod period, shared_ptr<Job> job, int reel_index, int reel_count, optional<string> content_summary
@@ -113,6 +134,7 @@ ReelWriter::ReelWriter (
                }
 
                _picture_asset->set_size (_film->frame_size());
+               _picture_asset->set_metadata (mxf_metadata());
 
                if (_film->encrypted ()) {
                        _picture_asset->set_key (_film->key());
@@ -136,6 +158,8 @@ ReelWriter::ReelWriter (
                        new dcp::SoundAsset (dcp::Fraction (_film->video_frame_rate(), 1), _film->audio_frame_rate (), _film->audio_channels (), standard)
                        );
 
+               _sound_asset->set_metadata (mxf_metadata());
+
                if (_film->encrypted ()) {
                        _sound_asset->set_key (_film->key ());
                }
@@ -266,6 +290,23 @@ ReelWriter::write (optional<Data> encoded, Frame frame, Eyes eyes)
        _last_written[eyes] = encoded;
 }
 
+
+void
+ReelWriter::write (shared_ptr<const dcp::AtmosFrame> atmos, AtmosMetadata metadata)
+{
+       if (!_atmos_asset) {
+               _atmos_asset = metadata.create (dcp::Fraction(_film->video_frame_rate(), 1));
+               if (_film->encrypted()) {
+                       _atmos_asset->set_key(_film->key());
+               }
+               _atmos_asset_writer = _atmos_asset->start_write (
+                       _film->directory().get() / atmos_asset_filename (_atmos_asset, _reel_index, _reel_count, _content_summary)
+                       );
+       }
+       _atmos_asset_writer->write (atmos);
+}
+
+
 void
 ReelWriter::fake_write (int size)
 {
@@ -360,6 +401,24 @@ ReelWriter::finish ()
 
                _sound_asset->set_file (audio_to);
        }
+
+       if (_atmos_asset) {
+               _atmos_asset_writer->finalize ();
+               boost::filesystem::path atmos_to;
+               atmos_to /= _film->dir (_film->dcp_name());
+               string const aaf = atmos_asset_filename (_atmos_asset, _reel_index, _reel_count, _content_summary);
+               atmos_to /= aaf;
+
+               boost::system::error_code ec;
+               boost::filesystem::rename (_film->file(aaf), atmos_to, ec);
+               if (ec) {
+                       throw FileError (
+                               String::compose (_("could not move atmos asset into the DCP (%1)"), ec.value ()), aaf
+                               );
+               }
+
+               _atmos_asset->set_file (atmos_to);
+       }
 }
 
 template <class T>
@@ -569,6 +628,10 @@ ReelWriter::create_reel (list<ReferencedReelAsset> const & refs, list<shared_ptr
                reel->add (ma);
        }
 
+       if (_atmos_asset) {
+               reel->add (shared_ptr<dcp::ReelAtmosAsset>(new dcp::ReelAtmosAsset(_atmos_asset, 0)));
+       }
+
        return reel;
 }
 
@@ -582,6 +645,10 @@ ReelWriter::calculate_digests (boost::function<void (float)> set_progress)
        if (_sound_asset) {
                _sound_asset->hash (set_progress);
        }
+
+       if (_atmos_asset) {
+               _atmos_asset->hash (set_progress);
+       }
 }
 
 Frame
@@ -634,6 +701,7 @@ ReelWriter::write (PlayerText subs, TextType type, optional<DCPTextTrack> track,
                } else {
                        shared_ptr<dcp::SMPTESubtitleAsset> s (new dcp::SMPTESubtitleAsset ());
                        s->set_content_title_text (_film->name ());
+                       s->set_metadata (mxf_metadata());
                        if (type == TEXT_OPEN_SUBTITLE && !lang.empty()) {
                                s->set_language (lang);
                        } else {