summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2018-07-09 00:43:13 +0100
committerCarl Hetherington <cth@carlh.net>2018-07-09 00:43:13 +0100
commit87c2c54ebfdc1e6ceb0673058c01fd30e13258c2 (patch)
tree10a7d3427cb1f399fc9cb298efff580247427bdd
parent34be688550e3acdd99c3ca612e7e4696710f3438 (diff)
Switch to UUIDs for Interop image subtitle identification (rather than indices). Basic and untested SMPTE image subtitle support.
-rw-r--r--src/interop_subtitle_asset.cc7
-rw-r--r--src/object.h2
-rw-r--r--src/smpte_subtitle_asset.cc30
-rw-r--r--src/subtitle_asset.cc10
-rw-r--r--src/subtitle_asset.h5
-rw-r--r--src/subtitle_asset_internal.cc12
-rw-r--r--src/subtitle_asset_internal.h7
-rw-r--r--test/data/write_interop_subtitle_test3.xml2
-rw-r--r--test/write_subtitle_test.cc34
9 files changed, 90 insertions, 19 deletions
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc
index 02e2d75b..2ef82c90 100644
--- a/src/interop_subtitle_asset.cc
+++ b/src/interop_subtitle_asset.cc
@@ -39,9 +39,11 @@
#include "util.h"
#include "font_asset.h"
#include "dcp_assert.h"
+#include "compose.hpp"
#include "subtitle_image.h"
#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
+#include <boost/weak_ptr.hpp>
#include <cmath>
#include <cstdio>
@@ -177,11 +179,12 @@ InteropSubtitleAsset::write (boost::filesystem::path p) const
_file = p;
/* Image subtitles */
- int n = 0;
BOOST_FOREACH (shared_ptr<dcp::Subtitle> i, _subtitles) {
shared_ptr<dcp::SubtitleImage> im = dynamic_pointer_cast<dcp::SubtitleImage> (i);
if (im) {
- im->png_image().write (p.parent_path() / image_subtitle_file (n++));
+ ImageUUIDMap::const_iterator uuid = _image_subtitle_uuid.find(im);
+ DCP_ASSERT (uuid != _image_subtitle_uuid.end());
+ im->png_image().write (p.parent_path() / String::compose("%1.png", uuid->second));
}
}
diff --git a/src/object.h b/src/object.h
index b2d0ad35..d44f1be2 100644
--- a/src/object.h
+++ b/src/object.h
@@ -46,6 +46,7 @@ class write_interop_subtitle_test2;
class write_interop_subtitle_test3;
class write_smpte_subtitle_test;
class write_smpte_subtitle_test2;
+class write_smpte_subtitle_test3;
namespace dcp {
@@ -70,6 +71,7 @@ protected:
friend struct ::write_interop_subtitle_test3;
friend struct ::write_smpte_subtitle_test;
friend struct ::write_smpte_subtitle_test2;
+ friend struct ::write_smpte_subtitle_test3;
/** ID */
std::string _id;
diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc
index 07d8f7eb..267ff27e 100644
--- a/src/smpte_subtitle_asset.cc
+++ b/src/smpte_subtitle_asset.cc
@@ -44,7 +44,7 @@
#include "util.h"
#include "compose.hpp"
#include "crypto_context.h"
-#include "crypto_context.h"
+#include "subtitle_image.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_util.h>
#include <libxml++/libxml++.h>
@@ -304,6 +304,8 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
descriptor.EditRate = ASDCP::Rational (_edit_rate.numerator, _edit_rate.denominator);
descriptor.EncodingName = "UTF-8";
+ /* Font references */
+
BOOST_FOREACH (shared_ptr<dcp::SMPTELoadFontNode> i, _load_font_nodes) {
list<Font>::const_iterator j = _fonts.begin ();
while (j != _fonts.end() && j->load_id != i->id) {
@@ -319,6 +321,17 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
}
}
+ /* Image subtitle references */
+
+ for (ImageUUIDMap::const_iterator i = _image_subtitle_uuid.begin(); i != _image_subtitle_uuid.end(); ++i) {
+ ASDCP::TimedText::TimedTextResourceDescriptor res;
+ unsigned int c;
+ Kumu::hex2bin (i->second.c_str(), res.ResourceID, Kumu::UUID_Length, &c);
+ DCP_ASSERT (c == Kumu::UUID_Length);
+ res.Type = ASDCP::TimedText::MT_PNG;
+ descriptor.ResourceList.push_back (res);
+ }
+
descriptor.NamespaceName = "dcst";
memcpy (descriptor.AssetID, writer_info.AssetUUID, ASDCP::UUIDlen);
descriptor.ContainerDuration = _intrinsic_duration;
@@ -329,12 +342,13 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
boost::throw_exception (FileError ("could not open subtitle MXF for writing", p.string(), r));
}
- /* XXX: no encryption */
r = writer.WriteTimedTextResource (xml_as_string (), enc.context(), enc.hmac());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("could not write XML to timed text resource", p.string(), r));
}
+ /* Font payload */
+
BOOST_FOREACH (shared_ptr<dcp::SMPTELoadFontNode> i, _load_font_nodes) {
list<Font>::const_iterator j = _fonts.begin ();
while (j != _fonts.end() && j->load_id != i->id) {
@@ -351,6 +365,18 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
}
}
+ /* Image subtitle payload */
+
+ for (ImageUUIDMap::const_iterator i = _image_subtitle_uuid.begin(); i != _image_subtitle_uuid.end(); ++i) {
+ ASDCP::TimedText::FrameBuffer buffer;
+ buffer.SetData (i->first->png_image().data().get(), i->first->png_image().size());
+ buffer.Size (i->first->png_image().size());
+ r = writer.WriteAncillaryResource (buffer, enc.context(), enc.hmac());
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception (MXFFileError ("could not write PNG data to timed text resource", p.string(), r));
+ }
+ }
+
writer.Finalize ();
_file = p;
diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc
index f93ffa85..5a096f20 100644
--- a/src/subtitle_asset.cc
+++ b/src/subtitle_asset.cc
@@ -373,6 +373,11 @@ void
SubtitleAsset::add (shared_ptr<Subtitle> s)
{
_subtitles.push_back (s);
+
+ shared_ptr<SubtitleImage> si = dynamic_pointer_cast<SubtitleImage> (s);
+ if (si) {
+ _image_subtitle_uuid[si] = make_uuid ();
+ }
}
Time
@@ -573,8 +578,10 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S
shared_ptr<SubtitleImage> ii = dynamic_pointer_cast<SubtitleImage>(i);
if (ii) {
text.reset ();
+ ImageUUIDMap::const_iterator uuid = _image_subtitle_uuid.find(ii);
+ DCP_ASSERT (uuid != _image_subtitle_uuid.end());
subtitle->children.push_back (
- shared_ptr<order::Image> (new order::Image (subtitle, ii->png_image(), ii->h_align(), ii->h_position(), ii->v_align(), ii->v_position()))
+ shared_ptr<order::Image> (new order::Image (subtitle, uuid->second, ii->png_image(), ii->h_align(), ii->h_position(), ii->v_align(), ii->v_position()))
);
}
}
@@ -589,7 +596,6 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S
context.time_code_rate = time_code_rate;
context.standard = standard;
context.spot_number = 1;
- context.image_number = 0;
root->write_xml (xml_root, context);
}
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
index 1108514a..31cca185 100644
--- a/src/subtitle_asset.h
+++ b/src/subtitle_asset.h
@@ -56,6 +56,7 @@ namespace dcp
{
class SubtitleString;
+class SubtitleImage;
class FontNode;
class TextNode;
class SubtitleNode;
@@ -164,6 +165,10 @@ protected:
/** TTF font data that we need */
std::list<Font> _fonts;
+ /** Map of image subtitles to UUIDs */
+ typedef std::map<boost::shared_ptr<dcp::SubtitleImage>, std::string> ImageUUIDMap;
+ ImageUUIDMap _image_subtitle_uuid;
+
private:
friend struct ::pull_fonts_test1;
friend struct ::pull_fonts_test2;
diff --git a/src/subtitle_asset_internal.cc b/src/subtitle_asset_internal.cc
index 13bdf6ab..7b9e18e9 100644
--- a/src/subtitle_asset_internal.cc
+++ b/src/subtitle_asset_internal.cc
@@ -238,13 +238,11 @@ order::Image::as_xml (xmlpp::Element* parent, Context& context) const
xmlpp::Element* e = parent->add_child ("Image", context.xmlns());
position_align (e, context, _h_align, _h_position, _v_align, _v_position);
- e->add_child_text (image_subtitle_file (context.image_number++));
+ if (context.standard == SMPTE) {
+ e->add_child_text (_id);
+ } else {
+ e->add_child_text (_id + ".png");
+ }
return e;
}
-
-string
-dcp::image_subtitle_file (int n)
-{
- return String::compose ("sub_%1.png", n);
-}
diff --git a/src/subtitle_asset_internal.h b/src/subtitle_asset_internal.h
index e2b1602e..b0034743 100644
--- a/src/subtitle_asset_internal.h
+++ b/src/subtitle_asset_internal.h
@@ -60,7 +60,6 @@ struct Context
int time_code_rate;
Standard standard;
int spot_number;
- int image_number;
};
class Font
@@ -168,9 +167,10 @@ private:
class Image : public Part
{
public:
- Image (boost::shared_ptr<Part> parent, Data png_data, HAlign h_align, float h_position, VAlign v_align, float v_position)
+ Image (boost::shared_ptr<Part> parent, std::string id, Data png_data, HAlign h_align, float h_position, VAlign v_align, float v_position)
: Part (parent)
, _png_data (png_data)
+ , _id (id)
, _h_align (h_align)
, _h_position (h_position)
, _v_align (v_align)
@@ -181,6 +181,7 @@ public:
private:
Data _png_data;
+ std::string _id; ///< the ID of this image (index for Interop, UUID for SMPTE)
HAlign _h_align;
float _h_position;
VAlign _v_align;
@@ -189,8 +190,6 @@ private:
}
-std::string image_subtitle_file (int n);
-
}
#endif
diff --git a/test/data/write_interop_subtitle_test3.xml b/test/data/write_interop_subtitle_test3.xml
index e92685b8..7ba72e47 100644
--- a/test/data/write_interop_subtitle_test3.xml
+++ b/test/data/write_interop_subtitle_test3.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
-<DCSubtitle Version="1.0"><SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID><MovieTitle>Test</MovieTitle><ReelNumber>1</ReelNumber><Language>EN</Language><Subtitle SpotNumber="1" TimeIn="00:04:09:229" TimeOut="00:04:11:229" FadeUpTime="0" FadeDownTime="0"><Image VAlign="top" VPosition="80">sub_0.png</Image></Subtitle></DCSubtitle>
+<DCSubtitle Version="1.0"><SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID><MovieTitle>Test</MovieTitle><ReelNumber>1</ReelNumber><Language>EN</Language><Subtitle SpotNumber="1" TimeIn="00:04:09:229" TimeOut="00:04:11:229" FadeUpTime="0" FadeDownTime="0"><Image VAlign="top" VPosition="80">822bd341-c751-45b1-94d2-410e4ffcff1b.png</Image></Subtitle></DCSubtitle>
diff --git a/test/write_subtitle_test.cc b/test/write_subtitle_test.cc
index dec815c0..cf595faf 100644
--- a/test/write_subtitle_test.cc
+++ b/test/write_subtitle_test.cc
@@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3)
dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"),
list<string>()
);
- check_file ("build/test/write_interop_subtitle_test3/sub_0.png", "test/data/sub.png");
+ check_file ("build/test/write_interop_subtitle_test3/822bd341-c751-45b1-94d2-410e4ffcff1b.png", "test/data/sub.png");
}
/* Write some subtitle content as SMPTE XML and check that it is right */
@@ -637,3 +637,35 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
list<string> ()
);
}
+
+/* Write some subtitle content as SMPTE using bitmaps and check that it is right */
+BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test3)
+{
+ dcp::SMPTESubtitleAsset c;
+ c.set_reel_number (1);
+ c.set_language ("EN");
+ c.set_content_title_text ("Test");
+
+ c.add (
+ shared_ptr<dcp::Subtitle> (
+ new dcp::SubtitleImage (
+ dcp::Data ("test/data/sub.png"),
+ dcp::Time (0, 4, 9, 22, 24),
+ dcp::Time (0, 4, 11, 22, 24),
+ 0,
+ dcp::HALIGN_CENTER,
+ 0.8,
+ dcp::VALIGN_TOP,
+ dcp::Time (0, 0, 0, 0, 24),
+ dcp::Time (0, 0, 0, 0, 24)
+ )
+ )
+ );
+
+ c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
+
+ boost::filesystem::create_directories ("build/test/write_smpte_subtitle_test3");
+ c.write ("build/test/write_smpte_subtitle_test3/subs.mxf");
+
+ /* XXX: check this result when we can read them back in again */
+}