Don't insist on writing optional metadata (#1923).
[dcpomatic.git] / src / lib / writer.cc
index 9ebdd92a3e3b2e25f6c06c1e840b81e19652a2a9..839156d34be51534db48b7894373c98e9ce08cef 100644 (file)
@@ -306,11 +306,14 @@ Writer::write (shared_ptr<const AudioBuffers> audio, DCPTime const time)
                                end - _audio_reel->period().to
                        };
 
+                       /* Be careful that part_lengths[0] + part_lengths[1] can't be bigger than audio->frames() */
                        Frame part_frames[2] = {
                                part_lengths[0].frames_ceil(afr),
-                               part_lengths[1].frames_ceil(afr)
+                               part_lengths[1].frames_floor(afr)
                        };
 
+                       DCPOMATIC_ASSERT ((part_frames[0] + part_frames[1]) <= audio->frames());
+
                        if (part_frames[0]) {
                                shared_ptr<AudioBuffers> part (new AudioBuffers(audio, part_frames[0], 0));
                                _audio_reel->write (part);
@@ -542,6 +545,7 @@ Writer::finish (boost::filesystem::path output_dcp)
        LOG_GENERAL_NC ("Finishing ReelWriters");
 
        for (auto& i: _reels) {
+               write_hanging_text (i);
                i.finish (output_dcp);
        }
 
@@ -618,13 +622,23 @@ Writer::finish (boost::filesystem::path output_dcp)
 
        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());
+       if (film()->release_territory()) {
+               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());
+       if (film()->chain()) {
+               cpl->set_chain (*film()->chain());
+       }
+       if (film()->distributor()) {
+               cpl->set_distributor (*film()->distributor());
+       }
+       if (film()->facility()) {
+               cpl->set_facility (*film()->facility());
+       }
+       if (film()->luminance()) {
+               cpl->set_luminance (*film()->luminance());
+       }
 
        auto ac = film()->mapped_audio_channels();
        dcp::MCASoundField field = (
@@ -729,15 +743,14 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp)
        }
        boost::algorithm::replace_all (text, "$AUDIO", description);
 
-       int h, m, s, fr;
-       film()->length().split(film()->video_frame_rate(), h, m, s, fr);
+       auto const hmsf = film()->length().split(film()->video_frame_rate());
        string length;
-       if (h == 0 && m == 0) {
-               length = String::compose("%1s", s);
-       } else if (h == 0 && m > 0) {
-               length = String::compose("%1m%2s", m, s);
-       } else if (h > 0 && m > 0) {
-               length = String::compose("%1h%2m%3s", h, m, s);
+       if (hmsf.h == 0 && hmsf.m == 0) {
+               length = String::compose("%1s", hmsf.s);
+       } else if (hmsf.h == 0 && hmsf.m > 0) {
+               length = String::compose("%1m%2s", hmsf.m, hmsf.s);
+       } else if (hmsf.h > 0 && hmsf.m > 0) {
+               length = String::compose("%1h%2m%3s", hmsf.h, hmsf.m, hmsf.s);
        }
 
        boost::algorithm::replace_all (text, "$LENGTH", length);
@@ -795,6 +808,29 @@ Writer::write (PlayerText text, TextType type, optional<DCPTextTrack> track, DCP
        while ((*reel)->period().to <= period.from) {
                ++(*reel);
                DCPOMATIC_ASSERT (*reel != _reels.end());
+               write_hanging_text (**reel);
+       }
+
+       auto back_off = [this](DCPTimePeriod period) {
+               period.to -= DCPTime::from_frames(2, film()->video_frame_rate());
+               return period;
+       };
+
+       if (period.to > (*reel)->period().to) {
+               /* This text goes off the end of the reel.  Store parts of it that should go into
+                * other reels.
+                */
+               for (auto i = std::next(*reel); i != _reels.end(); ++i) {
+                       auto overlap = i->period().overlap(period);
+                       if (overlap) {
+                               _hanging_texts.push_back (HangingText{text, type, track, back_off(*overlap)});
+                       }
+               }
+               /* Back off from the reel boundary by a couple of frames to avoid tripping checks
+                * for subtitles being too close together.
+                */
+               period.to = (*reel)->period().to;
+               period = back_off(period);
        }
 
        (*reel)->write (text, type, track, period);
@@ -904,3 +940,17 @@ Writer::calculate_referenced_digests (boost::function<void (float)> set_progress
        }
 }
 
+
+void
+Writer::write_hanging_text (ReelWriter& reel)
+{
+       vector<HangingText> new_hanging_texts;
+       for (auto i: _hanging_texts) {
+               if (i.period.from == reel.period().from) {
+                       reel.write (i.text, i.type, i.track, i.period);
+               } else {
+                       new_hanging_texts.push_back (i);
+               }
+       }
+       _hanging_texts = new_hanging_texts;
+}