summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2015-06-09 14:02:20 +0100
committerCarl Hetherington <cth@carlh.net>2015-06-09 14:02:20 +0100
commite4b8bed37b4fcfb932e2b899003f2a95df908ba0 (patch)
tree6af8acd73fdfdaa0025dca758cc29e488c4ce8a4 /src
parent2ac1dbfeaffa5166f104ef4a01fedc41f542cacf (diff)
Handle storing/recovery of fonts in SMPTE MXF files.
Diffstat (limited to 'src')
-rw-r--r--src/interop_subtitle_asset.cc4
-rw-r--r--src/smpte_load_font_node.cc10
-rw-r--r--src/smpte_load_font_node.h1
-rw-r--r--src/smpte_subtitle_asset.cc84
-rw-r--r--src/subtitle_asset.cc2
-rw-r--r--src/subtitle_asset.h14
6 files changed, 95 insertions, 20 deletions
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc
index 9565b12d..5be4c53c 100644
--- a/src/interop_subtitle_asset.cc
+++ b/src/interop_subtitle_asset.cc
@@ -36,6 +36,7 @@ using std::cout;
using std::cerr;
using std::map;
using boost::shared_ptr;
+using boost::shared_array;
using boost::optional;
using boost::dynamic_pointer_cast;
using namespace dcp;
@@ -192,6 +193,7 @@ 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)));
+ DCP_ASSERT (i->second.file);
+ assets.push_back (shared_ptr<Font> (new Font (i->second.file.get ())));
}
}
diff --git a/src/smpte_load_font_node.cc b/src/smpte_load_font_node.cc
index 11f7d5a4..28a020df 100644
--- a/src/smpte_load_font_node.cc
+++ b/src/smpte_load_font_node.cc
@@ -24,8 +24,16 @@ using std::string;
using boost::shared_ptr;
using namespace dcp;
+SMPTELoadFontNode::SMPTELoadFontNode (string id, string urn_)
+ : LoadFontNode (id)
+ , urn (urn_)
+{
+
+}
+
SMPTELoadFontNode::SMPTELoadFontNode (shared_ptr<const cxml::Node> node)
: LoadFontNode (node->string_attribute ("ID"))
+ , urn (node->content().substr (9))
{
- urn = node->content().substr (9);
+
}
diff --git a/src/smpte_load_font_node.h b/src/smpte_load_font_node.h
index a150d9be..e6b87f30 100644
--- a/src/smpte_load_font_node.h
+++ b/src/smpte_load_font_node.h
@@ -38,6 +38,7 @@ class SMPTELoadFontNode : public LoadFontNode
{
public:
SMPTELoadFontNode () {}
+ SMPTELoadFontNode (std::string id, std::string urn);
SMPTELoadFontNode (boost::shared_ptr<const cxml::Node> node);
std::string urn;
diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc
index 9878ea1f..026e9f63 100644
--- a/src/smpte_subtitle_asset.cc
+++ b/src/smpte_subtitle_asset.cc
@@ -26,9 +26,11 @@
#include "font_node.h"
#include "exceptions.h"
#include "xml.h"
+#include "raw_convert.h"
+#include "dcp_assert.h"
+#include "util.h"
#include "AS_DCP.h"
#include "KM_util.h"
-#include "raw_convert.h"
#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
@@ -38,13 +40,16 @@ using std::list;
using std::stringstream;
using std::cout;
using std::vector;
+using std::map;
using boost::shared_ptr;
using boost::split;
using boost::is_any_of;
+using boost::shared_array;
using namespace dcp;
SMPTESubtitleAsset::SMPTESubtitleAsset ()
- : _time_code_rate (0)
+ : _edit_rate (24, 1)
+ , _time_code_rate (24)
{
}
@@ -55,24 +60,25 @@ SMPTESubtitleAsset::SMPTESubtitleAsset ()
SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
: SubtitleAsset (file)
{
- shared_ptr<cxml::Document> xml (new cxml::Document ("SubtitleReel"));
-
ASDCP::TimedText::MXFReader reader;
Kumu::Result_t r = reader.OpenRead (file.string().c_str ());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("could not open MXF file for reading", file, r));
}
+
+ /* Read the subtitle XML */
string s;
reader.ReadTimedTextResource (s, 0, 0);
stringstream t;
t << s;
+ shared_ptr<cxml::Document> xml (new cxml::Document ("SubtitleReel"));
xml->read_stream (t);
ASDCP::WriterInfo info;
reader.FillWriterInfo (info);
_id = read_writer_info (info);
-
+
_load_font_nodes = type_children<dcp::SMPTELoadFontNode> (xml, "LoadFont");
_content_title_text = xml->string_child ("ContentTitleText");
@@ -107,6 +113,42 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
}
parse_subtitles (xml, font_nodes);
+
+ /* Read fonts */
+
+ ASDCP::TimedText::TimedTextDescriptor text_descriptor;
+ reader.FillTimedTextDescriptor (text_descriptor);
+ for (
+ ASDCP::TimedText::ResourceList_t::const_iterator i = text_descriptor.ResourceList.begin();
+ i != text_descriptor.ResourceList.end();
+ ++i) {
+
+ if (i->Type == ASDCP::TimedText::MT_OPENTYPE) {
+ ASDCP::TimedText::FrameBuffer buffer;
+ buffer.Capacity (10 * 1024 * 1024);
+ reader.ReadAncillaryResource (i->ResourceID, buffer);
+
+ char id[64];
+ Kumu::bin2UUIDhex (i->ResourceID, ASDCP::UUIDlen, id, sizeof (id));
+
+ shared_array<uint8_t> data (new uint8_t[buffer.Size()]);
+ memcpy (data.get(), buffer.RoData(), buffer.Size());
+
+ /* The IDs in the MXF have a 9 character prefix of unknown origin and meaning... */
+ string check_id = string (id).substr (9);
+
+ list<shared_ptr<SMPTELoadFontNode> >::const_iterator j = _load_font_nodes.begin ();
+ while (j != _load_font_nodes.end() && (*j)->urn != check_id) {
+ ++j;
+ }
+
+ if (j != _load_font_nodes.end ()) {
+ _fonts[(*j)->id] = FontData (data, buffer.Size ());
+ }
+ }
+ }
+
+
}
list<shared_ptr<LoadFontNode> >
@@ -172,13 +214,23 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
ASDCP::TimedText::TimedTextDescriptor descriptor;
descriptor.EditRate = ASDCP::Rational (_edit_rate.numerator, _edit_rate.denominator);
descriptor.EncodingName = "UTF-8";
- descriptor.ResourceList.clear ();
+
+ BOOST_FOREACH (shared_ptr<dcp::SMPTELoadFontNode> i, _load_font_nodes) {
+ map<string, FontData>::const_iterator j = _fonts.find (i->id);
+ if (j != _fonts.end ()) {
+ ASDCP::TimedText::TimedTextResourceDescriptor res;
+ unsigned int c;
+ Kumu::hex2bin (i->urn.c_str(), res.ResourceID, Kumu::UUID_Length, &c);
+ DCP_ASSERT (c == Kumu::UUID_Length);
+ res.Type = ASDCP::TimedText::MT_OPENTYPE;
+ descriptor.ResourceList.push_back (res);
+ }
+ }
+
descriptor.NamespaceName = "dcst";
memcpy (descriptor.AssetID, writer_info.AssetUUID, ASDCP::UUIDlen);
descriptor.ContainerDuration = latest_subtitle_out().as_editable_units (_edit_rate.numerator / _edit_rate.denominator);
- /* XXX: should write fonts into the file somehow */
-
ASDCP::TimedText::MXFWriter writer;
ASDCP::Result_t r = writer.OpenWrite (p.string().c_str(), writer_info, descriptor);
if (ASDCP_FAILURE (r)) {
@@ -191,6 +243,19 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
boost::throw_exception (MXFFileError ("could not write XML to timed text resource", p.string(), r));
}
+ BOOST_FOREACH (shared_ptr<dcp::SMPTELoadFontNode> i, _load_font_nodes) {
+ map<string, FontData>::const_iterator j = _fonts.find (i->id);
+ if (j != _fonts.end ()) {
+ ASDCP::TimedText::FrameBuffer buffer;
+ buffer.SetData (j->second.data.get(), j->second.size);
+ buffer.Size (j->second.size);
+ r = writer.WriteAncillaryResource (buffer);
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not write font to timed text resource", p.string(), r));
+ }
+ }
+ }
+
writer.Finalize ();
_file = p;
@@ -206,5 +271,6 @@ SMPTESubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions
void
SMPTESubtitleAsset::add_font (string id, boost::filesystem::path file)
{
- /* XXX */
+ add_font_data (id, file);
+ _load_font_nodes.push_back (shared_ptr<SMPTELoadFontNode> (new SMPTELoadFontNode (id, make_uuid ())));
}
diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc
index 70d7a955..085e5959 100644
--- a/src/subtitle_asset.cc
+++ b/src/subtitle_asset.cc
@@ -324,5 +324,5 @@ SubtitleAsset::add_font_data (string id, boost::filesystem::path file)
throw FileError ("could not read font file", file, -1);
}
- _fonts[id] = FontData (data, size, file);
+ _fonts[id] = FontData (data, size);
}
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
index 481556aa..4cbbff0d 100644
--- a/src/subtitle_asset.h
+++ b/src/subtitle_asset.h
@@ -31,6 +31,7 @@ namespace xmlpp {
}
struct interop_dcp_font_test;
+struct smpte_dcp_font_test;
namespace dcp
{
@@ -78,6 +79,7 @@ public:
protected:
friend struct ::interop_dcp_font_test;
+ friend struct ::smpte_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;
@@ -94,20 +96,16 @@ protected:
: 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;
+ /** .ttf file that this data was last written to */
+ mutable boost::optional<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.
+ * For Interop, the string is the font ID from the subtitle file.
+ * For SMPTE, the string is the font's URN from the subtitle file.
*/
std::map<std::string, FontData> _fonts;