fixing reserved symbol conflict with AS_02_USE (USE_AS_02)
authormikey <mikey@cinecert.com>
Mon, 3 Jun 2013 21:33:32 +0000 (21:33 +0000)
committermikey <>
Mon, 3 Jun 2013 21:33:32 +0000 (21:33 +0000)
13 files changed:
configure.ac
src/AS_02.h
src/AS_02_JP2K.cpp
src/AS_02_internal.h
src/AS_DCP_JP2K.cpp
src/AS_DCP_internal.h
src/MXF.cpp
src/Makefile.am
src/as-02-wrap.cpp
src/h__02_Reader.cpp
src/h__02_Writer.cpp
src/h__Writer.cpp
src/klvwalk.cpp

index 3ecb14c627cdd1bfdd893430e4a4648f9648555b..623ccc3bee2fdebb24139b24559fee0a8d05c306 100644 (file)
@@ -44,6 +44,8 @@ AC_CONFIG_SRCDIR([src/KM_error.h])
 #AC_CONFIG_HEADER([src/config.h])
 AM_INIT_AUTOMAKE([1.9 foreign])
 
+AC_CONFIG_MACRO_DIR([m4])
+
 # Checks for programs.
 AC_CANONICAL_BUILD
 AC_CANONICAL_HOST
@@ -73,7 +75,8 @@ AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])
 AC_ARG_ENABLE([freedist],
      [  --enable-freedist    ensure source distribution is of BSD-licensed code],
      [case "${enableval}" in
-       yes) freedist=true ;;
+       yes) freedist=true
+       AC_MSG_WARN([BSD licensed ASDCPlib creation ENABLED.]) ;;
        no)  freedist=false ;;
        *) AC_MSG_ERROR([bad value ${enableval} for --enable-freedist]) ;;
      esac],[freedist=false])
@@ -95,13 +98,13 @@ AC_ARG_ENABLE([random-case-UUID],
      esac],[random_case_UUID=false])
      AM_CONDITIONAL([ENABLE_RANDOM_UUID], [test x$random_case_UUID = xtrue])
 AC_ARG_ENABLE([as-02],
-     [  --enable-as-02    enable supprt for SMPTE ST 2067-5 MXF files, A.K.A. AS-02],
+     [  --enable-as-02    enable support for SMPTE ST 2067-5 MXF files, A.K.A. AS-02],
      [case "${enableval}" in
        yes) as_02_use=true ;;
        no)  as_02_use=false ;;
        *) AC_MSG_ERROR([bad value ${enableval} for --enable-as-02]) ;;
      esac],[as_02_use=false])
-     AM_CONDITIONAL([AS_02_USE], [test x$as_02_use = xtrue])
+     AM_CONDITIONAL([USE_AS_02], [test x$as_02_use = xtrue])
 
 # Checks for libraries.
 AC_CHECK_LIB([pthread], [pthread_create])
index ff1bfc381083a8e5988cfb5ed0c25528a892359d..dc6fc612e8ef91b9a1f162e1b4ffa77f61235dff 100644 (file)
@@ -68,7 +68,7 @@ namespace AS_02
   using Kumu::Result_t;
 
   namespace MXF {
-#if 1
+#if 0
     //
     class OP1aIndexBodyPartion : public ASDCP::MXF::Partition
     {
index 136fd278c7e08d746c13e6d6ab84e3475d2b999f..38b2e55aac44bd6e302f1df7f30739804e9b4404 100644 (file)
@@ -40,7 +40,7 @@ using Kumu::GenRandomValue;
 
 //------------------------------------------------------------------------------------------
 
-static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE ST 422 frame wrapping of JPEG 2000 codestreams";
+static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE ST 422 / ST 2067-5 frame wrapping of JPEG 2000 codestreams";
 static std::string PICT_DEF_LABEL = "Image Track";
 
 //------------------------------------------------------------------------------------------
@@ -68,77 +68,10 @@ public:
 
   Result_t    OpenRead(const char*, EssenceType_t);
   Result_t    ReadFrame(ui32_t, ASDCP::JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
-  Result_t    MD_to_JP2K_PDesc(ASDCP::JP2K::PictureDescriptor& PDesc);
-
-  Result_t OpenMXFRead(const char* filename);
-  // positions file before reading
-  Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
-                        const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
-
-  // reads from current position
-  Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
-                         const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
-
 };
 
 //
-ASDCP::Result_t
-AS_02::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(ASDCP::JP2K::PictureDescriptor& PDesc)
-{
-  memset(&PDesc, 0, sizeof(PDesc));
-  ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
-
-  PDesc.EditRate           = m_EditRate;
-  PDesc.SampleRate         = m_SampleRate;
-  assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL);
-  PDesc.ContainerDuration  = (ui32_t) PDescObj->ContainerDuration;
-  PDesc.StoredWidth        = PDescObj->StoredWidth;
-  PDesc.StoredHeight       = PDescObj->StoredHeight;
-  PDesc.AspectRatio        = PDescObj->AspectRatio;
-
-  if ( m_EssenceSubDescriptor != 0 )
-    {
-      PDesc.Rsize   = m_EssenceSubDescriptor->Rsize;
-      PDesc.Xsize   = m_EssenceSubDescriptor->Xsize;
-      PDesc.Ysize   = m_EssenceSubDescriptor->Ysize;
-      PDesc.XOsize  = m_EssenceSubDescriptor->XOsize;
-      PDesc.YOsize  = m_EssenceSubDescriptor->YOsize;
-      PDesc.XTsize  = m_EssenceSubDescriptor->XTsize;
-      PDesc.YTsize  = m_EssenceSubDescriptor->YTsize;
-      PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
-      PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
-      PDesc.Csize   = m_EssenceSubDescriptor->Csize;
-
-      // PictureComponentSizing
-      ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
-
-      if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
-       memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
-
-      else
-       DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
-
-      // CodingStyleDefault
-      memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
-      memcpy(&PDesc.CodingStyleDefault,
-            m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
-            m_EssenceSubDescriptor->CodingStyleDefault.Length());
-
-      // QuantizationDefault
-      memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
-      memcpy(&PDesc.QuantizationDefault,
-            m_EssenceSubDescriptor->QuantizationDefault.RoData(),
-            m_EssenceSubDescriptor->QuantizationDefault.Length());
-
-      PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
-    }
-
-  return RESULT_OK;
-}
-
-//
-//
-ASDCP::Result_t
+Result_t
 AS_02::JP2K::MXFReader::h__Reader::OpenRead(const char* filename, ASDCP::EssenceType_t type)
 {
   Result_t result = OpenMXFRead(filename);
@@ -186,7 +119,9 @@ AS_02::JP2K::MXFReader::h__Reader::OpenRead(const char* filename, ASDCP::Essence
          return RESULT_STATE;
        }
 
-      result = MD_to_JP2K_PDesc(m_PDesc);
+      assert(m_EssenceDescriptor);
+      assert(m_EssenceSubDescriptor);
+      result = MD_to_JP2K_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
     }
 
   return result;
@@ -194,7 +129,7 @@ AS_02::JP2K::MXFReader::h__Reader::OpenRead(const char* filename, ASDCP::Essence
 
 //
 //
-ASDCP::Result_t
+Result_t
 AS_02::JP2K::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::JP2K::FrameBuffer& FrameBuf,
                      ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC)
 {
@@ -285,7 +220,8 @@ AS_02::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, ASDCP::JP2K::FrameBuffer& Fra
 
 // Fill the struct with the values from the file's header.
 // Returns RESULT_INIT if the file is not open.
-ASDCP::Result_t AS_02::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
+Result_t
+AS_02::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
 {
   if ( m_Reader && m_Reader->m_File.IsOpen() )
     {
@@ -299,7 +235,8 @@ ASDCP::Result_t AS_02::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor&
 
 // Fill the struct with the values from the file's header.
 // Returns RESULT_INIT if the file is not open.
-ASDCP::Result_t AS_02::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
+Result_t
+AS_02::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
 {
   if ( m_Reader && m_Reader->m_File.IsOpen() )
     {
@@ -325,11 +262,7 @@ public:
   PictureDescriptor m_PDesc;
   byte_t            m_EssenceUL[SMPTE_UL_LENGTH];
 
-  //new attributes for AS-02 support 
-  AS_02::IndexStrategy_t m_IndexStrategy; //Shim parameter index_strategy_frame/clip
-  ui32_t m_PartitionSpace; //Shim parameter partition_spacing
-
-  h__Writer(const Dictionary& d) : h__AS02Writer(d), m_EssenceSubDescriptor(0), m_IndexStrategy(AS_02::IS_FOLLOW), m_PartitionSpace(60) {
+  h__Writer(const Dictionary& d) : h__AS02Writer(d), m_EssenceSubDescriptor(0) {
     memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
   }
 
@@ -339,139 +272,35 @@ public:
                     const ui32_t& PartitionSpace, const ui32_t& HeaderSize);
   Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
                           ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
-  Result_t WriteFrame(const ASDCP::JP2K::FrameBuffer&, bool add_index, ASDCP::AESEncContext*, ASDCP::HMACContext*);
+  Result_t WriteFrame(const ASDCP::JP2K::FrameBuffer&, ASDCP::AESEncContext*, ASDCP::HMACContext*);
   Result_t Finalize();
-  Result_t JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc);
-
-  //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);
-
-  ////new method to create BodyPartition for essence and index
-  //Result_t CreateBodyPartPair();
-  ////new method to finalize BodyPartion(index)
-  //Result_t CompleteIndexBodyPart();
-
-  // reimplement these functions in AS_02_PCM to support modifications for AS-02
-  //Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
-  //   const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
-  Result_t WriteMXFFooter();
-
-
 };
 
-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
-AS_02::JP2K::MXFWriter::h__Writer::JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc)
-{
-  assert(m_EssenceDescriptor);
-  assert(m_EssenceSubDescriptor);
-  ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
-
-  PDescObj->ContainerDuration = PDesc.ContainerDuration;
-  PDescObj->SampleRate = PDesc.EditRate;
-  PDescObj->FrameLayout = 0;
-  PDescObj->StoredWidth = PDesc.StoredWidth;
-  PDescObj->StoredHeight = PDesc.StoredHeight;
-  PDescObj->AspectRatio = PDesc.AspectRatio;
-
-  //  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
-  //    }
-
-  assert(m_Dict);
-  if ( PDesc.StoredWidth < 2049 )
-    {
-      PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
-      m_EssenceSubDescriptor->Rsize = 3;
-    }
-  else
-    {
-      PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
-      m_EssenceSubDescriptor->Rsize = 4;
-    }
-
-  m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
-  m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
-  m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
-  m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
-  m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
-  m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
-  m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
-  m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
-  m_EssenceSubDescriptor->Csize = PDesc.Csize;
-
-  const ui32_t tmp_buffer_len = 1024;
-  byte_t tmp_buffer[tmp_buffer_len];
-
-  // slh: this has to be done dynamically since the number of components is not always 3
-  *(ui32_t*)tmp_buffer = KM_i32_BE(m_EssenceSubDescriptor->Csize);
-  *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
-  memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * m_EssenceSubDescriptor->Csize);
-  const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * m_EssenceSubDescriptor->Csize);
-
-  /*
-   *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
-   *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));        
-   memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
-   const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
-  */
-
-  memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
-  m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
-
-  ui32_t precinct_set_size = 0, i;
-  for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
-    precinct_set_size++;
-
-  ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
-  memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
-  m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
-
-  ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
-  memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
-  m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
-
-  return RESULT_OK;
-}
-
 
 // Open the file for writing. The file must not exist. Returns error if
 // the operation cannot be completed.
-ASDCP::Result_t
+Result_t
 AS_02::JP2K::MXFWriter::h__Writer::OpenWrite(const char* filename, EssenceType_t type, const AS_02::IndexStrategy_t& IndexStrategy,
-                     const ui32_t& PartitionSpace, const ui32_t& HeaderSize)
+                                            const ui32_t& PartitionSpace_sec, const ui32_t& HeaderSize)
 {
   if ( ! m_State.Test_BEGIN() )
     return RESULT_STATE;
 
-  ASDCP::Result_t result = m_File.OpenWrite(filename);
+  if ( m_IndexStrategy != AS_02::IS_FOLLOW )
+    {
+      DefaultLogSink().Error("Only strategy IS_FOLLOW is supported at this time.\n");
+      return Kumu::RESULT_NOTIMPL;
+    }
+
+  Result_t result = m_File.OpenWrite(filename);
 
   if ( ASDCP_SUCCESS(result) )
     {
       m_IndexStrategy = IndexStrategy;
-      m_PartitionSpace = PartitionSpace;
+      m_PartitionSpace = PartitionSpace_sec; // later converted to edit units by SetSourceStream()
       m_HeaderSize = HeaderSize;
-      RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor(m_Dict);
-      tmp_rgba->ComponentMaxRef = 4095;
-      tmp_rgba->ComponentMinRef = 0;
 
-      m_EssenceDescriptor = tmp_rgba;
+      m_EssenceDescriptor = new RGBAEssenceDescriptor(m_Dict);
       m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor(m_Dict);
       m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
 
@@ -484,7 +313,7 @@ AS_02::JP2K::MXFWriter::h__Writer::OpenWrite(const char* filename, EssenceType_t
 }
 
 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
-ASDCP::Result_t
+Result_t
 AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
 {
   assert(m_Dict);
@@ -495,7 +324,13 @@ AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const PictureDescriptor& PDes
     LocalEditRate = PDesc.EditRate;
 
   m_PDesc = PDesc;
-  Result_t result = JP2K_PDesc_to_MD(m_PDesc);
+  assert(m_Dict);
+  Result_t result = JP2K_PDesc_to_MD(m_PDesc, *m_Dict,
+                                    static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor),
+                                    m_EssenceSubDescriptor);
+
+  static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->ComponentMaxRef = 4095; /// TODO: set with magic or some such thing
+  static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->ComponentMinRef = 0;
 
   if ( ASDCP_SUCCESS(result) )
     {
@@ -521,9 +356,32 @@ AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const PictureDescriptor& PDes
 // Fails if the file is not open, is finalized, or an operating system
 // error occurs.
 //
-ASDCP::Result_t
-AS_02::JP2K::MXFWriter::h__Writer::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, bool add_index,
+Result_t
+AS_02::JP2K::MXFWriter::h__Writer::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf,
                       AESEncContext* Ctx, HMACContext* HMAC)
+#if 1
+{
+  Result_t result = RESULT_OK;
+
+  if ( m_State.Test_READY() )
+    result = m_State.Goto_RUNNING(); // first time through
+  ui64_t StreamOffset = m_StreamOffset;
+
+  if ( ASDCP_SUCCESS(result) )
+    result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
+
+  if ( ASDCP_SUCCESS(result) )
+    {  
+      IndexTableSegment::IndexEntry Entry;
+      Entry.StreamOffset = StreamOffset;
+      m_IndexWriter.PushIndexEntry(Entry);
+    }
+
+  m_FramesWritten++;
+  return result;
+}
+#else
 {
   Result_t result = RESULT_OK;
 
@@ -562,29 +420,25 @@ AS_02::JP2K::MXFWriter::h__Writer::WriteFrame(const ASDCP::JP2K::FrameBuffer& Fr
   m_FramesWritten++;
   return result;
 }
-
+#endif
 
 // Closes the MXF file, writing the index and other closing information.
 //
-ASDCP::Result_t
+Result_t
 AS_02::JP2K::MXFWriter::h__Writer::Finalize()
 {
-  Result_t result = RESULT_OK;
-
   if ( ! m_State.Test_RUNNING() )
     return RESULT_STATE;
 
-  m_State.Goto_FINAL();
+  Result_t result = m_State.Goto_FINAL();
 
-  //the last Frame was written, complete the BodyPartion(Index), after that write the MXF-Footer
-  result = CompleteIndexBodyPart();
+  if ( ASDCP_SUCCESS(result) )
+    result = WriteAS02Footer();
 
-  if ( ASDCP_FAILURE(result) ){
-    return result;
-  }
-  return WriteMXFFooter();
+  return result;
 }
 
+
 //------------------------------------------------------------------------------------------
 
 
@@ -629,7 +483,7 @@ AS_02::JP2K::MXFWriter::RIP()
 
 // Open the file for writing. The file must not exist. Returns error if
 // the operation cannot be completed.
-ASDCP::Result_t
+Result_t
 AS_02::JP2K::MXFWriter::OpenWrite(const char* filename, const ASDCP::WriterInfo& Info,
                                  const ASDCP::JP2K::PictureDescriptor& PDesc,
                                  const IndexStrategy_t& Strategy,
@@ -639,7 +493,7 @@ AS_02::JP2K::MXFWriter::OpenWrite(const char* filename, const ASDCP::WriterInfo&
   m_Writer = new AS_02::JP2K::MXFWriter::h__Writer(DefaultSMPTEDict());
   m_Writer->m_Info = Info;
 
-  ASDCP::Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, Strategy, PartitionSpace, HeaderSize);
+  Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, Strategy, PartitionSpace, HeaderSize);
 
   if ( ASDCP_SUCCESS(result) )
     result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
@@ -650,22 +504,21 @@ AS_02::JP2K::MXFWriter::OpenWrite(const char* filename, const ASDCP::WriterInfo&
   return result;
 }
 
-
 // Writes a frame of essence to the MXF file. If the optional AESEncContext
 // argument is present, the essence is encrypted prior to writing.
 // Fails if the file is not open, is finalized, or an operating system
 // error occurs.
-ASDCP::Result_t 
+Result_t 
 AS_02::JP2K::MXFWriter::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
 {
   if ( m_Writer.empty() )
     return RESULT_INIT;
 
-  return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
+  return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC);
 }
 
 // Closes the MXF file, writing the index and other closing information.
-ASDCP::Result_t
+Result_t
 AS_02::JP2K::MXFWriter::Finalize()
 {
   if ( m_Writer.empty() )
index 0439ae4704f5329c690396751d121e6702a3472f..87e8451a8492fa98127febd9de4ece2999b91a72 100644 (file)
@@ -71,6 +71,34 @@ namespace AS_02
     }
   }
 
+  //
+  class AS02IndexWriter : public ASDCP::MXF::Partition
+    {
+      ASDCP::MXF::IndexTableSegment*  m_CurrentSegment;
+      ui32_t  m_BytesPerEditUnit;
+      ASDCP::MXF::Rational m_EditRate;
+
+      KM_NO_COPY_CONSTRUCT(AS02IndexWriter);
+      AS02IndexWriter();
+
+    public:
+      const ASDCP::Dictionary*&  m_Dict;
+      Kumu::fpos_t        m_ECOffset;
+      ASDCP::IPrimerLookup*      m_Lookup;
+      
+      AS02IndexWriter(const ASDCP::Dictionary*&);
+      virtual ~AS02IndexWriter();
+
+      Result_t WriteToFile(Kumu::FileWriter& Writer);
+      void     ResetCBR(Kumu::fpos_t offset);
+      void     Dump(FILE* = 0);
+
+      ui32_t GetDuration() const;
+      void PushIndexEntry(const ASDCP::MXF::IndexTableSegment::IndexEntry&);
+      void SetIndexParamsCBR(ASDCP::IPrimerLookup* lookup, ui32_t size, const ASDCP::Rational& Rate);
+      void SetIndexParamsVBR(ASDCP::IPrimerLookup* lookup, const ASDCP::Rational& Rate, Kumu::fpos_t offset);
+    };
+
   //
   class h__AS02Reader : public ASDCP::MXF::TrackFileReader<ASDCP::MXF::OP1aHeader, AS_02::MXF::AS02IndexReader>
     {
@@ -78,23 +106,22 @@ namespace AS_02
       h__AS02Reader();
 
     public:
-      Partition *m_pCurrentBodyPartition;
-      AS_02::MXF::OP1aIndexBodyPartion* m_pCurrentIndexPartition;
-      ui64_t     m_EssenceStart;
-      std::vector<Partition*> m_BodyPartList;
-      ui32_t     m_start_pos;
-      ui32_t     m_PartitionSpace;
-      IndexStrategy_t    m_IndexStrategy; //Shim parameter index_strategy_frame/clip
+      //      Partition *m_pCurrentBodyPartition;
+      //      ui64_t     m_EssenceStart;
+      //      std::vector<Partition*> m_BodyPartList;
+      //      ui32_t     m_start_pos;
+      //      ui32_t     m_PartitionSpace;
+      //      IndexStrategy_t    m_IndexStrategy; //Shim parameter index_strategy_frame/clip
 
       h__AS02Reader(const ASDCP::Dictionary&);
       virtual ~h__AS02Reader();
 
       Result_t OpenMXFRead(const char* filename);
+
       Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
                             const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC);
-      Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
-                          i8_t& temporalOffset, i8_t& keyFrameOffset);
 
+      Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset);
     };
 
   //
@@ -104,11 +131,9 @@ namespace AS_02
       h__AS02Writer();
 
     public:
-      AS_02::MXF::OP1aIndexBodyPartion*  m_CurrentIndexBodyPartition;
-      ui64_t     m_BodyOffset;
-      ui32_t     m_PartitionSpace;
+      AS02IndexWriter m_IndexWriter;
+      ui32_t     m_PartitionSpace;  // edit units per partition
       IndexStrategy_t    m_IndexStrategy; //Shim parameter index_strategy_frame/clip
-      std::vector<Partition*> m_BodyPartList;
 
       h__AS02Writer(const Dictionary&);
       virtual ~h__AS02Writer();
@@ -119,9 +144,8 @@ namespace AS_02
                               const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
                               ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
 
-      Result_t CreateBodyPart(const ASDCP::MXF::Rational& EditRate, ui32_t BytesPerEditUnit);
-      Result_t CreateBodyPartPair();
-      Result_t CompleteIndexBodyPart();
+      Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
+                              AESEncContext* Ctx, HMACContext* HMAC);
 
       Result_t WriteAS02Footer();
     };
index d5cbc85cc36793a23e11b8451748cd685ceddaca..df4f6a27b2db89d088d2a4a79fdffe6b32c8d266 100755 (executable)
@@ -200,6 +200,85 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
 }
 
 
+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
+ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
+                       const ASDCP::Dictionary& dict,
+                       ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
+                       ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor)
+{
+  if ( EssenceDescriptor == 0 || EssenceSubDescriptor == 0 )
+    return RESULT_PTR;
+
+  EssenceDescriptor->ContainerDuration = PDesc.ContainerDuration;
+  EssenceDescriptor->SampleRate = PDesc.EditRate;
+  EssenceDescriptor->FrameLayout = 0;
+  EssenceDescriptor->StoredWidth = PDesc.StoredWidth;
+  EssenceDescriptor->StoredHeight = PDesc.StoredHeight;
+  EssenceDescriptor->AspectRatio = PDesc.AspectRatio;
+
+  //  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 )
+    {
+      EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_2K));
+      EssenceSubDescriptor->Rsize = 3;
+    }
+  else
+    {
+      EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_4K));
+      EssenceSubDescriptor->Rsize = 4;
+    }
+
+  EssenceSubDescriptor->Xsize = PDesc.Xsize;
+  EssenceSubDescriptor->Ysize = PDesc.Ysize;
+  EssenceSubDescriptor->XOsize = PDesc.XOsize;
+  EssenceSubDescriptor->YOsize = PDesc.YOsize;
+  EssenceSubDescriptor->XTsize = PDesc.XTsize;
+  EssenceSubDescriptor->YTsize = PDesc.YTsize;
+  EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
+  EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
+  EssenceSubDescriptor->Csize = PDesc.Csize;
+
+  const ui32_t tmp_buffer_len = 1024;
+  byte_t tmp_buffer[tmp_buffer_len];
+
+  *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
+  *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
+  memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+
+  const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+  memcpy(EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
+  EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
+
+  ui32_t precinct_set_size = 0, i;
+  for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
+    precinct_set_size++;
+
+  ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
+  memcpy(EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
+  EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
+
+  ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
+  memcpy(EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
+  EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
+
+  return RESULT_OK;
+}
+
+
 //------------------------------------------------------------------------------------------
 //
 // hidden, internal implementation of JPEG 2000 reader
@@ -225,61 +304,61 @@ public:
 
   Result_t    OpenRead(const char*, EssenceType_t);
   Result_t    ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
-  Result_t    MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc);
 };
 
 //
 ASDCP::Result_t
-lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc)
+ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor&  EssenceDescriptor,
+                       const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
+                       const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
+                       ASDCP::JP2K::PictureDescriptor& PDesc)
 {
   memset(&PDesc, 0, sizeof(PDesc));
-  MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
 
-  PDesc.EditRate           = m_EditRate;
-  PDesc.SampleRate         = m_SampleRate;
-  assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL);
-  PDesc.ContainerDuration  = (ui32_t) PDescObj->ContainerDuration;
-  PDesc.StoredWidth        = PDescObj->StoredWidth;
-  PDesc.StoredHeight       = PDescObj->StoredHeight;
-  PDesc.AspectRatio        = PDescObj->AspectRatio;
-
-  if ( m_EssenceSubDescriptor != 0 )
+  PDesc.EditRate           = EditRate;
+  PDesc.SampleRate         = SampleRate;
+  assert(EssenceDescriptor.ContainerDuration <= 0xFFFFFFFFL);
+  PDesc.ContainerDuration  = (ui32_t) EssenceDescriptor.ContainerDuration;
+  PDesc.StoredWidth        = EssenceDescriptor.StoredWidth;
+  PDesc.StoredHeight       = EssenceDescriptor.StoredHeight;
+  PDesc.AspectRatio        = EssenceDescriptor.AspectRatio;
+
+  PDesc.Rsize   = EssenceSubDescriptor.Rsize;
+  PDesc.Xsize   = EssenceSubDescriptor.Xsize;
+  PDesc.Ysize   = EssenceSubDescriptor.Ysize;
+  PDesc.XOsize  = EssenceSubDescriptor.XOsize;
+  PDesc.YOsize  = EssenceSubDescriptor.YOsize;
+  PDesc.XTsize  = EssenceSubDescriptor.XTsize;
+  PDesc.YTsize  = EssenceSubDescriptor.YTsize;
+  PDesc.XTOsize = EssenceSubDescriptor.XTOsize;
+  PDesc.YTOsize = EssenceSubDescriptor.YTOsize;
+  PDesc.Csize   = EssenceSubDescriptor.Csize;
+
+  // PictureComponentSizing
+  ui32_t tmp_size = EssenceSubDescriptor.PictureComponentSizing.Length();
+
+  if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
     {
-      PDesc.Rsize   = m_EssenceSubDescriptor->Rsize;
-      PDesc.Xsize   = m_EssenceSubDescriptor->Xsize;
-      PDesc.Ysize   = m_EssenceSubDescriptor->Ysize;
-      PDesc.XOsize  = m_EssenceSubDescriptor->XOsize;
-      PDesc.YOsize  = m_EssenceSubDescriptor->YOsize;
-      PDesc.XTsize  = m_EssenceSubDescriptor->XTsize;
-      PDesc.YTsize  = m_EssenceSubDescriptor->YTsize;
-      PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
-      PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
-      PDesc.Csize   = m_EssenceSubDescriptor->Csize;
-
-      // PictureComponentSizing
-      ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
-
-      if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
-       memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
-
-      else
-       DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
-
-      // CodingStyleDefault
-      memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
-      memcpy(&PDesc.CodingStyleDefault,
-            m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
-            m_EssenceSubDescriptor->CodingStyleDefault.Length());
-
-      // QuantizationDefault
-      memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
-      memcpy(&PDesc.QuantizationDefault,
-            m_EssenceSubDescriptor->QuantizationDefault.RoData(),
-            m_EssenceSubDescriptor->QuantizationDefault.Length());
-
-      PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
+      memcpy(&PDesc.ImageComponents, EssenceSubDescriptor.PictureComponentSizing.RoData() + 8, tmp_size - 8);
+    }
+  else
+    {
+      DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
     }
 
+  // CodingStyleDefault
+  memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
+  memcpy(&PDesc.CodingStyleDefault,
+        EssenceSubDescriptor.CodingStyleDefault.RoData(),
+        EssenceSubDescriptor.CodingStyleDefault.Length());
+
+  // QuantizationDefault
+  memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
+  memcpy(&PDesc.QuantizationDefault,
+        EssenceSubDescriptor.QuantizationDefault.RoData(),
+        EssenceSubDescriptor.QuantizationDefault.Length());
+  
+  PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.Length() - 1;
   return RESULT_OK;
 }
 
@@ -411,7 +490,9 @@ lh__Reader::OpenRead(const char* filename, EssenceType_t type)
          return RESULT_STATE;
        }
 
-      result = MD_to_JP2K_PDesc(m_PDesc);
+      assert(m_EssenceDescriptor);
+      assert(m_EssenceSubDescriptor);
+      result = MD_to_JP2K_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
     }
 
   return result;
@@ -876,87 +957,8 @@ public:
                           ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
   Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
   Result_t Finalize();
-  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
-lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
-{
-  assert(m_EssenceDescriptor);
-  assert(m_EssenceSubDescriptor);
-  MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
-
-  PDescObj->ContainerDuration = PDesc.ContainerDuration;
-  PDescObj->SampleRate = PDesc.EditRate;
-  PDescObj->FrameLayout = 0;
-  PDescObj->StoredWidth = PDesc.StoredWidth;
-  PDescObj->StoredHeight = PDesc.StoredHeight;
-  PDescObj->AspectRatio = PDesc.AspectRatio;
-
-  //  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
-  //    }
-
-  assert(m_Dict);
-  if ( PDesc.StoredWidth < 2049 )
-    {
-      PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
-      m_EssenceSubDescriptor->Rsize = 3;
-    }
-  else
-    {
-      PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
-      m_EssenceSubDescriptor->Rsize = 4;
-    }
-
-  m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
-  m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
-  m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
-  m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
-  m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
-  m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
-  m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
-  m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
-  m_EssenceSubDescriptor->Csize = PDesc.Csize;
-
-  const ui32_t tmp_buffer_len = 1024;
-  byte_t tmp_buffer[tmp_buffer_len];
-
-  *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
-  *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
-  memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
-
-  const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
-  memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
-  m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
-
-  ui32_t precinct_set_size = 0, i;
-  for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
-    precinct_set_size++;
-
-  ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
-  memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
-  m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
-
-  ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
-  memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
-  m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
-
-  return RESULT_OK;
-}
-
-
 // Open the file for writing. The file must not exist. Returns error if
 // the operation cannot be completed.
 ASDCP::Result_t
@@ -1007,7 +1009,10 @@ lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& l
     LocalEditRate = PDesc.EditRate;
 
   m_PDesc = PDesc;
-  Result_t result = JP2K_PDesc_to_MD(m_PDesc);
+  assert(m_Dict);
+  Result_t result = JP2K_PDesc_to_MD(m_PDesc, *m_Dict,
+                                    (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor,
+                                    m_EssenceSubDescriptor);
 
   if ( ASDCP_SUCCESS(result) )
     {
index 493fae6efa69e00c78d4818f38609bd6550ab8c6..81889433baee7f370beb18f5be815be4bdf44cc4 100755 (executable)
@@ -128,10 +128,23 @@ namespace ASDCP
 
   Result_t MD_to_WriterInfo(MXF::Identification*, 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 MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor&  EssenceDescriptor,
+                           const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
+                           const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
+                           ASDCP::JP2K::PictureDescriptor& PDesc);
+
+  Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
+                           const ASDCP::Dictionary& dict,
+                           ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
+                           ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor);
+
   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);
 
@@ -145,6 +158,7 @@ namespace ASDCP
                             ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
                             AESEncContext* Ctx, HMACContext* HMAC);
 
+
   //
  class KLReader : public ASDCP::KLVPacket
     {
@@ -338,8 +352,9 @@ namespace ASDCP
        }
       };
       
-
+      //------------------------------------------------------------------------------------------
       //
+
       //
       template <class ClipT>
        struct TrackSet
@@ -433,7 +448,9 @@ namespace ASDCP
        inline Result_t Goto_FINAL()   { Goto_body(ST_RUNNING, ST_FINAL); }
       };
 
+      //------------------------------------------------------------------------------------------
       //
+
       //
       template <class HeaderType>
        class TrackFileWriter
@@ -472,7 +489,9 @@ namespace ASDCP
            default_md_object_init();
          }
 
-       virtual ~TrackFileWriter() {}
+       virtual ~TrackFileWriter() {
+         Close();
+       }
 
        const MXF::RIP& GetRIP() const { return m_RIP; }
 
@@ -724,13 +743,6 @@ namespace ASDCP
          m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
        }
 
-       //      
-       Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC)
-       {
-         return Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
-                                  m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC);
-       }
-
        //
        void Close()
        {
@@ -741,6 +753,9 @@ namespace ASDCP
       
   }/// namespace MXF
 
+  //------------------------------------------------------------------------------------------
+  //
+
   //
   class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
     {
@@ -773,14 +788,15 @@ namespace ASDCP
       h__ASDCPWriter(const Dictionary&);
       virtual ~h__ASDCPWriter();
 
-      Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
-
       // all the above for a single source clip
       Result_t WriteASDCPHeader(const std::string& PackageLabel, const UL& WrappingUL,
                                const std::string& TrackName, const UL& EssenceUL,
                                const UL& DataDefinition, const MXF::Rational& EditRate,
                                ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
 
+      Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
+      Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
+                              AESEncContext* Ctx, HMACContext* HMAC);
       Result_t WriteASDCPFooter();
     };
 
index 92b29d03ca103ab38fef04832a4dfd4baeced5ff..babbec74ea98ace1f97bdbb772dd9efe919bc590 100755 (executable)
@@ -985,7 +985,7 @@ ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const Kumu::FileReader& Reader)
   // slurp up the remainder of the footer
   ui32_t read_count = 0;
 
-  if ( ASDCP_SUCCESS(result) )
+  if ( ASDCP_SUCCESS(result) && IndexByteCount > 0 )
     {
       assert (IndexByteCount <= 0xFFFFFFFFL);
       // At this point, m_FooterData may not have been initialized
@@ -993,27 +993,27 @@ ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const Kumu::FileReader& Reader)
       // However, if IndexByteCount is zero then the capacity
       // doesn't change and the data pointer is not set.
       result = m_FooterData.Capacity((ui32_t) IndexByteCount);
-    }
 
-  if ( ASDCP_SUCCESS(result) && m_FooterData.Data() )
-    result = Reader.Read(m_FooterData.Data(), m_FooterData.Capacity(), &read_count);
+      if ( ASDCP_SUCCESS(result) )
+       result = Reader.Read(m_FooterData.Data(), m_FooterData.Capacity(), &read_count);
 
-  if ( ASDCP_SUCCESS(result) && read_count != m_FooterData.Capacity() )
-    {
-      DefaultLogSink().Error("Short read of footer partition: got %u, expecting %u\n",
-                            read_count, m_FooterData.Capacity());
-      return RESULT_FAIL;
-    }
-  else if( ASDCP_SUCCESS(result) && !m_FooterData.Data() )
-    {
-      DefaultLogSink().Error( "Buffer for footer partition not created: IndexByteCount = %u\n",
-                             IndexByteCount );
-      return RESULT_FAIL;
+      if ( ASDCP_SUCCESS(result) && read_count != m_FooterData.Capacity() )
+       {
+         DefaultLogSink().Error("Short read of footer partition: got %u, expecting %u\n",
+                                read_count, m_FooterData.Capacity());
+         return RESULT_FAIL;
+       }
+      else if( ASDCP_SUCCESS(result) && !m_FooterData.Data() )
+       {
+         DefaultLogSink().Error( "Buffer for footer partition not created: IndexByteCount = %u\n",
+                                 IndexByteCount );
+         return RESULT_FAIL;
+       }
+
+      if ( ASDCP_SUCCESS(result) )
+       result = InitFromBuffer(m_FooterData.RoData(), m_FooterData.Capacity());
     }
 
-  if ( ASDCP_SUCCESS(result) )
-    result = InitFromBuffer(m_FooterData.RoData(), m_FooterData.Capacity());
-  
   return result;
 }
 
index b7f75ef49f1643ecb360e3149564d8642a293ece..0a46bf7fb9090d9962cff6526bae709edf12b9c6 100644 (file)
@@ -26,8 +26,6 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-ACLOCAL_AMFLAGS = -I m4
-
 # Allow for configure's changes to this makefile
 AM_CPPFLAGS =
 AM_LDFLAGS =
@@ -70,7 +68,7 @@ include_HEADERS += \
 nodist_include_HEADERS = TimedText_Transform.h
 endif
 
-if AS_02_USE
+if USE_AS_02
 include_HEADERS                += AS_02.h
 endif
 
@@ -78,7 +76,7 @@ endif
 
 lib_LTLIBRARIES = libkumu.la libasdcp.la
 
-if AS_02_USE
+if USE_AS_02
 lib_LTLIBRARIES                += libas02.la
 endif
 
@@ -121,16 +119,15 @@ libasdcp_la_LDFLAGS = -release @VERSION@
 libasdcp_la_LIBADD = libkumu.la
 libasdcp_la_CPPFLAGS = -DASDCP_PLATFORM=\"@host@\"
 
-if AS_02_USE
+if USE_AS_02
 # sources for as-02 library
 libas02_la_SOURCES     = \
        AS_02.h \
-       AS_02_MXF.cpp \
-       AS_02_JP2K.cpp \
-       AS_02_PCM.cpp \
+       AS_02_internal.h \
        h__02_Reader.cpp \
        h__02_Writer.cpp \
-       AS_02_internal.h
+       AS_02_JP2K.cpp \
+       AS_02_PCM.cpp
 
 libas02_la_LDFLAGS = -release @VERSION@
 libas02_la_LIBADD = libasdcp.la libkumu.la
@@ -182,7 +179,7 @@ bin_PROGRAMS = \
        j2c-test blackwave klvwalk wavesplit \
        kmfilegen kmrandgen kmuuidgen
 
-if AS_02_USE
+if USE_AS_02
 bin_PROGRAMS += \
        as-02-wrap \
        as-02-unwrap
@@ -226,7 +223,7 @@ wavesplit_LDADD = libasdcp.la
 j2c_test_SOURCES = j2c-test.cpp
 j2c_test_LDADD = libasdcp.la
 
-if AS_02_USE
+if USE_AS_02
 as_02_wrap_SOURCES = as-02-wrap.cpp
 as_02_wrap_LDADD = libas02.la
 
index e6981bc22831ed1d92c98584997178eeba8811cb..a879caba5a87fbfb5e5c001f23ce5d28abe11f5a 100755 (executable)
@@ -108,7 +108,7 @@ USAGE: %s [-h|-help] [-V]\n\
 \n\
        %s [-a <uuid>] [-b <buffer-size>] [-C <UL>] [-d <duration>]\n\
           [-e|-E] [-f <start-frame>] [-j <key-id-string>] [-k <key-string>]\n\
-            [-M] [-p <n>/<d>]  [-v] [-W]\n\
+            [-M] [-p <n>/<d>] [-s <seconds>] [-v] [-W]\n\
           [-z|-Z] <input-file>+ <output-file>\n\n",
          PROGRAM_NAME, PROGRAM_NAME);
 
@@ -128,6 +128,7 @@ Options:\n\
   -d <duration>     - Number of frames to process, default all\n\
   -f <start-frame>  - Starting frame number, default 0\n\
   -p <n>/<d>        - Edit Rate of the output file.  24/1 is the default\n\
+  -s <seconds>      - Duration of a frame-wrapped partition (default 60)\n\
   -v                - Verbose, prints informative messages to stderr\n\
   -W                - Read input file only, do not write source file\n\
   -z                - Fail if j2c inputs have unequal parameters (default)\n\
@@ -177,7 +178,7 @@ public:
     error_flag(true), key_flag(false), key_id_flag(false), asset_id_flag(false),
     encrypt_header_flag(true), write_hmac(true), verbose_flag(false), fb_dump_size(0),
     no_write_flag(false), version_flag(false), help_flag(false), start_frame(0),
-    duration(0xffffffff), j2c_pedantic(true), fb_size(FRAME_BUFFER_SIZE),
+    duration(0xffffffff), j2c_pedantic(true), edit_rate(30,1), fb_size(FRAME_BUFFER_SIZE),
     show_ul_values(false), index_strategy(AS_02::IS_FOLLOW), partition_space(60)
   {
     memset(key_value, 0, KeyLen);
@@ -283,6 +284,11 @@ public:
                edit_rate.Denominator = 1;
                break;
 
+             case 's':
+               TEST_EXTRA_ARG(i, 's');
+               partition_space = abs(atoi(argv[i]));
+               break;
+
              case 'V': version_flag = true; break;
              case 'v': verbose_flag = true; break;
              case 'W': no_write_flag = true; break;
index 261b526a193f60ab46ceb42b6a8c2d99c7b0672d..d4708385ac2d3ebe99cb167cd6b2eb0036c403f4 100644 (file)
@@ -29,6 +29,7 @@
   \brief   MXF file reader base class
 */
 
+#define DEFAULT_MD_DECL
 #include "AS_02_internal.h"
 
 using namespace ASDCP;
@@ -63,28 +64,80 @@ AS_02::h__AS02Reader::h__AS02Reader(const ASDCP::Dictionary& d) : ASDCP::MXF::Tr
 AS_02::h__AS02Reader::~h__AS02Reader() {}
 
 
-#if 0
-//
-AS_02::h__AS02Reader::h__Reader(const Dictionary& d) :
-  m_HeaderPart(m_Dict), m_IndexAccess(m_Dict), m_Dict(&d), m_EssenceStart(0)
+
+// AS-DCP method of opening an MXF file for read
+Result_t
+AS_02::h__AS02Reader::OpenMXFRead(const char* filename)
+{
+  Result_t result = ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::OpenMXFRead(filename);
+
+  if ( KM_SUCCESS(result) )
+    result = ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::InitInfo();
+
+  if( KM_SUCCESS(result) )
+    {
+      //
+      InterchangeObject* Object;
+      m_Info.LabelSetType = LS_MXF_SMPTE;
+
+      if ( ! m_HeaderPart.OperationalPattern.ExactMatch(SMPTE_390_OPAtom_Entry().ul) )
+       {
+         char strbuf[IdentBufferLen];
+         const MDDEntry* Entry = m_Dict->FindUL(m_HeaderPart.OperationalPattern.Value());
+
+         if ( Entry == 0 )
+           {
+             DefaultLogSink().Warn("Operational pattern is not OP-1a: %s\n",
+                                   m_HeaderPart.OperationalPattern.EncodeString(strbuf, IdentBufferLen));
+           }
+         else
+           {
+             DefaultLogSink().Warn("Operational pattern is not OP-1a: %s\n", Entry->name);
+           }
+       }
+
+      //
+      if ( m_RIP.PairArray.front().ByteOffset != 0 )
+       {
+         DefaultLogSink().Error("First Partition in RIP is not at offset 0.\n");
+         result = RESULT_FORMAT;
+       }
+    }
+
+  if ( KM_SUCCESS(result) )
+    {
+      m_HeaderPart.BodyOffset = m_File.Tell();
+
+      result = m_File.Seek(m_HeaderPart.FooterPartition);
+
+      if ( ASDCP_SUCCESS(result) )
+       {
+         m_IndexAccess.m_Lookup = &m_HeaderPart.m_Primer;
+         result = m_IndexAccess.InitFromFile(m_File);
+       }
+    }
+
+  m_File.Seek(m_HeaderPart.BodyOffset);
+  return result;
+}
+
+// AS-DCP method of reading a plaintext or encrypted frame
+Result_t
+AS_02::h__AS02Reader::ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
+                                    const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
 {
-  m_pCurrentIndexPartition = 0;
-  //// start_pos = 0;
+  return ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::ReadEKLVFrame(m_HeaderPart, FrameNum, FrameBuf,
+                                                                                    EssenceUL, Ctx, HMAC);
 }
 
-AS_02::h__AS02Reader::~h__Reader()
+Result_t
+AS_02::h__AS02Reader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
+                           i8_t& temporalOffset, i8_t& keyFrameOffset)
 {
-  std::vector<Partition*>::iterator bli = m_BodyPartList.begin();
-  for ( ; bli != m_BodyPartList.end(); bli++ ){
-    delete(*bli);
-    *bli = 0;
-  }
-  Close();
+  return ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::LocateFrame(m_HeaderPart, FrameNum,
+                                                                                   streamOffset, temporalOffset, keyFrameOffset);
 }
-#endif
 
-//------------------------------------------------------------------------------------------
-//
 
 //
 // end h__02_Reader.cpp
index cf68f3a99d51a85058b96846cc2711cce0e76beb..8a4b073bdffc0ecb2533f8f84ed919aecf6a6c34 100644 (file)
 using namespace ASDCP;
 using namespace ASDCP::MXF;
 
+static const ui32_t CBRIndexEntriesPerSegment = 5000;
+
+
+//------------------------------------------------------------------------------------------
+//
+
+AS_02::AS02IndexWriter::AS02IndexWriter(const ASDCP::Dictionary*& d) :
+  Partition(d), m_CurrentSegment(0), m_BytesPerEditUnit(0), m_Dict(d), m_ECOffset(0), m_Lookup(0)
+{
+  BodySID = 0;
+  IndexSID = 129;
+}
+
+AS_02::AS02IndexWriter::~AS02IndexWriter() {}
+
+//
+Result_t
+AS_02::AS02IndexWriter::WriteToFile(Kumu::FileWriter& Writer)
+{
+  //      UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+
+  assert(m_Dict);
+  ASDCP::FrameBuffer FooterBuffer;
+  ui32_t   footer_size = m_PacketList->m_List.size() * MaxIndexSegmentSize; // segment-count * max-segment-size
+  Result_t result = FooterBuffer.Capacity(footer_size); 
+  ui32_t   iseg_count = 0;
+
+  if ( m_CurrentSegment != 0 )
+    {
+      m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size();
+      m_CurrentSegment = 0;
+    }
+
+  std::list<InterchangeObject*>::iterator pl_i = m_PacketList->m_List.begin();
+  for ( ; pl_i != m_PacketList->m_List.end() && ASDCP_SUCCESS(result); pl_i++ )
+    {
+      if ( (*pl_i)->IsA(OBJ_TYPE_ARGS(IndexTableSegment)) )
+       {
+         iseg_count++;
+         IndexTableSegment* Segment = (IndexTableSegment*)(*pl_i);
+
+         if ( m_BytesPerEditUnit != 0 )
+           {
+             if ( iseg_count != 1 )
+               return RESULT_STATE;
+
+             ///             Segment->IndexDuration = duration;
+           }
+       }
+
+      InterchangeObject* object = *pl_i;
+      object->m_Lookup = m_Lookup;
+
+      ASDCP::FrameBuffer WriteWrapper;
+      WriteWrapper.SetData(FooterBuffer.Data() + FooterBuffer.Size(),
+                          FooterBuffer.Capacity() - FooterBuffer.Size());
+      result = object->WriteToBuffer(WriteWrapper);
+      FooterBuffer.Size(FooterBuffer.Size() + WriteWrapper.Size());
+    }
+
+  if ( ASDCP_SUCCESS(result) )
+    {
+      IndexByteCount = FooterBuffer.Size();
+      UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+      result = Partition::WriteToFile(Writer, body_ul);
+    }
+
+  if ( ASDCP_SUCCESS(result) )
+    {
+      ui32_t write_count = 0;
+      result = Writer.Write(FooterBuffer.RoData(), FooterBuffer.Size(), &write_count);
+      assert(write_count == FooterBuffer.Size());
+    }
+
+  return result;
+}
+
+//
+void
+AS_02::AS02IndexWriter::ResetCBR(Kumu::fpos_t offset)
+{
+  m_ECOffset = offset;
+
+  std::list<InterchangeObject*>::iterator i;
+
+  for ( i = m_PacketList->m_List.begin(); i != m_PacketList->m_List.end(); ++i )
+    {
+      delete *i;
+    }
+
+  m_PacketList->m_List.clear();
+}
+
+//
+void
+AS_02::AS02IndexWriter::Dump(FILE* stream)
+{
+  if ( stream == 0 )
+    stream = stderr;
+
+  Partition::Dump(stream);
+
+  std::list<InterchangeObject*>::iterator i = m_PacketList->m_List.begin();
+  for ( ; i != m_PacketList->m_List.end(); i++ )
+    (*i)->Dump(stream);
+}
+
+//
+ui32_t
+AS_02::AS02IndexWriter::GetDuration() const
+{
+  ui32_t duration;
+  std::list<InterchangeObject*>::const_iterator i;
+
+  for ( i = m_PacketList->m_List.begin(); i != m_PacketList->m_List.end(); ++i )
+    {
+      if ( (*i)->IsA(OBJ_TYPE_ARGS(IndexTableSegment)) )
+       {
+         IndexTableSegment& Segment = *(IndexTableSegment*)*i;
+         duration += Segment.IndexDuration;
+       }
+    }
+
+  return duration;
+}
+
+//
+void
+AS_02::AS02IndexWriter::SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const ASDCP::Rational& Rate)
+{
+  assert(lookup);
+  m_Lookup = lookup;
+  m_BytesPerEditUnit = size;
+  m_EditRate = Rate;
+
+  IndexTableSegment* Index = new IndexTableSegment(m_Dict);
+  AddChildObject(Index);
+  Index->EditUnitByteCount = m_BytesPerEditUnit;
+  Index->IndexEditRate = Rate;
+}
+
+//
+void
+AS_02::AS02IndexWriter::SetIndexParamsVBR(IPrimerLookup* lookup, const ASDCP::Rational& Rate, Kumu::fpos_t offset)
+{
+  assert(lookup);
+  m_Lookup = lookup;
+  m_BytesPerEditUnit = 0;
+  m_EditRate = Rate;
+  m_ECOffset = offset;
+}
 
 //
-AS_02::h__AS02Writer::h__AS02Writer(const ASDCP::Dictionary& d) : ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d) {}
+void
+AS_02::AS02IndexWriter::PushIndexEntry(const IndexTableSegment::IndexEntry& Entry)
+{
+  if ( m_BytesPerEditUnit != 0 )  // are we CBR? that's bad 
+    {
+      DefaultLogSink().Error("Call to PushIndexEntry() failed: index is CBR\n");
+      return;
+    }
+
+  // do we have an available segment?
+  if ( m_CurrentSegment == 0 )
+    { // no, set up a new segment
+      m_CurrentSegment = new IndexTableSegment(m_Dict);
+      assert(m_CurrentSegment);
+      AddChildObject(m_CurrentSegment);
+      m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry());
+      m_CurrentSegment->IndexEditRate = m_EditRate;
+      m_CurrentSegment->IndexStartPosition = 0;
+    }
+  else if ( m_CurrentSegment->IndexEntryArray.size() >= CBRIndexEntriesPerSegment )
+    { // no, this one is full, start another
+      m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size();
+      ui64_t StartPosition = m_CurrentSegment->IndexStartPosition + m_CurrentSegment->IndexDuration;
+
+      m_CurrentSegment = new IndexTableSegment(m_Dict);
+      assert(m_CurrentSegment);
+      AddChildObject(m_CurrentSegment);
+      m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry());
+      m_CurrentSegment->IndexEditRate = m_EditRate;
+      m_CurrentSegment->IndexStartPosition = StartPosition;
+    }
+
+  m_CurrentSegment->IndexEntryArray.push_back(Entry);
+}
+
+
+//------------------------------------------------------------------------------------------
+//
+
+//
+AS_02::h__AS02Writer::h__AS02Writer(const ASDCP::Dictionary& d) : ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d),
+                                                                 m_IndexWriter(m_Dict), m_PartitionSpace(0),
+                                                                 m_IndexStrategy(AS_02::IS_FOLLOW) {}
+
 AS_02::h__AS02Writer::~h__AS02Writer() {}
 
 //
 Result_t
 AS_02::h__AS02Writer::WriteAS02Header(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
-                              const std::string& TrackName, const ASDCP::UL& EssenceUL,
-                              const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
-                              ui32_t TCFrameRate, ui32_t BytesPerEditUnit)
+                                     const std::string& TrackName, const ASDCP::UL& EssenceUL, const ASDCP::UL& DataDefinition,
+                                     const ASDCP::Rational& EditRate, ui32_t TCFrameRate, ui32_t BytesPerEditUnit)
 {
+  if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 )
+    {
+      DefaultLogSink().Error("Non-zero edit-rate reqired.\n");
+      return RESULT_PARAM;
+    }
+
   InitHeader();
+
   AddSourceClip(EditRate, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel);
   AddEssenceDescriptor(WrappingUL);
+  m_RIP.PairArray.push_back(RIP::Pair(0, 0)); // Header partition RIP entry
+  m_IndexWriter.OperationalPattern = m_HeaderPart.OperationalPattern;
 
   Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
 
-  //use the FrameRate for the indexing; initialize the SID counters
-  ///  m_CurrentBodySID = 0;
-  ///  m_CurrentIndexSID = 0;
-  m_PartitionSpace = m_PartitionSpace * TCFrameRate; ///// TODO ????
+  if ( ASDCP_SUCCESS(result) )
+    {
+      m_PartitionSpace *= ceil(EditRate.Quotient());  // convert seconds to edit units
+      Kumu::fpos_t ECoffset = m_File.Tell();
+      m_IndexWriter.IndexSID = 129;
+
+      if ( BytesPerEditUnit == 0 )
+       {
+         m_IndexWriter.SetIndexParamsVBR(&m_HeaderPart.m_Primer, EditRate, ECoffset);
+       }
+      else
+       {
+         m_IndexWriter.SetIndexParamsCBR(&m_HeaderPart.m_Primer, BytesPerEditUnit, EditRate);
+       }
+
+      UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+      Partition body_part(m_Dict);
+      body_part.BodySID = 1;
+      body_part.OperationalPattern = m_HeaderPart.OperationalPattern;
+      body_part.ThisPartition = m_File.Tell();
+      result = body_part.WriteToFile(m_File, body_ul);
+      m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition)); // Second RIP Entry
+
+    }
 
   return result;
 }
-    
+
+//     
+Result_t
+AS_02::h__AS02Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC)
+{
+  Result_t result = Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
+                                     m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC);
+
+  if ( m_FramesWritten > 0 && ( m_FramesWritten % m_PartitionSpace ) == 0 )
+    {
+      m_IndexWriter.ThisPartition = m_File.Tell();
+      m_IndexWriter.WriteToFile(m_File);
+      m_RIP.PairArray.push_back(RIP::Pair(129, m_IndexWriter.ThisPartition));
+
+      UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
+      Partition body_part(m_Dict);
+      body_part.BodySID = 1;
+      body_part.OperationalPattern = m_HeaderPart.OperationalPattern;
+      body_part.ThisPartition = m_File.Tell();
+      result = body_part.WriteToFile(m_File, body_ul);
+      m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition));
+      m_IndexWriter.ResetCBR(m_File.Tell());
+    }
+
+  return result;
+}
+
+// standard method of writing the header and footer of a completed MXF file
+//
+Result_t
+AS_02::h__AS02Writer::WriteAS02Footer()
+{
+
+  if ( m_IndexWriter.GetDuration() > 0 )
+    {
+      m_IndexWriter.ThisPartition = m_File.Tell();
+      m_IndexWriter.WriteToFile(m_File);
+      m_RIP.PairArray.push_back(RIP::Pair(129, m_IndexWriter.ThisPartition));
+    }
+
+  // update all Duration properties
+  ASDCP::MXF::Partition footer_part(m_Dict);
+  DurationElementList_t::iterator dli = m_DurationUpdateList.begin();
+
+  for (; dli != m_DurationUpdateList.end(); ++dli )
+    {
+      **dli = m_FramesWritten;
+    }
+
+  m_EssenceDescriptor->ContainerDuration = m_FramesWritten;
+  footer_part.PreviousPartition = m_RIP.PairArray.back().ByteOffset;
+
+  Kumu::fpos_t here = m_File.Tell();
+  m_RIP.PairArray.push_back(RIP::Pair(0, here)); // Last RIP Entry
+  m_HeaderPart.FooterPartition = here;
+
+  assert(m_Dict);
+  footer_part.OperationalPattern = m_HeaderPart.OperationalPattern;
+  footer_part.EssenceContainers = m_HeaderPart.EssenceContainers;
+  footer_part.FooterPartition = here;
+  footer_part.ThisPartition = here;
+
+  UL footer_ul(m_Dict->ul(MDD_CompleteFooter));
+  Result_t result = footer_part.WriteToFile(m_File, footer_ul);
+
+  if ( ASDCP_SUCCESS(result) )
+    result = m_RIP.WriteToFile(m_File);
+
+  if ( ASDCP_SUCCESS(result) )
+    result = m_File.Seek(0);
+
+  if ( ASDCP_SUCCESS(result) )
+    result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
+
+  if ( ASDCP_SUCCESS(result) )
+    {
+      ASDCP::MXF::Array<ASDCP::MXF::RIP::Pair>::const_iterator i = m_RIP.PairArray.begin();
+      ui64_t header_byte_count = m_HeaderPart.HeaderByteCount;
+      ui64_t previous_partition = 0;
+
+      for ( i = m_RIP.PairArray.begin(); ASDCP_SUCCESS(result) && i != m_RIP.PairArray.end(); ++i )
+       {
+         if ( i->BodySID == 0 )
+           continue;
+
+         result = m_File.Seek(i->ByteOffset);
+
+         if ( ASDCP_SUCCESS(result) )
+           {
+             ASDCP::MXF::Partition plain_part(m_Dict);
+             plain_part.InitFromFile(m_File);
+             plain_part.PreviousPartition = previous_partition;
+             plain_part.FooterPartition = footer_part.ThisPartition;
+             previous_partition = plain_part.ThisPartition;
+             result = m_File.Seek(i->ByteOffset);
+
+             if ( ASDCP_SUCCESS(result) )
+               {
+                 UL tmp_ul = plain_part.GetUL();
+                 result = plain_part.WriteToFile(m_File, tmp_ul);
+               }
+           }
+       }
+    }
+
+  m_File.Close();
+  return result;
+}
+
 
 //
 // end h__02_Writer.cpp
index 4290974d675bf13c23a4cbe24c0b664fc1dbea84..952972e0320ac396367d89069e18106e21cbdf3a 100755 (executable)
@@ -157,7 +157,14 @@ ASDCP::h__ASDCPWriter::WriteASDCPHeader(const std::string& PackageLabel, const U
   return result;
 }
 
-
+//
+Result_t
+ASDCP::h__ASDCPWriter::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
+                                      AESEncContext* Ctx, HMACContext* HMAC)
+{
+  return Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
+                          m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC);
+}
 
 // standard method of writing the header and footer of a completed MXF file
 //
index f87d2c50f662c1f696c5e6e453e0cf95182022e9..6ef04744b4cdd53e5bb8bbfea77f226d12d42300 100755 (executable)
@@ -78,12 +78,13 @@ void
 usage(FILE* stream = stdout)
 {
   fprintf(stream, "\
-USAGE: %s [-r] [-v] <input-file> [<input-file2> ...]\n\
+USAGE: %s [-r|-p] [-v] <input-file> [<input-file2> ...]\n\
 \n\
        %s [-h|-help] [-V]\n\
 \n\
   -h | -help   - Show help\n\
-  -r           - When KLV data is an MXF OPAtom file, display OPAtom headers\n\
+  -r           - When KLV data is an MXF OPAtom or OP 1a file, display headers\n\
+  -p           - Display partition headers by walking the RIP\n\
   -v           - Verbose. Prints informative messages to stderr\n\
   -V           - Show version information\n\
 \n\
@@ -104,10 +105,12 @@ USAGE: %s [-r] [-v] <input-file> [<input-file2> ...]\n\
    bool   help_flag;                // true if the help display option was selected
    bool   verbose_flag;             // true if the informative messages option was selected
    bool   read_mxf_flag;            // true if the -r option was selected
+   bool   walk_parts_flag;          // true if the -p option was selected
    FileList_t inFileList;           // File to operate on
 
    CommandOptions(int argc, const char** argv) :
-     error_flag(true), version_flag(false), help_flag(false), verbose_flag(false), read_mxf_flag(false)
+     error_flag(true), version_flag(false), help_flag(false),
+     verbose_flag(false), read_mxf_flag(false), walk_parts_flag(false)
    {
      for ( int i = 1; i < argc; i++ )
        {
@@ -124,6 +127,7 @@ USAGE: %s [-r] [-v] <input-file> [<input-file2> ...]\n\
               {
               case 'h': help_flag = true; break;
               case 'r': read_mxf_flag = true; break;
+              case 'p': walk_parts_flag = true; break;
               case 'V': version_flag = true; break;
               case 'v': verbose_flag = true; break;
 
@@ -267,6 +271,59 @@ main(int argc, const char** argv)
          if ( ASDCP_SUCCESS(result) )
            RIP.Dump(stdout);
        }
+      else if ( Options.walk_parts_flag )
+       {
+         Kumu::FileReader        Reader;
+         const Dictionary* Dict = &DefaultCompositeDict();
+         ASDCP::MXF::OP1aHeader Header(Dict);
+         ASDCP::MXF::RIP RIP(Dict);
+         
+         result = Reader.OpenRead((*fi).c_str());
+         
+         if ( ASDCP_SUCCESS(result) )
+           result = MXF::SeekToRIP(Reader);
+
+         if ( ASDCP_SUCCESS(result) )
+           {
+             result = RIP.InitFromFile(Reader);
+             ui32_t test_s = RIP.PairArray.size();
+
+             if ( ASDCP_FAILURE(result) )
+               {
+                 DefaultLogSink().Error("File contains no RIP\n");
+                 result = RESULT_OK;
+               }
+             else if ( RIP.PairArray.empty() )
+               {
+                 DefaultLogSink().Error("RIP contains no Pairs.\n");
+               }
+
+             Reader.Seek(0);
+           }
+         else
+           {
+             DefaultLogSink().Error("ASDCP::h__Reader::OpenMXFRead, SeekToRIP failed\n");
+           }
+
+         if ( ASDCP_SUCCESS(result) )
+           {
+             MXF::Array<MXF::RIP::Pair>::const_iterator i;
+             for ( i = RIP.PairArray.begin(); i != RIP.PairArray.end(); ++i )
+               {
+                 Reader.Seek(i->ByteOffset);
+                 MXF::Partition plain_part(Dict);
+                 plain_part.InitFromFile(Reader);
+
+                 if ( plain_part.ThisPartition != i->ByteOffset )
+                   {
+                     DefaultLogSink().Error("ThisPartition value error: wanted=%qu, got=%qu\n",
+                                            plain_part.ThisPartition, i->ByteOffset);
+                   }
+
+                 plain_part.Dump();
+               }
+           }
+       }
       else // dump klv
        {
          Kumu::FileReader Reader;