summaryrefslogtreecommitdiff
path: root/src/TimedText_Parser.cpp
diff options
context:
space:
mode:
authorjhurst <jhurst@cinecert.com>2007-06-08 02:24:37 +0000
committerjhurst <>2007-06-08 02:24:37 +0000
commit3a3aa48a5a4f7324a9e4c2273d0747d7f58a2813 (patch)
treebf218b1e6e4ee415ff94576e08b923801340c4a5 /src/TimedText_Parser.cpp
parent27915a74438fcf264d8dfd621dd5e79fa4065813 (diff)
fixed encryption for timed text
Diffstat (limited to 'src/TimedText_Parser.cpp')
-rw-r--r--src/TimedText_Parser.cpp245
1 files changed, 215 insertions, 30 deletions
diff --git a/src/TimedText_Parser.cpp b/src/TimedText_Parser.cpp
index 86236d5..a2683f9 100644
--- a/src/TimedText_Parser.cpp
+++ b/src/TimedText_Parser.cpp
@@ -32,43 +32,226 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AS_DCP_internal.h"
#include "AS_DCP_TimedText.h"
+#include "S12MTimecode.h"
#include "KM_xml.h"
using namespace Kumu;
using namespace ASDCP;
+const char* c_dcst_namespace_name = "http://www.smpte-ra.org/schemas/428-7/2007/DCST";
+
+
//------------------------------------------------------------------------------------------
-class ASDCP::TimedText::DCSubtitleParser::h__DCSubtitleParser
+typedef std::map<Kumu::UUID, TimedText::MIMEType_t> ResourceTypeMap_t;
+
+class ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser
{
- ui32_t m_FileReadCount;
+ XMLElement m_Root;
+ ResourceTypeMap_t m_ResourceTypes;
- ASDCP_NO_COPY_CONSTRUCT(h__DCSubtitleParser);
+ ASDCP_NO_COPY_CONSTRUCT(h__SubtitleParser);
public:
+ std::string m_XMLDoc;
TimedTextDescriptor m_TDesc;
- h__DCSubtitleParser() : m_FileReadCount(0)
+ h__SubtitleParser() : m_Root("**ParserRoot**")
{
- memset(&m_TDesc, 0, sizeof(m_TDesc));
+ memset(&m_TDesc.AssetID, 0, UUIDlen);
}
- ~h__DCSubtitleParser()
- {
- Close();
- }
+ ~h__SubtitleParser() {}
Result_t OpenRead(const char* filename);
- void Close() {}
+ Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf) const;
+};
- Result_t Reset()
- {
- m_FileReadCount = 0;
- return RESULT_OK;
- }
+//
+bool
+get_UUID_from_element(XMLElement* Element, UUID& ID)
+{
+ assert(Element);
+ const char* p = Element->GetBody().c_str();
+ if ( strncmp(p, "urn:uuid:", 9) == 0 ) p += 9;
+ return ID.DecodeHex(p);
+}
- Result_t ReadFrame(FrameBuffer&);
-};
+//
+bool
+get_UUID_from_child_element(const char* name, XMLElement* Parent, UUID& outID)
+{
+ assert(name); assert(Parent);
+ XMLElement* Child = Parent->GetChildWithName(name);
+ if ( Child == 0 ) return false;
+ return get_UUID_from_element(Child, outID);
+}
+
+//
+static ASDCP::Rational
+decode_rational(const char* str_rat)
+{
+ assert(str_rat);
+ ui32_t Num = atoi(str_rat);
+ ui32_t Den = 0;
+
+ const char* den_str = strrchr(str_rat, ' ');
+ if ( den_str != 0 )
+ Den = atoi(den_str+1);
+
+ return ASDCP::Rational(Num, Den);
+}
+
+//
+ui32_t
+CalculateSubtitleDuration(const XMLElement* begin, const XMLElement* end)
+{
+ assert(begin); assert(end);
+
+ S12MTimecode
+ beginTC(begin->GetAttrWithName("TimeIn"), 24),
+ endTC(end->GetAttrWithName("TimeOut"), 24);
+
+ if ( endTC < beginTC )
+ return 0;
+
+ return endTC.GetFrames() - beginTC.GetFrames();
+}
+
+//
+Result_t
+ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead(const char* filename)
+{
+ Result_t result = ReadFileIntoString(filename, m_XMLDoc);
+
+ if ( ! m_Root.ParseString(m_XMLDoc.c_str()) )
+ return RESULT_FORMAT;
+
+ m_TDesc.EncodingName = "UTF-8"; // the XML parser demands UTF-8
+ m_TDesc.ResourceList.clear();
+ m_TDesc.ContainerDuration = 0;
+ const XMLNamespace* ns = m_Root.Namespace();
+
+ if ( ns == 0 )
+ {
+ DefaultLogSink(). Warn("Document has no namespace name, assuming %s\n", c_dcst_namespace_name);
+ m_TDesc.NamespaceName = c_dcst_namespace_name;
+ }
+ else
+ m_TDesc.NamespaceName = ns->Name();
+
+ UUID DocID;
+ if ( ! get_UUID_from_child_element("Id", &m_Root, DocID) )
+ {
+ DefaultLogSink(). Error("Id element missing from input document\n");
+ return RESULT_FORMAT;
+ }
+
+ memcpy(m_TDesc.AssetID, DocID.Value(), DocID.Size());
+ XMLElement* EditRate = m_Root.GetChildWithName("EditRate");
+
+ if ( EditRate == 0 )
+ {
+ DefaultLogSink(). Error("EditRate element missing from input document\n");
+ return RESULT_FORMAT;
+ }
+
+ m_TDesc.EditRate = decode_rational(EditRate->GetBody().c_str());
+
+ // list of fonts
+ ElementList FontList;
+ m_Root.GetChildrenWithName("LoadFont", FontList);
+
+ for ( Elem_i i = FontList.begin(); i != FontList.end(); i++ )
+ {
+ UUID AssetID;
+ if ( ! get_UUID_from_element(*i, AssetID) )
+ {
+ DefaultLogSink(). Error("LoadFont element does not contain a urn:uuid value as expected.\n");
+ return RESULT_FORMAT;
+ }
+
+ TimedTextResourceDescriptor TmpResource;
+ memcpy(TmpResource.ResourceID, AssetID.Value(), UUIDlen);
+ TmpResource.Type = MT_OPENTYPE;
+ m_TDesc.ResourceList.push_back(TmpResource);
+ m_ResourceTypes.insert(ResourceTypeMap_t::value_type(UUID(TmpResource.ResourceID), MT_OPENTYPE));
+ }
+
+ // list of images
+ ElementList ImageList;
+ m_Root.GetChildrenWithName("Image", ImageList);
+
+ for ( Elem_i i = ImageList.begin(); i != ImageList.end(); i++ )
+ {
+ UUID AssetID;
+ if ( ! get_UUID_from_element(*i, AssetID) )
+ {
+ DefaultLogSink(). Error("Image element does not contain a urn:uuid value as expected.\n");
+ return RESULT_FORMAT;
+ }
+
+ TimedTextResourceDescriptor TmpResource;
+ memcpy(TmpResource.ResourceID, AssetID.Value(), UUIDlen);
+ TmpResource.Type = MT_PNG;
+ m_TDesc.ResourceList.push_back(TmpResource);
+ m_ResourceTypes.insert(ResourceTypeMap_t::value_type(UUID(TmpResource.ResourceID), MT_PNG));
+ }
+
+ // duration
+ ElementList InstanceList;
+ m_Root.GetChildrenWithName("Subtitle", InstanceList);
+ m_TDesc.ContainerDuration = CalculateSubtitleDuration(InstanceList.front(), InstanceList.back());
+
+ return RESULT_OK;
+}
+
+
+//
+Result_t
+ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf) const
+{
+ FrameBuf.AssetID(uuid);
+ UUID TmpID(uuid);
+ char buf[64];
+ FileReader Reader;
+
+ ResourceTypeMap_t::const_iterator rmi = m_ResourceTypes.find(TmpID);
+
+ if ( rmi == m_ResourceTypes.end() )
+ {
+ DefaultLogSink().Error("Unknown ancillary resource id: %s\n", TmpID.EncodeHex(buf, 64));
+ return RESULT_RANGE;
+ }
+
+ Result_t result = Reader.OpenRead(TmpID.EncodeHex(buf, 64));
+
+ if ( KM_SUCCESS(result) )
+ {
+ ui32_t read_count = 0;
+ result = Reader.Read(FrameBuf.Data(), FrameBuf.Capacity(), &read_count);
+
+ if ( KM_SUCCESS(result) )
+ {
+ FrameBuf.Size(read_count);
+
+ if ( (*rmi).second == MT_PNG )
+ FrameBuf.MIMEType("image/png");
+
+ else if ( (*rmi).second == MT_OPENTYPE )
+ FrameBuf.MIMEType("application/x-opentype");
+
+ else
+ FrameBuf.MIMEType("application/octet-stream");
+ }
+ }
+ else
+ {
+ DefaultLogSink(). Error("Error opening resource file %s.\n", buf);
+ }
+
+ return result;
+}
//------------------------------------------------------------------------------------------
@@ -85,47 +268,49 @@ ASDCP::TimedText::DCSubtitleParser::~DCSubtitleParser()
ASDCP::Result_t
ASDCP::TimedText::DCSubtitleParser::OpenRead(const char* filename) const
{
- const_cast<ASDCP::TimedText::DCSubtitleParser*>(this)->m_Parser = new h__DCSubtitleParser;
+ const_cast<ASDCP::TimedText::DCSubtitleParser*>(this)->m_Parser = new h__SubtitleParser;
Result_t result = m_Parser->OpenRead(filename);
if ( ASDCP_FAILURE(result) )
- const_cast<ASDCP::TimedText::DCSubtitleParser*>(this)->m_Parser.release();
+ const_cast<ASDCP::TimedText::DCSubtitleParser*>(this)->m_Parser = 0;
return result;
}
-// Rewinds the stream to the beginning.
+//
ASDCP::Result_t
-ASDCP::TimedText::DCSubtitleParser::Reset() const
+ASDCP::TimedText::DCSubtitleParser::FillDescriptor(TimedTextDescriptor& TDesc) const
{
if ( m_Parser.empty() )
return RESULT_INIT;
- return m_Parser->Reset();
+ TDesc = m_Parser->m_TDesc;
+ return RESULT_OK;
}
-// Places a frame of data in the frame buffer. Fails if the buffer is too small
-// or the stream is empty.
+// Reads the complete Timed Text Resource into the given string.
ASDCP::Result_t
-ASDCP::TimedText::DCSubtitleParser::ReadFrame(FrameBuffer& FB) const
+ASDCP::TimedText::DCSubtitleParser::ReadTimedTextResource(std::string& s) const
{
if ( m_Parser.empty() )
return RESULT_INIT;
- return m_Parser->ReadFrame(FB);
+ s = m_Parser->m_XMLDoc;
+ return RESULT_OK;
}
+//
ASDCP::Result_t
-ASDCP::TimedText::DCSubtitleParser::FillDescriptor(TimedTextDescriptor& PDesc) const
+ASDCP::TimedText::DCSubtitleParser::ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf) const
{
- if ( m_Parser.empty() )
+ if ( m_Parser.empty() )
return RESULT_INIT;
- PDesc = m_Parser->m_TDesc;
- return RESULT_OK;
+ return m_Parser->ReadAncillaryResource(uuid, FrameBuf);
}
+
//
// end AS_DCP_timedText.cpp
//