summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-06-09 11:13:02 +0100
committerCarl Hetherington <cth@carlh.net>2015-06-09 11:13:02 +0100
commit5c1b079a28941781c9cfa46d57e0c20b55681b32 (patch)
tree35c0d2aac409ca1b52699e974f299a64aa5ffc1f /src
parent6425742f95a4c2e539061b29016a4a5bd10ac9ae (diff)
Basically-working interop subtitle font handling.
Diffstat (limited to 'src')
-rw-r--r--src/asset.cc8
-rw-r--r--src/dcp.cc18
-rw-r--r--src/font.h2
-rw-r--r--src/interop_subtitle_asset.cc50
-rw-r--r--src/interop_subtitle_asset.h4
-rw-r--r--src/reel.cc9
-rw-r--r--src/smpte_subtitle_asset.cc5
-rw-r--r--src/smpte_subtitle_asset.h1
-rw-r--r--src/subtitle_asset.cc23
-rw-r--r--src/subtitle_asset.h33
10 files changed, 141 insertions, 12 deletions
diff --git a/src/asset.cc b/src/asset.cc
index 24fc5919..5760c905 100644
--- a/src/asset.cc
+++ b/src/asset.cc
@@ -71,10 +71,16 @@ Asset::write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const
asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
xmlpp::Node* chunk_list = asset->add_child ("ChunkList");
xmlpp::Node* chunk = chunk_list->add_child ("Chunk");
- optional<boost::filesystem::path> path = relative_to_root (root, _file);
+
+ optional<boost::filesystem::path> path = relative_to_root (
+ boost::filesystem::canonical (root),
+ boost::filesystem::canonical (_file)
+ );
+
if (!path) {
throw MiscError (String::compose ("Asset %1 is not within the directory %2", _file, root));
}
+
chunk->add_child("Path")->add_child_text (path.get().string ());
chunk->add_child("VolumeIndex")->add_child_text ("1");
chunk->add_child("Offset")->add_child_text ("0");
diff --git a/src/dcp.cc b/src/dcp.cc
index da12e4f9..12aaee47 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2015 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
@@ -29,6 +29,7 @@
#include "smpte_subtitle_asset.h"
#include "mono_picture_asset.h"
#include "stereo_picture_asset.h"
+#include "reel_subtitle_asset.h"
#include "util.h"
#include "metadata.h"
#include "exceptions.h"
@@ -40,6 +41,7 @@
#include "decrypted_kdm_key.h"
#include "dcp_assert.h"
#include "reel_asset.h"
+#include "font.h"
#include <xmlsec/xmldsig.h>
#include <xmlsec/app.h>
#include <libxml++/libxml++.h>
@@ -55,8 +57,10 @@ using std::ostream;
using std::make_pair;
using std::map;
using std::cout;
+using std::cerr;
using std::exception;
using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
using boost::algorithm::starts_with;
using namespace dcp;
@@ -117,7 +121,7 @@ DCP::read (bool keep_going, ReadErrors* errors)
*/
/* Make a list of non-CPL assets so that we can resolve the references
- from the CPL.
+ from the CPLs.
*/
list<shared_ptr<Asset> > other_assets;
@@ -171,6 +175,8 @@ DCP::read (bool keep_going, ReadErrors* errors)
default:
throw DCPReadError ("Unknown MXF essence type");
}
+ } else if (boost::filesystem::extension (path) == ".ttf") {
+ other_assets.push_back (shared_ptr<Font> (new Font (path)));
}
}
@@ -423,7 +429,13 @@ DCP::assets () const
BOOST_FOREACH (shared_ptr<CPL> i, cpls ()) {
assets.push_back (i);
BOOST_FOREACH (shared_ptr<const ReelAsset> j, i->reel_assets ()) {
- assets.push_back (j->asset_ref().object ());
+ shared_ptr<Asset> o = j->asset_ref().object ();
+ assets.push_back (o);
+ /* More Interop special-casing */
+ shared_ptr<InteropSubtitleAsset> sub = dynamic_pointer_cast<InteropSubtitleAsset> (o);
+ if (sub) {
+ sub->add_font_assets (assets);
+ }
}
}
diff --git a/src/font.h b/src/font.h
index 8e0b4e18..e87419c0 100644
--- a/src/font.h
+++ b/src/font.h
@@ -26,7 +26,7 @@
namespace dcp {
/** @class Font
- * @brief A (truetype) font asset for subtitles in a DCP.
+ * @brief A (truetype) font asset for subtitles in an Interop DCP.
*/
class Font : public Asset
{
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc
index 231dda16..9565b12d 100644
--- a/src/interop_subtitle_asset.cc
+++ b/src/interop_subtitle_asset.cc
@@ -23,6 +23,8 @@
#include "raw_convert.h"
#include "font_node.h"
#include "util.h"
+#include "font.h"
+#include "dcp_assert.h"
#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
#include <cmath>
@@ -31,6 +33,8 @@
using std::list;
using std::string;
using std::cout;
+using std::cerr;
+using std::map;
using boost::shared_ptr;
using boost::optional;
using boost::dynamic_pointer_cast;
@@ -85,9 +89,10 @@ InteropSubtitleAsset::xml_as_string () const
}
void
-InteropSubtitleAsset::add_font (string id, string uri)
+InteropSubtitleAsset::add_font (string id, boost::filesystem::path file)
{
- _load_font_nodes.push_back (shared_ptr<InteropLoadFontNode> (new InteropLoadFontNode (id, uri)));
+ add_font_data (id, file);
+ _load_font_nodes.push_back (shared_ptr<InteropLoadFontNode> (new InteropLoadFontNode (id, file.leaf().string ())));
}
bool
@@ -136,7 +141,7 @@ InteropSubtitleAsset::load_font_nodes () const
return lf;
}
-/** Write this content to an XML file */
+/** Write this content to an XML file with its fonts alongside */
void
InteropSubtitleAsset::write (boost::filesystem::path p) const
{
@@ -150,4 +155,43 @@ InteropSubtitleAsset::write (boost::filesystem::path p) const
fclose (f);
_file = p;
+
+ BOOST_FOREACH (shared_ptr<InteropLoadFontNode> i, _load_font_nodes) {
+ boost::filesystem::path file = p.parent_path() / i->uri;
+ FILE* f = fopen_boost (file, "w");
+ if (!f) {
+ throw FileError ("could not open font file for writing", file, errno);
+ }
+ map<string, FontData>::const_iterator j = _fonts.find (i->id);
+ if (j != _fonts.end ()) {
+ fwrite (j->second.data.get(), 1, j->second.size, f);
+ j->second.file = file;
+ }
+ fclose (f);
+ }
+}
+
+void
+InteropSubtitleAsset::resolve_fonts (list<shared_ptr<Object> > objects)
+{
+ BOOST_FOREACH (shared_ptr<Object> i, objects) {
+ shared_ptr<Font> font = dynamic_pointer_cast<Font> (i);
+ if (!font) {
+ continue;
+ }
+
+ BOOST_FOREACH (shared_ptr<InteropLoadFontNode> j, _load_font_nodes) {
+ if (j->uri == font->file().leaf().string ()) {
+ add_font_data (j->id, font->file ());
+ }
+ }
+ }
+}
+
+void
+InteropSubtitleAsset::add_font_assets (list<shared_ptr<Asset> >& assets)
+{
+ for (map<string, FontData>::const_iterator i = _fonts.begin(); i != _fonts.end(); ++i) {
+ assets.push_back (shared_ptr<Font> (new Font (i->second.file)));
+ }
}
diff --git a/src/interop_subtitle_asset.h b/src/interop_subtitle_asset.h
index 378bacc7..4d2c2893 100644
--- a/src/interop_subtitle_asset.h
+++ b/src/interop_subtitle_asset.h
@@ -47,10 +47,12 @@ public:
std::list<boost::shared_ptr<LoadFontNode> > load_font_nodes () const;
- void add_font (std::string id, std::string uri);
+ void add_font (std::string id, boost::filesystem::path file);
Glib::ustring xml_as_string () const;
void write (boost::filesystem::path path) const;
+ void resolve_fonts (std::list<boost::shared_ptr<Object> > objects);
+ void add_font_assets (std::list<boost::shared_ptr<Asset> >& assets);
/** Set the reel number or sub-element identifier
* of these subtitles.
diff --git a/src/reel.cc b/src/reel.cc
index 106fbf40..4d92d345 100644
--- a/src/reel.cc
+++ b/src/reel.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2015 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
@@ -30,6 +30,7 @@
#include "reel_subtitle_asset.h"
#include "decrypted_kdm_key.h"
#include "decrypted_kdm.h"
+#include "interop_subtitle_asset.h"
#include <libxml++/nodes/element.h>
using std::string;
@@ -176,5 +177,11 @@ Reel::resolve_refs (list<shared_ptr<Object> > objects)
if (_main_subtitle) {
_main_subtitle->asset_ref().resolve (objects);
+
+ /* Interop subtitle handling is all special cases */
+ shared_ptr<InteropSubtitleAsset> iop = dynamic_pointer_cast<InteropSubtitleAsset> (_main_subtitle->asset_ref().object ());
+ if (iop) {
+ iop->resolve_fonts (objects);
+ }
}
}
diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc
index 69e2712f..28d8b261 100644
--- a/src/smpte_subtitle_asset.cc
+++ b/src/smpte_subtitle_asset.cc
@@ -209,3 +209,8 @@ SMPTESubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions
return false;
}
+void
+SMPTESubtitleAsset::add_font (string id, boost::filesystem::path file)
+{
+ /* XXX */
+}
diff --git a/src/smpte_subtitle_asset.h b/src/smpte_subtitle_asset.h
index 3fb2571a..37f58c6f 100644
--- a/src/smpte_subtitle_asset.h
+++ b/src/smpte_subtitle_asset.h
@@ -53,6 +53,7 @@ public:
Glib::ustring xml_as_string () const;
void write (boost::filesystem::path path) const;
+ void add_font (std::string id, boost::filesystem::path file);
void set_content_title_text (std::string t) {
_content_title_text = t;
diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc
index 45177b95..70d7a955 100644
--- a/src/subtitle_asset.cc
+++ b/src/subtitle_asset.cc
@@ -29,6 +29,7 @@
#include "KM_util.h"
#include <libxml++/nodes/element.h>
#include <boost/algorithm/string.hpp>
+#include <boost/shared_array.hpp>
#include <fstream>
using std::string;
@@ -37,7 +38,9 @@ using std::ostream;
using std::ofstream;
using std::stringstream;
using std::cout;
+using std::cerr;
using boost::shared_ptr;
+using boost::shared_array;
using boost::optional;
using boost::dynamic_pointer_cast;
using namespace dcp;
@@ -304,4 +307,22 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* root, int time_code_rate, strin
}
}
-
+void
+SubtitleAsset::add_font_data (string id, boost::filesystem::path file)
+{
+ boost::uintmax_t size = boost::filesystem::file_size (file);
+ FILE* f = fopen_boost (file, "r");
+ if (!f) {
+ throw FileError ("could not open font file for reading", file, errno);
+ }
+
+ shared_array<uint8_t> data (new uint8_t[size]);
+ size_t const read = fread (data.get(), 1, size, f);
+ fclose (f);
+
+ if (read != size) {
+ throw FileError ("could not read font file", file, -1);
+ }
+
+ _fonts[id] = FontData (data, size, file);
+}
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
index 5fdb5f7a..481556aa 100644
--- a/src/subtitle_asset.h
+++ b/src/subtitle_asset.h
@@ -24,11 +24,14 @@
#include "dcp_time.h"
#include "subtitle_string.h"
#include <libcxml/cxml.h>
+#include <boost/shared_array.hpp>
namespace xmlpp {
class Element;
}
+struct interop_dcp_font_test;
+
namespace dcp
{
@@ -64,6 +67,7 @@ public:
}
void add (SubtitleString);
+ virtual void add_font (std::string id, boost::filesystem::path file) = 0;
virtual void write (boost::filesystem::path) const = 0;
virtual Glib::ustring xml_as_string () const = 0;
@@ -73,13 +77,40 @@ public:
virtual std::list<boost::shared_ptr<LoadFontNode> > load_font_nodes () const = 0;
protected:
+ friend struct ::interop_dcp_font_test;
+
void parse_subtitles (boost::shared_ptr<cxml::Document> xml, std::list<boost::shared_ptr<FontNode> > font_nodes);
-
void subtitles_as_xml (xmlpp::Element* root, int time_code_rate, std::string xmlns) const;
+ void add_font_data (std::string id, boost::filesystem::path file);
/** All our subtitles, in no particular order */
std::list<SubtitleString> _subtitles;
+ class FontData {
+ public:
+ FontData () {}
+
+ FontData (boost::shared_array<uint8_t> data_, boost::uintmax_t size_)
+ : data (data_)
+ , size (size_)
+ {}
+
+ FontData (boost::shared_array<uint8_t> data_, boost::uintmax_t size_, boost::filesystem::path file_)
+ : data (data_)
+ , size (size_)
+ , file (file_)
+ {}
+
+ boost::shared_array<uint8_t> data;
+ boost::uintmax_t size;
+ mutable boost::filesystem::path file;
+ };
+
+ /** Font data, keyed by a subclass-dependent identifier.
+ * For Interop fonts, the string is the font ID from the subtitle file.
+ */
+ std::map<std::string, FontData> _fonts;
+
private:
/** @struct ParseState
* @brief A struct to hold state when parsing a subtitle XML file.