diff options
Diffstat (limited to 'src/smpte_subtitle_asset.cc')
| -rw-r--r-- | src/smpte_subtitle_asset.cc | 109 |
1 files changed, 106 insertions, 3 deletions
diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc index e5a083b1..40afc76d 100644 --- a/src/smpte_subtitle_asset.cc +++ b/src/smpte_subtitle_asset.cc @@ -24,13 +24,19 @@ #include "xml.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> using std::string; using std::list; using std::stringstream; using std::cout; +using std::vector; using boost::shared_ptr; +using boost::split; +using boost::is_any_of; using namespace dcp; SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file, bool mxf) @@ -64,16 +70,37 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file, bool mxf) _load_font_nodes = type_children<dcp::SMPTELoadFontNode> (xml, "LoadFont"); - int tcr = xml->number_child<int> ("TimeCodeRate"); + _content_title_text = xml->string_child ("ContentTitleText"); + _annotation_text = xml->optional_string_child ("AnnotationText"); + _issue_date = LocalTime (xml->string_child ("IssueDate")); + _reel_number = xml->optional_number_child<int> ("ReelNumber"); + _language = xml->optional_string_child ("Language"); + + /* This is supposed to be two numbers, but a single number has been seen in the wild */ + string const er = xml->string_child ("EditRate"); + vector<string> er_parts; + split (er_parts, er, is_any_of (" ")); + if (er_parts.size() == 1) { + _edit_rate = Fraction (raw_convert<int> (er_parts[0]), 1); + } else if (er_parts.size() == 2) { + _edit_rate = Fraction (raw_convert<int> (er_parts[0]), raw_convert<int> (er_parts[1])); + } else { + throw XMLError ("malformed EditRate " + er); + } + + _time_code_rate = xml->number_child<int> ("TimeCodeRate"); + if (xml->optional_string_child ("StartTime")) { + _start_time = Time (xml->string_child ("StartTime"), _time_code_rate); + } shared_ptr<cxml::Node> subtitle_list = xml->optional_node_child ("SubtitleList"); list<cxml::NodePtr> f = subtitle_list->node_children ("Font"); list<shared_ptr<dcp::FontNode> > font_nodes; BOOST_FOREACH (cxml::NodePtr& i, f) { - font_nodes.push_back (shared_ptr<FontNode> (new FontNode (i, tcr))); + font_nodes.push_back (shared_ptr<FontNode> (new FontNode (i, _time_code_rate))); } - + parse_common (xml, font_nodes); } @@ -92,3 +119,79 @@ SMPTESubtitleAsset::valid_mxf (boost::filesystem::path file) Kumu::Result_t r = reader.OpenRead (file.string().c_str ()); return !ASDCP_FAILURE (r); } + +Glib::ustring +SMPTESubtitleAsset::xml_as_string () const +{ + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("dcst:SubtitleReel"); + root->set_namespace_declaration ("http://www.smpte-ra.org/schemas/428-7/2010/DCST", "dcst"); + root->set_namespace_declaration ("http://www.w3.org/2001/XMLSchema", "xs"); + + root->add_child("ID", "dcst")->add_child_text (_id); + root->add_child("ContentTitleText", "dcst")->add_child_text (_content_title_text); + if (_annotation_text) { + root->add_child("AnnotationText", "dcst")->add_child_text (_annotation_text.get ()); + } + root->add_child("IssueDate", "dcst")->add_child_text (_issue_date.as_string (true)); + if (_reel_number) { + root->add_child("ReelNumber", "dcst")->add_child_text (raw_convert<string> (_reel_number.get ())); + } + if (_language) { + root->add_child("Language", "dcst")->add_child_text (_language.get ()); + } + root->add_child("EditRate", "dcst")->add_child_text (_edit_rate.as_string ()); + root->add_child("TimeCodeRate", "dcst")->add_child_text (raw_convert<string> (_time_code_rate)); + if (_start_time) { + root->add_child("StartTime", "dcst")->add_child_text (_start_time.get().as_string ()); + } + + BOOST_FOREACH (shared_ptr<SMPTELoadFontNode> i, _load_font_nodes) { + xmlpp::Element* load_font = root->add_child("LoadFont", "dcst"); + load_font->add_child_text (i->urn); + load_font->set_attribute ("ID", i->id); + } + + subtitles_as_xml (root->add_child ("SubtitleList", "dcst"), _time_code_rate, "dcst"); + + return doc.write_to_string_formatted ("UTF-8"); +} + +/** Write this content to a MXF file */ +void +SMPTESubtitleAsset::write (boost::filesystem::path p) const +{ + ASDCP::WriterInfo writer_info; + fill_writer_info (&writer_info, _id, SMPTE); + + ASDCP::TimedText::TimedTextDescriptor descriptor; + descriptor.EditRate = ASDCP::Rational (_edit_rate.numerator, _edit_rate.denominator); + descriptor.EncodingName = "UTF-8"; + descriptor.ResourceList.clear (); + 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: fonts into descriptor? */ + + ASDCP::TimedText::MXFWriter writer; + Kumu::Result_t r = writer.OpenWrite (p.string().c_str(), writer_info, descriptor); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (FileError ("could not open subtitle MXF for writing", p.string(), r)); + } + + /* XXX: no encryption */ + writer.WriteTimedTextResource (xml_as_string ()); + + writer.Finalize (); + + _file = p; +} + +bool +SMPTESubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions options, NoteHandler note) const +{ + /* XXX */ + return false; +} + |
