Support ISDCF naming convention version 9.
authorCarl Hetherington <cth@carlh.net>
Tue, 10 Jun 2014 16:14:17 +0000 (17:14 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 10 Jun 2014 16:14:17 +0000 (17:14 +0100)
Reported-by: Elia Orselli
ChangeLog
src/lib/film.cc
src/lib/film.h
src/lib/isdcf_metadata.cc
src/lib/isdcf_metadata.h
src/lib/ratio.cc
src/wx/isdcf_metadata_dialog.cc
src/wx/isdcf_metadata_dialog.h
test/isdcf_name_test.cc [new file with mode: 0644]
test/wscript

index d9aeec1fb0ffe23ff77047ab387e4eb18c2b5220..26bd287dc7bc60f86cfa3ec46e3e7c999d675062 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2014-06-10  Carl Hetherington  <cth@carlh.net>
 
+       * Support ISDCF naming convention version 9 (#257).
+
        * Rename DCI to ISDCF when talking about the digital cinema
        naming convention (#362).
 
index fb30260395375d3cd79791cabd0b17b9dfb43c05..fd3e78c35874ca41683deb4706fa34b6ddd73174 100644 (file)
@@ -490,14 +490,20 @@ Film::isdcf_name (bool if_created_now) const
 {
        stringstream d;
 
-       string fixed_name = to_upper_copy (name());
-       for (size_t i = 0; i < fixed_name.length(); ++i) {
-               if (fixed_name[i] == ' ') {
-                       fixed_name[i] = '-';
+       string raw_name = name ();
+       string fixed_name;
+       bool cap_next = true;
+       for (size_t i = 0; i < raw_name.length(); ++i) {
+               if (raw_name[i] == ' ') {
+                       cap_next = true;
+               } else if (cap_next) {
+                       fixed_name += toupper (raw_name[i]);
+                       cap_next = false;
+               } else {
+                       fixed_name += tolower (raw_name[i]);
                }
        }
 
-       /* Spec is that the name part should be maximum 14 characters, as I understand it */
        if (fixed_name.length() > 14) {
                fixed_name = fixed_name.substr (0, 14);
        }
@@ -509,19 +515,60 @@ Film::isdcf_name (bool if_created_now) const
                d << "-" << isdcf_metadata().content_version;
        }
 
+       ISDCFMetadata const dm = isdcf_metadata ();
+
+       if (dm.temp_version) {
+               d << "-Temp";
+       }
+       
+       if (dm.pre_release) {
+               d << "-Pre";
+       }
+       
+       if (dm.red_band) {
+               d << "-RedBand";
+       }
+       
+       if (!dm.chain.empty ()) {
+               d << "-" << dm.chain;
+       }
+
        if (three_d ()) {
                d << "-3D";
        }
 
+       if (dm.two_d_version_of_three_d) {
+               d << "-2D";
+       }
+
+       if (!dm.mastered_luminance.empty ()) {
+               d << "-" << dm.mastered_luminance;
+       }
+
        if (video_frame_rate() != 24) {
                d << "-" << video_frame_rate();
        }
-
+       
        if (container()) {
                d << "_" << container()->isdcf_name();
        }
 
-       ISDCFMetadata const dm = isdcf_metadata ();
+       /* XXX: this only works for content which has been scaled to a given ratio,
+          and uses the first bit of content only.
+       */
+
+       ContentList cl = content ();
+       Ratio const * content_ratio = 0;
+       for (ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) {
+               shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*i);
+               if (vc && (content_ratio == 0 || vc->scale().ratio() != content_ratio)) {
+                       content_ratio = vc->scale().ratio();
+               }
+       }
+
+       if (content_ratio && content_ratio != container()) {
+               d << "-" << content_ratio->isdcf_name();
+       }
 
        if (!dm.audio_language.empty ()) {
                d << "_" << dm.audio_language;
@@ -560,8 +607,10 @@ Film::isdcf_name (bool if_created_now) const
                break;
        }
 
-       d << "_" << resolution_to_string (_resolution);
+       /* XXX: HI/VI */
 
+       d << "_" << resolution_to_string (_resolution);
+       
        if (!dm.studio.empty ()) {
                d << "_" << dm.studio;
        }
@@ -576,6 +625,16 @@ Film::isdcf_name (bool if_created_now) const
                d << "_" << dm.facility;
        }
 
+       if (_interop) {
+               d << "_IOP";
+       } else {
+               d << "_SMPTE";
+       }
+       
+       if (three_d ()) {
+               d << "-3D";
+       }
+
        if (!dm.package_type.empty ()) {
                d << "_" << dm.package_type;
        }
index f77309862badc22fd540006ead58e98726c6f9ef..96ea930ccd10a493e7c24099ebc487a77cdb8991 100644 (file)
@@ -46,6 +46,7 @@ class Playlist;
 class AudioContent;
 class Scaler;
 class Screen;
+class isdcf_name_test;
 
 /** @class Film
  *
@@ -282,6 +283,8 @@ public:
 
 private:
 
+       friend class ::isdcf_name_test;
+
        void signal_changed (Property);
        std::string video_identifier () const;
        void playlist_changed ();
index ae99280ca4de666d26aa526fe5f28a0f4e01702a..dfba50a9a2262ecf02c9e95a026cc9d2abab77a7 100644 (file)
@@ -38,6 +38,14 @@ ISDCFMetadata::ISDCFMetadata (shared_ptr<const cxml::Node> node)
        studio = node->string_child ("Studio");
        facility = node->string_child ("Facility");
        package_type = node->string_child ("PackageType");
+
+       /* This stuff was added later */
+       temp_version = node->optional_bool_child ("TempVersion").get_value_or (false);
+       pre_release = node->optional_bool_child ("PreRelease").get_value_or (false);
+       red_band = node->optional_bool_child ("RedBand").get_value_or (false);
+       chain = node->optional_string_child ("Chain").get_value_or ("");
+       two_d_version_of_three_d = node->optional_bool_child ("TwoDVersionOfThreeD").get_value_or (false);
+       mastered_luminance = node->optional_string_child ("MasteredLuminance").get_value_or ("");
 }
 
 void
@@ -51,6 +59,12 @@ ISDCFMetadata::as_xml (xmlpp::Node* root) const
        root->add_child("Studio")->add_child_text (studio);
        root->add_child("Facility")->add_child_text (facility);
        root->add_child("PackageType")->add_child_text (package_type);
+       root->add_child("TempVersion")->add_child_text (temp_version ? "1" : "0");
+       root->add_child("PreRelease")->add_child_text (pre_release ? "1" : "0");
+       root->add_child("RedBand")->add_child_text (red_band ? "1" : "0");
+       root->add_child("Chain")->add_child_text (chain);
+       root->add_child("TwoDVersionOfThreeD")->add_child_text (two_d_version_of_three_d ? "1" : "0");
+       root->add_child("MasteredLuminance")->add_child_text (mastered_luminance);
 }
 
 void
index cd63ba2eee3f3d365198d393460aef9be0686aec..0fb7e7baa0e1292468e0573d5d7424e7e7c165b2 100644 (file)
@@ -32,6 +32,10 @@ class ISDCFMetadata
 public:
        ISDCFMetadata ()
                : content_version (1)
+               , temp_version (false)
+               , pre_release (false)
+               , red_band (false)
+               , two_d_version_of_three_d (false)
        {}
        
        ISDCFMetadata (boost::shared_ptr<const cxml::Node>);
@@ -47,6 +51,18 @@ public:
        std::string studio;
        std::string facility;
        std::string package_type;
+       /** true if this is a temporary version (without final picture or sound) */
+       bool temp_version;
+       /** true if this is a pre-release version (final picture and sound, but without accessibility features) */
+       bool pre_release;
+       /** true if this has adult content */
+       bool red_band;
+       /** specific theatre chain or event */
+       std::string chain;
+       /** true if this is a 2D version of content that also exists in 3D */
+       bool two_d_version_of_three_d;
+       /** mastered luminance if there are multiple versions distributed (e.g. 35, 4fl, 6fl etc.) */
+       std::string mastered_luminance;
 };
 
 #endif
index a47b2101e54a175ae983025852f9d16a7c81ca9a..52577d3bbc5158f7ccdfea8a561caa0f055107c1 100644 (file)
@@ -32,12 +32,12 @@ vector<Ratio const *> Ratio::_ratios;
 void
 Ratio::setup_ratios ()
 {
-       _ratios.push_back (new Ratio (float(1290) / 1080, "119", _("1.19"), "F"));
-       _ratios.push_back (new Ratio (float(1440) / 1080, "133", _("4:3"), "F"));
-       _ratios.push_back (new Ratio (float(1480) / 1080, "137", _("Academy"), "F"));
-       _ratios.push_back (new Ratio (float(1485) / 1080, "138", _("1.375"), "F"));
-       _ratios.push_back (new Ratio (float(1800) / 1080, "166", _("1.66"), "F"));
-       _ratios.push_back (new Ratio (float(1920) / 1080, "178", _("16:9"), "F"));
+       _ratios.push_back (new Ratio (float(1290) / 1080, "119", _("1.19"), "119"));
+       _ratios.push_back (new Ratio (float(1440) / 1080, "133", _("4:3"), "133"));
+       _ratios.push_back (new Ratio (float(1480) / 1080, "137", _("Academy"), "137"));
+       _ratios.push_back (new Ratio (float(1485) / 1080, "138", _("1.375"), "137"));
+       _ratios.push_back (new Ratio (float(1800) / 1080, "166", _("1.66"), "166"));
+       _ratios.push_back (new Ratio (float(1920) / 1080, "178", _("16:9"), "178"));
        _ratios.push_back (new Ratio (float(1998) / 1080, "185", _("Flat"), "F"));
        _ratios.push_back (new Ratio (float(2048) /  858, "239", _("Scope"), "S"));
        _ratios.push_back (new Ratio (float(2048) / 1080, "full-frame", _("Full frame"), "C"));
index 0fd00ff7a8903c77921c9ee8d7fb70b3e812ceb1..e47c944d0c5e108e06b86fb6621ccf3721e883dc 100644 (file)
@@ -53,6 +53,24 @@ ISDCFMetadataDialog::ISDCFMetadataDialog (wxWindow* parent, ISDCFMetadata dm)
        add (_("Package Type (e.g. OV)"), true);
        _package_type = add (new wxTextCtrl (this, wxID_ANY));
 
+       _temp_version = add (new wxCheckBox (this, wxID_ANY, _("Temp version")));
+       add_spacer ();
+
+       _pre_release = add (new wxCheckBox (this, wxID_ANY, _("Pre-release")));
+       add_spacer ();
+
+       _red_band = add (new wxCheckBox (this, wxID_ANY, _("Red band")));
+       add_spacer ();
+
+       add (_("Chain"), true);
+       _chain = add (new wxTextCtrl (this, wxID_ANY));
+
+       _two_d_version_of_three_d = add (new wxCheckBox (this, wxID_ANY, _("2D version of content available in 3D")));
+       add_spacer ();
+
+       add (_("Mastered luminance (e.g. 4fl)"), true);
+       _mastered_luminance = add (new wxTextCtrl (this, wxID_ANY));
+       
        _content_version->SetRange (1, 1024);
 
        _content_version->SetValue (dm.content_version);
@@ -63,6 +81,12 @@ ISDCFMetadataDialog::ISDCFMetadataDialog (wxWindow* parent, ISDCFMetadata dm)
        _studio->SetValue (std_to_wx (dm.studio));
        _facility->SetValue (std_to_wx (dm.facility));
        _package_type->SetValue (std_to_wx (dm.package_type));
+       _temp_version->SetValue (dm.temp_version);
+       _pre_release->SetValue (dm.pre_release);
+       _red_band->SetValue (dm.red_band);
+       _chain->SetValue (std_to_wx (dm.chain));
+       _two_d_version_of_three_d->SetValue (dm.two_d_version_of_three_d);
+       _mastered_luminance->SetValue (std_to_wx (dm.mastered_luminance));
 
        layout ();
 }
@@ -80,6 +104,12 @@ ISDCFMetadataDialog::isdcf_metadata () const
        dm.studio = wx_to_std (_studio->GetValue ());
        dm.facility = wx_to_std (_facility->GetValue ());
        dm.package_type = wx_to_std (_package_type->GetValue ());
+       dm.temp_version = _temp_version->GetValue ();
+       dm.pre_release = _pre_release->GetValue ();
+       dm.red_band = _red_band->GetValue ();
+       dm.chain = wx_to_std (_chain->GetValue ());
+       dm.two_d_version_of_three_d = _two_d_version_of_three_d->GetValue ();
+       dm.mastered_luminance = wx_to_std (_mastered_luminance->GetValue ());
 
        return dm;
 }
index e20dbf5e37d72caade52c056611542d4dd7f9a93..516f832317912fe9ebaae5c39e02a747feaf2dec 100644 (file)
@@ -41,4 +41,10 @@ private:
        wxTextCtrl* _studio;
        wxTextCtrl* _facility;
        wxTextCtrl* _package_type;
+       wxCheckBox* _temp_version;
+       wxCheckBox* _pre_release;
+       wxCheckBox* _red_band;
+       wxTextCtrl* _chain;
+       wxCheckBox* _two_d_version_of_three_d;
+       wxTextCtrl* _mastered_luminance;
 };
diff --git a/test/isdcf_name_test.cc b/test/isdcf_name_test.cc
new file mode 100644 (file)
index 0000000..65f89c0
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/test/unit_test.hpp>
+#include "lib/film.h"
+#include "lib/ratio.h"
+#include "lib/dcp_content_type.h"
+#include "lib/image_content.h"
+#include "test.h"
+
+using std::cout;
+using boost::shared_ptr;
+
+BOOST_AUTO_TEST_CASE (isdcf_name_test)
+{
+       shared_ptr<Film> film = new_test_film ("isdcf_name_test");
+
+       /* A basic test */
+
+       film->set_name ("My Nice Film");
+       film->set_dcp_content_type (DCPContentType::from_isdcf_name ("FTR"));
+       film->set_container (Ratio::from_id ("185"));
+       film->_isdcf_date = boost::gregorian::date (2014, boost::gregorian::Jul, 4);
+       ISDCFMetadata m;
+       m.content_version = 1;
+       m.audio_language = "EN";
+       m.subtitle_language = "XX";
+       m.territory = "UK";
+       m.rating = "PG";
+       m.studio = "ST";
+       m.facility = "FA";
+       m.package_type = "OV";
+       film->set_isdcf_metadata (m);
+       film->set_interop (true);
+       BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilm_FTR-1_F_EN-XX_UK-PG_51_2K_ST_20140704_FA_IOP_OV");
+
+       /* Test a long name and some different data */
+
+       film->set_name ("My Nice Film With A Very Long Name");
+       film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TLR"));
+       film->set_container (Ratio::from_id ("239"));
+       film->_isdcf_date = boost::gregorian::date (2014, boost::gregorian::Jul, 4);
+       film->set_audio_channels (1);
+       film->set_resolution (RESOLUTION_4K);
+       m.content_version = 2;
+       m.audio_language = "DE";
+       m.subtitle_language = "FR";
+       m.territory = "US";
+       m.rating = "R";
+       m.studio = "DI";
+       m.facility = "PP";
+       m.package_type = "VF";
+       film->set_isdcf_metadata (m);
+       film->set_interop (false);
+       BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilmWith_TLR-2_S_DE-FR_US-R_10_4K_DI_20140704_PP_SMPTE_VF");
+
+       /* Test interior aspect ratio */
+
+       shared_ptr<ImageContent> content (new ImageContent (film, "test/data/simple_testcard_640x480.png"));
+       film->examine_and_add_content (content);
+       wait_for_jobs ();
+       content->set_scale (VideoContentScale (Ratio::from_id ("133")));
+       film->set_container (Ratio::from_id ("185"));
+       BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilmWith_TLR-2_F-133_DE-FR_US-R_10_4K_DI_20140704_PP_SMPTE_VF");
+
+       /* Test 3D */
+
+       film->set_three_d (true);
+       BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilmWith_TLR-2-3D_F-133_DE-FR_US-R_10_4K_DI_20140704_PP_SMPTE-3D_VF");
+
+       /* Test content type modifiers */
+
+       film->set_three_d (false);
+       m.temp_version = true;
+       m.pre_release = true;
+       m.red_band = true;
+       m.chain = "MyChain";
+       m.two_d_version_of_three_d = true;
+       m.mastered_luminance = "4fl";
+       film->set_isdcf_metadata (m);
+       film->set_video_frame_rate (48);
+       BOOST_CHECK_EQUAL (film->isdcf_name(false), "MyNiceFilmWith_TLR-2-Temp-Pre-RedBand-MyChain-2D-4fl-48_F-133_DE-FR_US-R_10_4K_DI_20140704_PP_SMPTE_VF");
+}
+
index 676f471049cfcf835e5da2bde766ef3ee053f687..09df146737a95c3cff4b1e28e5eef0d655f84218 100644 (file)
@@ -31,6 +31,7 @@ def build(bld):
                  film_metadata_test.cc
                  frame_rate_test.cc
                  image_test.cc
+                 isdcf_name_test.cc
                  job_test.cc
                  make_black_test.cc
                  pixel_formats_test.cc