Merge pull request #9 from dcbullock/master
[asdcplib.git] / src / AS_DCP_DCData.cpp
index 53e4497fc404b1b56d7d1db2032b624013f8ffcd..245b46b5240f8db6a65b46439febad0e5e9b18db 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004-2013, John Hurst
+Copyright (c) 2004-2018, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -32,16 +32,15 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <iostream>
 
 #include "AS_DCP.h"
-#include "AS_DCP_DCData_internal.h"
 #include "AS_DCP_internal.h"
 
 namespace ASDCP
 {
-namespace DCData
-{
-  static std::string DC_DATA_PACKAGE_LABEL = "File Package: SMPTE 382M frame wrapping of D-Cinema Generic data";
-  static std::string DC_DATA_DEF_LABEL = "D-Cinema Generic Data Track";
-} // namespace DCData
+  namespace DCData
+  {
+    static std::string DC_DATA_PACKAGE_LABEL = "File Package: SMPTE-GC frame wrapping of D-Cinema Generic data";
+    static std::string DC_DATA_DEF_LABEL = "D-Cinema Generic Data Track";
+  } // namespace DCData
 } // namespace ASDCP
 
 //
@@ -75,52 +74,101 @@ ASDCP::DCData::DCDataDescriptorDump(const DCDataDescriptor& DDesc, FILE* stream)
 
 //------------------------------------------------------------------------------------------
 
+typedef std::list<MXF::InterchangeObject*> SubDescriptorList_t;
+
+class ASDCP::DCData::MXFReader::h__Reader : public ASDCP::h__ASDCPReader
+{
+  bool m_PrivateLabelCompatibilityMode;
+  ASDCP_NO_COPY_CONSTRUCT(h__Reader);
+  h__Reader();
+
+ public:
+  DCDataDescriptor m_DDesc;
 
+  h__Reader(const Dictionary& d) : ASDCP::h__ASDCPReader(d), m_PrivateLabelCompatibilityMode(false), m_DDesc() {}
+  ~h__Reader() {}
+  Result_t    OpenRead(const std::string&);
+  Result_t    ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*);
+  Result_t    MD_to_DCData_DDesc(const MXF::DCDataDescriptor& descriptor_object, DCData::DCDataDescriptor& DDesc);
+  Result_t    MD_to_DCData_DDesc(const MXF::PrivateDCDataDescriptor& descriptor_object, DCData::DCDataDescriptor& DDesc);
+};
+
+//
 ASDCP::Result_t
-ASDCP::DCData::h__Reader::MD_to_DCData_DDesc(DCData::DCDataDescriptor& DDesc)
+ASDCP::DCData::MXFReader::h__Reader::MD_to_DCData_DDesc(const MXF::DCDataDescriptor& descriptor_object,
+                                                       DCData::DCDataDescriptor& DDesc)
 {
-  ASDCP_TEST_NULL(m_EssenceDescriptor);
-  MXF::DCDataDescriptor* DDescObj = m_EssenceDescriptor;
-  DDesc.EditRate = DDescObj->SampleRate;
-  assert(DDescObj->ContainerDuration <= 0xFFFFFFFFL);
-  DDesc.ContainerDuration = static_cast<ui32_t>(DDescObj->ContainerDuration);
-  memcpy(DDesc.DataEssenceCoding, DDescObj->DataEssenceCoding.Value(), SMPTE_UL_LENGTH);
+  DDesc.EditRate = descriptor_object.SampleRate;
+  assert(descriptor_object.ContainerDuration.const_get() <= 0xFFFFFFFFL);
+  DDesc.ContainerDuration = static_cast<ui32_t>(descriptor_object.ContainerDuration.const_get());
+  memcpy(DDesc.DataEssenceCoding, descriptor_object.DataEssenceCoding.Value(), SMPTE_UL_LENGTH);
+  return RESULT_OK;
+}
+
+//
+ASDCP::Result_t
+ASDCP::DCData::MXFReader::h__Reader::MD_to_DCData_DDesc(const MXF::PrivateDCDataDescriptor& descriptor_object,
+                                                       DCData::DCDataDescriptor& DDesc)
+{
+  DDesc.EditRate = descriptor_object.SampleRate;
+  assert(descriptor_object.ContainerDuration.const_get() <= 0xFFFFFFFFL);
+  DDesc.ContainerDuration = static_cast<ui32_t>(descriptor_object.ContainerDuration.const_get());
+  memcpy(DDesc.DataEssenceCoding, descriptor_object.DataEssenceCoding.Value(), SMPTE_UL_LENGTH);
   return RESULT_OK;
 }
 
 //
 //
 ASDCP::Result_t
-ASDCP::DCData::h__Reader::OpenRead(const char* filename)
+ASDCP::DCData::MXFReader::h__Reader::OpenRead(const std::string& filename)
 {
   Result_t result = OpenMXFRead(filename);
 
-  if( ASDCP_SUCCESS(result) )
-  {
-    if (NULL == m_EssenceDescriptor)
+  if( KM_SUCCESS(result) )
     {
-      InterchangeObject* iObj = NULL;
+      InterchangeObject* iObj = 0;
       result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(DCDataDescriptor), &iObj);
-      m_EssenceDescriptor = static_cast<MXF::DCDataDescriptor*>(iObj);
-    }
 
-    if ( ASDCP_SUCCESS(result) )
-    {
-      result = MD_to_DCData_DDesc(m_DDesc);
+      if ( KM_SUCCESS(result) )
+       {
+         const MXF::DCDataDescriptor* p = dynamic_cast<const MXF::DCDataDescriptor*>(iObj);
+         assert(p);
+         result = MD_to_DCData_DDesc(*p, m_DDesc);
+       }
+      else
+       {
+         result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(PrivateDCDataDescriptor), &iObj);
+         
+         if ( KM_SUCCESS(result) )
+           {
+             m_PrivateLabelCompatibilityMode = true;
+             const MXF::PrivateDCDataDescriptor* p = dynamic_cast<const MXF::PrivateDCDataDescriptor*>(iObj);
+             assert(p);
+             result = MD_to_DCData_DDesc(*p, m_DDesc);
+           }
+       }
+
+      if ( KM_FAILURE(result) )
+       {
+         DefaultLogSink().Error("DCDataDescriptor object not found in ST 429-14 file.\n");
+         result = RESULT_FORMAT;
+       }
     }
-  }
 
   // check for sample/frame rate sanity
   if ( ASDCP_SUCCESS(result)
-                && m_DDesc.EditRate != EditRate_24
-                && m_DDesc.EditRate != EditRate_25
-                && m_DDesc.EditRate != EditRate_30
-                && m_DDesc.EditRate != EditRate_48
-                && m_DDesc.EditRate != EditRate_50
-                && m_DDesc.EditRate != EditRate_60
-                && m_DDesc.EditRate != EditRate_96
-                && m_DDesc.EditRate != EditRate_100
-       && m_DDesc.EditRate != EditRate_120 )
+       && m_DDesc.EditRate != EditRate_24
+       && m_DDesc.EditRate != EditRate_25
+       && m_DDesc.EditRate != EditRate_30
+       && m_DDesc.EditRate != EditRate_48
+       && m_DDesc.EditRate != EditRate_50
+       && m_DDesc.EditRate != EditRate_60
+       && m_DDesc.EditRate != EditRate_96
+       && m_DDesc.EditRate != EditRate_100
+       && m_DDesc.EditRate != EditRate_120
+       && m_DDesc.EditRate != EditRate_192
+       && m_DDesc.EditRate != EditRate_200
+       && m_DDesc.EditRate != EditRate_240 )
   {
     DefaultLogSink().Error("DC Data file EditRate is not a supported value: %d/%d\n", // lu
                            m_DDesc.EditRate.Numerator, m_DDesc.EditRate.Denominator);
@@ -128,41 +176,28 @@ ASDCP::DCData::h__Reader::OpenRead(const char* filename)
     return RESULT_FORMAT;
   }
 
-  if( ASDCP_SUCCESS(result) )
-    result = InitMXFIndex();
-
-  if( ASDCP_SUCCESS(result) )
-    result = InitInfo();
-
   return result;
 }
 
 //
 //
 ASDCP::Result_t
-ASDCP::DCData::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
+ASDCP::DCData::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
                      AESDecContext* Ctx, HMACContext* HMAC)
 {
   if ( ! m_File.IsOpen() )
     return RESULT_INIT;
 
   assert(m_Dict);
+  if ( m_PrivateLabelCompatibilityMode )
+    {
+      return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_PrivateDCDataEssence), Ctx, HMAC);
+    }
+
   return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_DCDataEssence), Ctx, HMAC);
 }
 
 
-//
-//------------------------------------------------------------------------------------------
-
-class ASDCP::DCData::MXFReader::h__Reader : public DCData::h__Reader
-{
-  ASDCP_NO_COPY_CONSTRUCT(h__Reader);
-  h__Reader();
-
-  public:
-    h__Reader(const Dictionary& d) : DCData::h__Reader(d) {}
-};
-
 
 //------------------------------------------------------------------------------------------
 
@@ -198,13 +233,13 @@ ASDCP::DCData::MXFReader::~MXFReader()
 // Warning: direct manipulation of MXF structures can interfere
 // with the normal operation of the wrapper.  Caveat emptor!
 //
-ASDCP::MXF::OPAtomHeader&
-ASDCP::DCData::MXFReader::OPAtomHeader()
+ASDCP::MXF::OP1aHeader&
+ASDCP::DCData::MXFReader::OP1aHeader()
 {
   if ( m_Reader.empty() )
     {
-      assert(g_OPAtomHeader);
-      return *g_OPAtomHeader;
+      assert(g_OP1aHeader);
+      return *g_OP1aHeader;
     }
 
   return m_Reader->m_HeaderPart;
@@ -222,13 +257,28 @@ ASDCP::DCData::MXFReader::OPAtomIndexFooter()
       return *g_OPAtomIndexFooter;
     }
 
-  return m_Reader->m_FooterPart;
+  return m_Reader->m_IndexAccess;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper.  Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::DCData::MXFReader::RIP()
+{
+  if ( m_Reader.empty() )
+    {
+      assert(g_RIP);
+      return *g_RIP;
+    }
+
+  return m_Reader->m_RIP;
 }
 
 // Open the file for reading. The file must exist. Returns error if the
 // operation cannot be completed.
 ASDCP::Result_t
-ASDCP::DCData::MXFReader::OpenRead(const char* filename) const
+ASDCP::DCData::MXFReader::OpenRead(const std::string& filename) const
 {
   return m_Reader->OpenRead(filename);
 }
@@ -294,7 +344,7 @@ void
 ASDCP::DCData::MXFReader::DumpIndex(FILE* stream) const
 {
   if ( m_Reader->m_File.IsOpen() )
-    m_Reader->m_FooterPart.Dump(stream);
+    m_Reader->m_IndexAccess.Dump(stream);
 }
 
 //
@@ -314,9 +364,32 @@ ASDCP::DCData::MXFReader::Close() const
 //------------------------------------------------------------------------------------------
 
 
+class ASDCP::DCData::MXFWriter::h__Writer : public ASDCP::h__ASDCPWriter
+{
+  ASDCP_NO_COPY_CONSTRUCT(h__Writer);
+  h__Writer();
+
+public:
+  DCDataDescriptor m_DDesc;
+  byte_t           m_EssenceUL[SMPTE_UL_LENGTH];
+
+  h__Writer(const Dictionary& d) : ASDCP::h__ASDCPWriter(d) {
+    memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
+  }
+
+  ~h__Writer(){}
+
+  Result_t OpenWrite(const std::string&, ui32_t HeaderSize, const SubDescriptorList_t& subDescriptors);
+  Result_t SetSourceStream(const DCDataDescriptor&, const byte_t*, const std::string&, const std::string&);
+  Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+  Result_t Finalize();
+  Result_t DCData_DDesc_to_MD(DCData::DCDataDescriptor& DDesc);
+};
+
+
 //
 ASDCP::Result_t
-ASDCP::DCData::h__Writer::DCData_DDesc_to_MD(DCData::DCDataDescriptor& DDesc)
+ASDCP::DCData::MXFWriter::h__Writer::DCData_DDesc_to_MD(DCData::DCDataDescriptor& DDesc)
 {
   ASDCP_TEST_NULL(m_EssenceDescriptor);
   MXF::DCDataDescriptor* DDescObj = static_cast<MXF::DCDataDescriptor *>(m_EssenceDescriptor);
@@ -330,7 +403,7 @@ ASDCP::DCData::h__Writer::DCData_DDesc_to_MD(DCData::DCDataDescriptor& DDesc)
 
 //
 ASDCP::Result_t
-ASDCP::DCData::h__Writer::OpenWrite(char const* filename, ui32_t HeaderSize,
+ASDCP::DCData::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize,
                                     const SubDescriptorList_t& subDescriptors)
 {
   if ( ! m_State.Test_BEGIN() )
@@ -358,7 +431,7 @@ ASDCP::DCData::h__Writer::OpenWrite(char const* filename, ui32_t HeaderSize,
 
 //
 ASDCP::Result_t
-ASDCP::DCData::h__Writer::SetSourceStream(DCDataDescriptor const& DDesc,
+ASDCP::DCData::MXFWriter::h__Writer::SetSourceStream(DCDataDescriptor const& DDesc,
                                           const byte_t * essenceCoding,
                                           const std::string& packageLabel,
                                           const std::string& defLabel)
@@ -374,7 +447,10 @@ ASDCP::DCData::h__Writer::SetSourceStream(DCDataDescriptor const& DDesc,
        && DDesc.EditRate != EditRate_60
        && DDesc.EditRate != EditRate_96
        && DDesc.EditRate != EditRate_100
-       && DDesc.EditRate != EditRate_120 )
+       && DDesc.EditRate != EditRate_120
+       && DDesc.EditRate != EditRate_192
+       && DDesc.EditRate != EditRate_200
+       && DDesc.EditRate != EditRate_240 )
   {
     DefaultLogSink().Error("DCDataDescriptor.EditRate is not a supported value: %d/%d\n",
                            DDesc.EditRate.Numerator, DDesc.EditRate.Denominator);
@@ -398,9 +474,9 @@ ASDCP::DCData::h__Writer::SetSourceStream(DCDataDescriptor const& DDesc,
   {
     ui32_t TCFrameRate = m_DDesc.EditRate.Numerator;
 
-    result = WriteMXFHeader(packageLabel, UL(m_Dict->ul(MDD_DCDataWrapping)),
-                            defLabel, UL(m_EssenceUL), UL(m_Dict->ul(MDD_DataDataDef)),
-                            m_DDesc.EditRate, TCFrameRate);
+    result = WriteASDCPHeader(packageLabel, UL(m_Dict->ul(MDD_DCDataWrappingFrame)),
+                             defLabel, UL(m_EssenceUL), UL(m_Dict->ul(MDD_DataDataDef)),
+                             m_DDesc.EditRate, TCFrameRate);
   }
 
   return result;
@@ -408,7 +484,7 @@ ASDCP::DCData::h__Writer::SetSourceStream(DCDataDescriptor const& DDesc,
 
 //
 ASDCP::Result_t
-ASDCP::DCData::h__Writer::WriteFrame(const FrameBuffer& FrameBuf,
+ASDCP::DCData::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& FrameBuf,
                                                 ASDCP::AESEncContext* Ctx, ASDCP::HMACContext* HMAC)
 {
   Result_t result = RESULT_OK;
@@ -419,7 +495,7 @@ ASDCP::DCData::h__Writer::WriteFrame(const FrameBuffer& FrameBuf,
   ui64_t StreamOffset = m_StreamOffset;
 
   if ( ASDCP_SUCCESS(result) )
-    result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
+    result = WriteEKLVPacket(FrameBuf, m_EssenceUL, MXF_BER_LENGTH, Ctx, HMAC);
 
   if ( ASDCP_SUCCESS(result) )
   {
@@ -434,30 +510,17 @@ ASDCP::DCData::h__Writer::WriteFrame(const FrameBuffer& FrameBuf,
 // Closes the MXF file, writing the index and other closing information.
 //
 ASDCP::Result_t
-ASDCP::DCData::h__Writer::Finalize()
+ASDCP::DCData::MXFWriter::h__Writer::Finalize()
 {
   if ( ! m_State.Test_RUNNING() )
     return RESULT_STATE;
 
   m_State.Goto_FINAL();
 
-  return WriteMXFFooter();
+  return WriteASDCPFooter();
 }
 
 
-//
-//------------------------------------------------------------------------------------------
-
-
-class ASDCP::DCData::MXFWriter::h__Writer : public DCData::h__Writer
-{
-  ASDCP_NO_COPY_CONSTRUCT(h__Writer);
-  h__Writer();
-
-  public:
-    h__Writer(const Dictionary& d) : DCData::h__Writer(d) {}
-};
-
 
 //------------------------------------------------------------------------------------------
 
@@ -472,13 +535,13 @@ ASDCP::DCData::MXFWriter::~MXFWriter()
 // Warning: direct manipulation of MXF structures can interfere
 // with the normal operation of the wrapper.  Caveat emptor!
 //
-ASDCP::MXF::OPAtomHeader&
-ASDCP::DCData::MXFWriter::OPAtomHeader()
+ASDCP::MXF::OP1aHeader&
+ASDCP::DCData::MXFWriter::OP1aHeader()
 {
   if ( m_Writer.empty() )
     {
-      assert(g_OPAtomHeader);
-      return *g_OPAtomHeader;
+      assert(g_OP1aHeader);
+      return *g_OP1aHeader;
     }
 
   return m_Writer->m_HeaderPart;
@@ -499,10 +562,25 @@ ASDCP::DCData::MXFWriter::OPAtomIndexFooter()
   return m_Writer->m_FooterPart;
 }
 
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper.  Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::DCData::MXFWriter::RIP()
+{
+  if ( m_Writer.empty() )
+    {
+      assert(g_RIP);
+      return *g_RIP;
+    }
+
+  return m_Writer->m_RIP;
+}
+
 // Open the file for writing. The file must not exist. Returns error if
 // the operation cannot be completed.
 ASDCP::Result_t
-ASDCP::DCData::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info,
+ASDCP::DCData::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
                                       const DCDataDescriptor& DDesc, ui32_t HeaderSize)
 {
   if ( Info.LabelSetType != LS_MXF_SMPTE )