Denis' bug fixes
[asdcplib.git] / src / h__Writer.cpp
index cd51391dcd5d6d93f37e080937840102c6433754..1105e039de873964c7c937bb25b5efe035829f4d 100755 (executable)
@@ -30,22 +30,24 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include "AS_DCP_internal.h"
-#include "MemIO.h"
-#include "Timecode.h"
 #include "KLV.h"
 
 using namespace ASDCP;
 using namespace ASDCP::MXF;
 
 // a magic number identifying asdcplib
-#ifndef WM_BUILD_NUMBER
-#define WM_BUILD_NUMBER 0x4A48
+#ifndef ASDCP_BUILD_NUMBER
+#define ASDCP_BUILD_NUMBER 0x6A68
 #endif
 
 
 
 //
-ASDCP::h__Writer::h__Writer() : m_EssenceDescriptor(0), m_FramesWritten(0), m_StreamOffset(0)
+ASDCP::h__Writer::h__Writer() :
+  m_HeaderSize(0), m_EssenceStart(0),
+  m_MaterialPackage(0), m_MPTCSequence(0), m_MPTimecode(0), m_MPClSequence(0), m_MPClip(0),
+  m_FilePackage(0), m_FPTCSequence(0), m_FPTimecode(0), m_FPClSequence(0), m_FPClip(0),
+  m_EssenceDescriptor(0), m_FramesWritten(0), m_StreamOffset(0)
 {
 }
 
@@ -53,24 +55,6 @@ ASDCP::h__Writer::~h__Writer()
 {
 }
 
-
-const byte_t PictDD_Data[SMPTE_UL_LENGTH] = {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
-  0x01, 0x03, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00 };
-
-const byte_t SoundDD_Data[SMPTE_UL_LENGTH] = {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
-  0x01, 0x03, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00 };
-
-const byte_t TCDD_Data[SMPTE_UL_LENGTH] = {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
-  0x01, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00 };
-
-const byte_t DMDD_Data[SMPTE_UL_LENGTH] = {
-  0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
-  0x01, 0x03, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00 };
-
-
 //
 // add DMS CryptographicFramework entry to source package
 void
@@ -86,7 +70,7 @@ AddDMScrypt(Partition& HeaderPart, SourcePackage& Package, WriterInfo& Descr, co
   Sequence* Seq = new Sequence;
   HeaderPart.AddChildObject(Seq);
   NewTrack->Sequence = Seq->InstanceUID;
-  Seq->DataDefinition = UL(DMDD_Data);
+  Seq->DataDefinition = UL(Dict::ul(MDD_DescriptiveMetaDataDef));
 
   DMSegment* Segment = new DMSegment;
   HeaderPart.AddChildObject(Segment);
@@ -103,14 +87,15 @@ AddDMScrypt(Partition& HeaderPart, SourcePackage& Package, WriterInfo& Descr, co
 
   Context->ContextID.Set(Descr.ContextID);
   Context->SourceEssenceContainer = WrappingUL; // ??????
-  Context->CipherAlgorithm.Set(CipherAlgorithm_AES);
-  Context->MICAlgorithm.Set( Descr.UsesHMAC ? MICAlgorithm_HMAC_SHA1 : MICAlgorithm_NONE );
+  Context->CipherAlgorithm.Set(Dict::ul(MDD_CipherAlgorithm_AES));
+  Context->MICAlgorithm.Set( Descr.UsesHMAC ? Dict::ul(MDD_MICAlgorithm_HMAC_SHA1) : Dict::ul(MDD_MICAlgorithm_NONE) );
   Context->CryptographicKeyID.Set(Descr.CryptographicKeyID);
 }
 
 //
 Result_t
 ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL,
+                                const std::string& TrackName, const UL& DataDefinition,
                                 const MXF::Rational& EditRate,
                                 ui32_t TCFrameRate, ui32_t BytesPerEditUnit)
 {
@@ -122,9 +107,14 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
 
   // Set the Operational Pattern label -- we're just starting and have no RIP or index,
   // so we tell the world by using OP1a
-  m_HeaderPart.m_Preface->OperationalPattern = UL(OP1aUL);
+  m_HeaderPart.m_Preface->OperationalPattern = UL(Dict::ul(MDD_OP1a));
   m_HeaderPart.OperationalPattern = m_HeaderPart.m_Preface->OperationalPattern;
-  m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(1, 0)); // First RIP Entry
+
+  // First RIP Entry
+  if ( m_Info.LabelSetType == LS_MXF_SMPTE )
+    m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(0, 0)); // 3-part, no essence in header
+  else
+    m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(1, 0)); // 2-part, essence in header
 
   //
   // Identification
@@ -133,17 +123,17 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   m_HeaderPart.AddChildObject(Ident);
   m_HeaderPart.m_Preface->Identifications.push_back(Ident->InstanceUID);
 
-  Ident->ThisGenerationUID.GenRandomValue();
+  Kumu::GenRandomValue(Ident->ThisGenerationUID);
   Ident->CompanyName = m_Info.CompanyName.c_str();
   Ident->ProductName = m_Info.ProductName.c_str();
   Ident->VersionString = m_Info.ProductVersion.c_str();
   Ident->ProductUID.Set(m_Info.ProductUUID);
-  // Ident->Platform = WM_PLATFORM;
-  Ident->ToolkitVersion.Release = VersionType::RL_DEVELOPMENT;
+  Ident->Platform = ASDCP_PLATFORM;
   Ident->ToolkitVersion.Major = VERSION_MAJOR;
   Ident->ToolkitVersion.Minor = VERSION_APIMINOR;
   Ident->ToolkitVersion.Patch = VERSION_IMPMINOR;
-  Ident->ToolkitVersion.Build = WM_BUILD_NUMBER;
+  Ident->ToolkitVersion.Build = ASDCP_BUILD_NUMBER;
+  Ident->ToolkitVersion.Release = VersionType::RL_RELEASE;
 
   //
   ContentStorage* Storage = new ContentStorage;
@@ -160,12 +150,10 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   // Material Package
   //
   UMID PackageUMID;
-  PackageUMID.MakeUMID(0x0d); // Using mixed type. What is the actual type?
-
+  PackageUMID.MakeUMID(0x0f); // unidentified essence
   m_MaterialPackage = new MaterialPackage;
   m_MaterialPackage->Name = "AS-DCP Material Package";
   m_MaterialPackage->PackageUID = PackageUMID;
-
   m_HeaderPart.AddChildObject(m_MaterialPackage);
   Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
 
@@ -177,17 +165,17 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   NewTrack->TrackID = 1;
   NewTrack->TrackName = "Timecode Track";
 
-  Sequence* Seq = new Sequence;
-  m_HeaderPart.AddChildObject(Seq);
-  NewTrack->Sequence = Seq->InstanceUID;
-  Seq->DataDefinition = UL(TCDD_Data);
+  m_MPTCSequence = new Sequence;
+  m_HeaderPart.AddChildObject(m_MPTCSequence);
+  NewTrack->Sequence = m_MPTCSequence->InstanceUID;
+  m_MPTCSequence->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef));
 
   m_MPTimecode = new TimecodeComponent;
   m_HeaderPart.AddChildObject(m_MPTimecode);
-  Seq->StructuralComponents.push_back(m_MPTimecode->InstanceUID);
+  m_MPTCSequence->StructuralComponents.push_back(m_MPTimecode->InstanceUID);
   m_MPTimecode->RoundedTimecodeBase = TCFrameRate;
   m_MPTimecode->StartTimecode = ui64_C(0);
-  m_MPTimecode->DataDefinition = UL(TCDD_Data);
+  m_MPTimecode->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef));
 
   // Essence Track
   NewTrack = new Track;
@@ -195,15 +183,17 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   NewTrack->EditRate = EditRate;
   m_MaterialPackage->Tracks.push_back(NewTrack->InstanceUID);
   NewTrack->TrackID = 2;
-  NewTrack->TrackName = "Essence Track";
+  NewTrack->TrackName = TrackName.c_str();
 
-  Seq = new Sequence;
-  m_HeaderPart.AddChildObject(Seq);
-  NewTrack->Sequence = Seq->InstanceUID;
+  m_MPClSequence = new Sequence;
+  m_HeaderPart.AddChildObject(m_MPClSequence);
+  NewTrack->Sequence = m_MPClSequence->InstanceUID;
+  m_MPClSequence->DataDefinition = DataDefinition;
 
   m_MPClip = new SourceClip;
   m_HeaderPart.AddChildObject(m_MPClip);
-  Seq->StructuralComponents.push_back(m_MPClip->InstanceUID);
+  m_MPClSequence->StructuralComponents.push_back(m_MPClip->InstanceUID);
+  m_MPClip->DataDefinition = DataDefinition;
 
   //
   // File (Source) Package
@@ -215,8 +205,9 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   m_FilePackage->Name = PackageLabel.c_str();
   m_FilePackage->PackageUID = PackageUMID;
   ECD->LinkedPackageUID = PackageUMID;
+
   m_MPClip->SourcePackageID = PackageUMID;
-  m_MPClip->SourceTrackID = 1;
+  m_MPClip->SourceTrackID = 2;
 
   m_HeaderPart.AddChildObject(m_FilePackage);
   Storage->Packages.push_back(m_FilePackage->InstanceUID);
@@ -229,17 +220,17 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   NewTrack->TrackID = 1;
   NewTrack->TrackName = "Timecode Track";
 
-  Seq = new Sequence;
-  m_HeaderPart.AddChildObject(Seq);
-  NewTrack->Sequence = Seq->InstanceUID;
-  Seq->DataDefinition = UL(TCDD_Data);
+  m_FPTCSequence = new Sequence;
+  m_HeaderPart.AddChildObject(m_FPTCSequence);
+  NewTrack->Sequence = m_FPTCSequence->InstanceUID;
+  m_FPTCSequence->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef));
 
   m_FPTimecode = new TimecodeComponent;
   m_HeaderPart.AddChildObject(m_FPTimecode);
-  Seq->StructuralComponents.push_back(m_FPTimecode->InstanceUID);
+  m_FPTCSequence->StructuralComponents.push_back(m_FPTimecode->InstanceUID);
   m_FPTimecode->RoundedTimecodeBase = TCFrameRate;
   m_FPTimecode->StartTimecode = ui64_C(86400); // 01:00:00:00
-  m_FPTimecode->DataDefinition = UL(TCDD_Data);
+  m_FPTimecode->DataDefinition = UL(Dict::ul(MDD_TimecodeDataDef));
 
   // Essence Track
   NewTrack = new Track;
@@ -247,24 +238,27 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   NewTrack->EditRate = EditRate;
   m_FilePackage->Tracks.push_back(NewTrack->InstanceUID);
   NewTrack->TrackID = 2;
-  NewTrack->TrackName = "Essence Track";
+  NewTrack->TrackName = TrackName.c_str();
 
-  Seq = new Sequence;
-  m_HeaderPart.AddChildObject(Seq);
-  NewTrack->Sequence = Seq->InstanceUID;
+  m_FPClSequence = new Sequence;
+  m_HeaderPart.AddChildObject(m_FPClSequence);
+  NewTrack->Sequence = m_FPClSequence->InstanceUID;
+  m_FPClSequence->DataDefinition = DataDefinition;
 
   m_FPClip = new SourceClip;
   m_HeaderPart.AddChildObject(m_FPClip);
-  Seq->StructuralComponents.push_back(m_FPClip->InstanceUID);
+  m_FPClSequence->StructuralComponents.push_back(m_FPClip->InstanceUID);
+  m_FPClip->DataDefinition = DataDefinition;
+
+  // for now we do not allow setting this value, so all files will be 'original'
+  m_FPClip->SourceTrackID = 0;
+  m_FPClip->SourcePackageID = NilUMID;
 
   //
   // Essence Descriptor
   //
   m_EssenceDescriptor->EssenceContainer = WrappingUL;
   m_EssenceDescriptor->LinkedTrackID = NewTrack->TrackID;
-
-  // link the Material Package to the File Package ?????????????????????????????????
-  Seq->StructuralComponents.push_back(NewTrack->InstanceUID);
   m_HeaderPart.m_Preface->PrimaryPackage = m_FilePackage->InstanceUID;
 
   //
@@ -272,40 +266,59 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
   //
   if ( m_Info.EncryptedEssence )
     {
-      UL CryptEssenceUL(WrappingUL_Data_Crypt);
+      UL CryptEssenceUL(Dict::ul(MDD_EncryptedContainerLabel));
       m_HeaderPart.EssenceContainers.push_back(CryptEssenceUL);
-      m_HeaderPart.m_Preface->EssenceContainers.push_back(CryptEssenceUL);
-      m_HeaderPart.m_Preface->DMSchemes.push_back(UL(CryptoFrameworkUL_Data));
+      m_HeaderPart.m_Preface->DMSchemes.push_back(UL(Dict::ul(MDD_CryptographicFrameworkLabel)));
       AddDMScrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL);
     }
   else
     {
-      UL GCUL(GCMulti_Data);
-      m_HeaderPart.EssenceContainers.push_back(GCUL);
+      m_HeaderPart.EssenceContainers.push_back(UL(Dict::ul(MDD_GCMulti)));
       m_HeaderPart.EssenceContainers.push_back(WrappingUL);
-      m_HeaderPart.m_Preface->EssenceContainers = m_HeaderPart.EssenceContainers;
     }
 
+  m_HeaderPart.m_Preface->EssenceContainers = m_HeaderPart.EssenceContainers;
   m_HeaderPart.AddChildObject(m_EssenceDescriptor);
-  m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
 
-  // Write the header partition
-  Result_t result = m_HeaderPart.WriteToFile(m_File, HeaderPadding);
-
-  //
-  // Body Partition
-  //
+  std::list<FileDescriptor*>::iterator sdli = m_EssenceSubDescriptorList.begin();
+  for ( ; sdli != m_EssenceSubDescriptorList.end(); sdli++ )
+    m_HeaderPart.AddChildObject(*sdli);
 
+  m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
 
-  //
-  // Index setup
-  //
-  fpos_t ECoffset = m_File.Tell();
+  // Write the header partition
+  Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
 
-  if ( BytesPerEditUnit == 0 )
-    m_FooterPart.SetIndexParamsVBR(&m_HeaderPart.m_Primer, EditRate, ECoffset);
+  // create a body partition of we're writing proper 429-3/OP-Atom
+  if ( ASDCP_SUCCESS(result) && m_Info.LabelSetType == LS_MXF_SMPTE )
+    {
+      // Body Partition
+      m_BodyPart.EssenceContainers = m_HeaderPart.EssenceContainers;
+      m_BodyPart.ThisPartition = m_File.Tell();
+      m_BodyPart.BodySID = 1;
+      UL OPAtomUL(Dict::ul(MDD_OPAtom));
+      m_BodyPart.OperationalPattern = OPAtomUL;
+      m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(1, m_BodyPart.ThisPartition)); // Second RIP Entry
+      
+      UL BodyUL(Dict::ul(MDD_ClosedCompleteBodyPartition));
+      result = m_BodyPart.WriteToFile(m_File, BodyUL);
+    }
   else
-    m_FooterPart.SetIndexParamsCBR(&m_HeaderPart.m_Primer, BytesPerEditUnit, EditRate);
+    {
+      m_HeaderPart.BodySID = 1;
+    }
+
+  if ( ASDCP_SUCCESS(result) )
+    {
+      // Index setup
+      Kumu::fpos_t ECoffset = m_File.Tell();
+      m_FooterPart.IndexSID = 129;
+
+      if ( BytesPerEditUnit == 0 )
+       m_FooterPart.SetIndexParamsVBR(&m_HeaderPart.m_Primer, EditRate, ECoffset);
+      else
+       m_FooterPart.SetIndexParamsCBR(&m_HeaderPart.m_Primer, BytesPerEditUnit, EditRate);
+    }
 
   return result;
 }
@@ -317,11 +330,11 @@ Result_t
 ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
                                  AESEncContext* Ctx, HMACContext* HMAC)
 {
-  Result_t result;
+  Result_t result = RESULT_OK;
   IntegrityPack IntPack;
 
   byte_t overhead[128];
-  MemIOWriter Overhead(overhead, 128);
+  Kumu::MemIOWriter Overhead(overhead, 128);
 
   if ( FrameBuf.Size() == 0 )
     {
@@ -349,7 +362,10 @@ ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte
 
       if ( ASDCP_SUCCESS(result) )
        { // write UL
-         Overhead.WriteRaw((byte_t*)CryptEssenceUL_Data, klv_key_size);
+         if ( m_Info.LabelSetType == LS_MXF_INTEROP )
+           Overhead.WriteRaw(Dict::ul(MDD_MXFInterop_CryptEssence), SMPTE_UL_LENGTH);
+         else
+           Overhead.WriteRaw(Dict::ul(MDD_CryptEssence), SMPTE_UL_LENGTH);
 
          // construct encrypted triplet header
          ui32_t ETLength = klv_cryptinfo_size + m_CtFrameBuf.Size();
@@ -357,25 +373,25 @@ ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte
          if ( m_Info.UsesHMAC )
            ETLength += klv_intpack_size;
          else
-           ETLength += (klv_length_size * 3); // for empty intpack
+           ETLength += (MXF_BER_LENGTH * 3); // for empty intpack
 
-         Overhead.WriteBER(ETLength, klv_length_size);                  // write encrypted triplet length
-         Overhead.WriteBER(UUIDlen, klv_length_size);                   // write ContextID length
+         Overhead.WriteBER(ETLength, MXF_BER_LENGTH);                  // write encrypted triplet length
+         Overhead.WriteBER(UUIDlen, MXF_BER_LENGTH);                   // write ContextID length
          Overhead.WriteRaw(m_Info.ContextID, UUIDlen);                  // write ContextID
-         Overhead.WriteBER(sizeof(ui64_t), klv_length_size);            // write PlaintextOffset length
+         Overhead.WriteBER(sizeof(ui64_t), MXF_BER_LENGTH);            // write PlaintextOffset length
          Overhead.WriteUi64BE(FrameBuf.PlaintextOffset());              // write PlaintextOffset
-         Overhead.WriteBER(klv_key_size, klv_length_size);              // write essence UL length
-         Overhead.WriteRaw((byte_t*)EssenceUL, klv_key_size);           // write the essence UL
-         Overhead.WriteBER(sizeof(ui64_t), klv_length_size);            // write SourceLength length
+         Overhead.WriteBER(SMPTE_UL_LENGTH, MXF_BER_LENGTH);              // write essence UL length
+         Overhead.WriteRaw((byte_t*)EssenceUL, SMPTE_UL_LENGTH);           // write the essence UL
+         Overhead.WriteBER(sizeof(ui64_t), MXF_BER_LENGTH);            // write SourceLength length
          Overhead.WriteUi64BE(FrameBuf.Size());                         // write SourceLength
-         Overhead.WriteBER(m_CtFrameBuf.Size(), klv_length_size);       // write ESV length
+         Overhead.WriteBER(m_CtFrameBuf.Size(), MXF_BER_LENGTH);       // write ESV length
 
-         result = m_File.Writev(Overhead.Data(), Overhead.Size());
+         result = m_File.Writev(Overhead.Data(), Overhead.Length());
        }
 
       if ( ASDCP_SUCCESS(result) )
        {
-         m_StreamOffset += Overhead.Size();
+         m_StreamOffset += Overhead.Length();
          // write encrypted source value
          result = m_File.Writev((byte_t*)m_CtFrameBuf.RoData(), m_CtFrameBuf.Size());
        }
@@ -385,7 +401,7 @@ ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte
          m_StreamOffset += m_CtFrameBuf.Size();
 
          byte_t hmoverhead[512];
-         MemIOWriter HMACOverhead(hmoverhead, 512);
+         Kumu::MemIOWriter HMACOverhead(hmoverhead, 512);
 
          // write the HMAC
          if ( m_Info.UsesHMAC )
@@ -395,25 +411,25 @@ ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte
          else
            { // we still need the var-pack length values if the intpack is empty
              for ( ui32_t i = 0; i < 3 ; i++ )
-               HMACOverhead.WriteBER(0, klv_length_size);
+               HMACOverhead.WriteBER(0, MXF_BER_LENGTH);
            }
 
          // write HMAC
-         result = m_File.Writev(HMACOverhead.Data(), HMACOverhead.Size());
-         m_StreamOffset += HMACOverhead.Size();
+         result = m_File.Writev(HMACOverhead.Data(), HMACOverhead.Length());
+         m_StreamOffset += HMACOverhead.Length();
        }
     }
   else
     {
-      Overhead.WriteRaw((byte_t*)EssenceUL, klv_key_size);
-      Overhead.WriteBER(FrameBuf.Size(), klv_length_size);
-      result = m_File.Writev(Overhead.Data(), Overhead.Size());
+      Overhead.WriteRaw((byte_t*)EssenceUL, SMPTE_UL_LENGTH);
+      Overhead.WriteBER(FrameBuf.Size(), MXF_BER_LENGTH);
+      result = m_File.Writev(Overhead.Data(), Overhead.Length());
  
       if ( ASDCP_SUCCESS(result) )
        result = m_File.Writev((byte_t*)FrameBuf.RoData(), FrameBuf.Size());
 
       if ( ASDCP_SUCCESS(result) )
-       m_StreamOffset += Overhead.Size() + FrameBuf.Size();
+       m_StreamOffset += Overhead.Length() + FrameBuf.Size();
     }
 
   if ( ASDCP_SUCCESS(result) )
@@ -429,20 +445,29 @@ Result_t
 ASDCP::h__Writer::WriteMXFFooter()
 {
   // Set top-level file package correctly for OP-Atom
-  m_MPTimecode->Duration = m_FramesWritten;
-  m_MPClip->Duration = m_FramesWritten;
-  m_FPTimecode->Duration = m_FramesWritten;
-  m_FPClip->Duration = m_FramesWritten;
-  m_EssenceDescriptor->ContainerDuration = m_FramesWritten;
-
-  fpos_t here = m_File.Tell();
-  m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(1, here)); // Third RIP Entry
+
+  m_MPTCSequence->Duration = m_MPTimecode->Duration = m_MPClSequence->Duration = m_MPClip->Duration = 
+    m_FPTCSequence->Duration = m_FPTimecode->Duration = m_FPClSequence->Duration = m_FPClip->Duration = 
+    m_EssenceDescriptor->ContainerDuration = m_FramesWritten;
+
+  Kumu::fpos_t here = m_File.Tell();
+  m_HeaderPart.m_RIP.PairArray.push_back(RIP::Pair(0, here)); // Last RIP Entry
   m_HeaderPart.FooterPartition = here;
-  m_HeaderPart.BodySID = 1;
-  m_HeaderPart.IndexSID = m_FooterPart.IndexSID;
-  m_HeaderPart.OperationalPattern = UL(OPAtomUL);
+
+  // re-label the partition
+  UL OPAtomUL(Dict::ul(MDD_OPAtom));
+
+  if ( m_Info.LabelSetType == LS_MXF_INTEROP )
+    OPAtomUL.Set(Dict::ul(MDD_MXFInterop_OPAtom));
+  
+  m_HeaderPart.OperationalPattern = OPAtomUL;
   m_HeaderPart.m_Preface->OperationalPattern = m_HeaderPart.OperationalPattern;
 
+  if ( m_Info.LabelSetType == LS_MXF_SMPTE )
+    m_FooterPart.PreviousPartition = m_BodyPart.ThisPartition;
+  else
+    m_FooterPart.PreviousPartition = m_HeaderPart.ThisPartition;
+
   m_FooterPart.OperationalPattern = m_HeaderPart.OperationalPattern;
   m_FooterPart.EssenceContainers = m_HeaderPart.EssenceContainers;
   m_FooterPart.FooterPartition = here;
@@ -457,7 +482,7 @@ ASDCP::h__Writer::WriteMXFFooter()
     result = m_File.Seek(0);
 
   if ( ASDCP_SUCCESS(result) )
-    result = m_HeaderPart.WriteToFile(m_File, HeaderPadding);
+    result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
 
   m_File.Close();
   return result;