Allow > 60 fps 3D.
[asdcplib-cth.git] / src / AS_DCP_JP2K.cpp
index fa5955308f0973cd3f16db7124e933b1e1f137da..edb568743c677556bbfd055966f2f9bfb7babeda 100755 (executable)
@@ -162,7 +162,7 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
              PDesc.ImageComponents[i].YRsize
              );
     }
-  
+
   fprintf(stream, "               Scod: %hhu\n", PDesc.CodingStyleDefault.Scod);
   fprintf(stream, "   ProgressionOrder: %hhu\n", PDesc.CodingStyleDefault.SGcod.ProgressionOrder);
   fprintf(stream, "     NumberOfLayers: %hd\n",
@@ -232,7 +232,9 @@ ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
   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_ui32 = (ui32_t*) tmp_buffer;
+
+  *tmp_buffer_ui32 = 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);
 
@@ -310,7 +312,7 @@ ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor&  Esse
   memcpy(&PDesc.QuantizationDefault,
         EssenceSubDescriptor.QuantizationDefault.const_get().RoData(),
         EssenceSubDescriptor.QuantizationDefault.const_get().Length());
-  
+
   PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.const_get().Length() - 1;
   return RESULT_OK;
 }
@@ -391,7 +393,7 @@ lh__Reader::OpenRead(const std::string& filename, EssenceType_t type)
            {
              DefaultLogSink().Warn("EditRate and SampleRate do not match (%.03f, %.03f).\n",
                                    m_EditRate.Quotient(), m_SampleRate.Quotient());
-             
+
              if ( ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 )
                   || ( m_EditRate == EditRate_25 && m_SampleRate == EditRate_50 )
                   || ( m_EditRate == EditRate_30 && m_SampleRate == EditRate_60 )
@@ -512,7 +514,7 @@ ASDCP::JP2K::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
     stream = stderr;
 
   fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
-  
+
   fputc('\n', stream);
 
   if ( dump_len > 0 )
@@ -692,7 +694,7 @@ public:
     Result_t result = RESULT_OK;
 
     if ( phase == SP_LEFT )
-      {    
+      {
        if ( FilePosition != m_LastPosition )
          {
            m_LastPosition = FilePosition;
@@ -928,22 +930,32 @@ public:
 
   virtual ~lh__Writer(){}
 
-  Result_t OpenWrite(const std::string&, EssenceType_t type, ui32_t HeaderSize);
+  Result_t OpenWrite(const std::string&, EssenceType_t type, ui32_t HeaderSize, bool);
   Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
                           ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
-  Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
+  Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*, std::string* hash = 0);
+  Result_t FakeWriteFrame(int size, bool add_index);
   Result_t Finalize();
 };
 
-// Open the file for writing. The file must not exist. Returns error if
+// Open the file for writing. The file must not exist unless overwrite is true. Returns error if
 // the operation cannot be completed.
 ASDCP::Result_t
-lh__Writer::OpenWrite(const std::string& filename, EssenceType_t type, ui32_t HeaderSize)
+lh__Writer::OpenWrite(const std::string& filename, EssenceType_t type, ui32_t HeaderSize, bool overwrite)
 {
   if ( ! m_State.Test_BEGIN() )
     return RESULT_STATE;
 
-  Result_t result = m_File.OpenWrite(filename);
+  Result_t result = RESULT_OK;
+  if (overwrite)
+    {
+      result = m_File.OpenModify(filename);
+      m_File.Seek(0);
+    }
+  else
+    {
+      result = m_File.OpenWrite(filename);
+    }
 
   if ( ASDCP_SUCCESS(result) )
     {
@@ -1027,20 +1039,20 @@ lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& l
 //
 ASDCP::Result_t
 lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
-                      AESEncContext* Ctx, HMACContext* HMAC)
+                      AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
 {
   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);
+    result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC, hash);
 
   if ( ASDCP_SUCCESS(result) && add_index )
-    {  
+    {
       IndexTableSegment::IndexEntry Entry;
       Entry.StreamOffset = StreamOffset;
       m_FooterPart.PushIndexEntry(Entry);
@@ -1050,6 +1062,29 @@ lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
   return result;
 }
 
+Result_t
+lh__Writer::FakeWriteFrame(int size, bool add_index)
+{
+  Result_t result = RESULT_OK;
+
+  if ( m_State.Test_READY() )
+    result = m_State.Goto_RUNNING();
+
+  ui64_t StreamOffset = m_StreamOffset;
+
+  if ( ASDCP_SUCCESS(result) )
+    result = FakeWriteEKLVPacket(size);
+
+  if ( ASDCP_SUCCESS(result) && add_index )
+    {
+      IndexTableSegment::IndexEntry Entry;
+      Entry.StreamOffset = StreamOffset;
+      m_FooterPart.PushIndexEntry(Entry);
+    }
+
+  m_FramesWritten++;
+  return result;
+}
 
 // Closes the MXF file, writing the index and other closing information.
 //
@@ -1133,11 +1168,11 @@ ASDCP::JP2K::MXFWriter::RIP()
   return m_Writer->m_RIP;
 }
 
-// Open the file for writing. The file must not exist. Returns error if
+// Open the file for writing. The file must not exist unless overwrite is true. Returns error if
 // the operation cannot be completed.
 ASDCP::Result_t
 ASDCP::JP2K::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
-                                 const PictureDescriptor& PDesc, ui32_t HeaderSize)
+                                 const PictureDescriptor& PDesc, ui32_t HeaderSize, bool overwrite)
 {
   if ( Info.LabelSetType == LS_MXF_SMPTE )
     m_Writer = new h__Writer(DefaultSMPTEDict());
@@ -1146,7 +1181,7 @@ ASDCP::JP2K::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo&
 
   m_Writer->m_Info = Info;
 
-  Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, HeaderSize);
+  Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, HeaderSize, overwrite);
 
   if ( ASDCP_SUCCESS(result) )
     result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
@@ -1163,12 +1198,21 @@ ASDCP::JP2K::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo&
 // Fails if the file is not open, is finalized, or an operating system
 // error occurs.
 ASDCP::Result_t
-ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
+ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
+{
+  if ( m_Writer.empty() )
+    return RESULT_INIT;
+
+  return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC, hash);
+}
+
+ASDCP::Result_t
+ASDCP::JP2K::MXFWriter::FakeWriteFrame(int size)
 {
   if ( m_Writer.empty() )
     return RESULT_INIT;
 
-  return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
+  return m_Writer->FakeWriteFrame(size, true);
 }
 
 // Closes the MXF file, writing the index and other closing information.
@@ -1181,6 +1225,11 @@ ASDCP::JP2K::MXFWriter::Finalize()
   return m_Writer->Finalize();
 }
 
+ui64_t
+ASDCP::JP2K::MXFWriter::Tell() const
+{
+  return m_Writer->m_File.Tell();
+}
 
 //------------------------------------------------------------------------------------------
 //
@@ -1197,7 +1246,7 @@ public:
 
   //
   Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
-                     AESEncContext* Ctx, HMACContext* HMAC)
+                     AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
   {
     if ( m_NextPhase != phase )
       return RESULT_SPHASE;
@@ -1205,11 +1254,26 @@ public:
     if ( phase == SP_LEFT )
       {
        m_NextPhase = SP_RIGHT;
-       return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
+       return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC, hash);
       }
 
     m_NextPhase = SP_LEFT;
-    return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
+    return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC, hash);
+  }
+
+  Result_t FakeWriteFrame(int size, StereoscopicPhase_t phase)
+  {
+    if ( m_NextPhase != phase )
+      return RESULT_SPHASE;
+
+    if ( phase == SP_LEFT )
+      {
+       m_NextPhase = SP_RIGHT;
+       return lh__Writer::FakeWriteFrame(size, true);
+      }
+
+    m_NextPhase = SP_LEFT;
+    return lh__Writer::FakeWriteFrame(size, false);
   }
 
   //
@@ -1283,13 +1347,15 @@ ASDCP::JP2K::MXFSWriter::RIP()
 // the operation cannot be completed.
 ASDCP::Result_t
 ASDCP::JP2K::MXFSWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
-                                  const PictureDescriptor& PDesc, ui32_t HeaderSize)
+                                  const PictureDescriptor& PDesc, ui32_t HeaderSize, bool overwrite)
 {
   if ( Info.LabelSetType == LS_MXF_SMPTE )
     m_Writer = new h__SWriter(DefaultSMPTEDict());
   else
     m_Writer = new h__SWriter(DefaultInteropDict());
 
+#if 0
+  /* This check has been removed so that DCP-o-matic can use any edit rate it wants */
   if ( PDesc.EditRate != ASDCP::EditRate_24
        && PDesc.EditRate != ASDCP::EditRate_25
        && PDesc.EditRate != ASDCP::EditRate_30
@@ -1300,13 +1366,14 @@ ASDCP::JP2K::MXFSWriter::OpenWrite(const std::string& filename, const WriterInfo
       DefaultLogSink().Error("Stereoscopic wrapping requires 24, 25, 30, 48, 50 or 60 fps input streams.\n");
       return RESULT_FORMAT;
     }
+#endif
 
   if ( PDesc.StoredWidth > 2048 )
     DefaultLogSink().Warn("Wrapping non-standard 4K stereoscopic content. I hope you know what you are doing!\n");
 
   m_Writer->m_Info = Info;
 
-  Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000_S, HeaderSize);
+  Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000_S, HeaderSize, overwrite);
 
   if ( ASDCP_SUCCESS(result) )
     {
@@ -1345,10 +1412,10 @@ ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext*
   if ( m_Writer.empty() )
     return RESULT_INIT;
 
-  Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC);
+  Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC, 0);
 
   if ( ASDCP_SUCCESS(result) )
-    result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC);
+    result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC, 0);
 
   return result;
 }
@@ -1359,12 +1426,21 @@ ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext*
 // error occurs.
 ASDCP::Result_t
 ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
-                                   AESEncContext* Ctx, HMACContext* HMAC)
+                                   AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
+{
+  if ( m_Writer.empty() )
+    return RESULT_INIT;
+
+  return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC, hash);
+}
+
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::FakeWriteFrame(int size, StereoscopicPhase_t phase)
 {
   if ( m_Writer.empty() )
     return RESULT_INIT;
 
-  return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
+  return m_Writer->FakeWriteFrame(size, phase);
 }
 
 // Closes the MXF file, writing the index and other closing information.
@@ -1377,6 +1453,12 @@ ASDCP::JP2K::MXFSWriter::Finalize()
   return m_Writer->Finalize();
 }
 
+ui64_t
+ASDCP::JP2K::MXFSWriter::Tell() const
+{
+  return m_Writer->m_File.Tell();
+}
+
 //
 // end AS_DCP_JP2K.cpp
 //