Basic pass-through of font information when using DCP subtitles.
authorCarl Hetherington <cth@carlh.net>
Sat, 20 Dec 2014 22:29:21 +0000 (22:29 +0000)
committerCarl Hetherington <cth@carlh.net>
Sat, 20 Dec 2014 22:29:21 +0000 (22:29 +0000)
16 files changed:
TO_PORT
src/lib/film.cc
src/lib/film.h
src/lib/font.cc
src/lib/font.h
src/lib/player.cc
src/lib/player.h
src/lib/player_subtitles.h
src/lib/subrip_content.cc
src/lib/subrip_content.h
src/lib/subrip_decoder.cc
src/lib/transcoder.cc
src/lib/writer.cc
src/lib/writer.h
src/wx/fonts_dialog.cc
test/dcp_subtitle_test.cc

diff --git a/TO_PORT b/TO_PORT
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4818d253adee54801ed12303f90cfe5187b6e283 100644 (file)
--- a/TO_PORT
+++ b/TO_PORT
@@ -0,0 +1,3 @@
+c8926dcc6cb327ddf4796bf2bfe17d65c75940e5
+0ee1e8c65e2977638375a8f96dbea201210aac98
+f2851b7066d0e12102b0f3aabc2b827a261206a9
index 46c27d1952b9ae1b79cbc4eaae8a8657a0e4365c..d7620be8d291f476d1caccfccc13951a1e061106 100644 (file)
@@ -48,6 +48,7 @@
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/foreach.hpp>
 #include <unistd.h>
 #include <stdexcept>
 #include <iostream>
@@ -69,6 +70,7 @@ using std::make_pair;
 using std::endl;
 using std::cout;
 using std::list;
+using std::set;
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
@@ -1142,3 +1144,28 @@ Film::should_be_enough_disk_space (double& required, double& available) const
        available = double (s.available) / 1073741824.0f;
        return (available - required) > 1;
 }
+
+string
+Film::subtitle_language () const
+{
+       set<string> languages;
+       
+       ContentList cl = content ();
+       BOOST_FOREACH (shared_ptr<Content>& c, cl) {
+               shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (c);
+               if (sc) {
+                       languages.insert (sc->subtitle_language ());
+               }
+       }
+
+       string all;
+       BOOST_FOREACH (string s, languages) {
+               if (!all.empty ()) {
+                       all += "/" + s;
+               } else {
+                       all += s;
+               }
+       }
+
+       return all;
+}
index 8628d8b38e64276710d72c48e5adb9ef83d5add4..0227f26c99a3b7882ee17c969eb9d2ae63ee4ddf 100644 (file)
@@ -143,6 +143,8 @@ public:
                return _state_version;
        }
 
+       std::string subtitle_language () const;
+
        /** Identifiers for the parts of our state;
            used for signalling changes.
        */
index bf7a79a3dfcd91aca9e167bf70463d8589d3cdc0..ecf7aabf0146ae6c707ebf4218db19427d0d6a53 100644 (file)
 
 Font::Font (cxml::NodePtr node)
 {
-       id = node->optional_string_child ("Id");
+       id = node->string_child ("Id");
        file = node->optional_string_child ("File");
 }
 
 void
 Font::as_xml (xmlpp::Node* node)
 {
-       if (id) {
-               node->add_child("Id")->add_child_text (id.get ());
-       }
-
+       node->add_child("Id")->add_child_text (id);
        if (file) {
                node->add_child("File")->add_child_text (file.get().string ());
        }
index 7a26eefc9227f0f11554a9c9d9b5cfa4aa182fe7..6161c20a9061d4d66e97034037c78bdbbfcb3af3 100644 (file)
@@ -25,8 +25,6 @@
 class Font
 {
 public:
-       Font () {}
-
        Font (std::string id_)
                : id (id_) {}
 
@@ -34,8 +32,8 @@ public:
 
        void as_xml (xmlpp::Node* node);
        
-       /** Font ID, or empty for the default font */
-       boost::optional<std::string> id;
+       /** Font ID */
+       std::string id;
        boost::optional<boost::filesystem::path> file;
 };
 
index 396dc990684667b93060df953cb767f6e6246335..695ce00cef908ddf0c68aa1520f0a8dcca53c0c3 100644 (file)
@@ -551,12 +551,6 @@ Player::get_subtitles (DCPTime time, DCPTime length, bool starting)
                        continue;
                }
 
-               /* XXX: this will break down if we have multiple subtitle content */
-               ps.language = subtitle_content->subtitle_language();
-               if (ps.language.empty ()) {
-                       ps.language = _("Unknown");
-               }
-
                shared_ptr<SubtitleDecoder> subtitle_decoder = dynamic_pointer_cast<SubtitleDecoder> ((*j)->decoder);
                ContentTime const from = dcp_to_content_subtitle (*j, time);
                /* XXX: this video_frame_rate() should be the rate that the subtitle content has been prepared for */
@@ -592,3 +586,25 @@ Player::get_subtitles (DCPTime time, DCPTime length, bool starting)
 
        return ps;
 }
+
+list<shared_ptr<Font> >
+Player::get_subtitle_fonts ()
+{
+       if (!_have_valid_pieces) {
+               setup_pieces ();
+       }
+
+       list<shared_ptr<Font> > fonts;
+       BOOST_FOREACH (shared_ptr<Piece>& p, _pieces) {
+               shared_ptr<SubtitleContent> sc = dynamic_pointer_cast<SubtitleContent> (p->content);
+               if (sc) {
+                       /* XXX: things may go wrong if there are duplicate font IDs
+                          with different font files.
+                       */
+                       list<shared_ptr<Font> > f = sc->fonts ();
+                       copy (f.begin(), f.end(), back_inserter (fonts));
+               }
+       }
+
+       return fonts;
+}
index 5d2273a44018c04e50605fd71179f31176240f52..9a1e8cc23b1e8bb6eb32df6971da113f91d3c580 100644 (file)
@@ -89,6 +89,7 @@ public:
        std::list<boost::shared_ptr<PlayerVideo> > get_video (DCPTime time, bool accurate);
        boost::shared_ptr<AudioBuffers> get_audio (DCPTime time, DCPTime length, bool accurate);
        PlayerSubtitles get_subtitles (DCPTime time, DCPTime length, bool starting);
+       std::list<boost::shared_ptr<Font> > get_subtitle_fonts ();
 
        void set_video_container_size (dcp::Size);
        void set_approximate_size ();
index 804c87cb9e22b2fb62c062572d23599a0af8084b..65de500f63d265ca7bea8b6bbd5144122708a3e5 100644 (file)
@@ -37,8 +37,6 @@ public:
        /** ImageSubtitles, with their rectangles transformed as specified by their content */
        std::list<ImageSubtitle> image;
        std::list<dcp::SubtitleString> text;
-
-       std::string language;
 };
 
 #endif
index 969829b31e1a9075d2e7316fb1cfab2ecbaed58e..992947a2d9023c38758c14a22ed982689385ea8d 100644 (file)
@@ -32,6 +32,8 @@ using dcp::raw_convert;
 using boost::shared_ptr;
 using boost::lexical_cast;
 
+std::string const SubRipContent::font_id = "font";
+
 SubRipContent::SubRipContent (shared_ptr<const Film> film, boost::filesystem::path path)
        : Content (film, path)
        , SubtitleContent (film, path)
@@ -60,7 +62,7 @@ SubRipContent::examine (boost::shared_ptr<Job> job, bool calculate_digest)
 
        boost::mutex::scoped_lock lm (_mutex);
        _length = len;
-       _fonts.push_back (shared_ptr<Font> (new Font ()));
+       _fonts.push_back (shared_ptr<Font> (new Font (font_id)));
 }
 
 string
index 243032691b76b0179205f5614098e51cc8e25bb7..0202e21d7f32eb782a81989cc27947c75ea748fe 100644 (file)
@@ -42,6 +42,8 @@ public:
                return true;
        }
 
+       static std::string const font_id;
+       
 private:
        DCPTime _length;
 };
index e13b1106356cf8ea1228c4e8ea562050d59979d2..ea8997e31aab9667f76a5f305a5f01121eee181e 100644 (file)
@@ -60,7 +60,7 @@ SubRipDecoder::pass ()
                for (list<sub::Block>::const_iterator j = i->blocks.begin(); j != i->blocks.end(); ++j) {
                        out.push_back (
                                dcp::SubtitleString (
-                                       optional<string> (),
+                                       SubRipContent::font_id,
                                        j->italic,
                                        dcp::Color (255, 255, 255),
                                        /* .srt files don't specify size, so this is an arbitrary value */
index 9d8eebe255d63d16dac547ab5851e8388c601c0c..5718a05b4bc2852d65ee3325e405b0389f6467bc 100644 (file)
@@ -63,6 +63,11 @@ Transcoder::go ()
 
        DCPTime const frame = DCPTime::from_frames (1, _film->video_frame_rate ());
        DCPTime const length = _film->length ();
+
+       if (!_film->burn_subtitles ()) {
+               _writer->write (_player->get_subtitle_fonts ());
+       }
+       
        for (DCPTime t; t < length; t += frame) {
                list<shared_ptr<PlayerVideo> > v = _player->get_video (t, true);
                for (list<shared_ptr<PlayerVideo> >::const_iterator i = v.begin(); i != v.end(); ++i) {
index 5a6998c8af67c70f3ab25c40eb9c8977d86b7702..07b637d46369f3b0656f7db0af7aeeb7fc1020a5 100644 (file)
@@ -32,6 +32,7 @@
 #include "md5_digester.h"
 #include "encoded_data.h"
 #include "version.h"
+#include "font.h"
 #include <dcp/mono_picture_mxf.h>
 #include <dcp/stereo_picture_mxf.h>
 #include <dcp/sound_mxf.h>
@@ -616,7 +617,7 @@ Writer::write (PlayerSubtitles subs)
        }
        
        if (!_subtitle_content) {
-               _subtitle_content.reset (new dcp::InteropSubtitleContent (_film->name(), subs.language));
+               _subtitle_content.reset (new dcp::InteropSubtitleContent (_film->name(), _film->subtitle_language ()));
        }
        
        for (list<dcp::SubtitleString>::const_iterator i = subs.text.begin(); i != subs.text.end(); ++i) {
@@ -624,6 +625,19 @@ Writer::write (PlayerSubtitles subs)
        }
 }
 
+void
+Writer::write (list<shared_ptr<Font> > fonts)
+{
+       if (!_subtitle_content) {
+               _subtitle_content.reset (new dcp::InteropSubtitleContent (_film->name(), _film->subtitle_language ()));
+       }
+       
+       for (list<shared_ptr<Font> >::const_iterator i = fonts.begin(); i != fonts.end(); ++i) {
+               /* XXX: this LiberationSans-Regular needs to be a path to a DCP-o-matic-distributed copy */
+               _subtitle_content->add_font ((*i)->id, (*i)->file.get_value_or ("LiberationSans-Regular.ttf").leaf().string ());
+       }
+}
+
 bool
 operator< (QueueItem const & a, QueueItem const & b)
 {
index 5efb14e50e39ee9ebf682635dfb2a4f963ee1411..6aa0f4c1f38a28812600d6eb2f10efb521ec2f83 100644 (file)
@@ -24,7 +24,6 @@
 #include "exceptions.h"
 #include "types.h"
 #include "player_subtitles.h"
-#include <dcp/subtitle_content.h>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
 #include <boost/thread.hpp>
@@ -35,6 +34,7 @@ class Film;
 class EncodedData;
 class AudioBuffers;
 class Job;
+class Font;
 
 namespace dcp {
        class MonoPictureMXF;
@@ -45,6 +45,7 @@ namespace dcp {
        class PictureMXFWriter;
        class SoundMXF;
        class SoundMXFWriter;
+       class InteropSubtitleContent;
 }
 
 struct QueueItem
@@ -95,6 +96,7 @@ public:
        void fake_write (int, Eyes);
        void write (boost::shared_ptr<const AudioBuffers>);
        void write (PlayerSubtitles subs);
+       void write (std::list<boost::shared_ptr<Font> > fonts);
        void repeat (int f, Eyes);
        void finish ();
 
@@ -149,5 +151,5 @@ private:
        boost::shared_ptr<dcp::PictureMXFWriter> _picture_mxf_writer;
        boost::shared_ptr<dcp::SoundMXF> _sound_mxf;
        boost::shared_ptr<dcp::SoundMXFWriter> _sound_mxf_writer;
-       boost::shared_ptr<dcp::SubtitleContent> _subtitle_content;
+       boost::shared_ptr<dcp::InteropSubtitleContent> _subtitle_content;
 };
index 1edfcf100821bbbaa48e2539cb66dcea31980fcc..99d570263c12a88dcccb486a3fea70e23890b5a6 100644 (file)
@@ -89,7 +89,7 @@ FontsDialog::setup ()
                wxListItem item;
                item.SetId (n);
                _fonts->InsertItem (item);
-               _fonts->SetItem (n, 0, (*i)->id.get_value_or (wx_to_std (_("[Default]"))));
+               _fonts->SetItem (n, 0, std_to_wx ((*i)->id));
                if ((*i)->file) {
                        _fonts->SetItem (n, 1, (*i)->file.get().leaf().string ());
                }
index 12d9a7a1e4bf93dd9904132e9454197ce3d5a309..08e8a5cc03360b7b8c42c93f8fdc480f867fdbc2 100644 (file)
 using std::cout;
 using boost::shared_ptr;
 
-/** Test load of very simple DCP subtitle file */
+/** Test pass-through of a very simple DCP subtitle file */
 BOOST_AUTO_TEST_CASE (dcp_subtitle_test)
 {
        shared_ptr<Film> film = new_test_film ("dcp_subtitle_test");
        film->set_container (Ratio::from_id ("185"));
        film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TLR"));
        film->set_name ("frobozz");
+       film->set_burn_subtitles (false);
        shared_ptr<DCPSubtitleContent> content (new DCPSubtitleContent (film, "test/data/dcp_sub.xml"));
        film->examine_and_add_content (content, true);
        wait_for_jobs ();
 
        BOOST_CHECK_EQUAL (content->full_length(), DCPTime::from_seconds (2));
+
+       content->set_use_subtitles (true);
+       film->make_dcp ();
+       wait_for_jobs ();
+
+       check_dcp ("test/data/dcp_subtitle_test", film->dir (film->dcp_name ()));
 }