diff options
| author | jhurst <jhurst@cinecert.com> | 2007-06-08 02:24:37 +0000 |
|---|---|---|
| committer | jhurst <> | 2007-06-08 02:24:37 +0000 |
| commit | 3a3aa48a5a4f7324a9e4c2273d0747d7f58a2813 (patch) | |
| tree | bf218b1e6e4ee415ff94576e08b923801340c4a5 /src/TimedText_Parser.cpp | |
| parent | 27915a74438fcf264d8dfd621dd5e79fa4065813 (diff) | |
fixed encryption for timed text
Diffstat (limited to 'src/TimedText_Parser.cpp')
| -rw-r--r-- | src/TimedText_Parser.cpp | 245 |
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 // |
