summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-02-26 17:48:29 +0000
committerCarl Hetherington <cth@carlh.net>2014-02-26 17:48:29 +0000
commit471c9d05fc19484f3e50cf805d14237b72bbb7b2 (patch)
tree579ff1520617941734365a8e9f53985a86396507
parentd7d879c988d484cb1a5fd65831001f656605c34e (diff)
Hacks to support MXF-wrapped subtitles.
-rw-r--r--src/parse/subtitle.cc22
-rw-r--r--src/parse/subtitle.h2
-rw-r--r--src/subtitle_asset.cc79
-rw-r--r--src/subtitle_asset.h4
4 files changed, 93 insertions, 14 deletions
diff --git a/src/parse/subtitle.cc b/src/parse/subtitle.cc
index 612af716..914be677 100644
--- a/src/parse/subtitle.cc
+++ b/src/parse/subtitle.cc
@@ -84,10 +84,14 @@ Font::Font (list<shared_ptr<Font> > const & font_nodes)
LoadFont::LoadFont (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");
}
-
Subtitle::Subtitle (shared_ptr<const cxml::Node> node)
{
@@ -123,9 +127,19 @@ Subtitle::fade_time (shared_ptr<const cxml::Node> node, string name)
Text::Text (shared_ptr<const cxml::Node> node)
: v_align (CENTER)
{
+ /* Vertical position */
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 ();
+
+ /* Vertical alignment */
optional<string> v = node->optional_string_attribute ("VAlign");
+ if (!v) {
+ v = node->optional_string_attribute ("Valign");
+ }
if (v) {
v_align = string_to_valign (v.get ());
}
diff --git a/src/parse/subtitle.h b/src/parse/subtitle.h
index c20278a3..3d99d9bc 100644
--- a/src/parse/subtitle.h
+++ b/src/parse/subtitle.h
@@ -92,7 +92,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/subtitle_asset.cc b/src/subtitle_asset.cc
index a48a614d..4eb1a9cd 100644
--- a/src/subtitle_asset.cc
+++ b/src/subtitle_asset.cc
@@ -18,9 +18,12 @@
*/
#include <fstream>
+#include <cerrno>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <libxml++/nodes/element.h>
+#include "AS_DCP.h"
+#include "KM_util.h"
#include "subtitle_asset.h"
#include "parse/subtitle.h"
#include "util.h"
@@ -31,16 +34,34 @@ using std::list;
using std::ostream;
using std::ofstream;
using std::stringstream;
+using std::cout;
using boost::shared_ptr;
using boost::lexical_cast;
using boost::optional;
using namespace libdcp;
-SubtitleAsset::SubtitleAsset (string directory, string xml_file)
- : Asset (directory, xml_file)
+SubtitleAsset::SubtitleAsset (string directory, string file)
+ : Asset (directory, file)
, _need_sort (false)
{
- read_xml (path().string());
+ /* Grotesque hack: we should look in the PKL to see what type this file is;
+ instead we'll look at the first character to decide what to do.
+ I think this is easily fixable (properly) in 1.0.
+ */
+
+ FILE* f = fopen_boost (path(), "r");
+ if (!f) {
+ throw FileError ("Could not open file for reading", file, errno);
+ }
+ unsigned char test[1];
+ fread (test, 1, 1, f);
+ fclose (f);
+
+ if (test[0] == '<' || test[0] == 0xef) {
+ read_xml (path().string());
+ } else {
+ read_mxf (path().string());
+ }
}
SubtitleAsset::SubtitleAsset (string directory, string movie_title, string language)
@@ -54,13 +75,45 @@ SubtitleAsset::SubtitleAsset (string directory, string movie_title, string langu
}
void
+SubtitleAsset::read_mxf (string mxf_file)
+{
+ ASDCP::TimedText::MXFReader reader;
+ Kumu::Result_t r = reader.OpenRead (mxf_file.c_str ());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", mxf_file, r));
+ }
+
+ string s;
+ reader.ReadTimedTextResource (s, 0, 0);
+ shared_ptr<cxml::Document> xml (new cxml::Document ("SubtitleReel"));
+ stringstream t;
+ t << s;
+ xml->read_stream (t);
+ read_xml (xml);
+}
+
+void
SubtitleAsset::read_xml (string xml_file)
{
shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
xml->read_file (xml_file);
+ read_xml (xml);
+}
+
+void
+SubtitleAsset::read_xml (shared_ptr<cxml::Document> xml)
+{
+ /* XXX: hacks aplenty in here; need separate parsers for DCSubtitle and SubtitleReel */
- _uuid = xml->string_child ("SubtitleID");
- _movie_title = xml->string_child ("MovieTitle");
+ /* DCSubtitle */
+ optional<string> x = xml->optional_string_child ("SubtitleID");
+ if (!x) {
+ /* SubtitleReel */
+ x = xml->optional_string_child ("Id");
+ }
+ _uuid = x.get_value_or ("");
+
+ _movie_title = xml->optional_string_child ("MovieTitle");
_reel_number = xml->string_child ("ReelNumber");
_language = xml->string_child ("Language");
@@ -73,6 +126,12 @@ SubtitleAsset::read_xml (string xml_file)
in a sane way.
*/
+ shared_ptr<cxml::Node> subtitle_list = xml->optional_node_child ("SubtitleList");
+ if (subtitle_list) {
+ list<shared_ptr<libdcp::parse::Font> > font = type_children<libdcp::parse::Font> (subtitle_list, "Font");
+ copy (font.begin(), font.end(), back_inserter (font_nodes));
+ }
+
ParseState parse_state;
examine_font_nodes (xml, font_nodes, parse_state);
}
@@ -182,7 +241,7 @@ SubtitleAsset::font_id_to_name (string id) const
return "";
}
- if ((*i)->uri == "arial.ttf") {
+ if ((*i)->uri && (*i)->uri.get() == "arial.ttf") {
return "Arial";
}
@@ -316,7 +375,9 @@ SubtitleAsset::xml_as_string () const
root->set_attribute ("Version", "1.0");
root->add_child("SubtitleID")->add_child_text (_uuid);
- 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);
@@ -327,7 +388,9 @@ SubtitleAsset::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);
+ if (_load_font_nodes.front()->uri) {
+ load_font->set_attribute("URI", _load_font_nodes.front()->uri.get ());
+ }
}
list<shared_ptr<Subtitle> > sorted = _subtitles;
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
index 0598a296..a7ec641c 100644
--- a/src/subtitle_asset.h
+++ b/src/subtitle_asset.h
@@ -169,6 +169,8 @@ protected:
private:
std::string font_id_to_name (std::string id) const;
+ void read_mxf (std::string);
+ void read_xml (boost::shared_ptr<cxml::Document>);
struct ParseState {
std::list<boost::shared_ptr<parse::Font> > font_nodes;
@@ -190,7 +192,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;