Merge pull request #4 from cinecert/master
[asdcplib.git] / src / AS_DCP_MXF.cpp
index b5ad865110d34d37d4e98bd98b32e37d34f94ed0..d3606fe36a3163110d172096304ada311214e3bb 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004-2013, John Hurst
+Copyright (c) 2004-2016, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <KM_xml.h>
 #include "AS_DCP_internal.h"
 #include "JP2K.h"
+#include "ACES.h"
 #include "MPEG.h"
 #include "Wav.h"
+#include "KM_util.h"
 #include <iostream>
 #include <iomanip>
 
@@ -213,7 +215,8 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type)
            {
              type = ESS_TIMED_TEXT;
            }
-         else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCDataDescriptor))) )
+         else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCDataDescriptor)))
+                   || ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(PrivateDCDataDescriptor))) )
            {
              if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DolbyAtmosSubDescriptor))) )
                {
@@ -227,26 +230,54 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type)
        }
       else if (  TestHeader.OperationalPattern == UL(m_Dict->ul(MDD_OP1a)) )
        {
-         if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor))) )
-           {
-             type = ESS_AS02_JPEG_2000;
-           }
-         else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &md_object)) )
-           {
-             assert(md_object);
-             if ( static_cast<ASDCP::MXF::WaveAudioDescriptor*>(md_object)->AudioSamplingRate == SampleRate_96k )
-               {
-                 type = ESS_AS02_PCM_24b_96k;
-               }
-             else
-               {
-                 type = ESS_AS02_PCM_24b_48k;
-               }
-           }
-         else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor))) )
+         // ST 2065-5 Picture Descriptor does not have a mandatory SubDescriptor, check EssenceContainer instead
+         if (ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor))) )
+         {
+           MXF::RGBAEssenceDescriptor *rgba_descriptor = 0;
+           char buf[64];
+
+           if ASDCP_SUCCESS(TestHeader.GetMDObjectByType(m_Dict->ul(MDD_RGBAEssenceDescriptor), reinterpret_cast<MXF::InterchangeObject**>(&rgba_descriptor)))
            {
-             type = ESS_AS02_TIMED_TEXT;
+               if (rgba_descriptor->EssenceContainer == m_Dict->ul(MDD_MXFGCFrameWrappedACESPictures))
+                   type = ESS_AS02_ACES;
            }
+         }
+         if (type == ESS_UNKNOWN)
+         {
+
+           if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor))) )
+             {
+               type = ESS_AS02_JPEG_2000;
+             }
+           else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &md_object)) )
+             {
+               assert(md_object);
+               if ( static_cast<ASDCP::MXF::WaveAudioDescriptor*>(md_object)->AudioSamplingRate == SampleRate_96k )
+                 {
+                   type = ESS_AS02_PCM_24b_96k;
+                 }
+               else
+                 {
+                   type = ESS_AS02_PCM_24b_48k;
+                 }
+             }
+           else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor))) )
+             {
+               type = ESS_AS02_TIMED_TEXT;
+             }
+           else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(PIMFDynamicMetadataDescriptor))) )
+             {
+               type = ESS_DCDATA_UNKNOWN;
+             }
+           else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(ISXDDataEssenceDescriptor))) )
+             {
+               type = ESS_AS02_ISXD;
+             }
+           else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(ACESPictureSubDescriptor))) )
+             {
+               type = ESS_AS02_ACES;
+             }
+         }
        }
       else
        {
@@ -262,11 +293,11 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type)
 static bool
 string_is_xml(const ASDCP::FrameBuffer& buffer)
 {
-  std::string ns_prefix, type_name, namespace_name;
-  Kumu::AttributeList doc_attr_list;
-  return GetXMLDocType(buffer.RoData(), buffer.Size(),
-                      ns_prefix, type_name, namespace_name, doc_attr_list);
-}
+  return (strncmp((const char *)buffer.RoData(),             "<?xml", 5) == 0 ||
+          strncmp((const char *)buffer.RoData(), "\xEF\xBB\xBF<?xml", 8) == 0); // Allow BOM
+ }
+ //
 
 //
 ASDCP::Result_t
@@ -310,24 +341,43 @@ ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type)
            {
              type = ESS_JPEG_2000;
            }
-         else if ( ASDCP_SUCCESS(WavHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
+         else if(memcmp(FB.RoData(), AS_02::ACES::Magic, sizeof(AS_02::ACES::Magic)) == 0)
            {
-             switch ( WavHeader.samplespersec )
-               {
-               case 48000: type = ESS_PCM_24b_48k; break;
-               case 96000: type = ESS_PCM_24b_96k; break;
-               default:
-                 return RESULT_FORMAT;
-               }
+             type = ESS_AS02_ACES;
            }
-         else if ( ASDCP_SUCCESS(RF64Header.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
+         else if ( std::string((const char*)FB.RoData() + 8, 4) == "WAVE" )
            {
-             switch ( RF64Header.samplespersec )
+             if ( std::string((const char*)FB.RoData(), 4) == "RIFF" )
+               {
+                 result = WavHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset);
+
+                 if ( ASDCP_SUCCESS(result) )
+                   {
+                     switch ( WavHeader.samplespersec )
+                       {
+                       case 48000: type = ESS_PCM_24b_48k; break;
+                       case 96000: type = ESS_PCM_24b_96k; break;
+                       default:
+                         DefaultLogSink().Error("Unexpected sample rate: %d\n", WavHeader.samplespersec);
+                         result = RESULT_FORMAT;
+                       }
+                   }
+               }
+             else
                {
-               case 48000: type = ESS_PCM_24b_48k; break;
-               case 96000: type = ESS_PCM_24b_96k; break;
-               default:
-                 return RESULT_FORMAT;
+                 result = RF64Header.ReadFromBuffer(FB.RoData(), read_count, &data_offset);
+               
+                 if ( ASDCP_SUCCESS(result) )
+                   {
+                     switch ( RF64Header.samplespersec )
+                       {
+                       case 48000: type = ESS_PCM_24b_48k; break;
+                       case 96000: type = ESS_PCM_24b_96k; break;
+                       default:
+                         DefaultLogSink().Error("Unexpected sample rate: %d\n", WavHeader.samplespersec);
+                         result = RESULT_FORMAT;
+                       }
+                   }
                }
            }
          else if ( ASDCP_SUCCESS(AIFFHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
@@ -371,6 +421,10 @@ ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type)
                    {
                      type = ESS_JPEG_2000;
                    }
+                 else if(memcmp(FB.RoData(), AS_02::ACES::Magic, sizeof(AS_02::ACES::Magic)) == 0)
+                   {
+                       type = ESS_AS02_ACES;
+                   }
                  else if ( ASDCP_SUCCESS(WavHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
                    {
                      switch ( WavHeader.samplespersec )
@@ -635,7 +689,33 @@ ASDCP::IntegrityPack::TestValues(const ASDCP::FrameBuffer& FB, const byte_t* Ass
   HMAC->Update(FB.RoData(), FB.Size() - HMAC_SIZE);
   HMAC->Finalize();
 
-  return HMAC->TestHMACValue(p);
+  Result_t result = RESULT_OK;
+  result = HMAC->TestHMACValue(p);
+
+  if (KM_FAILURE(result))
+    {
+      Result_t r = RESULT_OK;
+      char hmac_str[HMAC_SIZE*10];
+      char found_str[HMAC_SIZE*10];
+      byte_t hmac_buf[HMAC_SIZE];
+
+
+      Kumu::bin2hex(p, HMAC_SIZE, found_str, HMAC_SIZE*10);
+
+      r = HMAC->GetHMACValue(hmac_buf);
+      if ( KM_SUCCESS( r ) )
+        {
+          Kumu::bin2hex(hmac_buf, HMAC_SIZE, hmac_str, HMAC_SIZE*10);
+        }
+      else
+        {
+          snprintf(hmac_str, HMAC_SIZE*10, " - read error - ");
+        }
+
+      DefaultLogSink().Error("IntegrityPack failure: HMAC is %s, expecting %s.\n", found_str, hmac_str);
+    }
+
+  return result;
 }
 
 //