big change rollup
[asdcplib.git] / src / AS_DCP_internal.h
index b59df2cebbcbdebdb85f56eec154d17853163474..af6b55317be1f58b922ad9a3f960e748674fa481 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004-2006, John Hurst
+Copyright (c) 2004-2012, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -42,10 +42,44 @@ using Kumu::DefaultLogSink;
 using namespace ASDCP;
 using namespace ASDCP::MXF;
 
+#ifdef DEFAULT_MD_DECL
+ASDCP::MXF::OPAtomHeader *g_OPAtomHeader;
+ASDCP::MXF::OPAtomIndexFooter *g_OPAtomIndexFooter;
+#else
+extern MXF::OPAtomHeader *g_OPAtomHeader;
+extern MXF::OPAtomIndexFooter *g_OPAtomIndexFooter;
+#endif
 
 
 namespace ASDCP
 {
+  void default_md_object_init();
+
+  //
+  static std::vector<int>
+    version_split(const char* str)
+  {
+    std::vector<int> result;
+    const char* pstr = str;
+    const char* r = strchr(pstr, '.');
+    
+    while ( r != 0 )
+      {
+       assert(r >= pstr);
+       if ( r > pstr )
+         result.push_back(atoi(pstr));
+
+       pstr = r + 1;
+       r = strchr(pstr, '.');
+      }
+
+    if( strlen(pstr) > 0 )
+      result.push_back(atoi(pstr));
+
+    assert(result.size() == 3);
+    return result;
+  }
+
   // constant values used to calculate KLV and EKLV packet sizes
   static const ui32_t klv_cryptinfo_size =
     MXF_BER_LENGTH
@@ -86,34 +120,177 @@ namespace ASDCP
   //
 
   Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&);
-  Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&);
+  Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&, const Dictionary&);
   Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
   Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
+  Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
+  Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc);
+  void     AddDMScrypt(Partition& HeaderPart, SourcePackage& Package,
+                      WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
+
+  Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict, const MXF::OPAtomHeader& HeaderPart,
+                           const ASDCP::WriterInfo& Info, Kumu::fpos_t& LastPosition, ASDCP::FrameBuffer& CtFrameBuf,
+                           ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
+                           const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
+  
+  //
+ class KLReader : public ASDCP::KLVPacket
+    {
+      ASDCP_NO_COPY_CONSTRUCT(KLReader);
+      byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
+
+    public:
+      KLReader() {}
+      ~KLReader() {}
+
+      inline const byte_t* Key() { return m_KeyBuf; }
+      inline const ui64_t  Length() { return m_ValueLength; }
+      inline const ui64_t  KLLength() { return m_KLLength; }
+      
+      Result_t ReadKLFromFile(Kumu::FileReader& Reader);
+    };
+
+  namespace MXF
+  {
+      //---------------------------------------------------------------------------------
+      //
+
+    ///      void default_md_object_init();
+
+      template <class HeaderType, class FooterType>
+      class TrackFileReader
+      {
+       KM_NO_COPY_CONSTRUCT(TrackFileReader);
+       TrackFileReader();
+
+      public:
+       const Dictionary*  m_Dict;
+       Kumu::FileReader   m_File;
+       HeaderType         m_HeaderPart;
+       FooterType         m_FooterPart;
+       WriterInfo         m_Info;
+       ASDCP::FrameBuffer m_CtFrameBuf;
+       Kumu::fpos_t       m_LastPosition;
+
+      TrackFileReader(const Dictionary& d) :
+       m_HeaderPart(m_Dict), m_FooterPart(m_Dict), m_Dict(&d)
+         {
+           default_md_object_init();
+         }
+
+       virtual ~TrackFileReader() {
+         Close();
+       }
+
+       Result_t InitInfo()
+       {
+         assert(m_Dict);
+         InterchangeObject* Object;
+
+         // Identification
+         Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object);
+
+         // Writer Info and SourcePackage
+         if ( KM_SUCCESS(result) )
+           {
+             MD_to_WriterInfo((Identification*)Object, m_Info);
+             result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(SourcePackage), &Object);
+           }
+
+         if ( KM_SUCCESS(result) )
+           {
+             SourcePackage* SP = (SourcePackage*)Object;
+             memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen);
+           }
+
+         // optional CryptographicContext
+         if ( KM_SUCCESS(result) )
+           {
+             Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object);
+             
+             if ( KM_SUCCESS(cr_result) )
+               MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict);
+           }
+
+         return result;
+       }
+
+       //
+       Result_t OpenMXFRead(const char* filename)
+       {
+         m_LastPosition = 0;
+         Result_t result = m_File.OpenRead(filename);
+
+         if ( KM_SUCCESS(result) )
+           result = m_HeaderPart.InitFromFile(m_File);
+         
+         return result;
+       }
+
+       // positions file before reading
+       Result_t ReadEKLVFrame(const ASDCP::MXF::Partition& CurrentPartition,
+                              ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
+                              const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
+       {
+         // look up frame index node
+         IndexTableSegment::IndexEntry TmpEntry;
+
+         if ( KM_FAILURE(m_FooterPart.Lookup(FrameNum, TmpEntry)) )
+           {
+             DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
+             return RESULT_RANGE;
+           }
+
+         // get frame position and go read the frame's key and length
+         Kumu::fpos_t FilePosition = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
+         Result_t result = RESULT_OK;
+
+         if ( FilePosition != m_LastPosition )
+           {
+             m_LastPosition = FilePosition;
+             result = m_File.Seek(FilePosition);
+           }
+
+         if( KM_SUCCESS(result) )
+           result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
+
+         return result;
+       }
+
+       // reads from current position
+       Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
+                               const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
+       {
+         assert(m_Dict);
+         return Read_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_LastPosition, m_CtFrameBuf,
+                                 FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC);
+       }
+
+       //
+       void     Close() {
+         m_File.Close();
+       }
+      };
+
+  }/// namespace MXF
 
   //
-  class h__Reader
+  class h__ASDCPReader : public MXF::TrackFileReader<OPAtomHeader, OPAtomIndexFooter>
     {
-      ASDCP_NO_COPY_CONSTRUCT(h__Reader);
+      ASDCP_NO_COPY_CONSTRUCT(h__ASDCPReader);
+      h__ASDCPReader();
 
     public:
-      Kumu::FileReader   m_File;
-      OPAtomHeader       m_HeaderPart;
-      Partition          m_BodyPart;
-      OPAtomIndexFooter  m_FooterPart;
-      ui64_t             m_EssenceStart;
-      WriterInfo         m_Info;
-      ASDCP::FrameBuffer m_CtFrameBuf;
-      Kumu::fpos_t       m_LastPosition;
+      Partition m_BodyPart;
 
-      h__Reader();
-      virtual ~h__Reader();
+      h__ASDCPReader(const Dictionary&);
+      virtual ~h__ASDCPReader();
 
-      Result_t InitInfo();
       Result_t OpenMXFRead(const char* filename);
+      Result_t InitInfo();
       Result_t InitMXFIndex();
-      Result_t ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
-                             const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
-      void     Close();
+      Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
+                            const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
     };
 
 
@@ -152,12 +329,16 @@ namespace ASDCP
       inline Result_t Goto_FINAL()   { Goto_body(ST_RUNNING, ST_FINAL); }
     };
 
+  typedef std::list<ui64_t*> DurationElementList_t;
+
   //
   class h__Writer
     {
       ASDCP_NO_COPY_CONSTRUCT(h__Writer);
+      h__Writer();
 
     public:
+      const Dictionary*  m_Dict;
       Kumu::FileWriter   m_File;
       ui32_t             m_HeaderSize;
       OPAtomHeader       m_HeaderPart;
@@ -166,31 +347,35 @@ 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<InterchangeObject*> m_EssenceSubDescriptorList;
 
       ui32_t             m_FramesWritten;
       ui64_t             m_StreamOffset;
       ASDCP::FrameBuffer m_CtFrameBuf;
       h__WriterState     m_State;
       WriterInfo         m_Info;
+      DurationElementList_t m_DurationUpdateList;
 
-      h__Writer();
+      h__Writer(const Dictionary&);
       virtual ~h__Writer();
 
+      void InitHeader();
+      void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
+                        const std::string& TrackName, const UL& EssenceUL,
+                        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,
+                             const std::string& TrackName, const UL& EssenceUL,
+                             const UL& DataDefinition, const MXF::Rational& EditRate,
                              ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
 
       Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
@@ -214,8 +399,8 @@ namespace ASDCP
 
       ~IntegrityPack() {}
   
-      Result_t CalcValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
-      Result_t TestValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
+      Result_t CalcValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
+      Result_t TestValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
     };