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 | |
| parent | 27915a74438fcf264d8dfd621dd5e79fa4065813 (diff) | |
fixed encryption for timed text
Diffstat (limited to 'src')
| -rwxr-xr-x | src/AS_DCP.h | 3 | ||||
| -rwxr-xr-x | src/AS_DCP_JP2K.cpp | 3 | ||||
| -rwxr-xr-x | src/AS_DCP_MPEG2.cpp | 2 | ||||
| -rwxr-xr-x | src/AS_DCP_MXF.cpp | 15 | ||||
| -rwxr-xr-x | src/AS_DCP_PCM.cpp | 2 | ||||
| -rw-r--r-- | src/AS_DCP_TimedText.cpp | 466 | ||||
| -rwxr-xr-x | src/AS_DCP_internal.h | 29 | ||||
| -rwxr-xr-x | src/Index.cpp | 2 | ||||
| -rw-r--r-- | src/KM_fileio.cpp | 407 | ||||
| -rwxr-xr-x | src/KM_fileio.h | 105 | ||||
| -rw-r--r-- | src/KM_xml.cpp | 329 | ||||
| -rw-r--r-- | src/KM_xml.h | 56 | ||||
| -rw-r--r-- | src/MDD.cpp | 41 | ||||
| -rwxr-xr-x | src/MDD.h | 13 | ||||
| -rwxr-xr-x | src/MXF.cpp | 161 | ||||
| -rwxr-xr-x | src/MXF.h | 16 | ||||
| -rwxr-xr-x | src/MXFTypes.cpp | 100 | ||||
| -rwxr-xr-x | src/MXFTypes.h | 19 | ||||
| -rwxr-xr-x | src/Metadata.cpp | 593 | ||||
| -rwxr-xr-x | src/Metadata.h | 70 | ||||
| -rw-r--r-- | src/TimedText_Parser.cpp | 245 | ||||
| -rwxr-xr-x | src/asdcp-test.cpp | 239 | ||||
| -rwxr-xr-x | src/h__Reader.cpp | 24 | ||||
| -rwxr-xr-x | src/h__Writer.cpp | 333 | ||||
| -rwxr-xr-x | src/klvwalk.cpp | 21 | ||||
| -rw-r--r-- | src/path-test.cpp | 122 |
26 files changed, 2876 insertions, 540 deletions
diff --git a/src/AS_DCP.h b/src/AS_DCP.h index 05b1e65..9dc7f5b 100755 --- a/src/AS_DCP.h +++ b/src/AS_DCP.h @@ -144,7 +144,7 @@ namespace ASDCP { // 1.0.1. If changes were also required in AS_DCP.h, the new version would be 1.1.1. const ui32_t VERSION_MAJOR = 1; const ui32_t VERSION_APIMINOR = 1; - const ui32_t VERSION_IMPMINOR = 14; + const ui32_t VERSION_IMPMINOR = 15; const char* Version(); // UUIDs are passed around as strings of UUIDlen bytes @@ -202,6 +202,7 @@ namespace ASDCP { ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs + ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources }; // Determine the type of essence contained in the given MXF file. RESULT_OK diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp index 0986a1d..c45f785 100755 --- a/src/AS_DCP_JP2K.cpp +++ b/src/AS_DCP_JP2K.cpp @@ -119,7 +119,6 @@ public: h__Reader() : m_EssenceDescriptor(0), m_EssenceSubDescriptor(0) {} Result_t OpenRead(const char*); Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); - Result_t ReadFrameGOPStart(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); Result_t MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc); }; @@ -206,7 +205,7 @@ ASDCP::JP2K::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& Frame if ( ! m_File.IsOpen() ) return RESULT_INIT; - return ReadEKLVPacket(FrameNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC); + return ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC); } //------------------------------------------------------------------------------------------ diff --git a/src/AS_DCP_MPEG2.cpp b/src/AS_DCP_MPEG2.cpp index b3044f6..d2f2885 100755 --- a/src/AS_DCP_MPEG2.cpp +++ b/src/AS_DCP_MPEG2.cpp @@ -230,7 +230,7 @@ ASDCP::MPEG2::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& Fram if ( ! m_File.IsOpen() ) return RESULT_INIT; - Result_t result = ReadEKLVPacket(FrameNum, FrameBuf, Dict::ul(MDD_MPEG2Essence), Ctx, HMAC); + Result_t result = ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_MPEG2Essence), Ctx, HMAC); if ( ASDCP_FAILURE(result) ) return result; diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp index 68d9d6b..9525cff 100755 --- a/src/AS_DCP_MXF.cpp +++ b/src/AS_DCP_MXF.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2006, John Hurst +Copyright (c) 2004-2007, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <KM_fileio.h> +#include <KM_xml.h> #include "AS_DCP_internal.h" #include "JP2K.h" #include "MPEG.h" @@ -156,6 +157,11 @@ ASDCP::EssenceType(const char* filename, EssenceType_t& type) { if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) ) type = ESS_MPEG2_VES; + else + { + if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCTimedTextDescriptor))) ) + type = ESS_TIMED_TEXT; + } } } } @@ -173,6 +179,8 @@ ASDCP::RawEssenceType(const char* filename, EssenceType_t& type) Kumu::FileReader Reader; ASDCP::Wav::SimpleWaveHeader WavHeader; ASDCP::AIFF::SimpleAIFFHeader AIFFHeader; + Kumu::XMLElement TmpElement("Tmp"); + ui32_t data_offset; ui32_t read_count; Result_t result = FB.Capacity(Wav::MaxWavHeader); // using Wav max because everything else is much smaller @@ -190,12 +198,17 @@ ASDCP::RawEssenceType(const char* filename, EssenceType_t& type) if ( ASDCP_SUCCESS(result) ) { const byte_t* p = FB.RoData(); + FB.Size(read_count); + ui32_t i = 0; while ( p[i] == 0 ) i++; if ( i > 1 && p[i] == 1 && (p[i+1] == ASDCP::MPEG2::SEQ_START || p[i+1] == ASDCP::MPEG2::PIC_START) ) type = ESS_MPEG2_VES; + else if ( TmpElement.TestString((const char*)p, FB.Size()) ) + type = ESS_TIMED_TEXT; + else if ( ASDCP_SUCCESS(WavHeader.ReadFromBuffer(p, read_count, &data_offset)) ) type = ESS_PCM_24b_48k; diff --git a/src/AS_DCP_PCM.cpp b/src/AS_DCP_PCM.cpp index 38bf8e4..815de31 100755 --- a/src/AS_DCP_PCM.cpp +++ b/src/AS_DCP_PCM.cpp @@ -202,7 +202,7 @@ ASDCP::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameB if ( ! m_File.IsOpen() ) return RESULT_INIT; - return ReadEKLVPacket(FrameNum, FrameBuf, Dict::ul(MDD_WAVEssence), Ctx, HMAC); + return ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_WAVEssence), Ctx, HMAC); } //------------------------------------------------------------------------------------------ diff --git a/src/AS_DCP_TimedText.cpp b/src/AS_DCP_TimedText.cpp index ccb7c3e..3e6108c 100644 --- a/src/AS_DCP_TimedText.cpp +++ b/src/AS_DCP_TimedText.cpp @@ -34,12 +34,50 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AS_DCP_TimedText.h" #include "KM_xml.h" -using namespace Kumu; -using namespace ASDCP; +static std::string TIMED_TEXT_PACKAGE_LABEL = "File Package: SMPTE 429-5 frame wrapping of D-Cinema Timed Text data"; +static std::string TIMED_TEXT_DEF_LABEL = "Timed Text Track"; //------------------------------------------------------------------------------------------ +const char* +MIME2str(TimedText::MIMEType_t m) +{ + if ( m == TimedText::MT_PNG ) + return "image/png"; + + else if ( m == TimedText::MT_OPENTYPE ) + return "application/x-opentype"; + + return "application/octet-stream"; +} + +// +void +ASDCP::TimedText::DescriptorDump(ASDCP::TimedText::TimedTextDescriptor const& TDesc, FILE* stream) +{ + if ( stream == 0 ) + stream = stderr; + + UUID TmpID(TDesc.AssetID); + char buf[64]; + + fprintf(stream, " EditRate: %u/%u\n", TDesc.EditRate.Numerator, TDesc.EditRate.Denominator); + fprintf(stream, "ContainerDuration: %u\n", TDesc.ContainerDuration); + fprintf(stream, " AssetID: %s\n", TmpID.EncodeHex(buf, 64)); + fprintf(stream, " NamespaceName: %s\n", TDesc.NamespaceName.c_str()); + fprintf(stream, " ResourceCount: %lu\n", TDesc.ResourceList.size()); + + TimedText::ResourceList_t::const_iterator ri; + for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end(); ri++ ) + { + TmpID.Set((*ri).ResourceID); + fprintf(stream, " %s: %s\n", + TmpID.EncodeHex(buf, 64), + MIME2str((*ri).Type)); + } +} + // void ASDCP::TimedText::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const @@ -49,7 +87,7 @@ ASDCP::TimedText::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const UUID TmpID(m_AssetID); char buf[64]; - fprintf(stream, "ID: %s (type %s)\n", TmpID.EncodeHex(buf, 64), m_MIMEType.c_str()); + fprintf(stream, "%s | %s | %u\n", TmpID.EncodeHex(buf, 64), m_MIMEType.c_str(), Size()); if ( dump_len > 0 ) Kumu::hexdump(m_Data, dump_len, stream); @@ -57,22 +95,192 @@ ASDCP::TimedText::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const //------------------------------------------------------------------------------------------ +typedef std::map<UUID, UUID> ResourceMap_t; + class ASDCP::TimedText::MXFReader::h__Reader : public ASDCP::h__Reader { - TimedTextDescriptor* m_EssenceDescriptor; + TimedTextDescriptor* m_EssenceDescriptor; + ResourceMap_t m_ResourceMap; ASDCP_NO_COPY_CONSTRUCT(h__Reader); public: TimedTextDescriptor m_TDesc; - h__Reader() : m_EssenceDescriptor(0) {} + h__Reader() : m_EssenceDescriptor(0) { + memset(&m_TDesc.AssetID, 0, UUIDlen); + } + Result_t OpenRead(const char*); - Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); - Result_t ReadFrameGOPStart(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); - Result_t MD_to_TimedText_PDesc(TimedText::TimedTextDescriptor& TDesc); + Result_t MD_to_TimedText_TDesc(TimedText::TimedTextDescriptor& TDesc); + Result_t ReadTimedTextResource(FrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC); + Result_t ReadAncillaryResource(const byte_t*, FrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC); }; +// +ASDCP::Result_t +ASDCP::TimedText::MXFReader::h__Reader::MD_to_TimedText_TDesc(TimedText::TimedTextDescriptor& TDesc) +{ + assert(m_EssenceDescriptor); + memset(&m_TDesc.AssetID, 0, UUIDlen); + MXF::DCTimedTextDescriptor* TDescObj = (MXF::DCTimedTextDescriptor*)m_EssenceDescriptor; + + TDesc.EditRate = TDescObj->SampleRate; + TDesc.ContainerDuration = TDescObj->ContainerDuration; + TDesc.NamespaceName = TDescObj->RootNamespaceName; + TDesc.EncodingName = TDescObj->UTFEncoding; + + Batch<UUID>::const_iterator sdi = TDescObj->SubDescriptors.begin(); + DCTimedTextResourceDescriptor* DescObject = 0; + Result_t result = RESULT_OK; + + for ( ; sdi != TDescObj->SubDescriptors.end() && KM_SUCCESS(result); sdi++ ) + { + result = m_HeaderPart.GetMDObjectByID(*sdi, (InterchangeObject**)&DescObject); + + if ( KM_SUCCESS(result) ) + { + TimedTextResourceDescriptor TmpResource; + memcpy(TmpResource.ResourceID, DescObject->ResourcePackageID.Value(), UUIDlen); + + if ( DescObject->ResourceMIMEType.find("font/") != std::string::npos ) + TmpResource.Type = MT_OPENTYPE; + + else if ( DescObject->ResourceMIMEType.find("image/png") != std::string::npos ) + TmpResource.Type = MT_PNG; + + else + TmpResource.Type = MT_BIN; + + TDesc.ResourceList.push_back(TmpResource); + m_ResourceMap.insert(ResourceMap_t::value_type(DescObject->ResourcePackageID, *sdi)); + } + else + { + DefaultLogSink().Error("Broken sub-descriptor link\n"); + return RESULT_FORMAT; + } + } + + return RESULT_OK; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFReader::h__Reader::OpenRead(char const* filename) +{ + Result_t result = OpenMXFRead(filename); + + if( ASDCP_SUCCESS(result) ) + { + if ( m_EssenceDescriptor == 0 ) + m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(DCTimedTextDescriptor), (InterchangeObject**)&m_EssenceDescriptor); + + result = MD_to_TimedText_TDesc(m_TDesc); + } + + if( ASDCP_SUCCESS(result) ) + result = InitMXFIndex(); + + if( ASDCP_SUCCESS(result) ) + result = InitInfo(); + + return result; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFReader::h__Reader::ReadTimedTextResource(FrameBuffer& FrameBuf, + AESDecContext* Ctx, HMACContext* HMAC) +{ + if ( ! m_File.IsOpen() ) + return RESULT_INIT; + + return ReadEKLVFrame(0, FrameBuf, Dict::ul(MDD_DCTimedTextEssence), Ctx, HMAC); +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFReader::h__Reader::ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf, + AESDecContext* Ctx, HMACContext* HMAC) +{ + KM_TEST_NULL_L(uuid); + UUID RID(uuid); + + ResourceMap_t::const_iterator ri = m_ResourceMap.find(RID); + if ( ri == m_ResourceMap.end() ) + { + char buf[64]; + DefaultLogSink().Error("No such resource: %s\n", RID.EncodeHex(buf, 64)); + return RESULT_FORMAT; + } + + DCTimedTextResourceDescriptor* DescObject = 0; + // get the subdescriptor + Result_t result = m_HeaderPart.GetMDObjectByID((*ri).second, (InterchangeObject**)&DescObject); + + if ( KM_SUCCESS(result) ) + { + Array<RIP::Pair>::const_iterator pi; + RIP::Pair TmpPair; + ui32_t sequence = 1; + + // look up the partition start in the RIP using the SID + // count the distance in because this is the sequence value needed to + // complete the HMAC + // result = m_HeaderPart.m_RIP.GetPairBySID(DescObject->ResourceSID, TmpPair); + for ( pi = m_HeaderPart.m_RIP.PairArray.begin(); pi != m_HeaderPart.m_RIP.PairArray.end(); pi++, sequence++ ) + { + if ( (*pi).BodySID == DescObject->ResourceSID ) + { + TmpPair = *pi; + break; + } + } + + if ( TmpPair.ByteOffset == 0 ) + { + DefaultLogSink().Error("Body SID not found in RIP set: %d\n", DescObject->ResourceSID); + return RESULT_FORMAT; + } + + if ( KM_SUCCESS(result) ) + { + FrameBuf.AssetID(uuid); + FrameBuf.MIMEType(DescObject->ResourceMIMEType); + + // seek tp the start of the partition + if ( (Kumu::fpos_t)TmpPair.ByteOffset != m_LastPosition ) + { + m_LastPosition = TmpPair.ByteOffset; + result = m_File.Seek(TmpPair.ByteOffset); + } + + // read the partition header + MXF::Partition GSPart; + result = GSPart.InitFromFile(m_File); + + if( ASDCP_SUCCESS(result) ) + { + // check the SID + if ( DescObject->ResourceSID != GSPart.BodySID ) + { + char buf[64]; + DefaultLogSink().Error("Generic stream partition body differs: %s\n", RID.EncodeHex(buf, 64)); + return RESULT_FORMAT; + } + + // read the essence packet + if( ASDCP_SUCCESS(result) ) + result = ReadEKLVPacket(0, FrameBuf, Dict::ul(MDD_DCTimedTextDescriptor), Ctx, HMAC); + } + } + } + + return result; +} + + //------------------------------------------------------------------------------------------ ASDCP::TimedText::MXFReader::MXFReader() @@ -93,18 +301,6 @@ ASDCP::TimedText::MXFReader::OpenRead(const char* filename) const return m_Reader->OpenRead(filename); } -// -ASDCP::Result_t -ASDCP::TimedText::MXFReader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf, - AESDecContext* Ctx, HMACContext* HMAC) const -{ - if ( m_Reader && m_Reader->m_File.IsOpen() ) - return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC); - - return RESULT_INIT; -} - - // Fill the struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. ASDCP::Result_t @@ -119,7 +315,6 @@ ASDCP::TimedText::MXFReader::FillDescriptor(TimedText::TimedTextDescriptor& TDes return RESULT_INIT; } - // Fill the struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. ASDCP::Result_t @@ -135,6 +330,43 @@ ASDCP::TimedText::MXFReader::FillWriterInfo(WriterInfo& Info) const } // +ASDCP::Result_t +ASDCP::TimedText::MXFReader::ReadTimedTextResource(std::string& s, AESDecContext* Ctx, HMACContext* HMAC) const +{ + FrameBuffer FrameBuf(2*Kumu::Megabyte); + + Result_t result = ReadTimedTextResource(FrameBuf, Ctx, HMAC); + + if ( ASDCP_SUCCESS(result) ) + s.assign((char*)FrameBuf.Data(), FrameBuf.Size()); + + return result; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFReader::ReadTimedTextResource(FrameBuffer& FrameBuf, + AESDecContext* Ctx, HMACContext* HMAC) const +{ + if ( m_Reader && m_Reader->m_File.IsOpen() ) + return m_Reader->ReadTimedTextResource(FrameBuf, Ctx, HMAC); + + return RESULT_INIT; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFReader::ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf, + AESDecContext* Ctx, HMACContext* HMAC) const +{ + if ( m_Reader && m_Reader->m_File.IsOpen() ) + return m_Reader->ReadAncillaryResource(uuid, FrameBuf, Ctx, HMAC); + + return RESULT_INIT; +} + + +// void ASDCP::TimedText::MXFReader::DumpHeaderMetadata(FILE* stream) const { @@ -160,10 +392,11 @@ class ASDCP::TimedText::MXFWriter::h__Writer : public ASDCP::h__Writer public: TimedTextDescriptor m_TDesc; byte_t m_EssenceUL[SMPTE_UL_LENGTH]; + ui32_t m_ResourceSID; ASDCP_NO_COPY_CONSTRUCT(h__Writer); - h__Writer() { + h__Writer() : m_ResourceSID(10) { memset(m_EssenceUL, 0, SMPTE_UL_LENGTH); } @@ -171,11 +404,172 @@ public: Result_t OpenWrite(const char*, ui32_t HeaderSize); Result_t SetSourceStream(const TimedTextDescriptor&); - Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); + Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0); + Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); Result_t Finalize(); - Result_t TimedText_PDesc_to_MD(TimedText::TimedTextDescriptor& PDesc); + Result_t TimedText_TDesc_to_MD(TimedText::TimedTextDescriptor& TDesc); }; +// +ASDCP::Result_t +ASDCP::TimedText::MXFWriter::h__Writer::TimedText_TDesc_to_MD(TimedText::TimedTextDescriptor& TDesc) +{ + assert(m_EssenceDescriptor); + // assert(m_EssenceSubDescriptor); + MXF::DCTimedTextDescriptor* TDescObj = (MXF::DCTimedTextDescriptor*)m_EssenceDescriptor; + + TDescObj->SampleRate = TDesc.EditRate; + TDescObj->ContainerDuration = TDesc.ContainerDuration; + TDescObj->RootNamespaceName = TDesc.NamespaceName; + TDescObj->UTFEncoding = TDesc.EncodingName; + + return RESULT_OK; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFWriter::h__Writer::OpenWrite(char const* filename, ui32_t HeaderSize) +{ + if ( ! m_State.Test_BEGIN() ) + return RESULT_STATE; + + Result_t result = m_File.OpenWrite(filename); + + if ( ASDCP_SUCCESS(result) ) + { + m_HeaderSize = HeaderSize; + m_EssenceDescriptor = new DCTimedTextDescriptor(); + result = m_State.Goto_INIT(); + } + + return result; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedTextDescriptor const& TDesc) +{ + if ( ! m_State.Test_INIT() ) + return RESULT_STATE; + + m_TDesc = TDesc; + ResourceList_t::const_iterator ri; + Result_t result = TimedText_TDesc_to_MD(m_TDesc); + + for ( ri = m_TDesc.ResourceList.begin() ; ri != m_TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ ) + { + DCTimedTextResourceDescriptor* resourceSubdescriptor = new DCTimedTextResourceDescriptor; + GenRandomValue(resourceSubdescriptor->InstanceUID); + resourceSubdescriptor->ResourcePackageID.Set((*ri).ResourceID); + resourceSubdescriptor->ResourceMIMEType = MIME2str((*ri).Type); + resourceSubdescriptor->ResourceSID = m_ResourceSID++; + m_EssenceSubDescriptorList.push_back((FileDescriptor*)resourceSubdescriptor); + m_EssenceDescriptor->SubDescriptors.push_back(resourceSubdescriptor->InstanceUID); + } + + m_ResourceSID = 10; + + if ( ASDCP_SUCCESS(result) ) + { + InitHeader(); + AddDMSegment(m_TDesc.EditRate, 24, TIMED_TEXT_DEF_LABEL, + UL(Dict::ul(MDD_PictureDataDef)), TIMED_TEXT_PACKAGE_LABEL); + + AddEssenceDescriptor(UL(Dict::ul(MDD_DCTimedTextWrapping))); + + result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize); + + if ( KM_SUCCESS(result) ) + result = CreateBodyPart(m_TDesc.EditRate); + } + + if ( ASDCP_SUCCESS(result) ) + { + memcpy(m_EssenceUL, Dict::ul(MDD_DCTimedTextEssence), SMPTE_UL_LENGTH); + m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container + result = m_State.Goto_READY(); + } + + return result; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFWriter::h__Writer::WriteTimedTextResource(const std::string& XMLDoc, + ASDCP::AESEncContext* Ctx, ASDCP::HMACContext* HMAC) +{ + Result_t result = m_State.Goto_RUNNING(); + + if ( ASDCP_SUCCESS(result) ) + { + // TODO: make sure it's XML + + ui32_t str_size = XMLDoc.size(); + FrameBuffer FrameBuf(str_size); + + memcpy(FrameBuf.Data(), XMLDoc.c_str(), str_size); + FrameBuf.Size(str_size); + + IndexTableSegment::IndexEntry Entry; + Entry.StreamOffset = m_StreamOffset; + + if ( ASDCP_SUCCESS(result) ) + result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC); + + if ( ASDCP_SUCCESS(result) ) + { + m_FooterPart.PushIndexEntry(Entry); + m_FramesWritten++; + } + } + + return result; +} + + +// +ASDCP::Result_t +ASDCP::TimedText::MXFWriter::h__Writer::WriteAncillaryResource(const ASDCP::TimedText::FrameBuffer& FrameBuf, + ASDCP::AESEncContext* Ctx, ASDCP::HMACContext* HMAC) +{ + if ( ! m_State.Test_RUNNING() ) + return RESULT_STATE; + + Kumu::fpos_t here = m_File.Tell(); + + // create generic stream partition header + MXF::Partition GSPart; + + GSPart.ThisPartition = here; + GSPart.PreviousPartition = m_HeaderPart.m_RIP.PairArray.back().ByteOffset; + GSPart.BodySID = m_ResourceSID; + GSPart.OperationalPattern = m_HeaderPart.OperationalPattern; + + m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(m_ResourceSID++, here)); + GSPart.EssenceContainers.push_back(UL(Dict::ul(MDD_DCTimedTextEssence))); + UL TmpUL(Dict::ul(MDD_GenericStreamPartition)); + Result_t result = GSPart.WriteToFile(m_File, TmpUL); + + if ( ASDCP_SUCCESS(result) ) + result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC); + + m_FramesWritten++; + return result; +} + +// +ASDCP::Result_t +ASDCP::TimedText::MXFWriter::h__Writer::Finalize() +{ + if ( ! m_State.Test_RUNNING() ) + return RESULT_STATE; + + m_FramesWritten = m_TDesc.ContainerDuration; + m_State.Goto_FINAL(); + + return WriteMXFFooter(); +} + //------------------------------------------------------------------------------------------ @@ -194,6 +588,12 @@ ASDCP::Result_t ASDCP::TimedText::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, const TimedTextDescriptor& TDesc, ui32_t HeaderSize) { + if ( Info.LabelSetType != LS_MXF_SMPTE ) + { + DefaultLogSink().Error("Timed Text support requires LS_MXF_SMPTE\n"); + return RESULT_FORMAT; + } + m_Writer = new h__Writer; Result_t result = m_Writer->OpenWrite(filename, HeaderSize); @@ -210,18 +610,24 @@ ASDCP::TimedText::MXFWriter::OpenWrite(const char* filename, const WriterInfo& I return result; } +// +ASDCP::Result_t +ASDCP::TimedText::MXFWriter::WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* Ctx, HMACContext* HMAC) +{ + if ( m_Writer.empty() ) + return RESULT_INIT; -// Writes a frame of essence to the MXF file. If the optional AESEncContext -// argument is present, the essence is encrypted prior to writing. -// Fails if the file is not open, is finalized, or an operating system -// error occurs. + return m_Writer->WriteTimedTextResource(XMLDoc, Ctx, HMAC); +} + +// ASDCP::Result_t -ASDCP::TimedText::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC) +ASDCP::TimedText::MXFWriter::WriteAncillaryResource(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC) { if ( m_Writer.empty() ) return RESULT_INIT; - return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC); + return m_Writer->WriteAncillaryResource(FrameBuf, Ctx, HMAC); } // Closes the MXF file, writing the index and other closing information. diff --git a/src/AS_DCP_internal.h b/src/AS_DCP_internal.h index 177a74d..ff86d40 100755 --- a/src/AS_DCP_internal.h +++ b/src/AS_DCP_internal.h @@ -111,6 +111,12 @@ namespace ASDCP Result_t InitInfo(); Result_t OpenMXFRead(const char* filename); Result_t InitMXFIndex(); + + // positions file before reading + Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, + const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC); + + // reads from current position Result_t ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC); void Close(); @@ -152,6 +158,8 @@ namespace ASDCP inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); } }; + typedef std::list<ui64_t*> DurationElementList_t; + // class h__Writer { @@ -166,16 +174,7 @@ namespace ASDCP ui64_t m_EssenceStart; MaterialPackage* m_MaterialPackage; - Sequence* m_MPTCSequence; - TimecodeComponent* m_MPTimecode; - Sequence* m_MPClSequence; - SourceClip* m_MPClip; //! Material Package SourceClip for each essence stream - SourcePackage* m_FilePackage; - Sequence* m_FPTCSequence; - TimecodeComponent* m_FPTimecode; - Sequence* m_FPClSequence; - SourceClip* m_FPClip; //! File Package SourceClip for each essence stream FileDescriptor* m_EssenceDescriptor; std::list<FileDescriptor*> m_EssenceSubDescriptorList; @@ -185,10 +184,22 @@ namespace ASDCP ASDCP::FrameBuffer m_CtFrameBuf; h__WriterState m_State; WriterInfo m_Info; + DurationElementList_t m_DurationUpdateList; h__Writer(); virtual ~h__Writer(); + void InitHeader(); + void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate, + const std::string& TrackName, const UL& DataDefinition, + const std::string& PackageLabel); + void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate, + const std::string& TrackName, const UL& DataDefinition, + const std::string& PackageLabel); + void AddEssenceDescriptor(const UL& WrappingUL); + Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0); + + // all the above for a single source clip Result_t WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL, const std::string& TrackName, const UL& DataDefinition, const MXF::Rational& EditRate, diff --git a/src/Index.cpp b/src/Index.cpp index c37db1b..5e0743c 100755 --- a/src/Index.cpp +++ b/src/Index.cpp @@ -125,7 +125,7 @@ ASDCP::MXF::IndexTableSegment::Dump(FILE* stream) } else { - fprintf(stream, " IndexEntryArray: %u entries\n", IndexEntryArray.size()); + fprintf(stream, " IndexEntryArray: %lu entries\n", IndexEntryArray.size()); } } diff --git a/src/KM_fileio.cpp b/src/KM_fileio.cpp index e01b01f..50e01d6 100644 --- a/src/KM_fileio.cpp +++ b/src/KM_fileio.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2006, John Hurst +Copyright (c) 2004-2007, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -53,6 +53,33 @@ struct iovec { typedef struct stat fstat_t; #endif +static void +split(const std::string& str, char separator, std::list<std::string>& components) +{ + const char* pstr = str.c_str(); + const char* r = strchr(pstr, separator); + + while( r != NULL ) + { + char* cp = new char[(r-pstr)+1]; + memcpy(cp, pstr, (r-pstr)); + cp[(r-pstr)] = '\0'; + + if( strlen(cp) > 0 ) + { + std::string s(cp); + components.push_back(s); + } + + delete[] cp; + pstr = r + 1; + r = strchr(pstr, separator); + } + + if( strlen(pstr) > 0 ) + components.push_back(std::string(pstr)); +} + // static Kumu::Result_t do_stat(const char* path, fstat_t* stat_info) @@ -104,14 +131,29 @@ do_fstat(HANDLE handle, fstat_t* stat_info) // bool -Kumu::PathIsFile(const char* pathname) +Kumu::PathExists(const std::string& pathname) +{ + if ( pathname.empty() ) + return false; + + fstat_t info; + + if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) + return true; + + return false; +} + +// +bool +Kumu::PathIsFile(const std::string& pathname) { - if ( pathname == 0 || *pathname == 0 ) + if ( pathname.empty() ) return false; fstat_t info; - if ( KM_SUCCESS(do_stat(pathname, &info)) ) + if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) { if ( info.st_mode & ( S_IFREG|S_IFLNK ) ) return true; @@ -123,14 +165,14 @@ Kumu::PathIsFile(const char* pathname) // bool -Kumu::PathIsDirectory(const char* pathname) +Kumu::PathIsDirectory(const std::string& pathname) { - if ( pathname == 0 || *pathname == 0 ) + if ( pathname.empty() ) return false; fstat_t info; - if ( KM_SUCCESS(do_stat(pathname, &info)) ) + if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) { if ( info.st_mode & S_IFDIR ) return true; @@ -139,17 +181,16 @@ Kumu::PathIsDirectory(const char* pathname) return false; } - // Kumu::fsize_t -Kumu::FileSize(const char* pathname) +Kumu::FileSize(const std::string& pathname) { - if ( pathname == 0 || *pathname == 0 ) - return false; + if ( pathname.empty() ) + return 0; fstat_t info; - if ( KM_SUCCESS(do_stat(pathname, &info)) ) + if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) { if ( info.st_mode & ( S_IFREG|S_IFLNK ) ) return(info.st_size); @@ -158,6 +199,346 @@ Kumu::FileSize(const char* pathname) return 0; } +// +static PathCompList_t& +s_PathMakeCanonical(PathCompList_t& CList, char separator, bool is_absolute) +{ + PathCompList_t::iterator ci, ri; // component and removal iterators + + for ( ci = CList.begin(); ci != CList.end(); ci++ ) + { + if ( *ci == "." && ( CList.size() > 1 || is_absolute ) ) + { + ri = ci++; + CList.erase(ri); + } + else if ( *ci == ".." && ci != CList.begin() ) + { + ri = ci; + ri--; + + if ( *ri != ".." ) + { + CList.erase(ri); + ri = ci++; + CList.erase(ri); + } + } + } + + return CList; +} + +// +std::string +Kumu::PathMakeCanonical(const std::string& Path, char separator) +{ + PathCompList_t CList; + bool is_absolute = PathIsAbsolute(Path, separator); + s_PathMakeCanonical(PathToComponents(Path, CList, separator), separator, is_absolute); + + if ( is_absolute ) + return ComponentsToAbsolutePath(CList, separator); + + return ComponentsToPath(CList, separator); +} + +// +bool +Kumu::PathsAreEquivalent(const std::string& lhs, const std::string& rhs) +{ + return PathMakeCanonical(lhs) == PathMakeCanonical(rhs); +} + +// +Kumu::PathCompList_t& +Kumu::PathToComponents(const std::string& Path, PathCompList_t& CList, char separator) +{ + split(Path, separator, CList); + return CList; +} + +// +std::string +Kumu::ComponentsToPath(const PathCompList_t& CList, char separator) +{ + if ( CList.empty() ) + return ""; + + PathCompList_t::const_iterator ci = CList.begin(); + std::string out_path = *ci; + + for ( ci++; ci != CList.end(); ci++ ) + out_path += separator + *ci; + + return out_path; +} + +// +std::string +Kumu::ComponentsToAbsolutePath(const PathCompList_t& CList, char separator) +{ + std::string out_path; + + if ( CList.empty() ) + out_path = separator; + else + { + PathCompList_t::const_iterator ci; + + for ( ci = CList.begin(); ci != CList.end(); ci++ ) + out_path += separator + *ci; + } + + return out_path; +} + +// +bool +Kumu::PathHasComponents(const std::string& Path, char separator) +{ + if ( strchr(Path.c_str(), separator) == 0 ) + return false; + + return true; +} + +// +bool +Kumu::PathIsAbsolute(const std::string& Path, char separator) +{ + if ( Path.empty() ) + return false; + + if ( Path[0] == separator) + return true; + + return false; +} + +// +std::string +Kumu::PathMakeAbsolute(const std::string& Path, char separator) +{ + if ( Path.empty() ) + { + std::string out_path; + out_path = separator; + return out_path; + } + + if ( PathIsAbsolute(Path, separator) ) + return Path; + + char cwd_buf [MaxFilePath]; + if ( getcwd(cwd_buf, MaxFilePath) == 0 ) + { + DefaultLogSink().Error("Error retrieving current working directory."); + return ""; + } + + PathCompList_t CList; + CList.push_back(cwd_buf); + CList.push_back(Path); + + return ComponentsToAbsolutePath(s_PathMakeCanonical(CList, separator, true), separator); +} + +// +std::string +Kumu::PathMakeLocal(const std::string& Path, const std::string& Parent) +{ + size_t pos = Path.find(Parent); + + if ( pos == 0 ) // Parent found at offset 0 + return Path.substr(Parent.size()+1); + + return Path; +} + +// +std::string +Kumu::PathBasename(const std::string& Path, char separator) +{ + PathCompList_t CList; + PathToComponents(Path, CList, separator); + + if ( CList.empty() ) + return ""; + + return CList.back(); +} + +// +std::string +Kumu::PathDirname(const std::string& Path, char separator) +{ + PathCompList_t CList; + bool is_absolute = PathIsAbsolute(Path, separator); + PathToComponents(Path, CList, separator); + + if ( CList.empty() ) + return is_absolute ? "/" : ""; + + CList.pop_back(); + + if ( is_absolute ) + return ComponentsToAbsolutePath(CList, separator); + + return ComponentsToPath(CList, separator); +} + +// +std::string +Kumu::PathGetExtension(const std::string& Path) +{ + std::string Basename = PathBasename(Path); + const char* p = strrchr(Basename.c_str(), '.'); + + if ( p++ == 0 ) + return ""; + + return p; +} + +// +std::string +Kumu::PathSetExtension(const std::string& Path, const std::string& Extension) // empty extension removes +{ + std::string Basename = PathBasename(Path); + const char* p = strrchr(Basename.c_str(), '.'); + + if ( p != 0 ) + Basename = Basename.substr(0, p - Basename.c_str()); + + if ( Extension.empty() ) + return Basename; + + return Basename + "." + Extension; +} + +// +Kumu::PathList_t& +Kumu::FindInPaths(const IPathMatch& Pattern, const Kumu::PathList_t& SearchPaths, + Kumu::PathList_t& FoundPaths, bool one_shot, char separator) +{ + PathList_t::const_iterator si; + for ( si = SearchPaths.begin(); si != SearchPaths.end(); si++ ) + { + FindInPath(Pattern, *si, FoundPaths, one_shot, separator); + + if ( one_shot && ! FoundPaths.empty() ) + break; + } + + return FoundPaths; +} + +// +Kumu::PathList_t& +Kumu::FindInPath(const IPathMatch& Pattern, const std::string& SearchDir, + Kumu::PathList_t& FoundPaths, bool one_shot, char separator) +{ + char name_buf[MaxFilePath]; + DirScanner Dir; + + if ( KM_SUCCESS(Dir.Open(SearchDir.c_str())) ) + { + while ( KM_SUCCESS(Dir.GetNext(name_buf)) ) + { + if ( name_buf[0] == '.' ) continue; // no hidden files + std::string tmp_path = SearchDir + separator + name_buf; + + if ( PathIsDirectory(tmp_path.c_str()) ) + FindInPath(Pattern, tmp_path, FoundPaths, one_shot, separator); + + else if ( Pattern.Match(name_buf) ) + { + FoundPaths.push_back(SearchDir + separator + name_buf); + if ( one_shot ) + break; + } + } + } + + return FoundPaths; +} + + +#ifndef KM_WIN32 + +// +Kumu::PathMatchRegex::PathMatchRegex(const std::string& s) +{ + int result = regcomp(&m_regex, s.c_str(), REG_NOSUB); // (REG_EXTENDED|REG_NOSUB|REG_NEWLINE)); + + if ( result ) + { + char buf[128]; + regerror(result, &m_regex, buf, 128); + DefaultLogSink().Error("PathMatchRegex: %s\n", buf); + regfree(&m_regex); + } +} + +Kumu::PathMatchRegex::PathMatchRegex(const PathMatchRegex& rhs) { + m_regex = rhs.m_regex; +} + +Kumu::PathMatchRegex::~PathMatchRegex() { + regfree(&m_regex); +} + +bool +Kumu::PathMatchRegex::Match(const std::string& s) const { + return ( regexec(&m_regex, s.c_str(), 0, 0, 0) == 0 ); +} + + + +// +Kumu::PathMatchGlob::PathMatchGlob(const std::string& glob) +{ + std::string regex; // convert glob to regex + + for ( const char* p = glob.c_str(); *p != 0; p++ ) + { + switch (*p) + { + case '.': regex += "\\."; break; + case '*': regex += ".*"; break; + case '?': regex += ".?"; break; + default: regex += *p; + } + } + regex += '$'; + + int result = regcomp(&m_regex, regex.c_str(), REG_NOSUB); + + if ( result ) + { + char buf[128]; + regerror(result, &m_regex, buf, 128); + DefaultLogSink().Error("PathMatchRegex: %s\n", buf); + regfree(&m_regex); + } +} + +Kumu::PathMatchGlob::PathMatchGlob(const PathMatchGlob& rhs) { + m_regex = rhs.m_regex; +} + +Kumu::PathMatchGlob::~PathMatchGlob() { + regfree(&m_regex); +} + +bool +Kumu::PathMatchGlob::Match(const std::string& s) const { + return ( regexec(&m_regex, s.c_str(), 0, 0, 0) == 0 ); +} + +#endif + //------------------------------------------------------------------------------------------ // portable aspects of the file classes @@ -438,7 +819,7 @@ Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written BOOL result = ::WriteFile(m_Handle, buf, buf_len, (DWORD*)bytes_written, NULL); ::SetErrorMode(prev); - if ( result == 0 || bytes_written != buf_len ) + if ( result == 0 || *bytes_written != buf_len ) return Kumu::RESULT_WRITEFAIL; return Kumu::RESULT_OK; diff --git a/src/KM_fileio.h b/src/KM_fileio.h index 96cdf00..43b164d 100755 --- a/src/KM_fileio.h +++ b/src/KM_fileio.h @@ -42,6 +42,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # include <unistd.h> # include <time.h> # include <sys/types.h> +#include <regex.h> #endif #include <sys/stat.h> @@ -50,36 +51,24 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Kumu { -#ifdef KM_WIN32 // class DirScanner { public: +#ifdef KM_WIN32 __int64 m_Handle; struct _finddatai64_t m_FileInfo; +#else + DIR* m_Handle; +#endif DirScanner() {}; ~DirScanner() { Close(); } + Result_t Open(const char*); Result_t Close(); Result_t GetNext(char*); }; -#else // KM_WIN32 - // POSIX directory scanner - // - class DirScanner - { - public: - DIR* m_Handle; - - DirScanner() : m_Handle(NULL) {} - ~DirScanner() { Close(); } - - Result_t Open(const char*); - Result_t Close(); - Result_t GetNext(char*); - }; -#endif // KM_WIN32 #ifdef KM_WIN32 typedef __int64 fsize_t; @@ -109,10 +98,86 @@ namespace Kumu const ui32_t MaxFilePath = Kilobyte; - bool PathIsFile(const char* pathname); - bool PathIsDirectory(const char* pathname); - fsize_t FileSize(const char* pathname); + // Path Manglers + // + typedef std::list<std::string> PathCompList_t; // a list of path components + typedef std::list<std::string> PathList_t; // a list of paths + + bool PathExists(const std::string& Path); // true if the path exists in the filesystem + bool PathIsFile(const std::string& Path); // true if the path exists in the filesystem and is a file + bool PathIsDirectory(const std::string& Path); // true if the path exists in the filesystem and is a directory + fsize_t FileSize(const std::string& Path); // returns the size of a regular file, 0 for a directory or device + bool PathsAreEquivalent(const std::string& lhs, const std::string& rhs); // true if paths point to the same filesystem entry + + // split and reassemble pats as lists of path components + PathCompList_t& PathToComponents(const std::string& Path, PathCompList_t& CList, char separator = '/'); // removes '//' + std::string ComponentsToPath(const PathCompList_t& CList, char separator = '/'); + std::string ComponentsToAbsolutePath(const PathCompList_t& CList, char separator = '/'); // add separator to the front + bool PathHasComponents(const std::string& Path, char separator = '/'); // true if paths starts with separator + + bool PathIsAbsolute(const std::string& Path, char separator = '/'); // true if path begins with separator + std::string PathMakeAbsolute(const std::string& Path, char separator = '/'); // compute position of relative path using getcwd() + std::string PathMakeLocal(const std::string& Path, const std::string& Parent); // remove Parent from front of Path, if it exists + std::string PathMakeCanonical(const std::string& Path, char separator = '/'); // remove '.' and '..' + + std::string PathBasename(const std::string& Path, char separator = '/'); // returns right-most path element (list back()) + std::string PathDirname(const std::string& Path, char separator = '/'); // returns everything but the right-most element + std::string PathGetExtension(const std::string& Path); // returns everything in the right-most element following the right-most '.' + std::string PathSetExtension(const std::string& Path, const std::string& Extension); // empty extension removes '.' as well + // + // + class IPathMatch + { + public: + virtual ~IPathMatch() {} + virtual bool Match(const std::string& s) const = 0; + }; + + class PathMatchAny : public IPathMatch + { + public: + virtual ~PathMatchAny() {} + inline bool Match(const std::string& s) const { return true; } + }; + + class PathMatchRegex : public IPathMatch + { + regex_t m_regex; + PathMatchRegex(); + const PathMatchRegex& operator=(const PathMatchRegex&); + + public: + PathMatchRegex(const std::string& Pattern); + PathMatchRegex(const PathMatchRegex&); + virtual ~PathMatchRegex(); + bool Match(const std::string& s) const; + }; + + class PathMatchGlob : public IPathMatch + { + regex_t m_regex; + PathMatchGlob(); + const PathMatchGlob& operator=(const PathMatchGlob&); + + public: + PathMatchGlob(const std::string& Pattern); + PathMatchGlob(const PathMatchGlob&); + virtual ~PathMatchGlob(); + bool Match(const std::string& s) const; + }; + + // Search all paths in SearchPaths for filenames matching Pattern (no directories are returned). + // Put results in FoundPaths. Returns after first find if one_shot is true. + PathList_t& FindInPath(const IPathMatch& Pattern, const std::string& SearchDir, + PathList_t& FoundPaths, bool one_shot, char separator); + + PathList_t& FindInPaths(const IPathMatch& Pattern, const PathList_t& SearchPaths, + PathList_t& FoundPaths, bool one_shot = false, char separator = '/'); + + + // Instant IO for strings + // // Reads an entire file into a string. Result_t ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size = 8 * Megabyte); diff --git a/src/KM_xml.cpp b/src/KM_xml.cpp index 605ea11..0310291 100644 --- a/src/KM_xml.cpp +++ b/src/KM_xml.cpp @@ -30,10 +30,36 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <KM_xml.h> +#include <KM_log.h> +#include <stack> +#include <map> +#ifdef ASDCP_USE_EXPAT +#include <expat.h> +#endif +using namespace Kumu; -Kumu::XMLElement::XMLElement(const char* name) + +class ns_map : public std::map<std::string, XMLNamespace*> +{ +public: + ns_map() {} + ~ns_map() + { + ns_map::iterator ni = begin(); + + while (ni != end() ) + { + // fprintf(stderr, "deleting namespace %s:%s\n", ni->second->Prefix().c_str(), ni->second->Name().c_str()); + delete ni->second; + ni++; + } + } +}; + + +Kumu::XMLElement::XMLElement(const char* name) : m_Namespace(0), m_NamespaceOwner(0) { m_Name = name; } @@ -42,6 +68,9 @@ Kumu::XMLElement::~XMLElement() { for ( Elem_i i = m_ChildList.begin(); i != m_ChildList.end(); i++ ) delete *i; + + if ( m_NamespaceOwner != 0 ) + delete (ns_map*)m_NamespaceOwner; } // @@ -72,6 +101,13 @@ Kumu::XMLElement::AddChildWithContent(const char* name, const std::string& value } // +void +Kumu::XMLElement::AppendBody(const std::string& value) +{ + m_Body += value; +} + +// Kumu::XMLElement* Kumu::XMLElement::AddChildWithContent(const char* name, const char* value) { @@ -105,7 +141,7 @@ Kumu::XMLElement::AddComment(const char* value) // void -Kumu::XMLElement::Render(std::string& outbuf) +Kumu::XMLElement::Render(std::string& outbuf) const { outbuf = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; RenderElement(outbuf, 0); @@ -121,7 +157,7 @@ add_spacer(std::string& outbuf, i32_t depth) // void -Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth) +Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth) const { add_spacer(outbuf, depth); @@ -164,6 +200,293 @@ Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth) outbuf += ">\n"; } +// +bool +Kumu::XMLElement::HasName(const char* name) const +{ + if ( name == 0 || *name == 0 ) + return false; + + return (m_Name == name); +} + + +void +Kumu::XMLElement::SetName(const char* name) +{ + if ( name != 0) + m_Name = name; +} + +// +const char* +Kumu::XMLElement::GetAttrWithName(const char* name) const +{ + for ( Attr_i i = m_AttrList.begin(); i != m_AttrList.end(); i++ ) + { + if ( (*i).name == name ) + return (*i).value.c_str(); + } + + return 0; +} + +// +Kumu::XMLElement* +Kumu::XMLElement::GetChildWithName(const char* name) const +{ + for ( Elem_i i = m_ChildList.begin(); i != m_ChildList.end(); i++ ) + { + if ( (*i)->HasName(name) ) + return *i; + } + + return 0; +} + +// +const Kumu::ElementList& +Kumu::XMLElement::GetChildrenWithName(const char* name, ElementList& outList) const +{ + assert(name); + for ( Elem_i i = m_ChildList.begin(); i != m_ChildList.end(); i++ ) + { + if ( (*i)->HasName(name) ) + outList.push_back(*i); + + if ( ! (*i)->m_ChildList.empty() ) + (*i)->GetChildrenWithName(name, outList); + } + + return outList; +} + +//---------------------------------------------------------------------------------------------------- + +#ifdef ASDCP_USE_EXPAT + + +class ExpatParseContext +{ + KM_NO_COPY_CONSTRUCT(ExpatParseContext); + ExpatParseContext(); +public: + ns_map* Namespaces; + std::stack<XMLElement*> Scope; + XMLElement* Root; + + ExpatParseContext(XMLElement* root) : Root(root) { + Namespaces = new ns_map; + assert(Root); + } + + ~ExpatParseContext() {} +}; + +// expat wrapper functions +// +static void +xph_start(void* p, const XML_Char* name, const XML_Char** attrs) +{ + assert(p); assert(name); assert(attrs); + ExpatParseContext* Ctx = (ExpatParseContext*)p; + XMLElement* Element; + + const char* ns_root = name; + const char* local_name = strchr(name, '|'); + if ( local_name != 0 ) + name = local_name + 1; + + if ( Ctx->Scope.empty() ) + { + Ctx->Scope.push(Ctx->Root); + } + else + { + Element = Ctx->Scope.top(); + Ctx->Scope.push(Element->AddChild(name)); + } + + Element = Ctx->Scope.top(); + Element->SetName(name); + + // map the namespace + std::string key; + if ( ns_root != name ) + key.assign(ns_root, name - ns_root - 1); + + ns_map::iterator ni = Ctx->Namespaces->find(key); + if ( ni != Ctx->Namespaces->end() ) + Element->SetNamespace(ni->second); + + // set attributes + for ( int i = 0; attrs[i] != 0; i += 2 ) + { + if ( ( local_name = strchr(attrs[i], '|') ) == 0 ) + local_name = attrs[i]; + else + local_name++; + + Element->SetAttr(local_name, attrs[i+1]); + } +} + +// +static void +xph_end(void* p, const XML_Char* name) +{ + assert(p); assert(name); + ExpatParseContext* Ctx = (ExpatParseContext*)p; + Ctx->Scope.pop(); +} + +// +static void +xph_char(void* p, const XML_Char* data, int len) +{ + assert(p); assert(data); + ExpatParseContext* Ctx = (ExpatParseContext*)p; + + if ( len > 0 ) + { + std::string tmp_str; + tmp_str.assign(data, len); + Ctx->Scope.top()->AppendBody(tmp_str); + } +} + +// +void +xph_namespace_start(void* p, const XML_Char* ns_prefix, const XML_Char* ns_name) +{ + assert(p); assert(ns_name); + ExpatParseContext* Ctx = (ExpatParseContext*)p; + + if ( ns_prefix == 0 ) + ns_prefix = ""; + + ns_map::iterator ni = Ctx->Namespaces->find(ns_name); + + if ( ni != Ctx->Namespaces->end() ) + { + if ( ni->second->Name() != std::string(ns_name) ) + { + DefaultLogSink().Error("Duplicate prefix: %s\n", ns_prefix); + return; + } + } + else + { + XMLNamespace* Namespace = new XMLNamespace(ns_prefix, ns_name); + Ctx->Namespaces->insert(ns_map::value_type(ns_name, Namespace)); + } +} + +// +bool +Kumu::XMLElement::ParseString(const std::string& document) +{ + XML_Parser Parser = XML_ParserCreateNS("UTF-8", '|'); + + if ( Parser == 0 ) + { + DefaultLogSink().Error("Error allocating memory for XML parser.\n"); + return false; + } + + ExpatParseContext Ctx(this); + XML_SetUserData(Parser, (void*)&Ctx); + XML_SetElementHandler(Parser, xph_start, xph_end); + XML_SetCharacterDataHandler(Parser, xph_char); + XML_SetStartNamespaceDeclHandler(Parser, xph_namespace_start); + + if ( ! XML_Parse(Parser, document.c_str(), document.size(), 1) ) + { + XML_ParserFree(Parser); + DefaultLogSink().Error("XML Parse error on line %d: %s\n", + XML_GetCurrentLineNumber(Parser), + XML_ErrorString(XML_GetErrorCode(Parser))); + return false; + } + + XML_ParserFree(Parser); + + if ( ! Ctx.Namespaces->empty() ) + m_NamespaceOwner = (void*)Ctx.Namespaces; + + return true; +} + +//------------------------------------------------------------------------------------------ + +struct xph_test_wrapper +{ + XML_Parser Parser; + bool Status; + + xph_test_wrapper(XML_Parser p) : Parser(p), Status(false) {} +}; + +// expat wrapper functions, map callbacks to IASAXHandler +// +static void +xph_test_start(void* p, const XML_Char* name, const XML_Char** attrs) +{ + assert(p); + xph_test_wrapper* Wrapper = (xph_test_wrapper*)p; + + Wrapper->Status = true; + XML_StopParser(Wrapper->Parser, false); +} + + +// +bool +Kumu::XMLElement::TestString(const char* document, ui32_t len) +{ + if ( document == 0 ) + return false; + + if ( len == 0 ) + len = strlen(document); + + XML_Parser Parser = XML_ParserCreate("UTF-8"); + + if ( Parser == 0 ) + { + DefaultLogSink().Error("Error allocating memory for XML parser.\n"); + return false; + } + + xph_test_wrapper Wrapper(Parser); + XML_SetUserData(Parser, (void*)&Wrapper); + XML_SetStartElementHandler(Parser, xph_test_start); + + XML_Parse(Parser, document, len, 1); + XML_ParserFree(Parser); + return Wrapper.Status; +} + +#else // no XML parser support + +// +bool +Kumu::XMLElement::ParseString(const std::string& document) +{ + DefaultLogSink().Error("asdcplib compiled without XML parser support.\n"); + return false; +} + +// +bool +Kumu::XMLElement::TestString(const char* document, ui32_t len) +{ + DefaultLogSink().Error("asdcplib compiled without XML parser support.\n"); + return false; +} + +#endif + // // end KM_xml.cpp diff --git a/src/KM_xml.h b/src/KM_xml.h index ae24ac1..31f5064 100644 --- a/src/KM_xml.h +++ b/src/KM_xml.h @@ -41,41 +41,79 @@ namespace Kumu { class XMLElement; + // struct NVPair { std::string name; std::string value; }; + // typedef std::list<NVPair> AttributeList; - typedef AttributeList::iterator Attr_i; + typedef AttributeList::const_iterator Attr_i; typedef std::list<XMLElement*> ElementList; - typedef ElementList::iterator Elem_i; + typedef ElementList::const_iterator Elem_i; + + // + class XMLNamespace + { + std::string m_Prefix; + std::string m_Name; + + KM_NO_COPY_CONSTRUCT(XMLNamespace); + XMLNamespace(); + + public: + XMLNamespace(const char* prefix, const char* name) : m_Prefix(prefix), m_Name(name) {} + ~XMLNamespace() {} + + inline const std::string& Prefix() const { return m_Prefix; } + inline const std::string& Name() const { return m_Name; } + }; // class XMLElement { - AttributeList m_AttrList; - ElementList m_ChildList; + AttributeList m_AttrList; + ElementList m_ChildList; + const XMLNamespace* m_Namespace; + void* m_NamespaceOwner; + + std::string m_Name; + std::string m_Body; KM_NO_COPY_CONSTRUCT(XMLElement); XMLElement(); public: - std::string m_Name; - std::string m_Body; - XMLElement(const char* name); ~XMLElement(); + inline const XMLNamespace* Namespace() const { return m_Namespace; } + inline void SetNamespace(const XMLNamespace* ns) { assert(ns); m_Namespace = ns; } + + bool ParseString(const std::string& document); + bool TestString(const char* document, ui32_t len = 0); + + // building + void SetName(const char* name); + void AppendBody(const std::string& value); void SetAttr(const char* name, const char* value); XMLElement* AddChild(const char* name); XMLElement* AddChildWithContent(const char* name, const char* value); XMLElement* AddChildWithContent(const char* name, const std::string& value); XMLElement* AddChildWithPrefixedContent(const char* name, const char* prefix, const char* value); void AddComment(const char* value); - void Render(std::string&); - void RenderElement(std::string& outbuf, ui32_t depth); + void Render(std::string&) const; + void RenderElement(std::string& outbuf, ui32_t depth) const; + + // querying + inline const std::string& GetBody() const { return m_Body; } + const char* GetAttrWithName(const char* name) const; + XMLElement* GetChildWithName(const char* name) const; + const ElementList& GetChildrenWithName(const char* name, ElementList& outList) const; + bool HasName(const char* name) const; + }; } // namespace Kumu diff --git a/src/MDD.cpp b/src/MDD.cpp index 9195df2..db43df0 100644 --- a/src/MDD.cpp +++ b/src/MDD.cpp @@ -798,10 +798,49 @@ static const ASDCP::MDDEntry s_MDD_Table[] = { { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x09, // 254 0x02, 0x09, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00 }, {0}, false, "CryptographicContext_CryptographicKeyID" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 255 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x00 }, + {0}, false, "DCTimedTextWrapping" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 256 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x01 }, + {0}, false, "DCTimedTextEssence" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 257 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x02 }, + {0}, false, "DCTimedTextDescriptor" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 258 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x03 }, + {0}, false, "DCTimedTextDescriptor_UTFEncoding" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 259 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x04 }, + {0}, false, "DCTimedTextDescriptor_RootNamespaceName" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 260 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x05 }, + {0}, false, "DCTimedTextResourceDescriptor" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 261 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x06 }, + {0}, false, "DCTimedTextResourceDescriptor_ResourcePackageID" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 262 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x07 }, + {0}, false, "DCTimedTextResourceDescriptor_ResourceMIMEType" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 263 + 0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x08 }, + {0}, false, "DCTimedTextResourceDescriptor_ResourceSID" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x04, // 264 + 0x06, 0x10, 0x10, 0x05, 0x01, 0x02, 0x11, 0x00 }, + {0}, false, "GenericStreamPartition" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 265 + 0x04, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }, + {0x02, 0x01}, false, "DMSegment_DataDefinition" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 266 + 0x07, 0x02, 0x02, 0x01, 0x01, 0x03, 0x00, 0x00 }, + {0x02, 0x02}, true, "DMSegment_Duration" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 267 + 0x01, 0x07, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00 }, + {0x61, 0x02}, false, "DMSegment_TrackIDList" }, { {0}, {0}, false, 0 } }; -const ui32_t s_MDD_Table_size = 255; +const ui32_t s_MDD_Table_size = 268; // // end MDD.cpp @@ -290,6 +290,19 @@ namespace ASDCP { MDD_CryptographicContext_CipherAlgorithm, // 252 MDD_CryptographicContext_MICAlgorithm, // 253 MDD_CryptographicContext_CryptographicKeyID, // 254 + MDD_DCTimedTextWrapping, // 255 + MDD_DCTimedTextEssence, // 256 + MDD_DCTimedTextDescriptor, // 257 + MDD_DCTimedTextDescriptor_UTFEncoding, // 258 + MDD_DCTimedTextDescriptor_RootNamespaceName, // 259 + MDD_DCTimedTextResourceDescriptor, // 260 + MDD_DCTimedTextResourceDescriptor_ResourcePackageID, // 261 + MDD_DCTimedTextResourceDescriptor_ResourceMIMEType, // 262 + MDD_DCTimedTextResourceDescriptor_ResourceSID, //263 + MDD_GenericStreamPartition, // 264 + MDD_DMSegment_DataDefinition, // 265 + MDD_DMSegment_Duration, // 266 + MDD_DMSegment_TrackIDList, // 267 }; // enum MDD_t } // namespaceASDCP diff --git a/src/MXF.cpp b/src/MXF.cpp index fb32e8a..fd0b709 100755 --- a/src/MXF.cpp +++ b/src/MXF.cpp @@ -30,6 +30,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "MXF.h" +#include "Metadata.h" #include <KM_log.h> using Kumu::DefaultLogSink; @@ -91,6 +92,23 @@ ASDCP::MXF::SeekToRIP(const Kumu::FileReader& Reader) // ASDCP::Result_t +ASDCP::MXF::RIP::GetPairBySID(ui32_t SID, Pair& outPair) const +{ + Array<Pair>::const_iterator pi = PairArray.begin(); + for ( ; pi != PairArray.end(); pi++ ) + { + if ( (*pi).BodySID == SID ) + { + outPair = *pi; + return RESULT_OK; + } + } + + return RESULT_FAIL; +} + +// +ASDCP::Result_t ASDCP::MXF::RIP::InitFromFile(const Kumu::FileReader& Reader) { Result_t result = KLVFilePacket::InitFromFile(Reader, Dict::ul(MDD_RandomIndexMetadata)); @@ -177,6 +195,23 @@ public: } // + Result_t GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object) + { + ASDCP_TEST_NULL(Object); + + std::map<UUID, InterchangeObject*>::iterator mi = m_Map.find(ObjectID); + + if ( mi == m_Map.end() ) + { + *Object = 0; + return RESULT_FAIL; + } + + *Object = (*mi).second; + return RESULT_OK; + } + + // Result_t GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object) { ASDCP_TEST_NULL(ObjectID); @@ -195,6 +230,21 @@ public: return RESULT_FAIL; } + + // + Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList) + { + ASDCP_TEST_NULL(ObjectID); + std::list<InterchangeObject*>::iterator li; + + for ( li = m_List.begin(); li != m_List.end(); li++ ) + { + if ( (*li)->HasUL(ObjectID) ) + ObjectList.push_back(*li); + } + + return ObjectList.empty() ? RESULT_FAIL : RESULT_OK; + } }; //------------------------------------------------------------------------------------------ @@ -503,7 +553,7 @@ ASDCP::MXF::Primer::Dump(FILE* stream) KLVPacket::Dump(stream, false); fprintf(stream, "Primer: %u %s\n", - LocalTagEntryBatch.size(), + (ui32_t)LocalTagEntryBatch.size(), ( LocalTagEntryBatch.size() == 1 ? "entry" : "entries" )); Batch<LocalTagEntry>::iterator i = LocalTagEntryBatch.begin(); @@ -619,15 +669,15 @@ ASDCP::MXF::OPAtomHeader::InitFromFile(const Kumu::FileReader& Reader) DefaultLogSink().Error("RIP contains no Pairs.\n"); result = RESULT_FORMAT; } - else if ( test_s < 2 || test_s > 3 ) - { - // OP-Atom states that there will be either two or three partitions, - // one closed header and one closed footer with an optional body - DefaultLogSink().Error("RIP count is not 2 or 3: %u\n", test_s); - return RESULT_FORMAT; - } else { + if ( test_s < 2 || test_s > 3 ) + { + // OP-Atom states that there will be either two or three partitions: + // one closed header and one closed footer with an optional body + DefaultLogSink().Warn("RIP count is not 2 or 3: %u\n", test_s); + } + m_HasRIP = true; if ( m_RIP.PairArray.front().ByteOffset != 0 ) @@ -730,6 +780,12 @@ ASDCP::MXF::OPAtomHeader::InitFromFile(const Kumu::FileReader& Reader) return result; } +ASDCP::Result_t +ASDCP::MXF::OPAtomHeader::GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object) +{ + return m_PacketList->GetMDObjectByID(ObjectID, Object); +} + // ASDCP::Result_t ASDCP::MXF::OPAtomHeader::GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object) @@ -743,6 +799,13 @@ ASDCP::MXF::OPAtomHeader::GetMDObjectByType(const byte_t* ObjectID, InterchangeO } // +ASDCP::Result_t +ASDCP::MXF::OPAtomHeader::GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList) +{ + return m_PacketList->GetMDObjectsByType(ObjectID, ObjectList); +} + +// ASDCP::MXF::Identification* ASDCP::MXF::OPAtomHeader::GetIdentification() { @@ -994,8 +1057,8 @@ ASDCP::MXF::OPAtomIndexFooter::WriteToFile(Kumu::FileWriter& Writer, ui64_t dura if ( ASDCP_SUCCESS(result) ) { - ui32_t write_count; - Writer.Write(FooterBuffer.RoData(), FooterBuffer.Size(), &write_count); + ui32_t write_count = 0; + result = Writer.Write(FooterBuffer.RoData(), FooterBuffer.Size(), &write_count); assert(write_count == FooterBuffer.Size()); } @@ -1206,6 +1269,84 @@ ASDCP::MXF::InterchangeObject::IsA(const byte_t* label) } +//------------------------------------------------------------------------------------------ + + +typedef std::map<ASDCP::UL, ASDCP::MXF::MXFObjectFactory_t>FactoryMap_t; +typedef FactoryMap_t::iterator FLi_t; + +// +class FactoryList : public FactoryMap_t +{ + Kumu::Mutex m_Lock; + +public: + FactoryList() {} + ~FactoryList() {} + + bool Empty() { + Kumu::AutoMutex BlockLock(m_Lock); + return empty(); + } + + FLi_t Find(const byte_t* label) { + Kumu::AutoMutex BlockLock(m_Lock); + return find(label); + } + + FLi_t End() { + Kumu::AutoMutex BlockLock(m_Lock); + return end(); + } + + void Insert(ASDCP::UL label, ASDCP::MXF::MXFObjectFactory_t factory) { + Kumu::AutoMutex BlockLock(m_Lock); + insert(FactoryList::value_type(label, factory)); + } +}; + +// +static FactoryList s_FactoryList; +static Kumu::Mutex s_InitLock; +static bool s_TypesInit = false; + + +// +void +ASDCP::MXF::SetObjectFactory(ASDCP::UL label, ASDCP::MXF::MXFObjectFactory_t factory) +{ + s_FactoryList.Insert(label, factory); +} + + +// +ASDCP::MXF::InterchangeObject* +ASDCP::MXF::CreateObject(const byte_t* label) +{ + if ( label == 0 ) + return 0; + + if ( ! s_TypesInit ) + { + Kumu::AutoMutex BlockLock(s_InitLock); + + if ( ! s_TypesInit ) + { + MXF::Metadata_InitTypes(); + s_TypesInit = true; + } + } + + FLi_t i = s_FactoryList.find(label); + + if ( i == s_FactoryList.end() ) + return new InterchangeObject; + + return i->second(); +} + + + // // end MXF.cpp // @@ -40,6 +40,16 @@ namespace ASDCP { class InterchangeObject; + // + typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(); + + // + void SetObjectFactory(UL label, MXFObjectFactory_t factory); + + // + InterchangeObject* CreateObject(const byte_t* label); + + // seek an open file handle to the start of the RIP KLV packet Result_t SeekToRIP(const Kumu::FileReader&); @@ -89,6 +99,7 @@ namespace ASDCP virtual ~RIP() {} virtual Result_t InitFromFile(const Kumu::FileReader& Reader); virtual Result_t WriteToFile(Kumu::FileWriter& Writer); + virtual Result_t GetPairBySID(ui32_t, Pair&) const; virtual void Dump(FILE* = 0); }; @@ -201,9 +212,6 @@ namespace ASDCP }; // - InterchangeObject* CreateObject(const byte_t* label); - - // class Preface : public InterchangeObject { ASDCP_NO_COPY_CONSTRUCT(Preface); @@ -314,7 +322,9 @@ namespace ASDCP virtual Result_t InitFromFile(const Kumu::FileReader& Reader); virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384); virtual void Dump(FILE* = 0); + virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0); virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0); + virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList); Identification* GetIdentification(); SourcePackage* GetSourcePackage(); }; diff --git a/src/MXFTypes.cpp b/src/MXFTypes.cpp index 625a2e2..3ef2294 100755 --- a/src/MXFTypes.cpp +++ b/src/MXFTypes.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2006, John Hurst +Copyright (c) 2005-2007, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <KM_prng.h> #include "MXFTypes.h" #include <KM_log.h> + using Kumu::DefaultLogSink; //------------------------------------------------------------------------------------------ @@ -144,43 +145,62 @@ ASDCP::UMID::EncodeString(char* str_buf, ui32_t buf_len) const //------------------------------------------------------------------------------------------ // +// const ASDCP::MXF::UTF16String& ASDCP::MXF::UTF16String::operator=(const char* sz) { if ( sz == 0 || *sz == 0 ) - { - m_length = 0; - *m_buffer = 0; - } + clear(); + else - { - ui32_t len = Kumu::xmin((ui32_t)strlen(sz), (IdentBufferLen - 1)); - m_length = len; - memcpy(m_buffer, sz, m_length); - m_buffer[m_length] = 0; - } + this->assign(sz); return *this; } +// +const ASDCP::MXF::UTF16String& +ASDCP::MXF::UTF16String::operator=(const std::string& str) +{ + this->assign(str); + return *this; +} + +// +const char* +ASDCP::MXF::UTF16String::EncodeString(char* str_buf, ui32_t buf_len) const +{ + ui32_t write_len = Kumu::xmin(buf_len - 1, (ui32_t)size()); + strncpy(str_buf, c_str(), write_len); + str_buf[write_len] = 0; + return str_buf; +} // bool ASDCP::MXF::UTF16String::Unarchive(Kumu::MemIOReader* Reader) { - const byte_t* p = Reader->CurrentData(); - m_length = Reader->Remainder(); - assert(m_length % 2 == 0); - m_length /= 2; - assert(IdentBufferLen >= m_length); - ui32_t i = 0; + clear(); + const ui16_t* p = (ui16_t*)Reader->CurrentData(); + ui32_t length = Reader->Remainder() / 2; + char mb_buf[MB_LEN_MAX+1]; - for ( i = 0; i < m_length; i++ ) - m_buffer[i] = p[(i*2)+1]; + for ( ui32_t i = 0; i < length; i++ ) + { + int count = wctomb(mb_buf, KM_i16_BE(p[i])); - m_buffer[i] = 0; + if ( count == -1 ) + { + DefaultLogSink().Error("Unable to decode wide character 0x%04hx\n", p[i]); + return false; + } - Reader->SkipOffset(m_length*2); + assert(count <= MB_LEN_MAX); + mb_buf[count] = 0; + this->append(mb_buf); + } + + Reader->SkipOffset(length*2); return true; } @@ -188,14 +208,42 @@ ASDCP::MXF::UTF16String::Unarchive(Kumu::MemIOReader* Reader) bool ASDCP::MXF::UTF16String::Archive(Kumu::MemIOWriter* Writer) const { - byte_t* p = Writer->Data() + Writer->Length(); + if ( size() > IdentBufferLen ) + { + DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen); + return false; + } + + const char* mbp = c_str(); + wchar_t wcp; + ui32_t remainder = size(); + ui32_t length = size(); ui32_t i = 0; - memset(p, 0, (m_length*2)+2); - for ( i = 0; i < m_length; i++ ) - p[(i*2)+1] = m_buffer[i]; + while ( i < length ) + { + int count = mbtowc(&wcp, mbp+i, remainder); + + if ( count == -1 ) + { + DefaultLogSink().Error("Error decoding multi-byte sequence starting at offset %u\n", i); + return false; + } + else if ( count == 0 ) + break; + + bool result = Writer->WriteUi16BE((ui16_t)wcp); + + if ( result == false ) + { + DefaultLogSink().Error("No more space in memory IO writer\n"); + return false; + } + + i += count; + remainder -= count; + } - Writer->AddOffset(m_length * 2); return true; } diff --git a/src/MXFTypes.h b/src/MXFTypes.h index c5541be..c6617aa 100755 --- a/src/MXFTypes.h +++ b/src/MXFTypes.h @@ -265,27 +265,18 @@ namespace ASDCP }; // - class UTF16String : public Kumu::IArchive + class UTF16String : public std::string, public Kumu::IArchive { - ui16_t m_length; - char m_buffer[IdentBufferLen]; - ASDCP_NO_COPY_CONSTRUCT(UTF16String); - public: - UTF16String() : m_length(0) { *m_buffer = 0; } + UTF16String() {} ~UTF16String() {} const UTF16String& operator=(const char*); + const UTF16String& operator=(const std::string&); - // - const char* EncodeString(char* str_buf, ui32_t buf_len) const { - strncpy(str_buf, m_buffer, Kumu::xmin(buf_len, ((ui32_t)m_length+1))); - str_buf[buf_len-1] = 0; - return str_buf; - } - + const char* EncodeString(char* str_buf, ui32_t buf_len) const; virtual bool Unarchive(Kumu::MemIOReader* Reader); - inline virtual bool HasValue() const { return m_length > 0; } + inline virtual bool HasValue() const { return ! empty(); } virtual bool Archive(Kumu::MemIOWriter* Writer) const; }; diff --git a/src/Metadata.cpp b/src/Metadata.cpp index 3290b1b..9509926 100755 --- a/src/Metadata.cpp +++ b/src/Metadata.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2006, John Hurst +Copyright (c) 2005-2007, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -33,138 +33,72 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <KM_mutex.h> #include "Metadata.h" +using namespace ASDCP; +using namespace ASDCP::MXF; + const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH; //------------------------------------------------------------------------------------------ -// -enum FLT_t - { - FLT_Preface, - FLT_IndexTableSegment, - FLT_Identification, - FLT_ContentStorage, - FLT_EssenceContainerData, - FLT_MaterialPackage, - FLT_SourcePackage, - FLT_StaticTrack, - FLT_Track, - FLT_Sequence, - FLT_SourceClip, - FLT_TimecodeComponent, - FLT_FileDescriptor, - FLT_GenericSoundEssenceDescriptor, - FLT_WaveAudioDescriptor, - FLT_GenericPictureEssenceDescriptor, - FLT_RGBAEssenceDescriptor, - FLT_JPEG2000PictureSubDescriptor, - FLT_CDCIEssenceDescriptor, - FLT_MPEG2VideoDescriptor, - FLT_DMSegment, - FLT_CryptographicFramework, - FLT_CryptographicContext, - }; - -// -typedef std::map<ASDCP::UL, FLT_t>::iterator FLi_t; - -class FactoryList : public std::map<ASDCP::UL, FLT_t> -{ - Kumu::Mutex m_Lock; - -public: - FactoryList() {} - ~FactoryList() {} - - bool Empty() { - Kumu::AutoMutex BlockLock(m_Lock); - return empty(); - } - - FLi_t Find(const byte_t* label) { - Kumu::AutoMutex BlockLock(m_Lock); - return find(label); - } - - FLi_t End() { - Kumu::AutoMutex BlockLock(m_Lock); - return end(); - } - -}; - -// -static FactoryList s_FactoryList; - -// -ASDCP::MXF::InterchangeObject* -ASDCP::MXF::CreateObject(const byte_t* label) -{ - if ( label == 0 ) - return 0; - - if ( s_FactoryList.empty() ) - { - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_Preface), FLT_Preface)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_IndexTableSegment), FLT_IndexTableSegment)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_Identification), FLT_Identification)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_ContentStorage), FLT_ContentStorage)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_EssenceContainerData), FLT_EssenceContainerData)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_MaterialPackage), FLT_MaterialPackage)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_SourcePackage), FLT_SourcePackage)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_StaticTrack), FLT_StaticTrack)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_Track), FLT_Track)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_Sequence), FLT_Sequence)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_SourceClip), FLT_SourceClip)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_TimecodeComponent), FLT_TimecodeComponent)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_FileDescriptor), FLT_FileDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_GenericSoundEssenceDescriptor), FLT_GenericSoundEssenceDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_WaveAudioDescriptor), FLT_WaveAudioDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_GenericPictureEssenceDescriptor), FLT_GenericPictureEssenceDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_RGBAEssenceDescriptor), FLT_RGBAEssenceDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_JPEG2000PictureSubDescriptor), FLT_JPEG2000PictureSubDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_CDCIEssenceDescriptor), FLT_CDCIEssenceDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_MPEG2VideoDescriptor), FLT_MPEG2VideoDescriptor)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_DMSegment), FLT_DMSegment)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_CryptographicFramework), FLT_CryptographicFramework)); - s_FactoryList.insert(FactoryList::value_type(Dict::ul(MDD_CryptographicContext), FLT_CryptographicContext)); - } - - FLi_t i = s_FactoryList.find(label); - - if ( i == s_FactoryList.end() ) - return new InterchangeObject; - - switch ( i->second ) - { - case FLT_Preface: return new Preface; - case FLT_IndexTableSegment: return new IndexTableSegment; - case FLT_Identification: return new Identification; - case FLT_ContentStorage: return new ContentStorage; - case FLT_EssenceContainerData: return new EssenceContainerData; - case FLT_MaterialPackage: return new MaterialPackage; - case FLT_SourcePackage: return new SourcePackage; - case FLT_StaticTrack: return new StaticTrack; - case FLT_Track: return new Track; - case FLT_Sequence: return new Sequence; - case FLT_SourceClip: return new SourceClip; - case FLT_TimecodeComponent: return new TimecodeComponent; - case FLT_FileDescriptor: return new FileDescriptor; - case FLT_GenericSoundEssenceDescriptor: return new GenericSoundEssenceDescriptor; - case FLT_WaveAudioDescriptor: return new WaveAudioDescriptor; - case FLT_GenericPictureEssenceDescriptor: return new GenericPictureEssenceDescriptor; - case FLT_RGBAEssenceDescriptor: return new RGBAEssenceDescriptor; - case FLT_JPEG2000PictureSubDescriptor: return new JPEG2000PictureSubDescriptor; - case FLT_CDCIEssenceDescriptor: return new CDCIEssenceDescriptor; - case FLT_MPEG2VideoDescriptor: return new MPEG2VideoDescriptor; - case FLT_DMSegment: return new DMSegment; - case FLT_CryptographicFramework: return new CryptographicFramework; - case FLT_CryptographicContext: return new CryptographicContext; - } - - return 0; -} +static InterchangeObject* Preface_Factory() { return new Preface; } +static InterchangeObject* IndexTableSegment_Factory() { return new IndexTableSegment; } + +static InterchangeObject* Identification_Factory() { return new Identification; } +static InterchangeObject* ContentStorage_Factory() { return new ContentStorage; } +static InterchangeObject* EssenceContainerData_Factory() { return new EssenceContainerData; } +static InterchangeObject* MaterialPackage_Factory() { return new MaterialPackage; } +static InterchangeObject* SourcePackage_Factory() { return new SourcePackage; } +static InterchangeObject* StaticTrack_Factory() { return new StaticTrack; } +static InterchangeObject* Track_Factory() { return new Track; } +static InterchangeObject* Sequence_Factory() { return new Sequence; } +static InterchangeObject* SourceClip_Factory() { return new SourceClip; } +static InterchangeObject* TimecodeComponent_Factory() { return new TimecodeComponent; } +static InterchangeObject* FileDescriptor_Factory() { return new FileDescriptor; } +static InterchangeObject* GenericSoundEssenceDescriptor_Factory() { return new GenericSoundEssenceDescriptor; } +static InterchangeObject* WaveAudioDescriptor_Factory() { return new WaveAudioDescriptor; } +static InterchangeObject* GenericPictureEssenceDescriptor_Factory() { return new GenericPictureEssenceDescriptor; } +static InterchangeObject* RGBAEssenceDescriptor_Factory() { return new RGBAEssenceDescriptor; } +static InterchangeObject* JPEG2000PictureSubDescriptor_Factory() { return new JPEG2000PictureSubDescriptor; } +static InterchangeObject* CDCIEssenceDescriptor_Factory() { return new CDCIEssenceDescriptor; } +static InterchangeObject* MPEG2VideoDescriptor_Factory() { return new MPEG2VideoDescriptor; } +static InterchangeObject* DMSegment_Factory() { return new DMSegment; } +static InterchangeObject* CryptographicFramework_Factory() { return new CryptographicFramework; } +static InterchangeObject* CryptographicContext_Factory() { return new CryptographicContext; } +static InterchangeObject* GenericDataEssenceDescriptor_Factory() { return new GenericDataEssenceDescriptor; } +static InterchangeObject* DCTimedTextDescriptor_Factory() { return new DCTimedTextDescriptor; } +static InterchangeObject* DCTimedTextResourceDescriptor_Factory() { return new DCTimedTextResourceDescriptor; } +void +ASDCP::MXF::Metadata_InitTypes() +{ + SetObjectFactory(Dict::ul(MDD_Preface), Preface_Factory); + SetObjectFactory(Dict::ul(MDD_IndexTableSegment), IndexTableSegment_Factory); + + SetObjectFactory(Dict::ul(MDD_Identification), Identification_Factory); + SetObjectFactory(Dict::ul(MDD_ContentStorage), ContentStorage_Factory); + SetObjectFactory(Dict::ul(MDD_EssenceContainerData), EssenceContainerData_Factory); + SetObjectFactory(Dict::ul(MDD_MaterialPackage), MaterialPackage_Factory); + SetObjectFactory(Dict::ul(MDD_SourcePackage), SourcePackage_Factory); + SetObjectFactory(Dict::ul(MDD_StaticTrack), StaticTrack_Factory); + SetObjectFactory(Dict::ul(MDD_Track), Track_Factory); + SetObjectFactory(Dict::ul(MDD_Sequence), Sequence_Factory); + SetObjectFactory(Dict::ul(MDD_SourceClip), SourceClip_Factory); + SetObjectFactory(Dict::ul(MDD_TimecodeComponent), TimecodeComponent_Factory); + SetObjectFactory(Dict::ul(MDD_FileDescriptor), FileDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_GenericSoundEssenceDescriptor), GenericSoundEssenceDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_WaveAudioDescriptor), WaveAudioDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_GenericPictureEssenceDescriptor), GenericPictureEssenceDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_RGBAEssenceDescriptor), RGBAEssenceDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_JPEG2000PictureSubDescriptor), JPEG2000PictureSubDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_CDCIEssenceDescriptor), CDCIEssenceDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_MPEG2VideoDescriptor), MPEG2VideoDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_DMSegment), DMSegment_Factory); + SetObjectFactory(Dict::ul(MDD_CryptographicFramework), CryptographicFramework_Factory); + SetObjectFactory(Dict::ul(MDD_CryptographicContext), CryptographicContext_Factory); + SetObjectFactory(Dict::ul(MDD_GenericDataEssenceDescriptor), GenericDataEssenceDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_DCTimedTextDescriptor), DCTimedTextDescriptor_Factory); + SetObjectFactory(Dict::ul(MDD_DCTimedTextResourceDescriptor), DCTimedTextResourceDescriptor_Factory); +} //------------------------------------------------------------------------------------------ // KLV Sets @@ -176,7 +110,7 @@ ASDCP::MXF::CreateObject(const byte_t* label) // ASDCP::Result_t -ASDCP::MXF::Identification::InitFromTLVSet(TLVReader& TLVSet) +Identification::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Identification, ThisGenerationUID)); @@ -193,7 +127,7 @@ ASDCP::MXF::Identification::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::Identification::WriteToTLVSet(TLVWriter& TLVSet) +Identification::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Identification, ThisGenerationUID)); @@ -210,7 +144,7 @@ ASDCP::MXF::Identification::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::Identification::Dump(FILE* stream) +Identification::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -232,7 +166,7 @@ ASDCP::MXF::Identification::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::Identification::InitFromBuffer(const byte_t* p, ui32_t l) +Identification::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_Identification); return InterchangeObject::InitFromBuffer(p, l); @@ -240,7 +174,7 @@ ASDCP::MXF::Identification::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::Identification::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +Identification::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_Identification); return InterchangeObject::WriteToBuffer(Buffer); @@ -251,7 +185,7 @@ ASDCP::MXF::Identification::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::ContentStorage::InitFromTLVSet(TLVReader& TLVSet) +ContentStorage::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(ContentStorage, Packages)); @@ -261,7 +195,7 @@ ASDCP::MXF::ContentStorage::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::ContentStorage::WriteToTLVSet(TLVWriter& TLVSet) +ContentStorage::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(ContentStorage, Packages)); @@ -271,7 +205,7 @@ ASDCP::MXF::ContentStorage::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::ContentStorage::Dump(FILE* stream) +ContentStorage::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -288,7 +222,7 @@ ASDCP::MXF::ContentStorage::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::ContentStorage::InitFromBuffer(const byte_t* p, ui32_t l) +ContentStorage::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_ContentStorage); return InterchangeObject::InitFromBuffer(p, l); @@ -296,7 +230,7 @@ ASDCP::MXF::ContentStorage::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::ContentStorage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +ContentStorage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_ContentStorage); return InterchangeObject::WriteToBuffer(Buffer); @@ -307,7 +241,7 @@ ASDCP::MXF::ContentStorage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::EssenceContainerData::InitFromTLVSet(TLVReader& TLVSet) +EssenceContainerData::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(EssenceContainerData, LinkedPackageUID)); @@ -318,7 +252,7 @@ ASDCP::MXF::EssenceContainerData::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::EssenceContainerData::WriteToTLVSet(TLVWriter& TLVSet) +EssenceContainerData::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(EssenceContainerData, LinkedPackageUID)); @@ -329,7 +263,7 @@ ASDCP::MXF::EssenceContainerData::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::EssenceContainerData::Dump(FILE* stream) +EssenceContainerData::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -345,7 +279,7 @@ ASDCP::MXF::EssenceContainerData::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::EssenceContainerData::InitFromBuffer(const byte_t* p, ui32_t l) +EssenceContainerData::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_EssenceContainerData); return InterchangeObject::InitFromBuffer(p, l); @@ -353,7 +287,7 @@ ASDCP::MXF::EssenceContainerData::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::EssenceContainerData::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +EssenceContainerData::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_EssenceContainerData); return InterchangeObject::WriteToBuffer(Buffer); @@ -364,7 +298,7 @@ ASDCP::MXF::EssenceContainerData::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::GenericPackage::InitFromTLVSet(TLVReader& TLVSet) +GenericPackage::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(GenericPackage, PackageUID)); @@ -377,7 +311,7 @@ ASDCP::MXF::GenericPackage::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::GenericPackage::WriteToTLVSet(TLVWriter& TLVSet) +GenericPackage::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(GenericPackage, PackageUID)); @@ -390,7 +324,7 @@ ASDCP::MXF::GenericPackage::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::GenericPackage::Dump(FILE* stream) +GenericPackage::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -413,7 +347,7 @@ ASDCP::MXF::GenericPackage::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::MaterialPackage::InitFromTLVSet(TLVReader& TLVSet) +MaterialPackage::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericPackage::InitFromTLVSet(TLVSet); return result; @@ -421,7 +355,7 @@ ASDCP::MXF::MaterialPackage::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::MaterialPackage::WriteToTLVSet(TLVWriter& TLVSet) +MaterialPackage::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericPackage::WriteToTLVSet(TLVSet); return result; @@ -429,7 +363,7 @@ ASDCP::MXF::MaterialPackage::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::MaterialPackage::Dump(FILE* stream) +MaterialPackage::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -442,7 +376,7 @@ ASDCP::MXF::MaterialPackage::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::MaterialPackage::InitFromBuffer(const byte_t* p, ui32_t l) +MaterialPackage::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_MaterialPackage); return InterchangeObject::InitFromBuffer(p, l); @@ -450,7 +384,7 @@ ASDCP::MXF::MaterialPackage::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::MaterialPackage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +MaterialPackage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_MaterialPackage); return InterchangeObject::WriteToBuffer(Buffer); @@ -461,7 +395,7 @@ ASDCP::MXF::MaterialPackage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::SourcePackage::InitFromTLVSet(TLVReader& TLVSet) +SourcePackage::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericPackage::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(SourcePackage, Descriptor)); @@ -470,7 +404,7 @@ ASDCP::MXF::SourcePackage::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::SourcePackage::WriteToTLVSet(TLVWriter& TLVSet) +SourcePackage::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericPackage::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(SourcePackage, Descriptor)); @@ -479,7 +413,7 @@ ASDCP::MXF::SourcePackage::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::SourcePackage::Dump(FILE* stream) +SourcePackage::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -493,7 +427,7 @@ ASDCP::MXF::SourcePackage::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::SourcePackage::InitFromBuffer(const byte_t* p, ui32_t l) +SourcePackage::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_SourcePackage); return InterchangeObject::InitFromBuffer(p, l); @@ -501,7 +435,7 @@ ASDCP::MXF::SourcePackage::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::SourcePackage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +SourcePackage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_SourcePackage); return InterchangeObject::WriteToBuffer(Buffer); @@ -512,7 +446,7 @@ ASDCP::MXF::SourcePackage::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::GenericTrack::InitFromTLVSet(TLVReader& TLVSet) +GenericTrack::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(GenericTrack, TrackID)); @@ -524,7 +458,7 @@ ASDCP::MXF::GenericTrack::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::GenericTrack::WriteToTLVSet(TLVWriter& TLVSet) +GenericTrack::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(GenericTrack, TrackID)); @@ -536,7 +470,7 @@ ASDCP::MXF::GenericTrack::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::GenericTrack::Dump(FILE* stream) +GenericTrack::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -557,7 +491,7 @@ ASDCP::MXF::GenericTrack::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::StaticTrack::InitFromTLVSet(TLVReader& TLVSet) +StaticTrack::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericTrack::InitFromTLVSet(TLVSet); return result; @@ -565,7 +499,7 @@ ASDCP::MXF::StaticTrack::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::StaticTrack::WriteToTLVSet(TLVWriter& TLVSet) +StaticTrack::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericTrack::WriteToTLVSet(TLVSet); return result; @@ -573,7 +507,7 @@ ASDCP::MXF::StaticTrack::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::StaticTrack::Dump(FILE* stream) +StaticTrack::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -586,7 +520,7 @@ ASDCP::MXF::StaticTrack::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::StaticTrack::InitFromBuffer(const byte_t* p, ui32_t l) +StaticTrack::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_StaticTrack); return InterchangeObject::InitFromBuffer(p, l); @@ -594,7 +528,7 @@ ASDCP::MXF::StaticTrack::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::StaticTrack::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +StaticTrack::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_StaticTrack); return InterchangeObject::WriteToBuffer(Buffer); @@ -605,7 +539,7 @@ ASDCP::MXF::StaticTrack::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::Track::InitFromTLVSet(TLVReader& TLVSet) +Track::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericTrack::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Track, EditRate)); @@ -615,7 +549,7 @@ ASDCP::MXF::Track::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::Track::WriteToTLVSet(TLVWriter& TLVSet) +Track::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericTrack::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Track, EditRate)); @@ -625,7 +559,7 @@ ASDCP::MXF::Track::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::Track::Dump(FILE* stream) +Track::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -640,7 +574,7 @@ ASDCP::MXF::Track::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::Track::InitFromBuffer(const byte_t* p, ui32_t l) +Track::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_Track); return InterchangeObject::InitFromBuffer(p, l); @@ -648,7 +582,7 @@ ASDCP::MXF::Track::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::Track::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +Track::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_Track); return InterchangeObject::WriteToBuffer(Buffer); @@ -659,7 +593,7 @@ ASDCP::MXF::Track::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::StructuralComponent::InitFromTLVSet(TLVReader& TLVSet) +StructuralComponent::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(StructuralComponent, DataDefinition)); @@ -669,7 +603,7 @@ ASDCP::MXF::StructuralComponent::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::StructuralComponent::WriteToTLVSet(TLVWriter& TLVSet) +StructuralComponent::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(StructuralComponent, DataDefinition)); @@ -679,7 +613,7 @@ ASDCP::MXF::StructuralComponent::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::StructuralComponent::Dump(FILE* stream) +StructuralComponent::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -698,7 +632,7 @@ ASDCP::MXF::StructuralComponent::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::Sequence::InitFromTLVSet(TLVReader& TLVSet) +Sequence::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = StructuralComponent::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Sequence, StructuralComponents)); @@ -707,7 +641,7 @@ ASDCP::MXF::Sequence::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::Sequence::WriteToTLVSet(TLVWriter& TLVSet) +Sequence::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = StructuralComponent::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Sequence, StructuralComponents)); @@ -716,7 +650,7 @@ ASDCP::MXF::Sequence::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::Sequence::Dump(FILE* stream) +Sequence::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -731,7 +665,7 @@ ASDCP::MXF::Sequence::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::Sequence::InitFromBuffer(const byte_t* p, ui32_t l) +Sequence::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_Sequence); return InterchangeObject::InitFromBuffer(p, l); @@ -739,7 +673,7 @@ ASDCP::MXF::Sequence::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::Sequence::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +Sequence::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_Sequence); return InterchangeObject::WriteToBuffer(Buffer); @@ -750,7 +684,7 @@ ASDCP::MXF::Sequence::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::SourceClip::InitFromTLVSet(TLVReader& TLVSet) +SourceClip::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = StructuralComponent::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi64(OBJ_READ_ARGS(SourceClip, StartPosition)); @@ -761,7 +695,7 @@ ASDCP::MXF::SourceClip::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::SourceClip::WriteToTLVSet(TLVWriter& TLVSet) +SourceClip::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = StructuralComponent::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi64(OBJ_WRITE_ARGS(SourceClip, StartPosition)); @@ -772,7 +706,7 @@ ASDCP::MXF::SourceClip::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::SourceClip::Dump(FILE* stream) +SourceClip::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -788,7 +722,7 @@ ASDCP::MXF::SourceClip::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::SourceClip::InitFromBuffer(const byte_t* p, ui32_t l) +SourceClip::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_SourceClip); return InterchangeObject::InitFromBuffer(p, l); @@ -796,7 +730,7 @@ ASDCP::MXF::SourceClip::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::SourceClip::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +SourceClip::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_SourceClip); return InterchangeObject::WriteToBuffer(Buffer); @@ -807,7 +741,7 @@ ASDCP::MXF::SourceClip::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::TimecodeComponent::InitFromTLVSet(TLVReader& TLVSet) +TimecodeComponent::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = StructuralComponent::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi16(OBJ_READ_ARGS(TimecodeComponent, RoundedTimecodeBase)); @@ -818,7 +752,7 @@ ASDCP::MXF::TimecodeComponent::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::TimecodeComponent::WriteToTLVSet(TLVWriter& TLVSet) +TimecodeComponent::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = StructuralComponent::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi16(OBJ_WRITE_ARGS(TimecodeComponent, RoundedTimecodeBase)); @@ -829,7 +763,7 @@ ASDCP::MXF::TimecodeComponent::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::TimecodeComponent::Dump(FILE* stream) +TimecodeComponent::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -845,7 +779,7 @@ ASDCP::MXF::TimecodeComponent::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::TimecodeComponent::InitFromBuffer(const byte_t* p, ui32_t l) +TimecodeComponent::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_TimecodeComponent); return InterchangeObject::InitFromBuffer(p, l); @@ -853,7 +787,7 @@ ASDCP::MXF::TimecodeComponent::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::TimecodeComponent::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +TimecodeComponent::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_TimecodeComponent); return InterchangeObject::WriteToBuffer(Buffer); @@ -864,7 +798,7 @@ ASDCP::MXF::TimecodeComponent::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::GenericDescriptor::InitFromTLVSet(TLVReader& TLVSet) +GenericDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(GenericDescriptor, Locators)); @@ -874,7 +808,7 @@ ASDCP::MXF::GenericDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::GenericDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +GenericDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(GenericDescriptor, Locators)); @@ -884,7 +818,7 @@ ASDCP::MXF::GenericDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::GenericDescriptor::Dump(FILE* stream) +GenericDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -905,7 +839,7 @@ ASDCP::MXF::GenericDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::FileDescriptor::InitFromTLVSet(TLVReader& TLVSet) +FileDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericDescriptor::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(FileDescriptor, LinkedTrackID)); @@ -918,7 +852,7 @@ ASDCP::MXF::FileDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::FileDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +FileDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericDescriptor::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(FileDescriptor, LinkedTrackID)); @@ -931,7 +865,7 @@ ASDCP::MXF::FileDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::FileDescriptor::Dump(FILE* stream) +FileDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -949,7 +883,7 @@ ASDCP::MXF::FileDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::FileDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +FileDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_FileDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -957,7 +891,7 @@ ASDCP::MXF::FileDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::FileDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +FileDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_FileDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -968,7 +902,7 @@ ASDCP::MXF::FileDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::GenericSoundEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) +GenericSoundEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = FileDescriptor::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(GenericSoundEssenceDescriptor, AudioSamplingRate)); @@ -982,7 +916,7 @@ ASDCP::MXF::GenericSoundEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::GenericSoundEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +GenericSoundEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = FileDescriptor::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(GenericSoundEssenceDescriptor, AudioSamplingRate)); @@ -996,7 +930,7 @@ ASDCP::MXF::GenericSoundEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::GenericSoundEssenceDescriptor::Dump(FILE* stream) +GenericSoundEssenceDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1015,7 +949,7 @@ ASDCP::MXF::GenericSoundEssenceDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::GenericSoundEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +GenericSoundEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_GenericSoundEssenceDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -1023,7 +957,7 @@ ASDCP::MXF::GenericSoundEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_ // ASDCP::Result_t -ASDCP::MXF::GenericSoundEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +GenericSoundEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_GenericSoundEssenceDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -1034,7 +968,7 @@ ASDCP::MXF::GenericSoundEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buf // ASDCP::Result_t -ASDCP::MXF::WaveAudioDescriptor::InitFromTLVSet(TLVReader& TLVSet) +WaveAudioDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericSoundEssenceDescriptor::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi16(OBJ_READ_ARGS(WaveAudioDescriptor, BlockAlign)); @@ -1045,7 +979,7 @@ ASDCP::MXF::WaveAudioDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::WaveAudioDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +WaveAudioDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericSoundEssenceDescriptor::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi16(OBJ_WRITE_ARGS(WaveAudioDescriptor, BlockAlign)); @@ -1056,7 +990,7 @@ ASDCP::MXF::WaveAudioDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::WaveAudioDescriptor::Dump(FILE* stream) +WaveAudioDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1072,7 +1006,7 @@ ASDCP::MXF::WaveAudioDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::WaveAudioDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +WaveAudioDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_WaveAudioDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -1080,7 +1014,7 @@ ASDCP::MXF::WaveAudioDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::WaveAudioDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +WaveAudioDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_WaveAudioDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -1091,7 +1025,7 @@ ASDCP::MXF::WaveAudioDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::GenericPictureEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) +GenericPictureEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = FileDescriptor::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi8(OBJ_READ_ARGS(GenericPictureEssenceDescriptor, FrameLayout)); @@ -1103,7 +1037,7 @@ ASDCP::MXF::GenericPictureEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::GenericPictureEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +GenericPictureEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = FileDescriptor::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi8(OBJ_WRITE_ARGS(GenericPictureEssenceDescriptor, FrameLayout)); @@ -1115,7 +1049,7 @@ ASDCP::MXF::GenericPictureEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::GenericPictureEssenceDescriptor::Dump(FILE* stream) +GenericPictureEssenceDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1132,7 +1066,7 @@ ASDCP::MXF::GenericPictureEssenceDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::GenericPictureEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +GenericPictureEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_GenericPictureEssenceDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -1140,7 +1074,7 @@ ASDCP::MXF::GenericPictureEssenceDescriptor::InitFromBuffer(const byte_t* p, ui3 // ASDCP::Result_t -ASDCP::MXF::GenericPictureEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +GenericPictureEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_GenericPictureEssenceDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -1151,7 +1085,7 @@ ASDCP::MXF::GenericPictureEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& B // ASDCP::Result_t -ASDCP::MXF::RGBAEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) +RGBAEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericPictureEssenceDescriptor::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(RGBAEssenceDescriptor, ComponentMaxRef)); @@ -1161,7 +1095,7 @@ ASDCP::MXF::RGBAEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::RGBAEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +RGBAEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericPictureEssenceDescriptor::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(RGBAEssenceDescriptor, ComponentMaxRef)); @@ -1171,7 +1105,7 @@ ASDCP::MXF::RGBAEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::RGBAEssenceDescriptor::Dump(FILE* stream) +RGBAEssenceDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1186,7 +1120,7 @@ ASDCP::MXF::RGBAEssenceDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::RGBAEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +RGBAEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_RGBAEssenceDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -1194,7 +1128,7 @@ ASDCP::MXF::RGBAEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::RGBAEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +RGBAEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_RGBAEssenceDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -1205,7 +1139,7 @@ ASDCP::MXF::RGBAEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::JPEG2000PictureSubDescriptor::InitFromTLVSet(TLVReader& TLVSet) +JPEG2000PictureSubDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi16(OBJ_READ_ARGS(JPEG2000PictureSubDescriptor, Rsize)); @@ -1226,7 +1160,7 @@ ASDCP::MXF::JPEG2000PictureSubDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::JPEG2000PictureSubDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +JPEG2000PictureSubDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi16(OBJ_WRITE_ARGS(JPEG2000PictureSubDescriptor, Rsize)); @@ -1247,7 +1181,7 @@ ASDCP::MXF::JPEG2000PictureSubDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::JPEG2000PictureSubDescriptor::Dump(FILE* stream) +JPEG2000PictureSubDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1273,7 +1207,7 @@ ASDCP::MXF::JPEG2000PictureSubDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::JPEG2000PictureSubDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +JPEG2000PictureSubDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_JPEG2000PictureSubDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -1281,7 +1215,7 @@ ASDCP::MXF::JPEG2000PictureSubDescriptor::InitFromBuffer(const byte_t* p, ui32_t // ASDCP::Result_t -ASDCP::MXF::JPEG2000PictureSubDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +JPEG2000PictureSubDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_JPEG2000PictureSubDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -1292,7 +1226,7 @@ ASDCP::MXF::JPEG2000PictureSubDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buff // ASDCP::Result_t -ASDCP::MXF::CDCIEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) +CDCIEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = GenericPictureEssenceDescriptor::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(CDCIEssenceDescriptor, ComponentDepth)); @@ -1304,7 +1238,7 @@ ASDCP::MXF::CDCIEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::CDCIEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +CDCIEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = GenericPictureEssenceDescriptor::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(CDCIEssenceDescriptor, ComponentDepth)); @@ -1316,7 +1250,7 @@ ASDCP::MXF::CDCIEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::CDCIEssenceDescriptor::Dump(FILE* stream) +CDCIEssenceDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1333,7 +1267,7 @@ ASDCP::MXF::CDCIEssenceDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::CDCIEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +CDCIEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_CDCIEssenceDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -1341,7 +1275,7 @@ ASDCP::MXF::CDCIEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::CDCIEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +CDCIEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_CDCIEssenceDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -1352,7 +1286,7 @@ ASDCP::MXF::CDCIEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::MPEG2VideoDescriptor::InitFromTLVSet(TLVReader& TLVSet) +MPEG2VideoDescriptor::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = CDCIEssenceDescriptor::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi8(OBJ_READ_ARGS(MPEG2VideoDescriptor, CodedContentType)); @@ -1364,7 +1298,7 @@ ASDCP::MXF::MPEG2VideoDescriptor::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::MPEG2VideoDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +MPEG2VideoDescriptor::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = CDCIEssenceDescriptor::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi8(OBJ_WRITE_ARGS(MPEG2VideoDescriptor, CodedContentType)); @@ -1376,7 +1310,7 @@ ASDCP::MXF::MPEG2VideoDescriptor::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::MPEG2VideoDescriptor::Dump(FILE* stream) +MPEG2VideoDescriptor::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1393,7 +1327,7 @@ ASDCP::MXF::MPEG2VideoDescriptor::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::MPEG2VideoDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +MPEG2VideoDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_MPEG2VideoDescriptor); return InterchangeObject::InitFromBuffer(p, l); @@ -1401,7 +1335,7 @@ ASDCP::MXF::MPEG2VideoDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::MPEG2VideoDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +MPEG2VideoDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_MPEG2VideoDescriptor); return InterchangeObject::WriteToBuffer(Buffer); @@ -1412,10 +1346,12 @@ ASDCP::MXF::MPEG2VideoDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::DMSegment::InitFromTLVSet(TLVReader& TLVSet) +DMSegment::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DMSegment, DataDefinition)); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi64(OBJ_READ_ARGS(DMSegment, EventStartPosition)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi64(OBJ_READ_ARGS(DMSegment, Duration)); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DMSegment, EventComment)); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DMSegment, DMFramework)); return result; @@ -1423,10 +1359,12 @@ ASDCP::MXF::DMSegment::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::DMSegment::WriteToTLVSet(TLVWriter& TLVSet) +DMSegment::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DMSegment, DataDefinition)); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi64(OBJ_WRITE_ARGS(DMSegment, EventStartPosition)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi64(OBJ_WRITE_ARGS(DMSegment, Duration)); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DMSegment, EventComment)); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DMSegment, DMFramework)); return result; @@ -1434,7 +1372,7 @@ ASDCP::MXF::DMSegment::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::DMSegment::Dump(FILE* stream) +DMSegment::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1443,14 +1381,16 @@ ASDCP::MXF::DMSegment::Dump(FILE* stream) stream = stderr; InterchangeObject::Dump(stream); + fprintf(stream, " %22s = %s\n", "DataDefinition", DataDefinition.EncodeString(identbuf, IdentBufferLen)); fprintf(stream, " %22s = %s\n", "EventStartPosition", i64sz(EventStartPosition, identbuf)); + fprintf(stream, " %22s = %s\n", "Duration", i64sz(Duration, identbuf)); fprintf(stream, " %22s = %s\n", "EventComment", EventComment.EncodeString(identbuf, IdentBufferLen)); fprintf(stream, " %22s = %s\n", "DMFramework", DMFramework.EncodeString(identbuf, IdentBufferLen)); } // ASDCP::Result_t -ASDCP::MXF::DMSegment::InitFromBuffer(const byte_t* p, ui32_t l) +DMSegment::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_DMSegment); return InterchangeObject::InitFromBuffer(p, l); @@ -1458,7 +1398,7 @@ ASDCP::MXF::DMSegment::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::DMSegment::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +DMSegment::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_DMSegment); return InterchangeObject::WriteToBuffer(Buffer); @@ -1469,7 +1409,7 @@ ASDCP::MXF::DMSegment::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::CryptographicFramework::InitFromTLVSet(TLVReader& TLVSet) +CryptographicFramework::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(CryptographicFramework, ContextSR)); @@ -1478,7 +1418,7 @@ ASDCP::MXF::CryptographicFramework::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::CryptographicFramework::WriteToTLVSet(TLVWriter& TLVSet) +CryptographicFramework::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(CryptographicFramework, ContextSR)); @@ -1487,7 +1427,7 @@ ASDCP::MXF::CryptographicFramework::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::CryptographicFramework::Dump(FILE* stream) +CryptographicFramework::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1501,7 +1441,7 @@ ASDCP::MXF::CryptographicFramework::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::CryptographicFramework::InitFromBuffer(const byte_t* p, ui32_t l) +CryptographicFramework::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_CryptographicFramework); return InterchangeObject::InitFromBuffer(p, l); @@ -1509,7 +1449,7 @@ ASDCP::MXF::CryptographicFramework::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::CryptographicFramework::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +CryptographicFramework::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_CryptographicFramework); return InterchangeObject::WriteToBuffer(Buffer); @@ -1520,7 +1460,7 @@ ASDCP::MXF::CryptographicFramework::WriteToBuffer(ASDCP::FrameBuffer& Buffer) // ASDCP::Result_t -ASDCP::MXF::CryptographicContext::InitFromTLVSet(TLVReader& TLVSet) +CryptographicContext::InitFromTLVSet(TLVReader& TLVSet) { Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(CryptographicContext, ContextID)); @@ -1533,7 +1473,7 @@ ASDCP::MXF::CryptographicContext::InitFromTLVSet(TLVReader& TLVSet) // ASDCP::Result_t -ASDCP::MXF::CryptographicContext::WriteToTLVSet(TLVWriter& TLVSet) +CryptographicContext::WriteToTLVSet(TLVWriter& TLVSet) { Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(CryptographicContext, ContextID)); @@ -1546,7 +1486,7 @@ ASDCP::MXF::CryptographicContext::WriteToTLVSet(TLVWriter& TLVSet) // void -ASDCP::MXF::CryptographicContext::Dump(FILE* stream) +CryptographicContext::Dump(FILE* stream) { char identbuf[IdentBufferLen]; *identbuf = 0; @@ -1564,7 +1504,7 @@ ASDCP::MXF::CryptographicContext::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::CryptographicContext::InitFromBuffer(const byte_t* p, ui32_t l) +CryptographicContext::InitFromBuffer(const byte_t* p, ui32_t l) { m_Typeinfo = &Dict::Type(MDD_CryptographicContext); return InterchangeObject::InitFromBuffer(p, l); @@ -1572,12 +1512,175 @@ ASDCP::MXF::CryptographicContext::InitFromBuffer(const byte_t* p, ui32_t l) // ASDCP::Result_t -ASDCP::MXF::CryptographicContext::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +CryptographicContext::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { m_Typeinfo = &Dict::Type(MDD_CryptographicContext); return InterchangeObject::WriteToBuffer(Buffer); } +//------------------------------------------------------------------------------------------ +// GenericDataEssenceDescriptor + +// +ASDCP::Result_t +GenericDataEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) +{ + Result_t result = FileDescriptor::InitFromTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(GenericDataEssenceDescriptor, DataEssenceCoding)); + return result; +} + +// +ASDCP::Result_t +GenericDataEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +{ + Result_t result = FileDescriptor::WriteToTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(GenericDataEssenceDescriptor, DataEssenceCoding)); + return result; +} + +// +void +GenericDataEssenceDescriptor::Dump(FILE* stream) +{ + char identbuf[IdentBufferLen]; + *identbuf = 0; + + if ( stream == 0 ) + stream = stderr; + + FileDescriptor::Dump(stream); + fprintf(stream, " %22s = %s\n", "DataEssenceCoding", DataEssenceCoding.EncodeString(identbuf, IdentBufferLen)); +} + +// +ASDCP::Result_t +GenericDataEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +{ + m_Typeinfo = &Dict::Type(MDD_GenericDataEssenceDescriptor); + return InterchangeObject::InitFromBuffer(p, l); +} + +// +ASDCP::Result_t +GenericDataEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +{ + m_Typeinfo = &Dict::Type(MDD_GenericDataEssenceDescriptor); + return InterchangeObject::WriteToBuffer(Buffer); +} + +//------------------------------------------------------------------------------------------ +// DCTimedTextDescriptor + +// +ASDCP::Result_t +DCTimedTextDescriptor::InitFromTLVSet(TLVReader& TLVSet) +{ + Result_t result = GenericDataEssenceDescriptor::InitFromTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextDescriptor, UTFEncoding)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextDescriptor, RootNamespaceName)); + return result; +} + +// +ASDCP::Result_t +DCTimedTextDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +{ + Result_t result = GenericDataEssenceDescriptor::WriteToTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextDescriptor, UTFEncoding)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextDescriptor, RootNamespaceName)); + return result; +} + +// +void +DCTimedTextDescriptor::Dump(FILE* stream) +{ + char identbuf[IdentBufferLen]; + *identbuf = 0; + + if ( stream == 0 ) + stream = stderr; + + GenericDataEssenceDescriptor::Dump(stream); + fprintf(stream, " %22s = %s\n", "UTFEncoding", UTFEncoding.EncodeString(identbuf, IdentBufferLen)); + fprintf(stream, " %22s = %s\n", "RootNamespaceName", RootNamespaceName.EncodeString(identbuf, IdentBufferLen)); +} + +// +ASDCP::Result_t +DCTimedTextDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +{ + m_Typeinfo = &Dict::Type(MDD_DCTimedTextDescriptor); + return InterchangeObject::InitFromBuffer(p, l); +} + +// +ASDCP::Result_t +DCTimedTextDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +{ + m_Typeinfo = &Dict::Type(MDD_DCTimedTextDescriptor); + return InterchangeObject::WriteToBuffer(Buffer); +} + +//------------------------------------------------------------------------------------------ +// DCTimedTextResourceDescriptor + +// +ASDCP::Result_t +DCTimedTextResourceDescriptor::InitFromTLVSet(TLVReader& TLVSet) +{ + Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextResourceDescriptor, ResourcePackageID)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextResourceDescriptor, ResourceMIMEType)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(DCTimedTextResourceDescriptor, ResourceSID)); + return result; +} + +// +ASDCP::Result_t +DCTimedTextResourceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +{ + Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextResourceDescriptor, ResourcePackageID)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextResourceDescriptor, ResourceMIMEType)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(DCTimedTextResourceDescriptor, ResourceSID)); + return result; +} + +// +void +DCTimedTextResourceDescriptor::Dump(FILE* stream) +{ + char identbuf[IdentBufferLen]; + *identbuf = 0; + + if ( stream == 0 ) + stream = stderr; + + InterchangeObject::Dump(stream); + fprintf(stream, " %22s = %s\n", "ResourcePackageID", ResourcePackageID.EncodeString(identbuf, IdentBufferLen)); + fprintf(stream, " %22s = %s\n", "ResourceMIMEType", ResourceMIMEType.EncodeString(identbuf, IdentBufferLen)); + fprintf(stream, " %22s = %d\n", "ResourceSID", ResourceSID); +} + +// +ASDCP::Result_t +DCTimedTextResourceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +{ + m_Typeinfo = &Dict::Type(MDD_DCTimedTextResourceDescriptor); + return InterchangeObject::InitFromBuffer(p, l); +} + +// +ASDCP::Result_t +DCTimedTextResourceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +{ + m_Typeinfo = &Dict::Type(MDD_DCTimedTextResourceDescriptor); + return InterchangeObject::WriteToBuffer(Buffer); +} + + // // end Metadata.cpp // diff --git a/src/Metadata.h b/src/Metadata.h index f158194..fbbe216 100755 --- a/src/Metadata.h +++ b/src/Metadata.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2006, John Hurst +Copyright (c) 2005-2007, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,8 +29,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \brief MXF metadata objects */ -#ifndef _METADATA_H_ -#define _METADATA_H_ +#ifndef _Metadata_H_ +#define _Metadata_H_ #include "MXF.h" @@ -38,6 +38,8 @@ namespace ASDCP { namespace MXF { + void Metadata_InitTypes(); + // // @@ -490,11 +492,13 @@ namespace ASDCP ASDCP_NO_COPY_CONSTRUCT(DMSegment); public: + UL DataDefinition; ui64_t EventStartPosition; + ui64_t Duration; UTF16String EventComment; UUID DMFramework; - DMSegment() : EventStartPosition(0) {} + DMSegment() : EventStartPosition(0), Duration(0) {} virtual ~DMSegment() {} virtual const char* HasName() { return "DMSegment"; } virtual Result_t InitFromTLVSet(TLVReader& TLVSet); @@ -544,11 +548,67 @@ namespace ASDCP virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&); }; + // + class GenericDataEssenceDescriptor : public FileDescriptor + { + ASDCP_NO_COPY_CONSTRUCT(GenericDataEssenceDescriptor); + + public: + UL DataEssenceCoding; + + GenericDataEssenceDescriptor() {} + virtual ~GenericDataEssenceDescriptor() {} + virtual const char* HasName() { return "GenericDataEssenceDescriptor"; } + virtual Result_t InitFromTLVSet(TLVReader& TLVSet); + virtual Result_t WriteToTLVSet(TLVWriter& TLVSet); + virtual void Dump(FILE* = 0); + virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l); + virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&); + }; + + // + class DCTimedTextDescriptor : public GenericDataEssenceDescriptor + { + ASDCP_NO_COPY_CONSTRUCT(DCTimedTextDescriptor); + + public: + UTF16String UTFEncoding; + UTF16String RootNamespaceName; + + DCTimedTextDescriptor() {} + virtual ~DCTimedTextDescriptor() {} + virtual const char* HasName() { return "DCTimedTextDescriptor"; } + virtual Result_t InitFromTLVSet(TLVReader& TLVSet); + virtual Result_t WriteToTLVSet(TLVWriter& TLVSet); + virtual void Dump(FILE* = 0); + virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l); + virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&); + }; + + // + class DCTimedTextResourceDescriptor : public InterchangeObject + { + ASDCP_NO_COPY_CONSTRUCT(DCTimedTextResourceDescriptor); + + public: + UUID ResourcePackageID; + UTF16String ResourceMIMEType; + ui32_t ResourceSID; + + DCTimedTextResourceDescriptor() : ResourceSID(0) {} + virtual ~DCTimedTextResourceDescriptor() {} + virtual const char* HasName() { return "DCTimedTextResourceDescriptor"; } + virtual Result_t InitFromTLVSet(TLVReader& TLVSet); + virtual Result_t WriteToTLVSet(TLVWriter& TLVSet); + virtual void Dump(FILE* = 0); + virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l); + virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&); + }; } // namespace MXF } // namespace ASDCP -#endif // _METADATA_H_ +#endif // _Metadata_H_ // // end Metadata.h 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 // diff --git a/src/asdcp-test.cpp b/src/asdcp-test.cpp index a2901da..4a1a586 100755 --- a/src/asdcp-test.cpp +++ b/src/asdcp-test.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2006, John Hurst +Copyright (c) 2003-2007, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -56,6 +56,11 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <WavFileWriter.h> #include <MXF.h> #include <Metadata.h> + +#ifdef ASDCP_WITH_TIMED_TEXT +#include <AS_DCP_TimedText.h> +#endif + #include <openssl/sha.h> using namespace ASDCP; @@ -1099,6 +1104,201 @@ read_PCM_file(CommandOptions& Options) } +#ifdef ASDCP_WITH_TIMED_TEXT + +//------------------------------------------------------------------------------------------ +// TimedText essence + + +// Write one or more plaintext timed text streams to a plaintext ASDCP file +// Write one or more plaintext timed text streams to a ciphertext ASDCP file +// +Result_t +write_timed_text_file(CommandOptions& Options) +{ + AESEncContext* Context = 0; + HMACContext* HMAC = 0; + TimedText::DCSubtitleParser Parser; + TimedText::MXFWriter Writer; + TimedText::FrameBuffer FrameBuffer; + TimedText::TimedTextDescriptor TDesc; + byte_t IV_buf[CBC_BLOCK_SIZE]; + Kumu::FortunaRNG RNG; + + // set up essence parser + Result_t result = Parser.OpenRead(Options.filenames[0]); + + // set up MXF writer + if ( ASDCP_SUCCESS(result) ) + { + Parser.FillDescriptor(TDesc); + FrameBuffer.Capacity(2*Kumu::Megabyte); + + if ( Options.verbose_flag ) + { + fputs("D-Cinema Timed-Text Descriptor:\n", stderr); + TimedText::DescriptorDump(TDesc); + } + } + + if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag ) + { + WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here + Kumu::GenRandomUUID(Info.AssetUUID); + + if ( Options.use_smpte_labels ) + { + Info.LabelSetType = LS_MXF_SMPTE; + fprintf(stderr, "ATTENTION! Writing SMPTE Universal Labels\n"); + } + + // configure encryption + if( Options.key_flag ) + { + Kumu::GenRandomUUID(Info.ContextID); + Info.EncryptedEssence = true; + + if ( Options.key_id_flag ) + memcpy(Info.CryptographicKeyID, Options.key_id_value, UUIDlen); + else + RNG.FillRandom(Info.CryptographicKeyID, UUIDlen); + + Context = new AESEncContext; + result = Context->InitKey(Options.key_value); + + if ( ASDCP_SUCCESS(result) ) + result = Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE)); + + if ( ASDCP_SUCCESS(result) && Options.write_hmac ) + { + Info.UsesHMAC = true; + HMAC = new HMACContext; + result = HMAC->InitKey(Options.key_value, Info.LabelSetType); + } + } + + if ( ASDCP_SUCCESS(result) ) + result = Writer.OpenWrite(Options.out_file, Info, TDesc); + } + + if ( ASDCP_FAILURE(result) ) + return result; + + std::string XMLDoc; + TimedText::ResourceList_t::const_iterator ri; + + result = Parser.ReadTimedTextResource(XMLDoc); + + if ( ASDCP_SUCCESS(result) ) + result = Writer.WriteTimedTextResource(XMLDoc, Context, HMAC); + + for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ ) + { + result = Parser.ReadAncillaryResource((*ri).ResourceID, FrameBuffer); + + if ( ASDCP_SUCCESS(result) ) + { + if ( Options.verbose_flag ) + FrameBuffer.Dump(stderr, Options.fb_dump_size); + + if ( ! Options.no_write_flag ) + { + result = Writer.WriteAncillaryResource(FrameBuffer, Context, HMAC); + + // The Writer class will forward the last block of ciphertext + // to the encryption context for use as the IV for the next + // frame. If you want to use non-sequitur IV values, un-comment + // the following line of code. + // if ( ASDCP_SUCCESS(result) && Options.key_flag ) + // Context->SetIVec(RNG.FillRandom(IV_buf, CBC_BLOCK_SIZE)); + } + } + + if ( result == RESULT_ENDOFFILE ) + result = RESULT_OK; + } + + if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag ) + result = Writer.Finalize(); + + return result; +} + + +// Read one or more timed text streams from a plaintext ASDCP file +// Read one or more timed text streams from a ciphertext ASDCP file +// Read one or more timed text streams from a ciphertext ASDCP file +// +Result_t +read_timed_text_file(CommandOptions& Options) +{ + AESDecContext* Context = 0; + HMACContext* HMAC = 0; + TimedText::MXFReader Reader; + TimedText::FrameBuffer FrameBuffer; + TimedText::TimedTextDescriptor TDesc; + + Result_t result = Reader.OpenRead(Options.filenames[0]); + + if ( ASDCP_SUCCESS(result) ) + { + Reader.FillDescriptor(TDesc); + FrameBuffer.Capacity(2*Kumu::Megabyte); + + if ( Options.verbose_flag ) + TimedText::DescriptorDump(TDesc); + } + + if ( ASDCP_SUCCESS(result) && Options.key_flag ) + { + Context = new AESDecContext; + result = Context->InitKey(Options.key_value); + + if ( ASDCP_SUCCESS(result) && Options.read_hmac ) + { + WriterInfo Info; + Reader.FillWriterInfo(Info); + + if ( Info.UsesHMAC ) + { + HMAC = new HMACContext; + result = HMAC->InitKey(Options.key_value, Info.LabelSetType); + } + else + { + fputs("File does not contain HMAC values, ignoring -m option.\n", stderr); + } + } + } + + if ( ASDCP_FAILURE(result) ) + return result; + + std::string XMLDoc; + TimedText::ResourceList_t::const_iterator ri; + + result = Reader.ReadTimedTextResource(XMLDoc, Context, HMAC); + + // do something with the XML here + fprintf(stderr, "XMLDoc size: %lu\n", XMLDoc.size()); + + for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ ) + { + result = Reader.ReadAncillaryResource((*ri).ResourceID, FrameBuffer, Context, HMAC); + + if ( ASDCP_SUCCESS(result) ) + { + // if ( Options.verbose_flag ) + FrameBuffer.Dump(stderr, Options.fb_dump_size); + + // do something with the resource data here + } + } + + return result; +} +#endif // ASDCP_WITH_TIMED_TEXT + //------------------------------------------------------------------------------------------ // @@ -1143,6 +1343,19 @@ class MyAudioDescriptor : public PCM::AudioDescriptor } }; +#ifdef ASDCP_WITH_TIMED_TEXT +class MyTextDescriptor : public TimedText::TimedTextDescriptor +{ + public: + void FillDescriptor(TimedText::MXFReader& Reader) { + Reader.FillDescriptor(*this); + } + + void Dump(FILE* stream) { + TimedText::DescriptorDump(*this, stream); + } +}; +#endif // MSVC didn't like the function template, so now it's a static class method template<class ReaderT, class DescriptorT> @@ -1209,6 +1422,13 @@ show_file_info(CommandOptions& Options) fputs("File essence type is JPEG 2000 pictures.\n", stdout); FileInfoWrapper<ASDCP::JP2K::MXFReader, MyPictureDescriptor>::file_info(Options); } +#ifdef ASDCP_WITH_TIMED_TEXT + else if ( EssenceType == ESS_TIMED_TEXT ) + { + fputs("File essence type is Timed Text.\n", stdout); + FileInfoWrapper<ASDCP::TimedText::MXFReader, MyTextDescriptor>::file_info(Options); + } +#endif else { fprintf(stderr, "File is not AS-DCP: %s\n", Options.filenames[0]); @@ -1358,6 +1578,14 @@ main(int argc, const char** argv) result = read_PCM_file(Options); break; + case ESS_TIMED_TEXT: +#ifdef ASDCP_WITH_TIMED_TEXT + result = read_timed_text_file(Options); + break; +#else + fprintf(stderr, "asdcplib compiled without timed text support.\n"); + return 7; +#endif default: fprintf(stderr, "%s: Unknown file type, not ASDCP essence.\n", Options.filenames[0]); return 5; @@ -1391,6 +1619,15 @@ main(int argc, const char** argv) result = write_PCM_file(Options); break; + case ESS_TIMED_TEXT: +#ifdef ASDCP_WITH_TIMED_TEXT + result = write_timed_text_file(Options); + break; +#else + fprintf(stderr, "asdcplib compiled without timed text support.\n"); + return 7; +#endif + default: fprintf(stderr, "%s: Unknown file type, not ASDCP-compatible essence.\n", Options.filenames[0]); diff --git a/src/h__Reader.cpp b/src/h__Reader.cpp index 2179ca6..7bc8955 100755 --- a/src/h__Reader.cpp +++ b/src/h__Reader.cpp @@ -112,7 +112,7 @@ ASDCP::h__Reader::OpenMXFRead(const char* filename) { // if this is a three partition file, go to the body // partition and read the partition pack - if ( m_HeaderPart.m_RIP.PairArray.size() == 3 ) + if ( m_HeaderPart.m_RIP.PairArray.size() > 2 ) { Array<RIP::Pair>::iterator r_i = m_HeaderPart.m_RIP.PairArray.begin(); r_i++; @@ -182,8 +182,8 @@ public: // standard method of reading a plaintext or encrypted frame Result_t -ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, - const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) +ASDCP::h__Reader::ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, + const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) { // look up frame index node IndexTableSegment::IndexEntry TmpEntry; @@ -195,9 +195,8 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, } // get frame position and go read the frame's key and length - Result_t result = RESULT_OK; - KLReader Reader; Kumu::fpos_t FilePosition = m_EssenceStart + TmpEntry.StreamOffset; + Result_t result = RESULT_OK; if ( FilePosition != m_LastPosition ) { @@ -205,8 +204,19 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, result = m_File.Seek(FilePosition); } - if ( ASDCP_SUCCESS(result) ) - result = Reader.ReadKLFromFile(m_File); + if( ASDCP_SUCCESS(result) ) + result = ReadEKLVPacket(FrameNum, FrameBuf, EssenceUL, Ctx, HMAC); + + return result; +} + + +Result_t +ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, + const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) +{ + KLReader Reader; + Result_t result = Reader.ReadKLFromFile(m_File); if ( ASDCP_FAILURE(result) ) return result; diff --git a/src/h__Writer.cpp b/src/h__Writer.cpp index 1105e03..1bada6b 100755 --- a/src/h__Writer.cpp +++ b/src/h__Writer.cpp @@ -45,8 +45,8 @@ using namespace ASDCP::MXF; // ASDCP::h__Writer::h__Writer() : m_HeaderSize(0), m_EssenceStart(0), - m_MaterialPackage(0), m_MPTCSequence(0), m_MPTimecode(0), m_MPClSequence(0), m_MPClip(0), - m_FilePackage(0), m_FPTCSequence(0), m_FPTimecode(0), m_FPClSequence(0), m_FPClip(0), + // m_MaterialPackage(0), m_MPTCSequence(0), m_MPTimecode(0), m_MPClSequence(0), m_MPClip(0), + // m_FilePackage(0), m_FPTCSequence(0), m_FPTimecode(0), m_FPClSequence(0), m_FPClip(0), m_EssenceDescriptor(0), m_FramesWritten(0), m_StreamOffset(0) { } @@ -93,13 +93,10 @@ AddDMScrypt(Partition& HeaderPart, SourcePackage& Package, WriterInfo& Descr, co } // -Result_t -ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL, - const std::string& TrackName, const UL& DataDefinition, - const MXF::Rational& EditRate, - ui32_t TCFrameRate, ui32_t BytesPerEditUnit) +void +ASDCP::h__Writer::InitHeader() { - ASDCP_TEST_NULL(m_EssenceDescriptor); + assert(m_EssenceDescriptor); m_HeaderPart.m_Primer.ClearTagList(); m_HeaderPart.m_Preface = new Preface; @@ -134,7 +131,69 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap Ident->ToolkitVersion.Patch = VERSION_IMPMINOR; Ident->ToolkitVersion.Build = ASDCP_BUILD_NUMBER; Ident->ToolkitVersion.Release = VersionType::RL_RELEASE; +} + +// +template <class ClipT> +struct TrackSet +{ + MXF::Track* Track; + MXF::Sequence* Sequence; + ClipT* Clip; + + TrackSet() : Track(0), Sequence(0), Clip(0) {} +}; + +// +template <class PackageT, class ClipT> +TrackSet<ClipT> +CreateTrackAndSequence(OPAtomHeader& Header, PackageT& Package, const std::string TrackName, + const MXF::Rational& EditRate, const UL& Definition, ui32_t TrackID) +{ + TrackSet<ClipT> NewTrack; + + NewTrack.Track = new Track; + Header.AddChildObject(NewTrack.Track); + NewTrack.Track->EditRate = EditRate; + Package.Tracks.push_back(NewTrack.Track->InstanceUID); + NewTrack.Track->TrackID = TrackID; + NewTrack.Track->TrackName = TrackName.c_str(); + + NewTrack.Sequence = new Sequence; + Header.AddChildObject(NewTrack.Sequence); + NewTrack.Track->Sequence = NewTrack.Sequence->InstanceUID; + NewTrack.Sequence->DataDefinition = Definition; + return NewTrack; +} + +// +template <class PackageT> +TrackSet<TimecodeComponent> +CreateTimecodeTrack(OPAtomHeader& Header, PackageT& Package, + const MXF::Rational& EditRate, ui32_t TCFrameRate, ui64_t TCStart) +{ + UL TCUL(Dict::ul(MDD_TimecodeDataDef)); + + TrackSet<TimecodeComponent> NewTrack = CreateTrackAndSequence<PackageT, TimecodeComponent>(Header, Package, "Timecode Track", EditRate, TCUL, 1); + + NewTrack.Clip = new TimecodeComponent; + Header.AddChildObject(NewTrack.Clip); + NewTrack.Sequence->StructuralComponents.push_back(NewTrack.Clip->InstanceUID); + NewTrack.Clip->RoundedTimecodeBase = TCFrameRate; + NewTrack.Clip->StartTimecode = TCStart; + NewTrack.Clip->DataDefinition = TCUL; + + return NewTrack; +} + + +// +void +ASDCP::h__Writer::AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate, + const std::string& TrackName, const UL& DataDefinition, + const std::string& PackageLabel) +{ // ContentStorage* Storage = new ContentStorage; m_HeaderPart.AddChildObject(Storage); @@ -146,119 +205,158 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap ECD->IndexSID = 129; ECD->BodySID = 1; + UUID assetUUID(m_Info.AssetUUID); + UMID SourcePackageUMID, MaterialPackageUMID; + SourcePackageUMID.MakeUMID(0x0f, assetUUID); + MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence + // // Material Package // - UMID PackageUMID; - PackageUMID.MakeUMID(0x0f); // unidentified essence m_MaterialPackage = new MaterialPackage; m_MaterialPackage->Name = "AS-DCP Material Package"; - m_MaterialPackage->PackageUID = PackageUMID; + m_MaterialPackage->PackageUID = MaterialPackageUMID; m_HeaderPart.AddChildObject(m_MaterialPackage); Storage->Packages.push_back(m_MaterialPackage->InstanceUID); - // Timecode Track - Track* NewTrack = new Track; - m_HeaderPart.AddChildObject(NewTrack); - NewTrack->EditRate = EditRate; - m_MaterialPackage->Tracks.push_back(NewTrack->InstanceUID); - NewTrack->TrackID = 1; - NewTrack->TrackName = "Timecode Track"; - - m_MPTCSequence = new Sequence; - m_HeaderPart.AddChildObject(m_MPTCSequence); - NewTrack->Sequence = m_MPTCSequence->InstanceUID; - m_MPTCSequence->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef)); - - m_MPTimecode = new TimecodeComponent; - m_HeaderPart.AddChildObject(m_MPTimecode); - m_MPTCSequence->StructuralComponents.push_back(m_MPTimecode->InstanceUID); - m_MPTimecode->RoundedTimecodeBase = TCFrameRate; - m_MPTimecode->StartTimecode = ui64_C(0); - m_MPTimecode->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef)); + TrackSet<TimecodeComponent> MPTCTrack = CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage, + EditRate, TCFrameRate, 0); + m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration)); + m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration)); - // Essence Track - NewTrack = new Track; - m_HeaderPart.AddChildObject(NewTrack); - NewTrack->EditRate = EditRate; - m_MaterialPackage->Tracks.push_back(NewTrack->InstanceUID); - NewTrack->TrackID = 2; - NewTrack->TrackName = TrackName.c_str(); - - m_MPClSequence = new Sequence; - m_HeaderPart.AddChildObject(m_MPClSequence); - NewTrack->Sequence = m_MPClSequence->InstanceUID; - m_MPClSequence->DataDefinition = DataDefinition; - - m_MPClip = new SourceClip; - m_HeaderPart.AddChildObject(m_MPClip); - m_MPClSequence->StructuralComponents.push_back(m_MPClip->InstanceUID); - m_MPClip->DataDefinition = DataDefinition; + TrackSet<SourceClip> MPTrack = CreateTrackAndSequence<MaterialPackage, SourceClip>(m_HeaderPart, *m_MaterialPackage, + TrackName, EditRate, DataDefinition, 2); + m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration)); + + MPTrack.Clip = new SourceClip; + m_HeaderPart.AddChildObject(MPTrack.Clip); + MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID); + MPTrack.Clip->DataDefinition = DataDefinition; + MPTrack.Clip->SourcePackageID = SourcePackageUMID; + MPTrack.Clip->SourceTrackID = 2; + m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration)); + // // File (Source) Package // + m_FilePackage = new SourcePackage; + m_FilePackage->Name = PackageLabel.c_str(); + m_FilePackage->PackageUID = SourcePackageUMID; + ECD->LinkedPackageUID = SourcePackageUMID; + + m_HeaderPart.AddChildObject(m_FilePackage); + Storage->Packages.push_back(m_FilePackage->InstanceUID); + + TrackSet<TimecodeComponent> FPTCTrack = CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage, + EditRate, TCFrameRate, ui64_C(3600) * TCFrameRate); + m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration)); + m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration)); + + TrackSet<SourceClip> FPTrack = CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage, + TrackName, EditRate, DataDefinition, 2); + m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration)); + + FPTrack.Clip = new SourceClip; + m_HeaderPart.AddChildObject(FPTrack.Clip); + FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID); + FPTrack.Clip->DataDefinition = DataDefinition; + + // for now we do not allow setting this value, so all files will be 'original' + FPTrack.Clip->SourceTrackID = 0; + FPTrack.Clip->SourcePackageID = NilUMID; + m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration)); + + m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID; +} + +// +void +ASDCP::h__Writer::AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate, + const std::string& TrackName, const UL& DataDefinition, + const std::string& PackageLabel) +{ + // + ContentStorage* Storage = new ContentStorage; + m_HeaderPart.AddChildObject(Storage); + m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID; + + EssenceContainerData* ECD = new EssenceContainerData; + m_HeaderPart.AddChildObject(ECD); + Storage->EssenceContainerData.push_back(ECD->InstanceUID); + ECD->IndexSID = 129; + ECD->BodySID = 1; + UUID assetUUID(m_Info.AssetUUID); - PackageUMID.MakeUMID(0x0f, assetUUID); + UMID SourcePackageUMID, MaterialPackageUMID; + SourcePackageUMID.MakeUMID(0x0f, assetUUID); + MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence + + // + // Material Package + // + m_MaterialPackage = new MaterialPackage; + m_MaterialPackage->Name = "AS-DCP Material Package"; + m_MaterialPackage->PackageUID = MaterialPackageUMID; + m_HeaderPart.AddChildObject(m_MaterialPackage); + Storage->Packages.push_back(m_MaterialPackage->InstanceUID); + TrackSet<TimecodeComponent> MPTCTrack = CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage, + EditRate, TCFrameRate, 0); + m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration)); + m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration)); + + TrackSet<DMSegment> MPTrack = CreateTrackAndSequence<MaterialPackage, DMSegment>(m_HeaderPart, *m_MaterialPackage, + TrackName, EditRate, DataDefinition, 2); + m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration)); + + MPTrack.Clip = new DMSegment; + m_HeaderPart.AddChildObject(MPTrack.Clip); + MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID); + MPTrack.Clip->DataDefinition = DataDefinition; + // MPTrack.Clip->SourcePackageID = SourcePackageUMID; + // MPTrack.Clip->SourceTrackID = 2; + m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration)); + + + // + // File (Source) Package + // m_FilePackage = new SourcePackage; m_FilePackage->Name = PackageLabel.c_str(); - m_FilePackage->PackageUID = PackageUMID; - ECD->LinkedPackageUID = PackageUMID; - - m_MPClip->SourcePackageID = PackageUMID; - m_MPClip->SourceTrackID = 2; + m_FilePackage->PackageUID = SourcePackageUMID; + ECD->LinkedPackageUID = SourcePackageUMID; m_HeaderPart.AddChildObject(m_FilePackage); Storage->Packages.push_back(m_FilePackage->InstanceUID); - // Timecode Track - NewTrack = new Track; - m_HeaderPart.AddChildObject(NewTrack); - NewTrack->EditRate = EditRate; - m_FilePackage->Tracks.push_back(NewTrack->InstanceUID); - NewTrack->TrackID = 1; - NewTrack->TrackName = "Timecode Track"; - - m_FPTCSequence = new Sequence; - m_HeaderPart.AddChildObject(m_FPTCSequence); - NewTrack->Sequence = m_FPTCSequence->InstanceUID; - m_FPTCSequence->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef)); - - m_FPTimecode = new TimecodeComponent; - m_HeaderPart.AddChildObject(m_FPTimecode); - m_FPTCSequence->StructuralComponents.push_back(m_FPTimecode->InstanceUID); - m_FPTimecode->RoundedTimecodeBase = TCFrameRate; - m_FPTimecode->StartTimecode = ui64_C(86400); // 01:00:00:00 - m_FPTimecode->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef)); + TrackSet<TimecodeComponent> FPTCTrack = CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage, + EditRate, TCFrameRate, ui64_C(3600) * TCFrameRate); + m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration)); + m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration)); - // Essence Track - NewTrack = new Track; - m_HeaderPart.AddChildObject(NewTrack); - NewTrack->EditRate = EditRate; - m_FilePackage->Tracks.push_back(NewTrack->InstanceUID); - NewTrack->TrackID = 2; - NewTrack->TrackName = TrackName.c_str(); - - m_FPClSequence = new Sequence; - m_HeaderPart.AddChildObject(m_FPClSequence); - NewTrack->Sequence = m_FPClSequence->InstanceUID; - m_FPClSequence->DataDefinition = DataDefinition; - - m_FPClip = new SourceClip; - m_HeaderPart.AddChildObject(m_FPClip); - m_FPClSequence->StructuralComponents.push_back(m_FPClip->InstanceUID); - m_FPClip->DataDefinition = DataDefinition; + TrackSet<DMSegment> FPTrack = CreateTrackAndSequence<SourcePackage, DMSegment>(m_HeaderPart, *m_FilePackage, + TrackName, EditRate, DataDefinition, 2); + m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration)); - // for now we do not allow setting this value, so all files will be 'original' - m_FPClip->SourceTrackID = 0; - m_FPClip->SourcePackageID = NilUMID; + FPTrack.Clip = new DMSegment; + m_HeaderPart.AddChildObject(FPTrack.Clip); + FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID); + FPTrack.Clip->DataDefinition = DataDefinition; + FPTrack.Clip->EventComment = "D-Cinema Timed Text"; + m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration)); + m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID; +} + +// +void +ASDCP::h__Writer::AddEssenceDescriptor(const UL& WrappingUL) +{ // // Essence Descriptor // m_EssenceDescriptor->EssenceContainer = WrappingUL; - m_EssenceDescriptor->LinkedTrackID = NewTrack->TrackID; m_HeaderPart.m_Preface->PrimaryPackage = m_FilePackage->InstanceUID; // @@ -282,15 +380,19 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap std::list<FileDescriptor*>::iterator sdli = m_EssenceSubDescriptorList.begin(); for ( ; sdli != m_EssenceSubDescriptorList.end(); sdli++ ) - m_HeaderPart.AddChildObject(*sdli); + m_HeaderPart.AddChildObject(*sdli); m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID; +} - // Write the header partition - Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize); +// +Result_t +ASDCP::h__Writer::CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit) +{ + Result_t result = RESULT_OK; - // create a body partition of we're writing proper 429-3/OP-Atom - if ( ASDCP_SUCCESS(result) && m_Info.LabelSetType == LS_MXF_SMPTE ) + // create a body partition if we're writing proper 429-3/OP-Atom + if ( m_Info.LabelSetType == LS_MXF_SMPTE ) { // Body Partition m_BodyPart.EssenceContainers = m_HeaderPart.EssenceContainers; @@ -323,6 +425,23 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap return result; } +// +Result_t +ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL, + const std::string& TrackName, const UL& DataDefinition, + const MXF::Rational& EditRate, ui32_t TCFrameRate, ui32_t BytesPerEditUnit) +{ + InitHeader(); + AddSourceClip(EditRate, TCFrameRate, TrackName, DataDefinition, PackageLabel); + AddEssenceDescriptor(WrappingUL); + + Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize); + + if ( KM_SUCCESS(result) ) + result = CreateBodyPart(EditRate, BytesPerEditUnit); + + return result; +} // standard method of writing a plaintext or encrypted frame @@ -446,9 +565,16 @@ ASDCP::h__Writer::WriteMXFFooter() { // Set top-level file package correctly for OP-Atom - m_MPTCSequence->Duration = m_MPTimecode->Duration = m_MPClSequence->Duration = m_MPClip->Duration = - m_FPTCSequence->Duration = m_FPTimecode->Duration = m_FPClSequence->Duration = m_FPClip->Duration = - m_EssenceDescriptor->ContainerDuration = m_FramesWritten; + // m_MPTCSequence->Duration = m_MPTimecode->Duration = m_MPClSequence->Duration = m_MPClip->Duration = + // m_FPTCSequence->Duration = m_FPTimecode->Duration = m_FPClSequence->Duration = m_FPClip->Duration = + + DurationElementList_t::iterator dli = m_DurationUpdateList.begin(); + + for (; dli != m_DurationUpdateList.end(); dli++ ) + **dli = m_FramesWritten; + + m_EssenceDescriptor->ContainerDuration = m_FramesWritten; + m_FooterPart.PreviousPartition = m_HeaderPart.m_RIP.PairArray.back().ByteOffset; Kumu::fpos_t here = m_File.Tell(); m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(0, here)); // Last RIP Entry @@ -463,11 +589,6 @@ ASDCP::h__Writer::WriteMXFFooter() m_HeaderPart.OperationalPattern = OPAtomUL; m_HeaderPart.m_Preface->OperationalPattern = m_HeaderPart.OperationalPattern; - if ( m_Info.LabelSetType == LS_MXF_SMPTE ) - m_FooterPart.PreviousPartition = m_BodyPart.ThisPartition; - else - m_FooterPart.PreviousPartition = m_HeaderPart.ThisPartition; - m_FooterPart.OperationalPattern = m_HeaderPart.OperationalPattern; m_FooterPart.EssenceContainers = m_HeaderPart.EssenceContainers; m_FooterPart.FooterPartition = here; diff --git a/src/klvwalk.cpp b/src/klvwalk.cpp index 467eff9..bf9d9fb 100755 --- a/src/klvwalk.cpp +++ b/src/klvwalk.cpp @@ -192,7 +192,7 @@ main(int argc, const char** argv) if (Options.verbose_flag) fprintf(stderr, "Opening file %s\n", ((*fi).c_str())); - if ( Options.read_mxf_flag ) + if ( Options.read_mxf_flag ) // dump MXF { Kumu::FileReader Reader; ASDCP::MXF::OPAtomHeader Header; @@ -204,6 +204,25 @@ main(int argc, const char** argv) Header.Dump(stdout); + if ( ASDCP_SUCCESS(result) && Header.m_RIP.PairArray.size() > 3 ) + { + MXF::Array<MXF::RIP::Pair>::const_iterator pi = Header.m_RIP.PairArray.begin(); + + for ( pi++; pi != Header.m_RIP.PairArray.end() && ASDCP_SUCCESS(result); pi++ ) + { + result = Reader.Seek((*pi).ByteOffset); + + if ( ASDCP_SUCCESS(result) ) + { + MXF::Partition TmpPart; + result = TmpPart.InitFromFile(Reader); + + if ( ASDCP_SUCCESS(result) && TmpPart.BodySID > 0 ) + TmpPart.Dump(stdout); + } + } + } + if ( ASDCP_SUCCESS(result) ) { ASDCP::MXF::OPAtomIndexFooter Index; diff --git a/src/path-test.cpp b/src/path-test.cpp new file mode 100644 index 0000000..bc0af33 --- /dev/null +++ b/src/path-test.cpp @@ -0,0 +1,122 @@ +/* +Copyright (c) 2004-2007, John Hurst +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! \file path-test.cpp + \version $Id$ + \brief test harness for path manglers defined in KM_fileio.h +*/ + + +#include <KM_fileio.h> +#include <iostream> + +using namespace std; +using namespace Kumu; + + +// +int +main(int argc, const char** argv) +{ + + string Path_1 = "path-test.cpp"; + assert(PathExists(Path_1)); + assert(PathIsFile(Path_1)); + assert(!PathIsDirectory(Path_1)); + + string Path_2 = "."; + assert(PathExists(Path_2)); + assert(!PathIsFile(Path_2)); + assert(PathIsDirectory(Path_2)); + + string Path_3 = "/foo/bar/baz.buz"; // must have 3 elements + PathCompList_t PathList_3; + PathToComponents(Path_3, PathList_3); + + assert(PathList_3.size() == 3); + + string Path_4 = ComponentsToPath(PathList_3); + string Path_5 = PathMakeAbsolute(Path_4); + string Path_6 = ComponentsToAbsolutePath(PathList_3); + assert(Path_3 == Path_6); + assert(PathsAreEquivalent(Path_3, Path_6)); + assert(!PathsAreEquivalent(Path_3, Path_4)); + + assert(!PathHasComponents(PathList_3.back())); + assert(PathHasComponents(Path_3)); + + assert(!PathIsAbsolute(Path_4)); + assert(PathIsAbsolute(Path_5)); + assert(PathMakeLocal(Path_3, "/foo") == "bar/baz.buz"); + + assert(PathsAreEquivalent("/foo/bar/baz", "/foo/bar/./baz")); + assert(PathsAreEquivalent("/foo/baz", "/foo/bar/../baz")); + + assert(PathBasename(Path_3) == "baz.buz"); + assert(PathDirname(Path_3) == "/foo/bar"); + assert(PathDirname("/foo") == "/"); + + assert(PathGetExtension(Path_3) == "buz"); + assert(PathGetExtension("foo") == ""); + assert(PathSetExtension("foo.bar", "") == "foo"); + assert(PathSetExtension(Path_3, "xml") == "baz.xml"); + + PathList_t InList, OutList; + InList.push_back("tmp"); + InList.push_back("Darwin"); + InList.push_back("."); + + cerr << "----------------------------------" << endl; + FindInPaths(PathMatchAny(), InList, OutList); + PathList_t::iterator pi; + + for ( pi = OutList.begin(); pi != OutList.end(); pi++ ) + cerr << *pi << endl; + + cerr << "----------------------------------" << endl; + OutList.clear(); + FindInPaths(PathMatchRegex("^[A-J].*\.h$"), InList, OutList); + + for ( pi = OutList.begin(); pi != OutList.end(); pi++ ) + cerr << *pi << endl; + + cerr << "----------------------------------" << endl; + OutList.clear(); + FindInPaths(PathMatchGlob("*.h"), InList, OutList); + + for ( pi = OutList.begin(); pi != OutList.end(); pi++ ) + cerr << *pi << endl; + + cerr << "----------------------------------" << endl; + + cerr << "OK" << endl; + + return 0; +} + +// +// end path-test.cpp +// |
