logging re-write
authorjhurst <jhurst@cinecert.com>
Sat, 22 Dec 2007 19:32:35 +0000 (19:32 +0000)
committerjhurst <>
Sat, 22 Dec 2007 19:32:35 +0000 (19:32 +0000)
19 files changed:
README
src/AS_DCP_JP2K.cpp
src/AS_DCP_MXF.cpp
src/AS_DCP_TimedText.cpp
src/KM_error.h
src/KM_log.cpp
src/KM_log.h
src/KM_memio.h
src/KM_util.cpp
src/KM_util.h
src/MDD.cpp
src/MDD.h
src/MXF.h
src/MXFTypes.h
src/Metadata.cpp
src/Metadata.h
src/S12MTimecode.h
src/TimedText_Parser.cpp
src/asdcp-test.cpp

diff --git a/README b/README
index 5d863bc8d38bcc23ae1967e5e0fa4720ed469eb8..ab795c3cfef85360f0544c95d53c35d2aa17c0a9 100755 (executable)
--- a/README
+++ b/README
@@ -116,17 +116,26 @@ utilities all respond to -h.
 
 
 Change History
-2007.10.29 - Bug fixes v.1.2.17
+2007.12.13 - Bug fixes v.1.2.17
  o Changed Result_t implementation to use int instead of long, which
    was causing trouble on some 64 bit platforms.
- o Fixed EKLV HMAC. Broke backward compatibility with older Interop
-   files. To validate these files use asdcplib-1.1.14. This should
-   not cause too much trouble since files with broken and non-broken
-   HMAC have been in the wild for years without trouble.
+ o Fixed EKLV HMAC. NOTE: Breaks backward compatibility with older
+   Interop files. To validate these files, use asdcplib-1.1.14. This
+   should not cause too much trouble since files with broken and
+   non-broken HMAC have been in the wild for years without issue.
  o Fixed HMAC sequence numbering in encrypted stereoscopic files.
  o Finished stereoscopic test targets in the makefile.
  o Fixed the win32 build, now expects VS2005 compiler by default,
-   use WITH_VC6=1 top get VS6 flags.
+   use WITH_VC6=1 top get VC6 flags.
+ o Stereoscopic and Timed Text modes now have SMPTE UL values.
+   NOTE: SMPTE 429-5 and 429-10 are not yet published. It is possible
+   that these UL values may change before publication. Please use
+   caution when using these features for production work.
+ o Changed a bunch of symbol names in the 429-5 implementation to
+   better match the spec.
+ o Added -U option to asdcp-test to dump the UL library to stdout.
+ o Fixed erroneous placement of the PictureEssenceCoding UL in JP2K
+   files (Interop and SMPTE modes).
 
 
 2007.10.22 - Timed Text, Stereoscopic Picture and Bug fixes v.1.2.16
index a1d9514f53da27d5f69205753dd481d1b43f094a..8f771739ffb8b6865aca548c3a84871b49692ea8 100755 (executable)
@@ -570,6 +570,9 @@ public:
   Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc);
 };
 
+const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
+const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
+static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
 
 //
 ASDCP::Result_t
@@ -579,21 +582,31 @@ lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
   assert(m_EssenceSubDescriptor);
   MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
 
-  PDescObj->SampleRate = PDesc.EditRate;
   PDescObj->ContainerDuration = PDesc.ContainerDuration;
+  PDescObj->SampleRate = PDesc.EditRate;
+  PDescObj->FrameLayout = 0;
   PDescObj->StoredWidth = PDesc.StoredWidth;
   PDescObj->StoredHeight = PDesc.StoredHeight;
   PDescObj->AspectRatio = PDesc.AspectRatio;
-  PDescObj->FrameLayout = 0;
+
+  //  if ( m_Info.LabelSetType == LS_MXF_SMPTE )
+  //    {
+  // PictureEssenceCoding UL = 
+  // Video Line Map       ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
+  // CaptureGamma         UL = 
+  // ComponentMaxRef      ui32_t = 4095
+  // ComponentMinRef      ui32_t = 0
+  // PixelLayout          byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
+  //    }
 
   if ( PDesc.StoredWidth < 2049 )
     {
-      PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_2K));
+      PDescObj->PictureEssenceCoding.Set(Dict::ul(MDD_JP2KEssenceCompression_2K));
       m_EssenceSubDescriptor->Rsize = 3;
     }
   else
     {
-      PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_4K));
+      PDescObj->PictureEssenceCoding.Set(Dict::ul(MDD_JP2KEssenceCompression_4K));
       m_EssenceSubDescriptor->Rsize = 4;
     }
 
index 2392057e553629f17b11b382b25593f4c021a496..192965d78416c8f4d905a4cb8328bf8589594429 100755 (executable)
@@ -158,7 +158,7 @@ ASDCP::EssenceType(const char* filename, EssenceType_t& type)
        type = ESS_PCM_24b_48k;
       else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) )
        type = ESS_MPEG2_VES;
-      else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCTimedTextDescriptor))) )
+      else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor))) )
        type = ESS_TIMED_TEXT;
     }
 
index 7f89b1fa6235e60c389db3cdb80881f241005670..47a02790d4922bcfe9344098790d4e1f2002b213 100644 (file)
@@ -33,7 +33,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AS_DCP_internal.h"
 #include "KM_xml.h"
 
-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_PACKAGE_LABEL = "File Package: SMPTE 429-5 clip wrapping of D-Cinema Timed Text data";
 static std::string TIMED_TEXT_DEF_LABEL = "Timed Text Track";
 
 
@@ -46,7 +46,7 @@ MIME2str(TimedText::MIMEType_t m)
     return "image/png";
 
   else if ( m == TimedText::MT_OPENTYPE )
-    return "application/x-opentype";
+    return "application/x-font-opentype";
 
   return "application/octet-stream";
 }
@@ -64,8 +64,8 @@ ASDCP::TimedText::DescriptorDump(ASDCP::TimedText::TimedTextDescriptor const& TD
   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());
+  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++ )
@@ -98,8 +98,8 @@ typedef std::map<UUID, UUID> ResourceMap_t;
 
 class ASDCP::TimedText::MXFReader::h__Reader : public ASDCP::h__Reader
 {
-  DCTimedTextDescriptor* m_EssenceDescriptor;
-  ResourceMap_t          m_ResourceMap;
+  MXF::TimedTextDescriptor* m_EssenceDescriptor;
+  ResourceMap_t             m_ResourceMap;
 
   ASDCP_NO_COPY_CONSTRUCT(h__Reader);
 
@@ -122,40 +122,40 @@ ASDCP::TimedText::MXFReader::h__Reader::MD_to_TimedText_TDesc(TimedText::TimedTe
 {
   assert(m_EssenceDescriptor);
   memset(&m_TDesc.AssetID, 0, UUIDlen);
-  MXF::DCTimedTextDescriptor* TDescObj = (MXF::DCTimedTextDescriptor*)m_EssenceDescriptor;
+  MXF::TimedTextDescriptor* TDescObj = (MXF::TimedTextDescriptor*)m_EssenceDescriptor;
 
   TDesc.EditRate = TDescObj->SampleRate;
   TDesc.ContainerDuration = TDescObj->ContainerDuration;
   memcpy(TDesc.AssetID, TDescObj->ResourceID.Value(), UUIDlen);
-  TDesc.NamespaceName = TDescObj->RootNamespaceName;
-  TDesc.EncodingName = TDescObj->UTFEncoding;
+  TDesc.NamespaceName = TDescObj->NamespaceURI;
+  TDesc.EncodingName = TDescObj->UCSEncoding;
 
   Batch<UUID>::const_iterator sdi = TDescObj->SubDescriptors.begin();
-  DCTimedTextResourceDescriptor* DescObject = 0;
+  TimedTextResourceSubDescriptor* DescObject = 0;
   Result_t result = RESULT_OK;
 
   for ( ; sdi != TDescObj->SubDescriptors.end() && KM_SUCCESS(result); sdi++ )
     {
       InterchangeObject* tmp_iobj = 0;
       result = m_HeaderPart.GetMDObjectByID(*sdi, &tmp_iobj);
-      DescObject = static_cast<DCTimedTextResourceDescriptor*>(tmp_iobj);
+      DescObject = static_cast<TimedTextResourceSubDescriptor*>(tmp_iobj);
 
       if ( KM_SUCCESS(result) )
        {
          TimedTextResourceDescriptor TmpResource;
-         memcpy(TmpResource.ResourceID, DescObject->ResourceID.Value(), UUIDlen);
+         memcpy(TmpResource.ResourceID, DescObject->AncillaryResourceID.Value(), UUIDlen);
 
-         if ( DescObject->ResourceMIMEType.find("font/") != std::string::npos )
+         if ( DescObject->MIMEMediaType.find("font/") != std::string::npos )
            TmpResource.Type = MT_OPENTYPE;
 
-         else if ( DescObject->ResourceMIMEType.find("image/png") != std::string::npos )
+         else if ( DescObject->MIMEMediaType.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->ResourceID, *sdi));
+         m_ResourceMap.insert(ResourceMap_t::value_type(DescObject->AncillaryResourceID, *sdi));
        }
       else
        {
@@ -178,8 +178,8 @@ ASDCP::TimedText::MXFReader::h__Reader::OpenRead(char const* filename)
       if ( m_EssenceDescriptor == 0 )
        {
          InterchangeObject* tmp_iobj = 0;
-         result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(DCTimedTextDescriptor), &tmp_iobj);
-         m_EssenceDescriptor = static_cast<DCTimedTextDescriptor*>(tmp_iobj);
+         result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor), &tmp_iobj);
+         m_EssenceDescriptor = static_cast<MXF::TimedTextDescriptor*>(tmp_iobj);
        }
 
       if( ASDCP_SUCCESS(result) )
@@ -203,7 +203,7 @@ ASDCP::TimedText::MXFReader::h__Reader::ReadTimedTextResource(FrameBuffer& Frame
   if ( ! m_File.IsOpen() )
     return RESULT_INIT;
 
-  Result_t result = ReadEKLVFrame(0, FrameBuf, Dict::ul(MDD_DCTimedTextEssence), Ctx, HMAC);
+  Result_t result = ReadEKLVFrame(0, FrameBuf, Dict::ul(MDD_TimedTextEssence), Ctx, HMAC);
 
  if( ASDCP_SUCCESS(result) )
    {
@@ -230,11 +230,11 @@ ASDCP::TimedText::MXFReader::h__Reader::ReadAncillaryResource(const byte_t* uuid
       return RESULT_RANGE;
     }
 
-  DCTimedTextResourceDescriptor* DescObject = 0;
+  TimedTextResourceSubDescriptor* DescObject = 0;
   // get the subdescriptor
   InterchangeObject* tmp_iobj = 0;
   Result_t result = m_HeaderPart.GetMDObjectByID((*ri).second, &tmp_iobj);
-  DescObject = static_cast<DCTimedTextResourceDescriptor*>(tmp_iobj);
+  DescObject = static_cast<TimedTextResourceSubDescriptor*>(tmp_iobj);
 
   if ( KM_SUCCESS(result) )
     {
@@ -247,7 +247,7 @@ ASDCP::TimedText::MXFReader::h__Reader::ReadAncillaryResource(const byte_t* uuid
       // value needed to  complete the HMAC.
       for ( pi = m_HeaderPart.m_RIP.PairArray.begin(); pi != m_HeaderPart.m_RIP.PairArray.end(); pi++, sequence++ )
        {
-         if ( (*pi).BodySID == DescObject->ResourceSID )
+         if ( (*pi).BodySID == DescObject->EssenceStreamID )
            {
              TmpPair = *pi;
              break;
@@ -256,14 +256,14 @@ ASDCP::TimedText::MXFReader::h__Reader::ReadAncillaryResource(const byte_t* uuid
 
       if ( TmpPair.ByteOffset == 0 )
        {
-         DefaultLogSink().Error("Body SID not found in RIP set: %d\n", DescObject->ResourceSID);
+         DefaultLogSink().Error("Body SID not found in RIP set: %d\n", DescObject->EssenceStreamID);
          return RESULT_FORMAT;
        }
 
       if ( KM_SUCCESS(result) )
        {
          FrameBuf.AssetID(uuid);
-         FrameBuf.MIMEType(DescObject->ResourceMIMEType);
+         FrameBuf.MIMEType(DescObject->MIMEMediaType);
 
          // seek tp the start of the partition
          if ( (Kumu::fpos_t)TmpPair.ByteOffset != m_LastPosition )
@@ -279,7 +279,7 @@ ASDCP::TimedText::MXFReader::h__Reader::ReadAncillaryResource(const byte_t* uuid
          if( ASDCP_SUCCESS(result) )
            {
              // check the SID
-             if ( DescObject->ResourceSID != GSPart.BodySID )
+             if ( DescObject->EssenceStreamID != GSPart.BodySID )
                {
                  char buf[64];
                  DefaultLogSink().Error("Generic stream partition body differs: %s\n", RID.EncodeHex(buf, 64));
@@ -288,7 +288,7 @@ ASDCP::TimedText::MXFReader::h__Reader::ReadAncillaryResource(const byte_t* uuid
 
              // read the essence packet
              if( ASDCP_SUCCESS(result) )
-               result = ReadEKLVPacket(0, 1, FrameBuf, Dict::ul(MDD_DCTimedTextDescriptor), Ctx, HMAC);
+               result = ReadEKLVPacket(0, 1, FrameBuf, Dict::ul(MDD_TimedTextDescriptor), Ctx, HMAC);
            }
        }
     }
@@ -408,11 +408,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;
+  ui32_t              m_EssenceStreamID;
 
   ASDCP_NO_COPY_CONSTRUCT(h__Writer);
 
-  h__Writer() : m_ResourceSID(10) {
+  h__Writer() : m_EssenceStreamID(10) {
     memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
   }
 
@@ -431,13 +431,13 @@ ASDCP::Result_t
 ASDCP::TimedText::MXFWriter::h__Writer::TimedText_TDesc_to_MD(TimedText::TimedTextDescriptor& TDesc)
 {
   assert(m_EssenceDescriptor);
-  MXF::DCTimedTextDescriptor* TDescObj = (MXF::DCTimedTextDescriptor*)m_EssenceDescriptor;
+  MXF::TimedTextDescriptor* TDescObj = (MXF::TimedTextDescriptor*)m_EssenceDescriptor;
 
   TDescObj->SampleRate = TDesc.EditRate;
   TDescObj->ContainerDuration = TDesc.ContainerDuration;
   TDescObj->ResourceID.Set(TDesc.AssetID);
-  TDescObj->RootNamespaceName = TDesc.NamespaceName;
-  TDescObj->UTFEncoding = TDesc.EncodingName;
+  TDescObj->NamespaceURI = TDesc.NamespaceName;
+  TDescObj->UCSEncoding = TDesc.EncodingName;
 
   return RESULT_OK;
 }
@@ -454,7 +454,7 @@ ASDCP::TimedText::MXFWriter::h__Writer::OpenWrite(char const* filename, ui32_t H
   if ( ASDCP_SUCCESS(result) )
     {
       m_HeaderSize = HeaderSize;
-      m_EssenceDescriptor = new DCTimedTextDescriptor();
+      m_EssenceDescriptor = new MXF::TimedTextDescriptor();
       result = m_State.Goto_INIT();
     }
 
@@ -474,16 +474,16 @@ ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedT
 
   for ( ri = m_TDesc.ResourceList.begin() ; ri != m_TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ )
     {
-      DCTimedTextResourceDescriptor* resourceSubdescriptor = new DCTimedTextResourceDescriptor;
+      TimedTextResourceSubDescriptor* resourceSubdescriptor = new TimedTextResourceSubDescriptor;
       GenRandomValue(resourceSubdescriptor->InstanceUID);
-      resourceSubdescriptor->ResourceID.Set((*ri).ResourceID);
-      resourceSubdescriptor->ResourceMIMEType = MIME2str((*ri).Type);
-      resourceSubdescriptor->ResourceSID = m_ResourceSID++;
+      resourceSubdescriptor->AncillaryResourceID.Set((*ri).ResourceID);
+      resourceSubdescriptor->MIMEMediaType = MIME2str((*ri).Type);
+      resourceSubdescriptor->EssenceStreamID = m_EssenceStreamID++;
       m_EssenceSubDescriptorList.push_back((FileDescriptor*)resourceSubdescriptor);
       m_EssenceDescriptor->SubDescriptors.push_back(resourceSubdescriptor->InstanceUID);
     }
 
-  m_ResourceSID = 10;
+  m_EssenceStreamID = 10;
 
   if ( ASDCP_SUCCESS(result) )
     {
@@ -491,7 +491,7 @@ ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedT
       AddDMSegment(m_TDesc.EditRate, 24, TIMED_TEXT_DEF_LABEL,
                   UL(Dict::ul(MDD_PictureDataDef)), TIMED_TEXT_PACKAGE_LABEL);
 
-      AddEssenceDescriptor(UL(Dict::ul(MDD_DCTimedTextWrapping)));
+      AddEssenceDescriptor(UL(Dict::ul(MDD_TimedTextWrapping)));
 
       result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
       
@@ -501,7 +501,7 @@ ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedT
 
   if ( ASDCP_SUCCESS(result) )
     {
-      memcpy(m_EssenceUL, Dict::ul(MDD_DCTimedTextEssence), SMPTE_UL_LENGTH);
+      memcpy(m_EssenceUL, Dict::ul(MDD_TimedTextEssence), SMPTE_UL_LENGTH);
       m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
       result = m_State.Goto_READY();
     }
@@ -558,11 +558,11 @@ ASDCP::TimedText::MXFWriter::h__Writer::WriteAncillaryResource(const ASDCP::Time
 
   GSPart.ThisPartition = here;
   GSPart.PreviousPartition = m_HeaderPart.m_RIP.PairArray.back().ByteOffset;
-  GSPart.BodySID = m_ResourceSID;
+  GSPart.BodySID = m_EssenceStreamID;
   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)));
+  m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(m_EssenceStreamID++, here));
+  GSPart.EssenceContainers.push_back(UL(Dict::ul(MDD_TimedTextEssence)));
   UL TmpUL(Dict::ul(MDD_GenericStreamPartition));
   Result_t result = GSPart.WriteToFile(m_File, TmpUL);
 
index 31d4f3ecf70a3a5964ffeb444e083d3a62f59c11..8ea755561f9559053fb3affad84968426f8cf3e0 100755 (executable)
@@ -49,6 +49,7 @@ namespace Kumu
 
     public:
       static const Result_t& Find(int);
+      static Result_t Delete(int);
 
       Result_t(int v, const char* l);
       ~Result_t();
index a76df09136437523715e5490174ea26a14d1f003..0c4a3bf69f427cbfabdfb54dbc4c36688fbe035d 100755 (executable)
@@ -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
@@ -41,27 +41,21 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <unistd.h>
 #endif
 
+//------------------------------------------------------------------------------------------
+//
 
 void
-Kumu::StdioLogSink::vLogf(ILogSink::LogType_t type, const char* fmt, va_list* list)
+Kumu::ILogSink::vLogf(LogType_t type, const char* fmt, va_list* list)
 {
-  AutoMutex L(m_Lock);
+  char buf[MaxLogLength];
+  vsnprintf(buf, MaxLogLength, fmt, *list);
 
-  switch ( type )
-    {
-    case LOG_CRIT:   fprintf(m_stream, "[%d CRT]: ", getpid()); break;
-    case LOG_ALERT:  fprintf(m_stream, "[%d ALR]: ", getpid()); break;
-    case LOG_NOTICE: fprintf(m_stream, "[%d NTC]: ", getpid()); break;
-    case LOG_ERROR:  fprintf(m_stream, "[%d ERR]: ", getpid()); break;
-    case LOG_WARN:   fprintf(m_stream, "[%d WRN]: ", getpid()); break;
-    case LOG_INFO:   fprintf(m_stream, "[%d INF]: ", getpid()); break;
-    case LOG_DEBUG:  fprintf(m_stream, "[%d DBG]: ", getpid()); break;
-    default:         fprintf(m_stream, "[%d DFL]: ", getpid());
-    }
-
-  vfprintf(m_stream, fmt, *list);
+  WriteEntry(LogEntry(getpid(), type, buf));
 }
 
+//------------------------------------------------------------------------------------------
+//
+
 static Kumu::ILogSink* s_DefaultLogSink;
 static Kumu::StdioLogSink s_StderrLogSink;
 
@@ -82,74 +76,155 @@ Kumu::DefaultLogSink()
   return *s_DefaultLogSink;
 }
 
+//------------------------------------------------------------------------------------------
+//
+
+void
+Kumu::StdioLogSink::WriteEntry(const LogEntry& Entry)
+{
+  AutoMutex L(m_Lock);
+  std::string buf;
+  if ( Entry.CreateStringWithFilter(m_filter, buf) )
+    fputs(buf.c_str(), m_stream);
+}
+
 //---------------------------------------------------------------------------------
+
 #ifdef KM_WIN32
+//
+void
+Kumu::WinDbgLogSink::WriteEntry(const LogEntry& Entry)
+{
+  AutoMutex L(m_Lock);
+  std::string buf;
+  if ( Entry.CreateStringWithFilter(m_filter, buf) )
+    ::OutputDebugString(buf.c_str());
+}
+#endif
+
+//------------------------------------------------------------------------------------------
+//
 
+#ifndef KM_WIN32
 //
 void
-Kumu::WinDbgLogSink::vLogf(ILogSink::LogType_t type, const char* fmt, va_list* list)
+Kumu::StreamLogSink::WriteEntry(const LogEntry& Entry)
 {
   AutoMutex L(m_Lock);
-  char msg_buf[MaxLogLength];
+  std::string buf;
+  if ( Entry.CreateStringWithFilter(m_filter, buf) )
+    write(m_fd, buf.c_str(), buf.size());
+}
+#endif
 
-  DWORD pid = GetCurrentProcessId();
+//------------------------------------------------------------------------------------------
 
-  switch ( type )
+bool
+Kumu::LogEntry::CreateStringWithFilter(i32_t filter, std::string& out_buf) const
+{
+  const char* p = 0;
+
+  switch ( Type )
     {
-    case LOG_CRIT:   snprintf(msg_buf, MaxLogLength, "[%d CRT]: ", pid); break;
-    case LOG_ALERT:  snprintf(msg_buf, MaxLogLength, "[%d ALR]: ", pid); break;
-    case LOG_NOTICE: snprintf(msg_buf, MaxLogLength, "[%d NTC]: ", pid); break;
-    case LOG_ERROR:  snprintf(msg_buf, MaxLogLength, "[%d ERR]: ", pid); break;
-    case LOG_WARN:   snprintf(msg_buf, MaxLogLength, "[%d WRN]: ", pid); break;
-    case LOG_INFO:   snprintf(msg_buf, MaxLogLength, "[%d INF]: ", pid); break;
-    case LOG_DEBUG:  snprintf(msg_buf, MaxLogLength, "[%d DBG]: ", pid); break;
-    default:         snprintf(msg_buf, MaxLogLength, "[%d DFL]: ", pid);
+    case LOG_CRIT:
+      if ( (filter & LOG_ALLOW_CRIT) != 0 )
+       p = " CRT";
+      break;
+
+    case LOG_ALERT:
+      if ( (filter & LOG_ALLOW_ALERT) != 0 )
+       p = " ALR";
+      break;
+
+    case LOG_NOTICE:
+      if ( (filter & LOG_ALLOW_NOTICE) != 0 )
+       p = " NTC";
+      break;
+
+    case LOG_ERROR:
+      if ( (filter & LOG_ALLOW_ERROR) != 0 )
+       p = " ERR";
+      break;
+
+    case LOG_WARN:
+      if ( (filter & LOG_ALLOW_WARN) != 0 )
+       p = " WRN";
+      break;
+
+    case LOG_INFO:
+      if ( (filter & LOG_ALLOW_INFO) != 0 )
+       p = " INF";
+      break;
+
+    case LOG_DEBUG:
+      if ( (filter & LOG_ALLOW_DEBUG) != 0 )
+       p = " DBG";
+      break;
+
+    default:
+      if ( (filter & LOG_ALLOW_DEFAULT) != 0 )
+       p = " DFL";
+      break;
     }
-  
-  ui32_t len = strlen(msg_buf);
-  vsnprintf(msg_buf + len, MaxLogLength - len, fmt, *list);
-  msg_buf[MaxLogLength-1] = 0;
-  ::OutputDebugString(msg_buf);
-}
 
-#else
+  if ( p == 0 )
+    return false;
 
-void
-Kumu::StreamLogSink::vLogf(ILogSink::LogType_t type, const char* fmt, va_list* list)
-{
-  AutoMutex L(m_Lock);
-  char msg_buf[MaxLogLength];
-  char ts_buf[MaxLogLength];
-  Timestamp Now;
+  char buf[64];
+  out_buf = "[";
 
-  switch ( type )
+  if ( (filter & LOG_ALLOW_TIMESTAMP) != 0 )
     {
-    case LOG_CRIT:   snprintf(msg_buf, MaxLogLength, "[%s %d CRT]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
-    case LOG_ALERT:  snprintf(msg_buf, MaxLogLength, "[%s %d ALR]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
-    case LOG_NOTICE: snprintf(msg_buf, MaxLogLength, "[%s %d NTC]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
-    case LOG_ERROR:  snprintf(msg_buf, MaxLogLength, "[%s %d ERR]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
-    case LOG_WARN:   snprintf(msg_buf, MaxLogLength, "[%s %d WRN]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
-    case LOG_INFO:   snprintf(msg_buf, MaxLogLength, "[%s %d INF]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
-    case LOG_DEBUG:  snprintf(msg_buf, MaxLogLength, "[%s %d DBG]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
-    default:         snprintf(msg_buf, MaxLogLength, "[%s %d DFL]: ",
-                             Now.EncodeString(ts_buf, MaxLogLength), getpid());
+      Timestamp Now;
+      out_buf += Now.EncodeString(buf, 64);
+
+      if ( (filter & LOG_ALLOW_PID) != 0 )
+       out_buf += " ";
+    }
+
+  if ( (filter & LOG_ALLOW_PID) != 0 )
+    {
+      snprintf(buf, 64, "%d", PID);
+      out_buf += buf;
     }
-  
-  ui32_t len = strlen(msg_buf);
-  vsnprintf(msg_buf + len, MaxLogLength - len, fmt, *list);
-  msg_buf[MaxLogLength-1] = 0;
-  write(m_fd, msg_buf, strlen(msg_buf));
+
+  out_buf += "] " + Msg;
+  return true;
 }
-#endif
 
 
+//
+ui32_t
+Kumu::LogEntry::ArchiveLength() const
+{
+  return sizeof(ui32_t)
+    + EventTime.ArchiveLength()
+    + sizeof(ui32_t)
+    + sizeof(ui32_t) + Msg.size();
+}
+
+//
+bool
+Kumu::LogEntry::Archive(Kumu::MemIOWriter* Writer) const
+{
+  if ( ! Writer->WriteUi32BE(PID) ) return false;
+  if ( ! EventTime.Archive(Writer) ) return false;
+  if ( ! Writer->WriteUi32BE(Type) ) return false;
+  if ( ! ArchiveString(*Writer, Msg) ) return false;
+  return true;
+}
+
+//
+bool
+Kumu::LogEntry::Unarchive(Kumu::MemIOReader* Reader)
+{
+  if ( ! Reader->ReadUi32BE(&PID) ) return false;
+  if ( ! EventTime.Unarchive(Reader) ) return false;
+  if ( ! Reader->ReadUi32BE((ui32_t*)&Type) ) return false;
+  if ( ! UnarchiveString(*Reader, Msg) ) return false;
+  return true;
+}
+
 //
 // end
 //
index 9838f4ce519734356154737d2e415374dc541113..0042119a2aa67b01a450c38279bb01b853bad2c8 100755 (executable)
@@ -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
@@ -35,12 +35,15 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <KM_platform.h>
 #include <KM_mutex.h>
+#include <KM_util.h>
 #include <stdarg.h>
 #include <errno.h>
 
-#define LOG_MSG_IMPL(t) va_list args; va_start(args, fmt); vLogf((t), fmt, &args); va_end(args)
-
-
+#define LOG_MSG_IMPL(t) \
+  va_list args; \
+  va_start(args, fmt); \
+  vLogf((t), fmt, &args); \
+  va_end(args)
 
 // Returns RESULT_PTR if the given argument is NULL.
 # define KM_TEST_NULL_L(p) \
@@ -69,30 +72,101 @@ namespace Kumu
   //---------------------------------------------------------------------------------
   // message logging
 
-  // Error and debug messages will be delivered to an object having this interface.
-  // The default implementation sends only LOG_ERROR and LOG_WARN messages to stderr.
-  // To receive LOG_INFO or LOG_DEBUG messages, or to send messages somewhere other
-  // than stderr, implement this interface and register an instance of your new class
-  // by calling SetDefaultLogSink().
+  // Log messages are recorded by objects which implement the interface given
+  // in the class ILogSink below. The library maintains a pointer to a default
+  // log sink which is used by the library to report messages.
+  //
+
+  // types of log messages
+  enum LogType_t {
+    LOG_DEBUG,    // detailed developer info
+    LOG_INFO,     // developer info
+    LOG_WARN,     // library non-fatal or near-miss error
+    LOG_ERROR,    // library fatal error
+    LOG_NOTICE,   // application user info
+    LOG_ALERT,    // application non-fatal or near-miss error
+    LOG_CRIT,     // application fatal error
+  };
+
+
+  // OR these values together to come up with sink filter flags.
+  // The default mask is 0x0000ffff (no time stamp, no pid, all messages).
+  const i32_t LOG_ALLOW_TIMESTAMP = 0x01000000;
+  const i32_t LOG_ALLOW_PID       = 0x02000000;
+
+  const i32_t LOG_ALLOW_DEBUG     = 0x00000001;
+  const i32_t LOG_ALLOW_INFO      = 0x00000002;
+  const i32_t LOG_ALLOW_WARN      = 0x00000004;
+  const i32_t LOG_ALLOW_ERROR     = 0x00000008;
+  const i32_t LOG_ALLOW_NOTICE    = 0x00000010;
+  const i32_t LOG_ALLOW_ALERT     = 0x00000020;
+  const i32_t LOG_ALLOW_CRIT      = 0x00000040;
+
+  const i32_t LOG_ALLOW_DEFAULT   = 0x00008000; // show messages having an unknown type
+  const i32_t LOG_ALLOW_NONE      = 0x00000000;
+  const i32_t LOG_ALLOW_MESSAGES  = 0x0000ffff;
+  const i32_t LOG_ALLOW_ANY       = 0xffffffff;
+
+  // A log message with environmental metadata
+ class LogEntry : public IArchive
+  {
+  public:
+    ui32_t      PID;
+    Timestamp   EventTime;
+    LogType_t   Type;
+    std::string Msg;
+
+    LogEntry() {}
+    LogEntry(ui32_t pid, LogType_t t, const char* m) : PID(pid), Type(t), Msg(m) { assert(m); }
+    virtual ~LogEntry() {}
+
+    bool   CreateStringWithFilter(i32_t, std::string&) const;
+
+    // IArchive
+    bool   HasValue() const { return ! Msg.empty(); }
+    ui32_t ArchiveLength() const;
+    bool   Archive(MemIOWriter* Writer) const;
+    bool   Unarchive(MemIOReader* Reader);
+  };
+
+
+  typedef ArchivableList<LogEntry> LogEntryList_t;
+  
+  //
   class ILogSink
     {
-    public:
-      enum LogType_t { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR,
-                      LOG_NOTICE, LOG_ALERT, LOG_CRIT };
+    protected:
+      i32_t m_filter;
 
+    public:
       virtual ~ILogSink() {}
 
-      void Critical(const char* fmt, ...) { LOG_MSG_IMPL(LOG_CRIT); }
-      void Alert(const char* fmt, ...)    { LOG_MSG_IMPL(LOG_ALERT); }
-      void Notice(const char* fmt, ...)   { LOG_MSG_IMPL(LOG_NOTICE); }
+      void  SetFilterFlags(i32_t f) { m_filter = f; }
+      i32_t GetFilterFlags() const  { return m_filter; }
+      void  SetFilterFlag(i32_t f) { m_filter |= f; }
+      void  UnsetFilterFlag(i32_t f) { m_filter &= ~f; }
+      bool  TestFilterFlag(i32_t f) const  { return ((m_filter & f) != 0); }
+
+      // library messages
       void Error(const char* fmt, ...)    { LOG_MSG_IMPL(LOG_ERROR); }
       void Warn(const char* fmt, ...)     { LOG_MSG_IMPL(LOG_WARN);  }
       void Info(const char* fmt, ...)     { LOG_MSG_IMPL(LOG_INFO);  }
       void Debug(const char* fmt, ...)    { LOG_MSG_IMPL(LOG_DEBUG); }
-      void Logf(ILogSink::LogType_t type, const char* fmt, ...) { LOG_MSG_IMPL(type); }
-      virtual void vLogf(LogType_t, const char*, va_list*) = 0; // log a formatted string with a va_list struct
+
+      // application messages
+      void Critical(const char* fmt, ...) { LOG_MSG_IMPL(LOG_CRIT); }
+      void Alert(const char* fmt, ...)    { LOG_MSG_IMPL(LOG_ALERT); }
+      void Notice(const char* fmt, ...)   { LOG_MSG_IMPL(LOG_NOTICE); }
+
+      // message with type
+      void Logf(LogType_t type, const char* fmt, ...) { LOG_MSG_IMPL(type); }
+
+      // actual log sink input
+      virtual void vLogf(LogType_t, const char*, va_list*);
+      virtual void WriteEntry(const LogEntry&) = 0;
     };
 
+
   // Sets the internal default sink to the given receiver. If the given value
   // is zero, sets the default sink to the internally allocated stderr sink.
   void SetDefaultLogSink(ILogSink* = 0);
@@ -100,7 +174,67 @@ namespace Kumu
   // Returns the internal default sink.
   ILogSink& DefaultLogSink();
 
+
+  // Sets a log sink as the default until the object is destroyed.
+  // The original default sink is saved and then restored on delete.
+  class LogSinkContext
+  {
+    KM_NO_COPY_CONSTRUCT(LogSinkContext);
+    LogSinkContext();
+    ILogSink* m_orig;
+
+  public:
+    LogSinkContext(ILogSink& sink) {
+      m_orig = &DefaultLogSink();
+      SetDefaultLogSink(&sink);
+    }
+
+    ~LogSinkContext() {
+      SetDefaultLogSink(m_orig);
+    }
+  };
+
+  //------------------------------------------------------------------------------------------
   //
+
+  // write messages to two subordinate log sinks 
+  class TeeLogSink : public ILogSink
+  {
+    KM_NO_COPY_CONSTRUCT(TeeLogSink);
+    TeeLogSink();
+
+    ILogSink& m_a;
+    ILogSink& m_b;
+
+  public:
+    TeeLogSink(ILogSink& a, ILogSink& b) : m_a(a), m_b(b) {}
+    virtual ~TeeLogSink() {}
+
+    void WriteEntry(const LogEntry& Entry) {
+      m_a.WriteEntry(Entry);
+      m_a.WriteEntry(Entry);
+    }
+  };
+
+  // collect log messages into the given list
+  class EntryListLogSink : public ILogSink
+  {
+    KM_NO_COPY_CONSTRUCT(EntryListLogSink);
+    EntryListLogSink();
+
+    LogEntryList_t& m_Target;
+
+  public:
+    EntryListLogSink(LogEntryList_t& target) : m_Target(target) {}
+    virtual ~EntryListLogSink() {}
+
+    void WriteEntry(const LogEntry& Entry) {
+      m_Target.push_back(Entry);
+    }
+  };
+
+
+  // write messages to a POSIX stdio stream
   class StdioLogSink : public ILogSink
     {
       Mutex m_Lock;
@@ -111,11 +245,12 @@ namespace Kumu
       StdioLogSink() : m_stream(stderr) {};
       StdioLogSink(FILE* stream) : m_stream(stream) {}
       virtual ~StdioLogSink() {}
-      virtual void vLogf(LogType_t, const char*, va_list*);
+
+    void WriteEntry(const LogEntry&);
     };
 
 #ifdef KM_WIN32
-  //
+  // write messages to the Win32 debug stream
   class WinDbgLogSink : public ILogSink
     {
       Mutex m_Lock;
@@ -124,12 +259,13 @@ namespace Kumu
     public:
       WinDbgLogSink() {}
       virtual ~WinDbgLogSink() {}
-      virtual void vLogf(LogType_t, const char*, va_list*);
-    };
 
-#else
+      void WriteEntry(const LogEntry&);
+    };
+#endif
 
-  //
+#ifndef KM_WIN32
+  // write messages to a POSIX file descriptor
   class StreamLogSink : public ILogSink
     {
       Mutex m_Lock;
@@ -140,10 +276,12 @@ namespace Kumu
     public:
       StreamLogSink(int fd) : m_fd(fd) {}
       virtual ~StreamLogSink() {}
-      virtual void vLogf(LogType_t, const char*, va_list*);
+
+      void WriteEntry(const LogEntry&);
     };
 #endif
 
+
 } // namespace Kumu
 
 #endif // _KM_LOG_H_
index 483bbde1bb2239c469480050f5e3013c1440ed40..c034e82fd77548526afa00ff3f8ee323683ad01b 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2006, John Hurst
+Copyright (c) 2006-2007, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -61,8 +61,8 @@ namespace Kumu
       inline void    Reset() { m_size = 0; }
       inline byte_t* Data() { return m_p; }
       inline byte_t* CurrentData() { return m_p + m_size; }
-      inline ui32_t Length() { return m_size; }
-      inline ui32_t Remainder() { return m_capacity - m_size; }
+      inline ui32_t  Length() { return m_size; }
+      inline ui32_t  Remainder() { return m_capacity - m_size; }
 
       inline bool AddOffset(ui32_t offset) {
        if ( ( m_size + offset ) > m_capacity )
index 76b793901a5eb4e2efc0ad7d85169e5872c3d69d..d1e82e100f082838cb52fb35d0982d99cad49366 100755 (executable)
@@ -49,7 +49,7 @@ struct map_entry_t
   Kumu::Result_t* result;
 };
 
-const ui32_t MapMax = 512;
+const ui32_t MapMax = 1024;
 const ui32_t MapSize = MapMax * (sizeof(struct map_entry_t));
 static bool s_MapInit = false;
 static struct map_entry_t s_ResultMap[MapSize];
@@ -71,10 +71,39 @@ Kumu::Result_t::Find(int v)
   return RESULT_FAIL;
 }
 
+//
+Kumu::Result_t
+Kumu::Result_t::Delete(int v)
+{
+  if ( v >= RESULT_NOTAFILE.Value() )
+    {
+      DefaultLogSink().Error("Cannot delete core result code: %ld\n", v);
+      return RESULT_FAIL;
+    }
+
+  for ( ui32_t i = 0; s_ResultMap[i].result != 0 && i < MapMax; i++ )
+    {
+      if ( s_ResultMap[i].rcode == v )
+       {
+         s_ResultMap[i].rcode = 0;
+         s_ResultMap[i++].result = 0;
+
+         for ( ; s_ResultMap[i].result != 0 && i < MapMax; i++ )
+           s_ResultMap[i-1] = s_ResultMap[i];
+
+         return RESULT_OK;
+       }
+    }
+
+  return RESULT_FALSE;
+}
+
+
 //
 Kumu::Result_t::Result_t(int v, const char* l) : value(v), label(l)
 {
   assert(l);
+  assert(value < (int)MapMax);
 
   if ( v == 0 )
     return;
@@ -875,6 +904,15 @@ Kumu::Timestamp::DecodeString(const char* datestr)
          TmpStamp.Second = atoi(datestr + 17);
        }
 
+      if ( datestr[19] == '.' )
+       {
+         if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) && isdigit(datestr[22]) ) )
+           return false;
+         
+         // we don't carry the ms value
+         datestr += 4;
+       }
+
       if ( datestr[19] == '-' || datestr[19] == '+' )
        {
          if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
@@ -1047,24 +1085,32 @@ Kumu::ByteString::Set(const ByteString& Buf)
 
 
 // Sets the size of the internally allocate buffer.
-// Resets content length to zero.
 Kumu::Result_t
 Kumu::ByteString::Capacity(ui32_t cap_size)
 {
-  if ( m_Capacity < cap_size )
+  if ( m_Capacity >= cap_size )
+    return RESULT_OK;
+
+  byte_t* tmp_data = 0;
+  if ( m_Data != 0 )
     {
-      if ( m_Data != 0 )
+      if ( m_Length > 0 )
+       tmp_data = m_Data;
+      else
        free(m_Data);
+    }
                
-      m_Data = (byte_t*)malloc(cap_size);
-               
-      if ( m_Data == 0 )
-       return RESULT_ALLOC;
-               
-      m_Capacity = cap_size;
-      m_Length = 0;
+  if ( ( m_Data = (byte_t*)malloc(cap_size) ) == 0 )
+    return RESULT_ALLOC;
+
+  if ( tmp_data != 0 )
+    {
+      assert(m_Length > 0);
+      memcpy(m_Data, tmp_data, m_Length);
+      free(tmp_data);
     }
-       
+               
+  m_Capacity = cap_size;
   return RESULT_OK;
 }
 
index 244fc4513e34ac6aa38c024707688e99495539fb..f7176f6aa04457a6017bafa3322668b198fa94cf 100755 (executable)
@@ -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
@@ -170,11 +170,59 @@ namespace Kumu
     {
     public:
       virtual ~IArchive(){}
-      virtual bool HasValue() const = 0;
-      virtual bool Archive(MemIOWriter* Writer) const = 0;
-      virtual bool Unarchive(MemIOReader* Reader) = 0;
+      virtual bool   HasValue() const = 0;
+      virtual ui32_t ArchiveLength() const = 0;
+      virtual bool   Archive(MemIOWriter* Writer) const = 0;
+      virtual bool   Unarchive(MemIOReader* Reader) = 0;
     };
 
+  //
+  template <class T>
+  class ArchivableList : public std::list<T>, public IArchive
+    {
+    public:
+      ArchivableList() {}
+      virtual ~ArchivableList() {}
+
+      bool HasValue() const { return ! this->empty(); }
+
+      ui32_t ArchiveLength() const
+      {
+       ui32_t arch_size = sizeof(ui32_t);
+
+       typename ArchivableList<T>::const_iterator i = this->begin();
+       for ( ; i != this->end(); i++ )
+         arch_size += i->ArchiveLength();
+
+       return arch_size;
+      }
+
+      bool Unarchive(Kumu::MemIOReader* Reader)
+       {
+         if ( Reader == 0 ) return false;
+         ui32_t read_size = 0;
+         if ( ! Reader->ReadUi32BE(&read_size) ) return false;
+         for ( ui32_t i = 0; i < read_size; i++ )
+           {
+             T TmpTP;
+             if ( ! TmpTP.Unarchive(Reader) ) return false;
+             this->push_back(TmpTP);
+           }
+
+         return true;
+       }
+
+      bool Archive(Kumu::MemIOWriter* Writer) const
+       {
+         if ( Writer == 0 ) return false;
+         if ( ! Writer->WriteUi32BE(this->size()) ) return false;
+         typename ArchivableList<T>::const_iterator i = this->begin();
+         for ( ; i != this->end(); i++ )
+           if ( ! i->Archive(Writer) ) return false;
+
+         return true;
+       }
+    };
 
   //
   // the base of all identifier classes, Identifier is not usually used directly
@@ -256,6 +304,8 @@ namespace Kumu
 
       inline bool HasValue() const { return m_HasValue; }
 
+      inline ui32_t ArchiveLength() const { return SIZE; }
+
       inline bool Unarchive(Kumu::MemIOReader* Reader) {
        m_HasValue = Reader->ReadRaw(m_Value, SIZE);
        return m_HasValue;
@@ -266,42 +316,6 @@ namespace Kumu
       }
     };
 
-  //
-  template <class T>
-  class IdentifierList : public std::list<T>, public IArchive
-    {
-    public:
-      IdentifierList() {}
-      virtual ~IdentifierList() {}
-
-      bool HasValue() const { return ! this->empty(); }
-
-      bool Unarchive(Kumu::MemIOReader* Reader)
-       {
-         if ( Reader == 0 )return false;
-         ui32_t read_size = 0;
-         if ( ! Reader->ReadUi32BE(&read_size) ) return false;
-         for ( ui32_t i = 0; i < read_size; i++ )
-           {
-             T TmpTP;
-             if ( ! TmpTP.Unarchive(Reader) ) return false;
-             this->push_back(TmpTP);
-           }
-
-         return true;
-       }
-
-      bool Archive(Kumu::MemIOWriter* Writer) const
-       {
-         if ( Writer == 0 )return false;
-         if ( ! Writer->WriteUi32BE(this->size()) ) return false;
-         typename IdentifierList<T>::const_iterator i = this->begin();
-         for ( ; i != this->end(); i++ )
-           if ( ! (*i).Archive(Writer) ) return false;
-
-         return true;
-       }
-    };
 
   // UUID
   //
@@ -388,9 +402,10 @@ namespace Kumu
       // | 16 bits int, big-endian |    8 bits   |   8 bits  |   8 bits   |    8 bits    |    8 bits    |
       // |        Year A.D         | Month(1-12) | Day(1-31) | Hour(0-23) | Minute(0-59) | Second(0-59) |
       //
-      virtual bool HasValue() const;
-      virtual bool Archive(MemIOWriter* Writer) const;
-      virtual bool Unarchive(MemIOReader* Reader);
+      virtual bool   HasValue() const;
+      virtual ui32_t ArchiveLength() const { return 8L; }
+      virtual bool   Archive(MemIOWriter* Writer) const;
+      virtual bool   Unarchive(MemIOReader* Reader);
     };
 
   //
@@ -408,8 +423,7 @@ namespace Kumu
       ByteString(ui32_t cap);
       virtual ~ByteString();
 
-      // Sets the size of the internally allocated buffer.
-      // Resets content Size to zero.
+      // Sets or resets the size of the internally allocated buffer.
       Result_t Capacity(ui32_t cap);
 
       Result_t Append(const ByteString&);
@@ -437,6 +451,8 @@ namespace Kumu
 
       inline virtual bool HasValue() const { return m_Length > 0; }
 
+      inline virtual ui32_t ArchiveLength() const { return m_Length; }
+
       inline virtual bool Archive(MemIOWriter* Writer) const {
        assert(Writer);
        if ( ! Writer->WriteUi32BE(m_Length) ) return false;
index c7ddd7cbe4dbfc2924ed0b58e304d8cfe97931c1..a88fa815557922da10c08baf20a281977b7d7229 100644 (file)
@@ -798,39 +798,39 @@ 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_ResourceID" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 259
-      0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x04 },
-      {0}, false, "DCTimedTextDescriptor_UTFEncoding" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 260
-      0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x05 },
-      {0}, false, "DCTimedTextDescriptor_RootNamespaceName" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 261
-      0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x06 },
-      {0}, false, "DCTimedTextResourceDescriptor" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 262
-      0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x07 },
-      {0}, false, "DCTimedTextResourceDescriptor_ResourceID" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 263
-      0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x08 },
-      {0}, false, "DCTimedTextResourceDescriptor_ResourceMIMEType" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 264
-      0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0x09 },
-    {0}, false, "DCTimedTextResourceDescriptor_ResourceSID" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x09, // 255
+      0x0d, 0x01, 0x03, 0x01, 0x02, 0x13, 0x01, 0x01 },
+      {0}, false, "TimedTextWrapping" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01, 0x09, // 256
+      0x0d, 0x01, 0x03, 0x01, 0x17, 0x01, 0x0b, 0x01 },
+      {0}, false, "TimedTextEssence" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x7f, 0x01, 0x01, // 257
+      0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x64, 0x00 },
+      {0}, false, "TimedTextDescriptor" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0c, // 258
+      0x01, 0x01, 0x15, 0x12, 0x00, 0x00, 0x00, 0x00 },
+      {0}, false, "TimedTextDescriptor_ResourceID" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0c, // 259
+      0x04, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 },
+      {0}, false, "TimedTextDescriptor_UCSEncoding" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x08, // 260
+      0x01, 0x02, 0x01, 0x05, 0x01, 0x00, 0x00, 0x00 },
+      {0}, false, "TimedTextDescriptor_NamespaceURI" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x7f, 0x01, 0x01, // 261
+      0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x65, 0x00 },
+      {0}, false, "TimedTextResourceSubDescriptor" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0c, // 262
+      0x01, 0x01, 0x15, 0x13, 0x00, 0x00, 0x00, 0x00 },
+      {0}, false, "TimedTextResourceSubDescriptor_AncillaryResourceID" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x07, // 263
+      0x04, 0x09, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 },
+      {0}, false, "TimedTextResourceSubDescriptor_MIMEMediaType" },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x04, // 264
+      0x01, 0x03, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00 },
+      {0}, false, "TimedTextResourceSubDescriptor_EssenceStreamID" },
   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x04, // 265
       0x06, 0x10, 0x10, 0x05, 0x01, 0x02, 0x11, 0x00 },
-    {0}, false, "GenericStreamPartition" },
+      {0}, false, "GenericStreamPartition" },
   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 266
       0x04, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
     {0x02, 0x01}, false, "DMSegment_DataDefinition" },
@@ -840,9 +840,10 @@ static const ASDCP::MDDEntry s_MDD_Table[] = {
   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 268
       0x01, 0x07, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00 },
     {0x61, 0x02}, false, "DMSegment_TrackIDList" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x00, 0x01, 0x01, 0x01, // 269
-      0x0d, 0x01, 0x03, 0x01, 0xfa, 0xce, 0x00, 0xf6 },
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x7f, 0x01, 0x01, // 269
+      0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x71, 0x00 },
     {0}, false, "StereoscopicPictureSubDescriptor" },
+
   { {0}, {0}, false, 0 }
 };
 
index 4218f9d24e652193afe46efff0fd6a9d32c78fe5..e3145f5be50d5716135a1f7a24b6230195a03c87 100755 (executable)
--- a/src/MDD.h
+++ b/src/MDD.h
@@ -290,21 +290,22 @@ 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_ResourceID, // 258
-       MDD_DCTimedTextDescriptor_UTFEncoding, // 259
-       MDD_DCTimedTextDescriptor_RootNamespaceName, // 260
-       MDD_DCTimedTextResourceDescriptor, // 261
-       MDD_DCTimedTextResourceDescriptor_ResourceID, // 262
-       MDD_DCTimedTextResourceDescriptor_ResourceMIMEType, // 263
-       MDD_DCTimedTextResourceDescriptor_ResourceSID, // 264
+       MDD_TimedTextWrapping, // 255
+       MDD_TimedTextEssence, // 256
+       MDD_TimedTextDescriptor, // 257
+       MDD_TimedTextDescriptor_ResourceID, // 258
+       MDD_TimedTextDescriptor_UCSEncoding, // 259
+       MDD_TimedTextDescriptor_NamespaceURI, // 260
+       MDD_TimedTextResourceSubDescriptor, // 261
+       MDD_TimedTextResourceSubDescriptor_AncillaryResourceID, // 262
+       MDD_TimedTextResourceSubDescriptor_MIMEMediaType, // 263
+       MDD_TimedTextResourceSubDescriptor_EssenceStreamID, // 264
        MDD_GenericStreamPartition, // 265
        MDD_DMSegment_DataDefinition, // 266
        MDD_DMSegment_Duration, // 267
        MDD_DMSegment_TrackIDList, // 268
        MDD_StereoscopicPictureSubDescriptor, // 269
+       MDD_Max,
     }; // enum MDD_t
 } // namespaceASDCP
 
index f3c244907af75ba2fe6a7b70fa53b015b5e0c2a2..6a9b14d47dca824db2cd5aa00242bcc614c30e15 100755 (executable)
--- a/src/MXF.h
+++ b/src/MXF.h
@@ -78,15 +78,16 @@ namespace ASDCP
                return str_buf;
              }
 
-             inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+             inline bool HasValue() const { return true; }
+             inline ui32_t ArchiveLength() const { return sizeof(ui32_t) + sizeof(ui64_t); }
+
+             inline bool Unarchive(Kumu::MemIOReader* Reader) {
                if ( ! Reader->ReadUi32BE(&BodySID) ) return false;
                if ( ! Reader->ReadUi64BE(&ByteOffset) ) return false;
                return true;
              }
              
-             inline virtual bool HasValue() const { return true; }
-         
-             inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+             inline bool Archive(Kumu::MemIOWriter* Writer) const {
                if ( ! Writer->WriteUi32BE(BodySID) ) return false;
                if ( ! Writer->WriteUi64BE(ByteOffset) ) return false;
                return true;
@@ -148,7 +149,7 @@ namespace ASDCP
 
        public:
          //
-         class LocalTagEntry
+       class LocalTagEntry : Kumu::IArchive
            {
            public:
              TagValue    Tag;
@@ -160,6 +161,9 @@ namespace ASDCP
                return str_buf;
              }
 
+             inline bool HasValue() const { return UL.HasValue(); }
+             inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
+
              inline bool Unarchive(Kumu::MemIOReader* Reader) {
                if ( ! Reader->ReadUi8(&Tag.a) ) return false;
                if ( ! Reader->ReadUi8(&Tag.b) ) return false;
@@ -246,7 +250,7 @@ namespace ASDCP
 
        public:
          //
-         class DeltaEntry
+       class DeltaEntry : public Kumu::IArchive
            {
            public:
              i8_t    PosTableIndex;
@@ -254,13 +258,15 @@ namespace ASDCP
              ui32_t  ElementData;
 
              DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
+             inline bool HasValue() const { return true; }
+             ui32_t      ArchiveLength() const { return sizeof(ui32_t) + 2; }
              bool        Unarchive(Kumu::MemIOReader* Reader);
              bool        Archive(Kumu::MemIOWriter* Writer) const;
              const char* EncodeString(char* str_buf, ui32_t buf_len) const;
            };
 
          //
-         class IndexEntry
+         class IndexEntry : public Kumu::IArchive
            {
            public:
              i8_t               TemporalOffset;
@@ -274,6 +280,8 @@ namespace ASDCP
              //              Array<Rational>    PosTable;
 
              IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {}
+             inline bool HasValue() const { return true; }
+             ui32_t      ArchiveLength() const { return sizeof(ui64_t) + 3; };
              bool        Unarchive(Kumu::MemIOReader* Reader);
              bool        Archive(Kumu::MemIOWriter* Writer) const;
              const char* EncodeString(char* str_buf, ui32_t buf_len) const;
index c6617aa96a536759dd453c5093f1ee814344805a..1fa6176d9cf253f0d260edbf8cdf78a8a29f6c02 100755 (executable)
@@ -125,6 +125,18 @@ namespace ASDCP
 
          inline virtual bool HasValue() const { return ! this->empty(); }
 
+         virtual ui32_t ArchiveLength() const {
+           ui32_t arch_size = sizeof(ui32_t)*2;
+
+           typename std::vector<T>::const_iterator l_i = this->begin();
+           assert(l_i != this->end());
+
+           for ( ; l_i != this->end(); l_i++ )
+             arch_size += l_i->ArchiveLength();
+           
+           return arch_size;
+         }
+
          //
          virtual bool Archive(Kumu::MemIOWriter* Writer) const {
            if ( ! Writer->WriteUi32BE(this->size()) ) return false;
@@ -188,6 +200,17 @@ namespace ASDCP
 
          inline virtual bool HasValue() const { return ! this->empty(); }
 
+         virtual ui32_t ArchiveLength() const {
+           ui32_t arch_size = 0;
+
+           typename std::list<T>::const_iterator l_i = this->begin();
+
+           for ( ; l_i != this->end(); l_i++ )
+             arch_size += l_i->ArchiveLength();
+           
+           return arch_size;
+         }
+
          //
          virtual bool Archive(Kumu::MemIOWriter* Writer) const {
            bool result = true;
@@ -255,6 +278,7 @@ namespace ASDCP
          }
 
          inline virtual bool HasValue() const { return true; }
+         inline virtual ui32_t ArchiveLength() const { return 8L; }
 
          //
          inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
@@ -275,8 +299,9 @@ namespace ASDCP
          const UTF16String& operator=(const std::string&);
 
          const char* EncodeString(char* str_buf, ui32_t buf_len) const;
-         virtual bool Unarchive(Kumu::MemIOReader* Reader);
          inline virtual bool HasValue() const { return ! empty(); }
+         inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + size(); }
+         virtual bool Unarchive(Kumu::MemIOReader* Reader);
          virtual bool Archive(Kumu::MemIOWriter* Writer) const;
        };
 
@@ -322,6 +347,7 @@ namespace ASDCP
          }
 
          inline virtual bool HasValue() const { return true; }
+         inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
 
          inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
            if ( ! Writer->WriteUi32BE((ui32_t)Numerator) ) return false;
@@ -341,7 +367,7 @@ namespace ASDCP
          ui16_t Minor;
          ui16_t Patch;
          ui16_t Build;
-         ui16_t Release;
+         Release_t Release;
 
          VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
          ~VersionType() {}
@@ -364,6 +390,7 @@ namespace ASDCP
          }
 
          inline virtual bool HasValue() const { return true; }
+         inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
 
          virtual bool Archive(Kumu::MemIOWriter* Writer) const {
            if ( ! Writer->WriteUi16BE(Major) ) return false;
index c9eb689d4e291a76574bb495a5a7ba9fd1c2ee9d..838fc53c5008be5d6b935904b09e2476a773fa66 100755 (executable)
@@ -65,8 +65,8 @@ 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; }
+static InterchangeObject* TimedTextDescriptor_Factory() { return new TimedTextDescriptor; }
+static InterchangeObject* TimedTextResourceSubDescriptor_Factory() { return new TimedTextResourceSubDescriptor; }
 static InterchangeObject* StereoscopicPictureSubDescriptor_Factory() { return new StereoscopicPictureSubDescriptor; }
 
 
@@ -98,8 +98,8 @@ ASDCP::MXF::Metadata_InitTypes()
   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);
+  SetObjectFactory(Dict::ul(MDD_TimedTextDescriptor), TimedTextDescriptor_Factory);
+  SetObjectFactory(Dict::ul(MDD_TimedTextResourceSubDescriptor), TimedTextResourceSubDescriptor_Factory);
   SetObjectFactory(Dict::ul(MDD_StereoscopicPictureSubDescriptor), StereoscopicPictureSubDescriptor_Factory);
 }
 
@@ -1035,6 +1035,7 @@ GenericPictureEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet)
   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(GenericPictureEssenceDescriptor, StoredWidth));
   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(GenericPictureEssenceDescriptor, StoredHeight));
   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(GenericPictureEssenceDescriptor, AspectRatio));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(GenericPictureEssenceDescriptor, PictureEssenceCoding));
   return result;
 }
 
@@ -1047,6 +1048,7 @@ GenericPictureEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(GenericPictureEssenceDescriptor, StoredWidth));
   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(GenericPictureEssenceDescriptor, StoredHeight));
   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(GenericPictureEssenceDescriptor, AspectRatio));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(GenericPictureEssenceDescriptor, PictureEssenceCoding));
   return result;
 }
 
@@ -1065,6 +1067,7 @@ GenericPictureEssenceDescriptor::Dump(FILE* stream)
   fprintf(stream, "  %22s = %d\n",  "StoredWidth", StoredWidth);
   fprintf(stream, "  %22s = %d\n",  "StoredHeight", StoredHeight);
   fprintf(stream, "  %22s = %s\n",  "AspectRatio", AspectRatio.EncodeString(identbuf, IdentBufferLen));
+  fprintf(stream, "  %22s = %s\n",  "PictureEssenceCoding", PictureEssenceCoding.EncodeString(identbuf, IdentBufferLen));
 }
 
 //
@@ -1573,33 +1576,33 @@ GenericDataEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
 }
 
 //------------------------------------------------------------------------------------------
-// DCTimedTextDescriptor
+// TimedTextDescriptor
 
 //
 ASDCP::Result_t
-DCTimedTextDescriptor::InitFromTLVSet(TLVReader& TLVSet)
+TimedTextDescriptor::InitFromTLVSet(TLVReader& TLVSet)
 {
   Result_t result = GenericDataEssenceDescriptor::InitFromTLVSet(TLVSet);
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextDescriptor, ResourceID));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextDescriptor, UTFEncoding));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextDescriptor, RootNamespaceName));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(TimedTextDescriptor, ResourceID));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(TimedTextDescriptor, UCSEncoding));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(TimedTextDescriptor, NamespaceURI));
   return result;
 }
 
 //
 ASDCP::Result_t
-DCTimedTextDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
+TimedTextDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
 {
   Result_t result = GenericDataEssenceDescriptor::WriteToTLVSet(TLVSet);
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextDescriptor, ResourceID));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextDescriptor, UTFEncoding));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextDescriptor, RootNamespaceName));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(TimedTextDescriptor, ResourceID));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(TimedTextDescriptor, UCSEncoding));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(TimedTextDescriptor, NamespaceURI));
   return result;
 }
 
 //
 void
-DCTimedTextDescriptor::Dump(FILE* stream)
+TimedTextDescriptor::Dump(FILE* stream)
 {
   char identbuf[IdentBufferLen];
   *identbuf = 0;
@@ -1609,54 +1612,54 @@ DCTimedTextDescriptor::Dump(FILE* stream)
 
   GenericDataEssenceDescriptor::Dump(stream);
   fprintf(stream, "  %22s = %s\n",  "ResourceID", ResourceID.EncodeString(identbuf, IdentBufferLen));
-  fprintf(stream, "  %22s = %s\n",  "UTFEncoding", UTFEncoding.EncodeString(identbuf, IdentBufferLen));
-  fprintf(stream, "  %22s = %s\n",  "RootNamespaceName", RootNamespaceName.EncodeString(identbuf, IdentBufferLen));
+  fprintf(stream, "  %22s = %s\n",  "UCSEncoding", UCSEncoding.EncodeString(identbuf, IdentBufferLen));
+  fprintf(stream, "  %22s = %s\n",  "NamespaceURI", NamespaceURI.EncodeString(identbuf, IdentBufferLen));
 }
 
 //
 ASDCP::Result_t
-DCTimedTextDescriptor::InitFromBuffer(const byte_t* p, ui32_t l)
+TimedTextDescriptor::InitFromBuffer(const byte_t* p, ui32_t l)
 {
-  m_Typeinfo = &Dict::Type(MDD_DCTimedTextDescriptor);
+  m_Typeinfo = &Dict::Type(MDD_TimedTextDescriptor);
   return InterchangeObject::InitFromBuffer(p, l);
 }
 
 //
 ASDCP::Result_t
-DCTimedTextDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
+TimedTextDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
 {
-  m_Typeinfo = &Dict::Type(MDD_DCTimedTextDescriptor);
+  m_Typeinfo = &Dict::Type(MDD_TimedTextDescriptor);
   return InterchangeObject::WriteToBuffer(Buffer);
 }
 
 //------------------------------------------------------------------------------------------
-// DCTimedTextResourceDescriptor
+// TimedTextResourceSubDescriptor
 
 //
 ASDCP::Result_t
-DCTimedTextResourceDescriptor::InitFromTLVSet(TLVReader& TLVSet)
+TimedTextResourceSubDescriptor::InitFromTLVSet(TLVReader& TLVSet)
 {
   Result_t result = InterchangeObject::InitFromTLVSet(TLVSet);
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextResourceDescriptor, ResourceID));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(DCTimedTextResourceDescriptor, ResourceMIMEType));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(DCTimedTextResourceDescriptor, ResourceSID));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(TimedTextResourceSubDescriptor, AncillaryResourceID));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(TimedTextResourceSubDescriptor, MIMEMediaType));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(TimedTextResourceSubDescriptor, EssenceStreamID));
   return result;
 }
 
 //
 ASDCP::Result_t
-DCTimedTextResourceDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
+TimedTextResourceSubDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
 {
   Result_t result = InterchangeObject::WriteToTLVSet(TLVSet);
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextResourceDescriptor, ResourceID));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(DCTimedTextResourceDescriptor, ResourceMIMEType));
-  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(DCTimedTextResourceDescriptor, ResourceSID));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(TimedTextResourceSubDescriptor, AncillaryResourceID));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(TimedTextResourceSubDescriptor, MIMEMediaType));
+  if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(TimedTextResourceSubDescriptor, EssenceStreamID));
   return result;
 }
 
 //
 void
-DCTimedTextResourceDescriptor::Dump(FILE* stream)
+TimedTextResourceSubDescriptor::Dump(FILE* stream)
 {
   char identbuf[IdentBufferLen];
   *identbuf = 0;
@@ -1665,24 +1668,24 @@ DCTimedTextResourceDescriptor::Dump(FILE* stream)
     stream = stderr;
 
   InterchangeObject::Dump(stream);
-  fprintf(stream, "  %22s = %s\n",  "ResourceID", ResourceID.EncodeString(identbuf, IdentBufferLen));
-  fprintf(stream, "  %22s = %s\n",  "ResourceMIMEType", ResourceMIMEType.EncodeString(identbuf, IdentBufferLen));
-  fprintf(stream, "  %22s = %d\n",  "ResourceSID", ResourceSID);
+  fprintf(stream, "  %22s = %s\n",  "AncillaryResourceID", AncillaryResourceID.EncodeString(identbuf, IdentBufferLen));
+  fprintf(stream, "  %22s = %s\n",  "MIMEMediaType", MIMEMediaType.EncodeString(identbuf, IdentBufferLen));
+  fprintf(stream, "  %22s = %d\n",  "EssenceStreamID", EssenceStreamID);
 }
 
 //
 ASDCP::Result_t
-DCTimedTextResourceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l)
+TimedTextResourceSubDescriptor::InitFromBuffer(const byte_t* p, ui32_t l)
 {
-  m_Typeinfo = &Dict::Type(MDD_DCTimedTextResourceDescriptor);
+  m_Typeinfo = &Dict::Type(MDD_TimedTextResourceSubDescriptor);
   return InterchangeObject::InitFromBuffer(p, l);
 }
 
 //
 ASDCP::Result_t
-DCTimedTextResourceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
+TimedTextResourceSubDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
 {
-  m_Typeinfo = &Dict::Type(MDD_DCTimedTextResourceDescriptor);
+  m_Typeinfo = &Dict::Type(MDD_TimedTextResourceSubDescriptor);
   return InterchangeObject::WriteToBuffer(Buffer);
 }
 
index bcd3b6f78eddfda6280db03959aadd0e6c8570b7..207e031daf23130e83c05c32573b49a90a187c46 100755 (executable)
@@ -384,6 +384,7 @@ namespace ASDCP
           ui32_t StoredWidth;
           ui32_t StoredHeight;
           Rational AspectRatio;
+          UL PictureEssenceCoding;
 
          GenericPictureEssenceDescriptor() : FrameLayout(0), StoredWidth(0), StoredHeight(0) {}
          virtual ~GenericPictureEssenceDescriptor() {}
@@ -567,18 +568,18 @@ namespace ASDCP
        };
 
       //
-      class DCTimedTextDescriptor : public GenericDataEssenceDescriptor
+      class TimedTextDescriptor : public GenericDataEssenceDescriptor
        {
-         ASDCP_NO_COPY_CONSTRUCT(DCTimedTextDescriptor);
+         ASDCP_NO_COPY_CONSTRUCT(TimedTextDescriptor);
 
        public:
           UUID ResourceID;
-          UTF16String UTFEncoding;
-          UTF16String RootNamespaceName;
+          UTF16String UCSEncoding;
+          UTF16String NamespaceURI;
 
-         DCTimedTextDescriptor() {}
-         virtual ~DCTimedTextDescriptor() {}
-          virtual const char* HasName() { return "DCTimedTextDescriptor"; }
+         TimedTextDescriptor() {}
+         virtual ~TimedTextDescriptor() {}
+          virtual const char* HasName() { return "TimedTextDescriptor"; }
           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
          virtual void     Dump(FILE* = 0);
@@ -587,18 +588,18 @@ namespace ASDCP
        };
 
       //
-      class DCTimedTextResourceDescriptor : public InterchangeObject
+      class TimedTextResourceSubDescriptor : public InterchangeObject
        {
-         ASDCP_NO_COPY_CONSTRUCT(DCTimedTextResourceDescriptor);
+         ASDCP_NO_COPY_CONSTRUCT(TimedTextResourceSubDescriptor);
 
        public:
-          UUID ResourceID;
-          UTF16String ResourceMIMEType;
-          ui32_t ResourceSID;
+          UUID AncillaryResourceID;
+          UTF16String MIMEMediaType;
+          ui32_t EssenceStreamID;
 
-         DCTimedTextResourceDescriptor() : ResourceSID(0) {}
-         virtual ~DCTimedTextResourceDescriptor() {}
-          virtual const char* HasName() { return "DCTimedTextResourceDescriptor"; }
+         TimedTextResourceSubDescriptor() : EssenceStreamID(0) {}
+         virtual ~TimedTextResourceSubDescriptor() {}
+          virtual const char* HasName() { return "TimedTextResourceSubDescriptor"; }
           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
          virtual void     Dump(FILE* = 0);
index 23ccbb4a79ee8da6d3172cf7ef0bed5070224151..0a885287836aa1c858f535078a36bd37e708d657 100644 (file)
@@ -130,6 +130,7 @@ public:
 
   // IArchive
   bool HasValue() const { return (m_FPS > 0); }
+  ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
 
   bool Archive(Kumu::MemIOWriter* Writer) const
   {
index 8595b31330929727463bf2c86315d84d64e65f0f..8c319092f74a3567095714683a39894254e58bd9 100644 (file)
@@ -304,7 +304,7 @@ ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::ReadAncillaryResource(con
        FrameBuf.MIMEType("image/png");
              
       else if ( (*rmi).second == MT_OPENTYPE )
-       FrameBuf.MIMEType("application/x-opentype");
+       FrameBuf.MIMEType("application/x-font-opentype");
 
       else
        FrameBuf.MIMEType("application/octet-stream");
index ffd3246711ba589859bfbc6e854fa72e092cb6e4..eadfc76847e4ebef344c6b3c4143e5a1d15e8b86 100755 (executable)
@@ -151,6 +151,7 @@ Major modes:\n\
   -h | -help        - Show help\n\
   -i                - Show file info\n\
   -t                - Calculate message digest of input file\n\
+  -U                - Dump UL catalog to stdout\n\
   -u                - Generate a random UUID value to stdout\n\
   -V                - Show version information\n\
   -x <root-name>    - Extract essence from AS-DCP file to named file(s)\n\
@@ -211,7 +212,8 @@ enum MajorMode_t
   MMT_GEN_ID,
   MMT_GEN_KEY,
   MMT_GOP_START,
-  MMT_DIGEST
+  MMT_DIGEST,
+  MMT_UL_LIST,
 };
 
 
@@ -310,6 +312,7 @@ public:
              case 'h': help_flag = true; break;
              case 'v': verbose_flag = true; break;
              case 'g': mode = MMT_GEN_KEY; break;
+             case 'U': mode = MMT_UL_LIST; break;
              case 'u': mode = MMT_GEN_ID; break;
              case 'e': encrypt_header_flag = true; break;
              case 'E': encrypt_header_flag = false; break;
@@ -1752,6 +1755,7 @@ int
 main(int argc, const char** argv)
 {
   Result_t result = RESULT_OK;
+  char     str_buf[64];
   CommandOptions Options(argc, argv);
 
   if ( Options.version_flag )
@@ -1781,23 +1785,33 @@ main(int argc, const char** argv)
     {
       Kumu::FortunaRNG RNG;
       byte_t bin_buf[KeyLen];
-      char   str_buf[40];
 
       RNG.FillRandom(bin_buf, KeyLen);
-      printf("%s\n", Kumu::bin2hex(bin_buf, KeyLen, str_buf, 40));
+      printf("%s\n", Kumu::bin2hex(bin_buf, KeyLen, str_buf, 64));
     }
   else if ( Options.mode == MMT_GEN_ID )
     {
       UUID TmpID;
       Kumu::GenRandomValue(TmpID);
-      char   str_buf[40];
-      printf("%s\n", TmpID.EncodeHex(str_buf, 40));
+      printf("%s\n", TmpID.EncodeHex(str_buf, 64));
     }
   else if ( Options.mode == MMT_DIGEST )
     {
       for ( ui32_t i = 0; i < Options.file_count && ASDCP_SUCCESS(result); i++ )
        result = digest_file(Options.filenames[i]);
     }
+  else if ( Options.mode == MMT_UL_LIST )
+    {
+      MDD_t di = (MDD_t)0;
+
+      while ( di < MDD_Max )
+       {
+         MDDEntry TmpType = Dict::Type(di);
+         UL TmpUL(TmpType.ul);
+         fprintf(stdout, "%s: %s\n", TmpUL.EncodeString(str_buf, 64), TmpType.name);
+         di = (MDD_t)(di + 1);
+       }
+    }
   else if ( Options.mode == MMT_EXTRACT )
     {
       EssenceType_t EssenceType;
@@ -1879,6 +1893,11 @@ main(int argc, const char** argv)
            }
        }
     }
+  else
+    {
+      fprintf(stderr, "Unhandled mode: %d.\n", Options.mode);
+      return 6;
+    }
 
   if ( ASDCP_FAILURE(result) )
     {