From 9c01623c3038b978ba732de2ad147d29fad60afe Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 31 Jul 2016 23:52:02 +0100 Subject: [PATCH] Allow configuration of MXF/XML filenames (part of #710). --- ChangeLog | 4 +++ src/lib/dcp_subtitle_decoder.cc | 2 +- src/lib/dcpomatic_time.h | 12 +++++-- src/lib/ffmpeg_subtitle_stream.cc | 2 +- src/lib/film.cc | 6 ++++ src/lib/film.h | 6 +++- src/lib/overlaps.cc | 2 +- src/lib/playlist.cc | 25 +++++++++++++++ src/lib/playlist.h | 1 + src/lib/reel_writer.cc | 11 ++++--- src/lib/reel_writer.h | 10 +++++- src/lib/subtitle_decoder.cc | 2 +- src/lib/text_subtitle_decoder.cc | 2 +- src/lib/util.cc | 10 ++++-- src/lib/util.h | 4 +-- src/lib/writer.cc | 2 +- src/wx/timeline.cc | 2 +- test/dcpomatic_time_test.cc | 10 +++--- test/file_naming_test.cc | 52 +++++++++++++++++++++++++++++++ test/wscript | 1 + 20 files changed, 143 insertions(+), 23 deletions(-) create mode 100644 test/file_naming_test.cc diff --git a/ChangeLog b/ChangeLog index 63d924e08..25d5b00dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-07-31 Carl Hetherington + + * Allow configuration of MXF/XML filenames (part of #710). + 2016-07-29 Carl Hetherington * Version 2.9.8 released. diff --git a/src/lib/dcp_subtitle_decoder.cc b/src/lib/dcp_subtitle_decoder.cc index 81dfc6598..d7b39d5de 100644 --- a/src/lib/dcp_subtitle_decoder.cc +++ b/src/lib/dcp_subtitle_decoder.cc @@ -98,7 +98,7 @@ DCPSubtitleDecoder::text_subtitles_during (ContentTimePeriod p, bool starting) c for (list::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { ContentTimePeriod period = content_time_period (*i); - if ((starting && p.contains (period.from)) || (!starting && p.overlaps (period))) { + if ((starting && p.contains(period.from)) || (!starting && p.overlap(period))) { d.push_back (period); } } diff --git a/src/lib/dcpomatic_time.h b/src/lib/dcpomatic_time.h index e6ca493b2..a94b605d2 100644 --- a/src/lib/dcpomatic_time.h +++ b/src/lib/dcpomatic_time.h @@ -28,6 +28,7 @@ #include "frame_rate_change.h" #include "dcpomatic_assert.h" #include +#include #include #include #include @@ -261,8 +262,15 @@ public: return TimePeriod (from + o, to + o); } - bool overlaps (TimePeriod const & other) const { - return (from < other.to && to > other.from); + boost::optional > overlap (TimePeriod const & other) { + T const max_from = std::max (from, other.from); + T const min_to = std::min (to, other.to); + + if (max_from >= min_to) { + return boost::optional > (); + } + + return TimePeriod (max_from, min_to); } bool contains (T const & other) const { diff --git a/src/lib/ffmpeg_subtitle_stream.cc b/src/lib/ffmpeg_subtitle_stream.cc index d1992f138..eb870c241 100644 --- a/src/lib/ffmpeg_subtitle_stream.cc +++ b/src/lib/ffmpeg_subtitle_stream.cc @@ -157,7 +157,7 @@ FFmpegSubtitleStream::subtitles_during (ContentTimePeriod period, bool starting, /* XXX: inefficient */ for (map::const_iterator i = subs.begin(); i != subs.end(); ++i) { - if ((starting && period.contains (i->second.from)) || (!starting && period.overlaps (i->second))) { + if ((starting && period.contains(i->second.from)) || (!starting && period.overlap(i->second))) { d.push_back (i->second); } } diff --git a/src/lib/film.cc b/src/lib/film.cc index 0138211cf..5e204e126 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -1447,3 +1447,9 @@ Film::reels () const return p; } + +string +Film::content_summary (DCPTimePeriod period) const +{ + return _playlist->content_summary (period); +} diff --git a/src/lib/film.h b/src/lib/film.h index 3063fc761..d63065f8d 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -157,9 +157,13 @@ public: } std::list reels () const; - std::list mapped_audio_channels () const; + /** @param A period within the DCP + * @return Name of the content which most contributes to the given period. + */ + std::string content_summary (DCPTimePeriod period) const; + /** Identifiers for the parts of our state; used for signalling changes. */ diff --git a/src/lib/overlaps.cc b/src/lib/overlaps.cc index 9e1b27517..ccef4cef8 100644 --- a/src/lib/overlaps.cc +++ b/src/lib/overlaps.cc @@ -31,7 +31,7 @@ ContentList overlaps (ContentList cl, function (shared_p ContentList overlaps; DCPTimePeriod period (from, to); BOOST_FOREACH (shared_ptr i, cl) { - if (part(i) && DCPTimePeriod(i->position(), i->end()).overlaps (period)) { + if (part(i) && DCPTimePeriod(i->position(), i->end()).overlap(period)) { overlaps.push_back (i); } } diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index 739c5a20b..a8b5a26eb 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -511,3 +511,28 @@ Playlist::required_disk_space (int j2k_bandwidth, int audio_channels, int audio_ /* Add on 64k for bits and pieces (metadata, subs etc) */ return video + audio + 65536; } + +string +Playlist::content_summary (DCPTimePeriod period) const +{ + string best_summary; + int best_score = -1; + BOOST_FOREACH (shared_ptr i, _content) { + int score = 0; + optional const o = DCPTimePeriod(i->position(), i->end()).overlap (period); + if (o) { + score += 100 * o.get().duration().get() / period.duration().get(); + } + + if (i->video) { + score += 100; + } + + if (score > best_score) { + best_summary = i->path(0).leaf().string(); + best_score = score; + } + } + + return best_summary; +} diff --git a/src/lib/playlist.h b/src/lib/playlist.h index 50ae1401a..e84b51a73 100644 --- a/src/lib/playlist.h +++ b/src/lib/playlist.h @@ -66,6 +66,7 @@ public: DCPTime video_end () const; DCPTime subtitle_end () const; FrameRateChange active_frame_rate_change (DCPTime, int dcp_frame_rate) const; + std::string content_summary (DCPTimePeriod period) const; void set_sequence (bool); void maybe_sequence (); diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc index b712ac3c5..176c54c8f 100644 --- a/src/lib/reel_writer.cc +++ b/src/lib/reel_writer.cc @@ -60,7 +60,9 @@ using dcp::Data; int const ReelWriter::_info_size = 48; -ReelWriter::ReelWriter (shared_ptr film, DCPTimePeriod period, shared_ptr job, int reel_index, int reel_count) +ReelWriter::ReelWriter ( + shared_ptr film, DCPTimePeriod period, shared_ptr job, int reel_index, int reel_count, optional content_summary + ) : _film (film) , _period (period) , _first_nonexistant_frame (0) @@ -69,6 +71,7 @@ ReelWriter::ReelWriter (shared_ptr film, DCPTimePeriod period, share , _total_written_audio_frames (0) , _reel_index (reel_index) , _reel_count (reel_count) + , _content_summary (content_summary) { /* Create our picture asset in a subdirectory, named according to those film's parameters which affect the video output. We will hard-link @@ -113,7 +116,7 @@ ReelWriter::ReelWriter (shared_ptr film, DCPTimePeriod period, share of the DCP directory until the last minute. */ _sound_asset_writer = _sound_asset->start_write ( - _film->directory() / audio_asset_filename (_sound_asset, _reel_index, _reel_count), + _film->directory() / audio_asset_filename (_sound_asset, _reel_index, _reel_count, _content_summary), _film->interop() ? dcp::INTEROP : dcp::SMPTE ); } @@ -268,7 +271,7 @@ ReelWriter::finish () boost::filesystem::path video_from = _picture_asset->file (); boost::filesystem::path video_to; video_to /= _film->dir (_film->dcp_name()); - video_to /= video_asset_filename (_picture_asset, _reel_index, _reel_count); + video_to /= video_asset_filename (_picture_asset, _reel_index, _reel_count, _content_summary); boost::system::error_code ec; boost::filesystem::create_hard_link (video_from, video_to, ec); @@ -288,7 +291,7 @@ ReelWriter::finish () if (_sound_asset) { boost::filesystem::path audio_to; audio_to /= _film->dir (_film->dcp_name ()); - string const aaf = audio_asset_filename (_sound_asset, _reel_index, _reel_count); + string const aaf = audio_asset_filename (_sound_asset, _reel_index, _reel_count, _content_summary); audio_to /= aaf; boost::system::error_code ec; diff --git a/src/lib/reel_writer.h b/src/lib/reel_writer.h index a80f51dc2..274f62b9f 100644 --- a/src/lib/reel_writer.h +++ b/src/lib/reel_writer.h @@ -47,7 +47,14 @@ namespace dcp { class ReelWriter { public: - ReelWriter (boost::shared_ptr film, DCPTimePeriod period, boost::shared_ptr job, int reel_index, int reel_count); + ReelWriter ( + boost::shared_ptr film, + DCPTimePeriod period, + boost::shared_ptr job, + int reel_index, + int reel_count, + boost::optional content_summary + ); void write (boost::optional encoded, Frame frame, Eyes eyes); void fake_write (Frame frame, Eyes eyes, int size); @@ -106,6 +113,7 @@ private: int _reel_index; /** number of reels in the DCP */ int _reel_count; + boost::optional _content_summary; boost::shared_ptr _picture_asset; boost::shared_ptr _picture_asset_writer; diff --git a/src/lib/subtitle_decoder.cc b/src/lib/subtitle_decoder.cc index b31b4873f..5ae1a703e 100644 --- a/src/lib/subtitle_decoder.cc +++ b/src/lib/subtitle_decoder.cc @@ -93,7 +93,7 @@ SubtitleDecoder::get (list const & subs, list const & sp, list out; for (typename list::const_iterator i = subs.begin(); i != subs.end(); ++i) { - if ((starting && period.contains (i->period().from)) || (!starting && period.overlaps (i->period ()))) { + if ((starting && period.contains(i->period().from)) || (!starting && period.overlap(i->period()))) { out.push_back (*i); } } diff --git a/src/lib/text_subtitle_decoder.cc b/src/lib/text_subtitle_decoder.cc index ad9c00b63..bec2ab9b7 100644 --- a/src/lib/text_subtitle_decoder.cc +++ b/src/lib/text_subtitle_decoder.cc @@ -87,7 +87,7 @@ TextSubtitleDecoder::text_subtitles_during (ContentTimePeriod p, bool starting) for (vector::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { ContentTimePeriod t = content_time_period (*i); - if ((starting && p.contains (t.from)) || (!starting && p.overlaps (t))) { + if ((starting && p.contains (t.from)) || (!starting && p.overlap (t))) { d.push_back (t); } } diff --git a/src/lib/util.cc b/src/lib/util.cc index c8d0561be..a0d6453ff 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -617,24 +617,30 @@ split_get_request (string url) } string -video_asset_filename (shared_ptr asset, int reel_index, int reel_count) +video_asset_filename (shared_ptr asset, int reel_index, int reel_count, optional summary) { dcp::NameFormat::Map values; values['t'] = "j2c"; values['i'] = asset->id(); values['r'] = raw_convert (reel_index + 1); values['n'] = raw_convert (reel_count); + if (summary) { + values['c'] = summary.get(); + } return Config::instance()->dcp_filename_format().get(values) + ".mxf"; } string -audio_asset_filename (shared_ptr asset, int reel_index, int reel_count) +audio_asset_filename (shared_ptr asset, int reel_index, int reel_count, optional summary) { dcp::NameFormat::Map values; values['t'] = "pcm"; values['i'] = asset->id(); values['r'] = raw_convert (reel_index + 1); values['n'] = raw_convert (reel_count); + if (summary) { + values['c'] = summary.get(); + } return Config::instance()->dcp_filename_format().get(values) + ".mxf"; } diff --git a/src/lib/util.h b/src/lib/util.h index b3621bb13..21c0b6661 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -74,8 +74,8 @@ extern int stride_round_up (int, int const *, int); extern void* wrapped_av_malloc (size_t); extern void set_backtrace_file (boost::filesystem::path); extern std::map split_get_request (std::string url); -extern std::string video_asset_filename (boost::shared_ptr asset, int reel_index, int reel_count); -extern std::string audio_asset_filename (boost::shared_ptr asset, int reel_index, int reel_count); +extern std::string video_asset_filename (boost::shared_ptr asset, int reel_index, int reel_count, boost::optional content_summary); +extern std::string audio_asset_filename (boost::shared_ptr asset, int reel_index, int reel_count, boost::optional content_summary); extern float relaxed_string_to_float (std::string); extern bool string_not_empty (std::string); diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 9aee7d92f..a5085abae 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -87,7 +87,7 @@ Writer::Writer (shared_ptr film, weak_ptr j) int reel_index = 0; list const reels = _film->reels (); BOOST_FOREACH (DCPTimePeriod p, reels) { - _reels.push_back (ReelWriter (film, p, job, reel_index++, reels.size())); + _reels.push_back (ReelWriter (film, p, job, reel_index++, reels.size(), _film->content_summary(p))); } /* We can keep track of the current audio and subtitle reels easily because audio diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index 6bb216df8..30c2dbddc 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -262,7 +262,7 @@ Timeline::assign_tracks () shared_ptr test_content = test->content(); if (test && test->track() && test->track().get() == t) { - if (content_period.overlaps (DCPTimePeriod(test_content->position(), test_content->end()))) { + if (content_period.overlap (DCPTimePeriod(test_content->position(), test_content->end()))) { /* we have an overlap on track `t' */ ++t; break; diff --git a/test/dcpomatic_time_test.cc b/test/dcpomatic_time_test.cc index 716ec98d7..6dd4094da 100644 --- a/test/dcpomatic_time_test.cc +++ b/test/dcpomatic_time_test.cc @@ -55,18 +55,20 @@ BOOST_AUTO_TEST_CASE (dcpomatic_time_period_overlaps_test) TimePeriod a (DCPTime (0), DCPTime (4)); TimePeriod b (DCPTime (4), DCPTime (8)); - BOOST_CHECK (!a.overlaps (b)); + BOOST_CHECK (!a.overlap (b)); /* Some more obvious non-overlaps */ a = TimePeriod (DCPTime (0), DCPTime (4)); b = TimePeriod (DCPTime (5), DCPTime (8)); - BOOST_CHECK (!a.overlaps (b)); + BOOST_CHECK (!a.overlap (b)); /* Some overlaps */ a = TimePeriod (DCPTime (0), DCPTime (4)); b = TimePeriod (DCPTime (3), DCPTime (8)); - BOOST_CHECK (a.overlaps (b)); + BOOST_CHECK (a.overlap (b)); + BOOST_CHECK_EQUAL (a.overlap(b).get(), DCPTimePeriod(DCPTime(3), DCPTime(4))); a = TimePeriod (DCPTime (1), DCPTime (9)); b = TimePeriod (DCPTime (0), DCPTime (10)); - BOOST_CHECK (a.overlaps (b)); + BOOST_CHECK (a.overlap (b)); + BOOST_CHECK_EQUAL (a.overlap(b).get(), DCPTimePeriod(DCPTime(1), DCPTime(9))); } diff --git a/test/file_naming_test.cc b/test/file_naming_test.cc new file mode 100644 index 000000000..4c2b0af47 --- /dev/null +++ b/test/file_naming_test.cc @@ -0,0 +1,52 @@ +/* + Copyright (C) 2016 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + +#include "test.h" +#include "lib/config.h" +#include "lib/film.h" +#include "lib/ffmpeg_content.h" +#include "lib/dcp_content_type.h" +#include + +using boost::shared_ptr; + +BOOST_AUTO_TEST_CASE (file_naming_test) +{ + dcp::FilenameFormat nf ("%c"); + Config::instance()->set_dcp_filename_format (dcp::FilenameFormat ("%c")); + shared_ptr film = new_test_film ("file_naming_test"); + film->set_name ("file_naming_test"); + film->set_dcp_content_type (DCPContentType::from_isdcf_name ("FTR")); + shared_ptr r (new FFmpegContent (film, "test/data/flat_red.png")); + film->examine_and_add_content (r); + shared_ptr g (new FFmpegContent (film, "test/data/flat_green.png")); + film->examine_and_add_content (g); + shared_ptr b (new FFmpegContent (film, "test/data/flat_blue.png")); + film->examine_and_add_content (b); + wait_for_jobs (); + + film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT); + film->make_dcp (); + wait_for_jobs (); + + BOOST_CHECK (boost::filesystem::exists (film->file (film->dcp_name() + "/flat_red.png.mxf"))); + BOOST_CHECK (boost::filesystem::exists (film->file (film->dcp_name() + "/flat_green.png.mxf"))); + BOOST_CHECK (boost::filesystem::exists (film->file (film->dcp_name() + "/flat_blue.png.mxf"))); +} diff --git a/test/wscript b/test/wscript index 49e874ea9..a7a406856 100644 --- a/test/wscript +++ b/test/wscript @@ -63,6 +63,7 @@ def build(bld): ffmpeg_pts_offset_test.cc file_group_test.cc file_log_test.cc + file_naming_test.cc film_metadata_test.cc frame_rate_test.cc image_filename_sorter_test.cc -- 2.30.2