summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-05-04 01:14:12 +0100
committerCarl Hetherington <cth@carlh.net>2014-05-04 01:14:12 +0100
commit41c4d628f7ef3c9f9b434d34ff099f5fe4de1ae4 (patch)
treef912e10cfd99245933ffd3eaa0d39a01aec1daad /src
parent09e16aa3acf7878b54a4995a0be79890f26db09f (diff)
Port support for MXF-wrapped subtitles from 0.x
Diffstat (limited to 'src')
-rw-r--r--src/dcp.cc5
-rw-r--r--src/load_font.cc11
-rw-r--r--src/load_font.h3
-rw-r--r--src/mxf.cc2
-rw-r--r--src/subtitle_content.cc57
-rw-r--r--src/subtitle_content.h13
-rw-r--r--src/text.cc7
7 files changed, 80 insertions, 18 deletions
diff --git a/src/dcp.cc b/src/dcp.cc
index 044e1f53..9374bffd 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -133,7 +133,7 @@ DCP::read (bool keep_going, ReadErrors* errors)
if (root == "CompositionPlaylist") {
_assets.push_back (shared_ptr<CPL> (new CPL (path)));
} else if (root == "DCSubtitle") {
- _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (path)));
+ _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (path, false)));
}
} else if (boost::algorithm::ends_with (path.string(), ".mxf")) {
ASDCP::EssenceType_t type;
@@ -154,6 +154,9 @@ DCP::read (bool keep_going, ReadErrors* errors)
case ASDCP::ESS_JPEG_2000_S:
_assets.push_back (shared_ptr<StereoPictureMXF> (new StereoPictureMXF (path)));
break;
+ case ASDCP::ESS_TIMED_TEXT:
+ _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (path, true)));
+ break;
default:
throw DCPReadError ("Unknown MXF essence type");
}
diff --git a/src/load_font.cc b/src/load_font.cc
index 707f4a0b..b46569c8 100644
--- a/src/load_font.cc
+++ b/src/load_font.cc
@@ -20,11 +20,18 @@
#include "load_font.h"
#include <libcxml/cxml.h>
+using std::string;
using boost::shared_ptr;
+using boost::optional;
using namespace dcp;
LoadFont::LoadFont (boost::shared_ptr<const cxml::Node> node)
{
- id = node->string_attribute ("Id");
- uri = node->string_attribute ("URI");
+ optional<string> x = node->optional_string_attribute ("Id");
+ if (!x) {
+ x = node->optional_string_attribute ("ID");
+ }
+ id = x.get_value_or ("");
+
+ uri = node->optional_string_attribute ("URI");
}
diff --git a/src/load_font.h b/src/load_font.h
index 6319b1de..6d52a509 100644
--- a/src/load_font.h
+++ b/src/load_font.h
@@ -18,6 +18,7 @@
*/
#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
namespace cxml {
class Node;
@@ -32,7 +33,7 @@ public:
LoadFont (boost::shared_ptr<const cxml::Node> node);
std::string id;
- std::string uri;
+ boost::optional<std::string> uri;
};
}
diff --git a/src/mxf.cc b/src/mxf.cc
index 3f8ab5d3..d73c590b 100644
--- a/src/mxf.cc
+++ b/src/mxf.cc
@@ -148,7 +148,7 @@ void
MXF::read_writer_info (ASDCP::WriterInfo const & info)
{
char buffer[64];
- Kumu::bin2UUIDhex (info.AssetUUID, 16, buffer, 64);
+ Kumu::bin2UUIDhex (info.AssetUUID, ASDCP::UUIDlen, buffer, sizeof (buffer));
_id = buffer;
}
diff --git a/src/subtitle_content.cc b/src/subtitle_content.cc
index f338517e..0aaab9a2 100644
--- a/src/subtitle_content.cc
+++ b/src/subtitle_content.cc
@@ -24,6 +24,8 @@
#include "text.h"
#include "load_font.h"
#include "subtitle_string.h"
+#include "AS_DCP.h"
+#include "KM_util.h"
#include <libxml++/nodes/element.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
@@ -40,15 +42,42 @@ using boost::lexical_cast;
using boost::optional;
using namespace dcp;
-SubtitleContent::SubtitleContent (boost::filesystem::path file)
+SubtitleContent::SubtitleContent (boost::filesystem::path file, bool mxf)
: Content (file)
, _need_sort (false)
{
- shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
- xml->read_file (file);
+ shared_ptr<cxml::Document> xml;
- _id = xml->string_child ("SubtitleID");
- _movie_title = xml->string_child ("MovieTitle");
+ if (mxf) {
+ 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));
+ }
+
+ string s;
+ reader.ReadTimedTextResource (s, 0, 0);
+ xml.reset (new cxml::Document ("SubtitleReel"));
+ stringstream t;
+ t << s;
+ xml->read_stream (t);
+
+ ASDCP::WriterInfo info;
+ reader.FillWriterInfo (info);
+
+ char buffer[64];
+ Kumu::bin2UUIDhex (info.AssetUUID, ASDCP::UUIDlen, buffer, sizeof (buffer));
+ _id = buffer;
+
+ } else {
+ xml.reset (new cxml::Document ("DCSubtitle"));
+ xml->read_file (file);
+ _id = xml->string_child ("SubtitleID");
+ }
+
+ /* XXX: hacks aplenty in here; probably need separate parsers for DCSubtitle and SubtitleReel */
+
+ _movie_title = xml->optional_string_child ("MovieTitle");
_reel_number = xml->string_child ("ReelNumber");
_language = xml->string_child ("Language");
@@ -60,6 +89,12 @@ SubtitleContent::SubtitleContent (boost::filesystem::path file)
/* Now make Subtitle objects to represent the raw XML nodes
in a sane way.
*/
+
+ shared_ptr<cxml::Node> subtitle_list = xml->optional_node_child ("SubtitleList");
+ if (subtitle_list) {
+ list<shared_ptr<dcp::Font> > font = type_children<dcp::Font> (subtitle_list, "Font");
+ copy (font.begin(), font.end(), back_inserter (font_nodes));
+ }
ParseState parse_state;
examine_font_nodes (xml, font_nodes, parse_state);
@@ -180,7 +215,7 @@ SubtitleContent::font_id_to_name (string id) const
return "";
}
- if ((*i)->uri == "arial.ttf") {
+ if ((*i)->uri && (*i)->uri.get() == "arial.ttf") {
return "Arial";
}
@@ -220,7 +255,9 @@ SubtitleContent::xml_as_string () const
root->set_attribute ("Version", "1.0");
root->add_child("SubtitleID")->add_child_text (_id);
- root->add_child("MovieTitle")->add_child_text (_movie_title);
+ if (_movie_title) {
+ root->add_child("MovieTitle")->add_child_text (_movie_title.get ());
+ }
root->add_child("ReelNumber")->add_child_text (lexical_cast<string> (_reel_number));
root->add_child("Language")->add_child_text (_language);
@@ -230,8 +267,10 @@ SubtitleContent::xml_as_string () const
if (!_load_font_nodes.empty ()) {
xmlpp::Element* load_font = root->add_child("LoadFont");
- load_font->set_attribute("Id", _load_font_nodes.front()->id);
- load_font->set_attribute("URI", _load_font_nodes.front()->uri);
+ load_font->set_attribute ("Id", _load_font_nodes.front()->id);
+ if (_load_font_nodes.front()->uri) {
+ load_font->set_attribute ("URI", _load_font_nodes.front()->uri.get ());
+ }
}
list<shared_ptr<SubtitleString> > sorted = _subtitles;
diff --git a/src/subtitle_content.h b/src/subtitle_content.h
index 410c5934..2c606921 100644
--- a/src/subtitle_content.h
+++ b/src/subtitle_content.h
@@ -34,12 +34,19 @@ class Subtitle;
class LoadFont;
/** @class SubtitleContent
- * @brief A representation of an XML file containing subtitles.
+ * @brief A representation of an XML or MXF file containing subtitles.
+ *
+ * XXX: perhaps this should inhert from MXF, or there should be different
+ * classes for XML and MXF subs.
*/
class SubtitleContent : public Content
{
public:
- SubtitleContent (boost::filesystem::path file);
+ /** Construct a SubtitleContent.
+ * @param file Filename.
+ * @param mxf true if the file is an MXF file, false for XML.
+ */
+ SubtitleContent (boost::filesystem::path file, bool mxf);
SubtitleContent (Fraction edit_rate, std::string movie_title, std::string language);
bool equals (
@@ -98,7 +105,7 @@ private:
ParseState& parse_state
);
- std::string _movie_title;
+ boost::optional<std::string> _movie_title;
/* strangely, this is sometimes a string */
std::string _reel_number;
std::string _language;
diff --git a/src/text.cc b/src/text.cc
index 888cab29..6fbdbe6e 100644
--- a/src/text.cc
+++ b/src/text.cc
@@ -39,7 +39,12 @@ Text::Text (boost::shared_ptr<const cxml::Node> node)
: v_align (CENTER)
{
text = node->content ();
- v_position = node->number_attribute<float> ("VPosition");
+ optional<float> x = node->optional_number_attribute<float> ("VPosition");
+ if (!x) {
+ x = node->number_attribute<float> ("Vposition");
+ }
+ v_position = x.get ();
+
optional<string> v = node->optional_string_attribute ("VAlign");
if (v) {
v_align = string_to_valign (v.get ());