X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fsmpte_subtitle_asset.cc;h=0c0181f42d5c1604252d55d37b4e9b40129fc71b;hb=e4d5298e7a179d4103581cba05cbc516f94acf60;hp=cb6e90c1007204dea790faf6a8ceb92d0705f594;hpb=093e2c266a9801ac8b5dcf709409bf4998fda970;p=libdcp.git diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc index cb6e90c1..0c0181f4 100644 --- a/src/smpte_subtitle_asset.cc +++ b/src/smpte_subtitle_asset.cc @@ -1,20 +1,34 @@ /* Copyright (C) 2012-2015 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of libdcp. + + libdcp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + libdcp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - + along with libdcp. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. */ /** @file src/smpte_subtitle_asset.cc @@ -29,17 +43,15 @@ #include "raw_convert.h" #include "dcp_assert.h" #include "util.h" -#include "AS_DCP.h" -#include "KM_util.h" #include "compose.hpp" +#include +#include #include #include #include using std::string; using std::list; -using std::stringstream; -using std::cout; using std::vector; using std::map; using boost::shared_ptr; @@ -50,7 +62,8 @@ using boost::dynamic_pointer_cast; using namespace dcp; SMPTESubtitleAsset::SMPTESubtitleAsset () - : _edit_rate (24, 1) + : _intrinsic_duration (0) + , _edit_rate (24, 1) , _time_code_rate (24) { @@ -70,9 +83,7 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) if (!ASDCP_FAILURE (r)) { string s; reader->ReadTimedTextResource (s, 0, 0); - stringstream t; - t << s; - xml->read_stream (t); + xml->read_string (s); ASDCP::WriterInfo info; reader->FillWriterInfo (info); _id = read_writer_info (info); @@ -80,11 +91,11 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) reader.reset (); try { xml->read_file (file); - _id = xml->string_child ("Id").substr (9); + _id = remove_urn_uuid (xml->string_child ("Id")); } catch (cxml::Error& e) { boost::throw_exception ( DCPReadError ( - String::compose ("could not read subtitles from %1; MXF failed with %2, XML failed with %3", file, static_cast (r), e.what ()) + String::compose ("MXF failed with %1, XML failed with %2", file, static_cast (r), e.what ()) ) ); } @@ -117,49 +128,56 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file) shared_ptr subtitle_list = xml->optional_node_child ("SubtitleList"); - list f = subtitle_list->node_children ("Font"); list > font_nodes; - BOOST_FOREACH (cxml::NodePtr& i, f) { - font_nodes.push_back (shared_ptr (new FontNode (i, _time_code_rate))); + BOOST_FOREACH (cxml::NodePtr const & i, subtitle_list->node_children ("Font")) { + font_nodes.push_back (shared_ptr (new FontNode (i, _time_code_rate, SMPTE))); } - parse_subtitles (xml, font_nodes); + list > subtitle_nodes; + BOOST_FOREACH (cxml::NodePtr const & i, subtitle_list->node_children ("Subtitle")) { + subtitle_nodes.push_back (shared_ptr (new SubtitleNode (i, _time_code_rate, SMPTE))); + } + + parse_subtitles (xml, font_nodes, subtitle_nodes); if (reader) { - read_fonts (reader); - } -} + ASDCP::TimedText::TimedTextDescriptor descriptor; + reader->FillTimedTextDescriptor (descriptor); -void -SMPTESubtitleAsset::read_fonts (shared_ptr reader) -{ - 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); + /* Load fonts */ - char id[64]; - Kumu::bin2UUIDhex (i->ResourceID, ASDCP::UUIDlen, id, sizeof (id)); + for ( + ASDCP::TimedText::ResourceList_t::const_iterator i = descriptor.ResourceList.begin(); + i != descriptor.ResourceList.end(); + ++i) { - shared_array data (new uint8_t[buffer.Size()]); - memcpy (data.get(), buffer.RoData(), buffer.Size()); + if (i->Type == ASDCP::TimedText::MT_OPENTYPE) { + ASDCP::TimedText::FrameBuffer buffer; + buffer.Capacity (10 * 1024 * 1024); + reader->ReadAncillaryResource (i->ResourceID, buffer); - list >::const_iterator j = _load_font_nodes.begin (); - while (j != _load_font_nodes.end() && (*j)->urn != id) { - ++j; - } + char id[64]; + Kumu::bin2UUIDhex (i->ResourceID, ASDCP::UUIDlen, id, sizeof (id)); + + shared_array data (new uint8_t[buffer.Size()]); + memcpy (data.get(), buffer.RoData(), buffer.Size()); + + list >::const_iterator j = _load_font_nodes.begin (); + while (j != _load_font_nodes.end() && (*j)->urn != id) { + ++j; + } - if (j != _load_font_nodes.end ()) { - _fonts.push_back (Font ((*j)->id, (*j)->urn, Data (data, buffer.Size ()))); + if (j != _load_font_nodes.end ()) { + _fonts.push_back (Font ((*j)->id, (*j)->urn, Data (data, buffer.Size ()))); + } } } + + /* Get intrinsic duration */ + _intrinsic_duration = descriptor.ContainerDuration; + } else { + /* Guess intrinsic duration */ + _intrinsic_duration = latest_subtitle_out().as_editable_units (_edit_rate.numerator / _edit_rate.denominator); } } @@ -179,7 +197,7 @@ SMPTESubtitleAsset::valid_mxf (boost::filesystem::path file) return !ASDCP_FAILURE (r); } -Glib::ustring +string SMPTESubtitleAsset::xml_as_string () const { xmlpp::Document doc; @@ -187,7 +205,7 @@ SMPTESubtitleAsset::xml_as_string () const 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("Id", "dcst")->add_child_text ("urn:uuid:" + _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 ()); @@ -202,7 +220,7 @@ SMPTESubtitleAsset::xml_as_string () const root->add_child("EditRate", "dcst")->add_child_text (_edit_rate.as_string ()); root->add_child("TimeCodeRate", "dcst")->add_child_text (raw_convert (_time_code_rate)); if (_start_time) { - root->add_child("StartTime", "dcst")->add_child_text (_start_time.get().as_string ()); + root->add_child("StartTime", "dcst")->add_child_text (_start_time.get().as_string (SMPTE)); } BOOST_FOREACH (shared_ptr i, _load_font_nodes) { @@ -211,7 +229,7 @@ SMPTESubtitleAsset::xml_as_string () const load_font->set_attribute ("ID", i->id); } - subtitles_as_xml (root->add_child ("SubtitleList", "dcst"), _time_code_rate, "dcst"); + subtitles_as_xml (root->add_child ("SubtitleList", "dcst"), _time_code_rate, SMPTE); return doc.write_to_string_formatted ("UTF-8"); } @@ -244,7 +262,7 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const 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); + descriptor.ContainerDuration = _intrinsic_duration; ASDCP::TimedText::MXFWriter writer; ASDCP::Result_t r = writer.OpenWrite (p.string().c_str(), writer_info, descriptor); @@ -265,8 +283,8 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const } if (j != _fonts.end ()) { ASDCP::TimedText::FrameBuffer buffer; - buffer.SetData (j->data.data.get(), j->data.size); - buffer.Size (j->data.size); + buffer.SetData (j->data.data().get(), j->data.size()); + buffer.Size (j->data.size()); r = writer.WriteAncillaryResource (buffer); if (ASDCP_FAILURE (r)) { boost::throw_exception (MXFFileError ("could not write font to timed text resource", p.string(), r)); @@ -364,3 +382,10 @@ SMPTESubtitleAsset::add_font (string load_id, boost::filesystem::path file) _fonts.push_back (Font (load_id, uuid, file)); _load_font_nodes.push_back (shared_ptr (new SMPTELoadFontNode (load_id, uuid))); } + +void +SMPTESubtitleAsset::add (dcp::SubtitleString s) +{ + SubtitleAsset::add (s); + _intrinsic_duration = latest_subtitle_out().as_editable_units (_edit_rate.numerator / _edit_rate.denominator); +}