summaryrefslogtreecommitdiff
path: root/src/asdcp
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-07-01 12:22:38 +0100
committerCarl Hetherington <cth@carlh.net>2019-12-03 17:01:32 +0100
commitdfb6aa39a8000fc071dfa0680584dae173535c9a (patch)
treeccf64f8dbc81ab13d36f3319475fc0e59f95e2ec /src/asdcp
parent8204f14304dd463a42f8540413cf95cf49e1f829 (diff)
Move public headers into src/asdcp and install them in a asdcp subdirectory.
Diffstat (limited to 'src/asdcp')
-rwxr-xr-xsrc/asdcp/AS_DCP.h1944
-rwxr-xr-xsrc/asdcp/KM_error.h194
-rwxr-xr-xsrc/asdcp/KM_fileio.h388
-rwxr-xr-xsrc/asdcp/KM_memio.h254
-rw-r--r--src/asdcp/KM_platform.h247
-rwxr-xr-xsrc/asdcp/KM_prng.h63
-rw-r--r--src/asdcp/KM_tai.h107
-rwxr-xr-xsrc/asdcp/KM_util.h556
8 files changed, 3753 insertions, 0 deletions
diff --git a/src/asdcp/AS_DCP.h b/src/asdcp/AS_DCP.h
new file mode 100755
index 0000000..72b847e
--- /dev/null
+++ b/src/asdcp/AS_DCP.h
@@ -0,0 +1,1944 @@
+/*
+Copyright (c) 2003-2014, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*! \file AS_DCP.h
+ \version $Id$
+ \brief AS-DCP library, public interface
+
+The asdcplib library is a set of file access objects that offer simplified
+access to files conforming to the standards published by the SMPTE
+D-Cinema Technology Committee 21DC. The file format, labeled AS-DCP,
+is described in a series of documents which includes but may not
+be be limited to:
+
+ o SMPTE ST 429-2:2011 DCP Operational Constraints
+ o SMPTE ST 429-3:2006 Sound and Picture Track File
+ o SMPTE ST 429-4:2006 MXF JPEG 2000 Application
+ o SMPTE ST 429-5:2009 Timed Text Track File
+ o SMPTE ST 429-6:2006 MXF Track File Essence Encryption
+ o SMPTE ST 429-10:2008 Stereoscopic Picture Track File
+ o SMPTE ST 429-14:2008 Aux Data Track File
+ o SMPTE ST 330:2004 - UMID
+ o SMPTE ST 336:2001 - KLV
+ o SMPTE ST 377:2004 - MXF (old version, required)
+ o SMPTE ST 377-1:2011 - MXF
+ o SMPTE ST 377-4:2012 - MXF Multichannel Audio Labeling Framework
+ o SMPTE ST 390:2011 - MXF OP-Atom
+ o SMPTE ST 379-1:2009 - MXF Generic Container (GC)
+ o SMPTE ST 381-1:2005 - MPEG2 picture in GC
+ o SMPTE ST 422:2006 - JPEG 2000 picture in GC
+ o SMPTE ST 382:2007 - WAV/PCM sound in GC
+ o IETF RFC 2104 - HMAC/SHA1
+ o NIST FIPS 197 - AES (Rijndael) (via OpenSSL)
+
+ o MXF Interop Track File Specification
+ o MXF Interop Track File Essence Encryption Specification
+ o MXF Interop Operational Constraints Specification
+ - Note: the MXF Interop documents are not formally published.
+ Contact the asdcplib support address to get copies.
+
+The following use cases are supported by the library:
+
+ o Write essence to a plaintext or ciphertext AS-DCP file:
+ o Read essence from a plaintext or ciphertext AS-DCP file:
+ MPEG2 Video Elementary Stream
+ JPEG 2000 codestreams
+ JPEG 2000 stereoscopic codestream pairs
+ PCM audio streams
+ SMPTE 429-7 Timed Text XML with font and image resources
+ Aux Data (frame-wrapped synchronous blob)
+ Proposed Dolby (TM) Atmos track file
+
+ o Read header metadata from an AS-DCP file
+
+This project depends upon the following libraries:
+ - OpenSSL http://www.openssl.org/
+ - Expat http://expat.sourceforge.net/ or
+ Xerces-C http://xerces.apache.org/xerces-c/
+ An XML library is not needed if you don't need support for SMPTE ST 429-5:2009.
+*/
+
+#ifndef _AS_DCP_H_
+#define _AS_DCP_H_
+
+#include <asdcp/KM_error.h>
+#include <asdcp/KM_fileio.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <math.h>
+#include <iosfwd>
+#include <string>
+#include <cstring>
+#include <list>
+
+//--------------------------------------------------------------------------------
+// common integer types
+// supply your own by defining ASDCP_NO_BASE_TYPES
+
+#ifndef ASDCP_NO_BASE_TYPES
+typedef unsigned char byte_t;
+typedef char i8_t;
+typedef unsigned char ui8_t;
+typedef short i16_t;
+typedef unsigned short ui16_t;
+typedef int i32_t;
+typedef unsigned int ui32_t;
+#endif
+
+
+//--------------------------------------------------------------------------------
+// convenience macros
+
+// Convenience macros for managing return values in predicates
+#define ASDCP_SUCCESS(v) (((v) < 0) ? 0 : 1)
+#define ASDCP_FAILURE(v) (((v) < 0) ? 1 : 0)
+
+
+// Returns RESULT_PTR if the given argument is NULL.
+// See Result_t below for an explanation of RESULT_* symbols.
+#define ASDCP_TEST_NULL(p) \
+ if ( (p) == 0 ) { \
+ return ASDCP::RESULT_PTR; \
+ }
+
+// Returns RESULT_PTR if the given argument is NULL. See Result_t
+// below for an explanation of RESULT_* symbols. It then assumes
+// that the argument is a pointer to a string and returns
+// RESULT_NULL_STR if the first character is '\0'.
+//
+#define ASDCP_TEST_NULL_STR(p) \
+ ASDCP_TEST_NULL(p); \
+ if ( (p)[0] == '\0' ) { \
+ return ASDCP::RESULT_NULL_STR; \
+ }
+
+// Produces copy constructor boilerplate. Allows convenient private
+// declatarion of copy constructors to prevent the compiler from
+// silently manufacturing default methods.
+#define ASDCP_NO_COPY_CONSTRUCT(T) \
+ T(const T&); \
+ T& operator=(const T&)
+
+//--------------------------------------------------------------------------------
+// All library components are defined in the namespace ASDCP
+//
+namespace ASDCP {
+ //
+ // The version number declaration and explanation have moved to ../configure.ac
+ const char* Version();
+
+ // UUIDs are passed around as strings of UUIDlen bytes
+ const ui32_t UUIDlen = 16;
+
+ // Encryption keys are passed around as strings of KeyLen bytes
+ const ui32_t KeyLen = 16;
+
+ //---------------------------------------------------------------------------------
+ // return values
+
+ using Kumu::Result_t;
+
+ using Kumu::RESULT_FALSE;
+ using Kumu::RESULT_OK;
+ using Kumu::RESULT_FAIL;
+ using Kumu::RESULT_PTR;
+ using Kumu::RESULT_NULL_STR;
+ using Kumu::RESULT_ALLOC;
+ using Kumu::RESULT_PARAM;
+ using Kumu::RESULT_SMALLBUF;
+ using Kumu::RESULT_INIT;
+ using Kumu::RESULT_NOT_FOUND;
+ using Kumu::RESULT_NO_PERM;
+ using Kumu::RESULT_FILEOPEN;
+ using Kumu::RESULT_BADSEEK;
+ using Kumu::RESULT_READFAIL;
+ using Kumu::RESULT_WRITEFAIL;
+ using Kumu::RESULT_STATE;
+ using Kumu::RESULT_ENDOFFILE;
+ using Kumu::RESULT_CONFIG;
+
+ KM_DECLARE_RESULT(FORMAT, -101, "The file format is not proper OP-Atom/AS-DCP.");
+ KM_DECLARE_RESULT(RAW_ESS, -102, "Unknown raw essence file type.");
+ KM_DECLARE_RESULT(RAW_FORMAT, -103, "Raw essence format invalid.");
+ KM_DECLARE_RESULT(RANGE, -104, "Frame number out of range.");
+ KM_DECLARE_RESULT(CRYPT_CTX, -105, "AESEncContext required when writing to encrypted file.");
+ KM_DECLARE_RESULT(LARGE_PTO, -106, "Plaintext offset exceeds frame buffer size.");
+ KM_DECLARE_RESULT(CAPEXTMEM, -107, "Cannot resize externally allocated memory.");
+ KM_DECLARE_RESULT(CHECKFAIL, -108, "The check value did not decrypt correctly.");
+ KM_DECLARE_RESULT(HMACFAIL, -109, "HMAC authentication failure.");
+ KM_DECLARE_RESULT(HMAC_CTX, -110, "HMAC context required.");
+ KM_DECLARE_RESULT(CRYPT_INIT, -111, "Error initializing block cipher context.");
+ KM_DECLARE_RESULT(EMPTY_FB, -112, "Empty frame buffer.");
+ KM_DECLARE_RESULT(KLV_CODING, -113, "KLV coding error.");
+ KM_DECLARE_RESULT(SPHASE, -114, "Stereoscopic phase mismatch.");
+ KM_DECLARE_RESULT(SFORMAT, -115, "Rate mismatch, file may contain stereoscopic essence.");
+
+ //---------------------------------------------------------------------------------
+ // file identification
+
+ // The file accessors in this library implement a bounded set of essence types.
+ // This list will be expanded when support for new types is added to the library.
+ enum EssenceType_t {
+ ESS_UNKNOWN, // the file is not a supported AS-DCP of AS-02 essence container
+
+ //
+ ESS_MPEG2_VES, // the file contains an MPEG-2 video elementary stream
+
+ // d-cinema essence types
+ ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
+ ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
+ ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
+ ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources
+ ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic)
+ ESS_DCDATA_UNKNOWN, // the file contains one or more D-Cinema Data bytestreams
+ ESS_DCDATA_DOLBY_ATMOS, // the file contains one or more DolbyATMOS bytestreams
+
+ // IMF essence types
+ ESS_AS02_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
+ ESS_AS02_PCM_24b_48k, // the file contains one or more PCM audio pairs, clip wrapped
+ ESS_AS02_PCM_24b_96k, // the file contains one or more PCM audio pairs, clip wrapped
+ ESS_AS02_TIMED_TEXT, // the file contains a TTML document and zero or more resources
+
+ ESS_MAX
+ };
+
+ // Determine the type of essence contained in the given MXF file. RESULT_OK
+ // is returned if the file is successfully opened and contains a valid MXF
+ // stream. If there is an error, the result code will indicate the reason.
+ Result_t EssenceType(const std::string& filename, EssenceType_t& type);
+
+ // Determine the type of essence contained in the given raw file. RESULT_OK
+ // is returned if the file is successfully opened and contains a known
+ // stream type. If there is an error, the result code will indicate the reason.
+ Result_t RawEssenceType(const std::string& filename, EssenceType_t& type);
+
+
+ //---------------------------------------------------------------------------------
+ // base types
+
+ // A simple container for rational numbers.
+ class Rational
+ {
+ public:
+ i32_t Numerator;
+ i32_t Denominator;
+
+ Rational() : Numerator(0), Denominator(0) {}
+ Rational(i32_t n, i32_t d) : Numerator(n), Denominator(d) {}
+
+ inline double Quotient() const {
+ return (double)Numerator / (double)Denominator;
+ }
+
+ inline bool operator==(const Rational& rhs) const {
+ return ( rhs.Numerator == Numerator && rhs.Denominator == Denominator );
+ }
+
+ inline bool operator!=(const Rational& rhs) const {
+ return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
+ }
+
+ inline bool operator<(const Rational& rhs) {
+ if ( Numerator < rhs.Numerator ) return true;
+ if ( Numerator == rhs.Numerator && Denominator < rhs.Denominator ) return true;
+ return false;
+ }
+
+ inline bool operator>(const Rational& rhs) {
+ if ( Numerator > rhs.Numerator ) return true;
+ if ( Numerator == rhs.Numerator && Denominator > rhs.Denominator ) return true;
+ return false;
+ }
+ };
+
+ // Encodes a rational number as a string having a single delimiter character between
+ // numerator and denominator. Retuns the buffer pointer to allow convenient in-line use.
+ const char* EncodeRational(const Rational&, char* str_buf, ui32_t buf_len, char delimiter = ' ');
+
+ // Decodes a rational number havng a single non-digit delimiter character between
+ // the numerator and denominator. Returns false if the string does not contain
+ // the expected syntax.
+ bool DecodeRational(const char* str_rat, Rational&);
+
+
+ // common edit rates, use these instead of hard coded constants
+ const Rational EditRate_24 = Rational(24,1);
+ const Rational EditRate_23_98 = Rational(24000,1001); // Not a DCI-compliant value!
+ const Rational EditRate_48 = Rational(48,1);
+ const Rational SampleRate_48k = Rational(48000,1);
+ const Rational SampleRate_96k = Rational(96000,1);
+
+ // Additional frame rates, see ST 428-11, ST 429-13
+ // These rates are new and not supported by all systems. Do not assume that
+ // a package made using one of these rates will work just anywhere!
+ const Rational EditRate_25 = Rational(25,1);
+ const Rational EditRate_30 = Rational(30,1);
+ const Rational EditRate_50 = Rational(50,1);
+ const Rational EditRate_60 = Rational(60,1);
+ const Rational EditRate_96 = Rational(96,1);
+ const Rational EditRate_100 = Rational(100,1);
+ const Rational EditRate_120 = Rational(120,1);
+
+ // Archival frame rates, see ST 428-21
+ // These rates are new and not supported by all systems. Do not assume that
+ // a package made using one of these rates will work just anywhere!
+ const Rational EditRate_16 = Rational(16,1);
+ const Rational EditRate_18 = Rational(200,11); // 18.182
+ const Rational EditRate_20 = Rational(20,1);
+ const Rational EditRate_22 = Rational(240,11); // 21.818
+
+
+ // Non-reference counting container for internal member objects.
+ // Please do not use this class for any other purpose.
+ template <class T>
+ class mem_ptr
+ {
+ T* m_p; // the thing we point to
+ mem_ptr(T&);
+
+ public:
+ mem_ptr() : m_p(0) {}
+ mem_ptr(T* p) : m_p(p) {}
+ ~mem_ptr() { delete m_p; }
+
+ inline T& operator*() const { return *m_p; }
+ inline T* operator->() const { return m_p; }
+ inline operator T*()const { return m_p; }
+ inline const mem_ptr<T>& operator=(T* p) { set(p); return *this; }
+ inline T* set(T* p) { delete m_p; m_p = p; return m_p; }
+ inline T* get() const { return m_p; }
+ inline void release() { m_p = 0; }
+ inline bool empty() const { return m_p == 0; }
+ };
+
+
+ //---------------------------------------------------------------------------------
+ // WriterInfo class - encapsulates writer identification details used for
+ // OpenWrite() calls. Replace these values at runtime to identify your product.
+ //
+ // MXF files use SMPTE Universal Labels to identify data items. The set of Labels
+ // in a file is determined by the MXF Operational Pattern and any constraining
+ // documentation. There are currently two flavors of AS-DCP file in use: MXF Interop
+ // (AKA JPEG Interop) and SMPTE. The two differ in the values of three labels:
+ //
+ // OPAtom
+ // Interop : 06 0e 2b 34 04 01 01 01 0d 01 02 01 10 00 00 00
+ // SMPTE : 06 0e 2b 34 04 01 01 02 0d 01 02 01 10 00 00 00
+ //
+ // EKLV Packet:
+ // Interop : 06 0e 2b 34 02 04 01 07 0d 01 03 01 02 7e 01 00
+ // SMPTE : 06 0e 2b 34 02 04 01 01 0d 01 03 01 02 7e 01 00
+ //
+ // GenericDescriptor/SubDescriptors:
+ // Interop : 06 0e 2b 34 01 01 01 02 06 01 01 04 06 10 00 00
+ // SMPTE : 06 0e 2b 34 01 01 01 09 06 01 01 04 06 10 00 00
+ //
+ // asdcplib will read any (otherwise valid) file which has any combination of the
+ // above values. When writing files, MXF Interop labels are used by default. To
+ // write a file containing SMPTE labels, replace the default label set value in
+ // the WriterInfo before calling OpenWrite()
+ //
+ //
+ enum LabelSet_t
+ {
+ LS_MXF_UNKNOWN,
+ LS_MXF_INTEROP,
+ LS_MXF_SMPTE,
+ LS_MAX
+ };
+
+ //
+ struct WriterInfo
+ {
+ byte_t ProductUUID[UUIDlen];
+ byte_t AssetUUID[UUIDlen];
+ byte_t ContextID[UUIDlen];
+ byte_t CryptographicKeyID[UUIDlen];
+ bool EncryptedEssence; // true if essence data is (or is going to be) encrypted
+ bool UsesHMAC; // true if HMAC exists or is to be calculated
+ std::string ProductVersion;
+ std::string CompanyName;
+ std::string ProductName;
+ LabelSet_t LabelSetType;
+
+ WriterInfo() : EncryptedEssence(false), UsesHMAC(false), LabelSetType(LS_MXF_INTEROP)
+ {
+ static byte_t default_ProductUUID_Data[UUIDlen] = {
+ 0x43, 0x05, 0x9a, 0x1d, 0x04, 0x32, 0x41, 0x01,
+ 0xb8, 0x3f, 0x73, 0x68, 0x15, 0xac, 0xf3, 0x1d };
+
+ memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
+ memset(AssetUUID, 0, UUIDlen);
+ memset(ContextID, 0, UUIDlen);
+ memset(CryptographicKeyID, 0, UUIDlen);
+
+ ProductVersion = "Unreleased ";
+ ProductVersion += Version();
+ CompanyName = "DCI";
+ ProductName = "asdcplib";
+ }
+ };
+
+ // Print WriterInfo to std::ostream
+ std::ostream& operator << (std::ostream& strm, const WriterInfo& winfo);
+ // Print WriterInfo to stream, stderr by default.
+ void WriterInfoDump(const WriterInfo&, FILE* = 0);
+
+ //---------------------------------------------------------------------------------
+ // cryptographic support
+
+ // The following classes define interfaces to Rijndael contexts having the following properties:
+ // o 16 byte key
+ // o CBC mode with 16 byte block size
+ const ui32_t CBC_KEY_SIZE = 16;
+ const ui32_t CBC_BLOCK_SIZE = 16;
+ const ui32_t HMAC_SIZE = 20;
+
+ //
+ class AESEncContext
+ {
+ class h__AESContext;
+ mem_ptr<h__AESContext> m_Context;
+ ASDCP_NO_COPY_CONSTRUCT(AESEncContext);
+
+ public:
+ AESEncContext();
+ ~AESEncContext();
+
+ // Initializes Rijndael CBC encryption context.
+ // Returns error if the key argument is NULL.
+ Result_t InitKey(const byte_t* key);
+
+ // Initializes 16 byte CBC Initialization Vector. This operation may be performed
+ // any number of times for a given key.
+ // Returns error if the i_vec argument is NULL.
+ Result_t SetIVec(const byte_t* i_vec);
+ Result_t GetIVec(byte_t* i_vec) const;
+
+ // Encrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
+ // Returns error if either argument is NULL.
+ Result_t EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size);
+ };
+
+ //
+ class AESDecContext
+ {
+ class h__AESContext;
+ mem_ptr<h__AESContext> m_Context;
+ ASDCP_NO_COPY_CONSTRUCT(AESDecContext);
+
+ public:
+ AESDecContext();
+ ~AESDecContext();
+
+ // Initializes Rijndael CBC decryption context.
+ // Returns error if the key argument is NULL.
+ Result_t InitKey(const byte_t* key);
+
+ // Initializes 16 byte CBC Initialization Vector. This operation may be performed
+ // any number of times for a given key.
+ // Returns error if the i_vec argument is NULL.
+ Result_t SetIVec(const byte_t* i_vec);
+
+ // Decrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
+ // Returns error if either argument is NULL.
+ Result_t DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size);
+ };
+
+ //
+ class HMACContext
+ {
+ class h__HMACContext;
+ mem_ptr<h__HMACContext> m_Context;
+ ASDCP_NO_COPY_CONSTRUCT(HMACContext);
+
+ public:
+ HMACContext();
+ ~HMACContext();
+
+ // Initializes HMAC context. The key argument must point to a binary
+ // key that is CBC_KEY_SIZE bytes in length. Returns error if the key
+ // argument is NULL.
+ Result_t InitKey(const byte_t* key, LabelSet_t);
+
+ // Reset internal state, allows repeated cycles of Update -> Finalize
+ void Reset();
+
+ // Add data to the digest. Returns error if the key argument is NULL or
+ // if the digest has been finalized.
+ Result_t Update(const byte_t* buf, ui32_t buf_len);
+
+ // Finalize digest. Returns error if the digest has already been finalized.
+ Result_t Finalize();
+
+ // Writes HMAC value to given buffer. buf must point to a writable area of
+ // memory that is at least HMAC_SIZE bytes in length. Returns error if the
+ // buf argument is NULL or if the digest has not been finalized.
+ Result_t GetHMACValue(byte_t* buf) const;
+
+ // Tests the given value against the finalized value in the object. buf must
+ // point to a readable area of memory that is at least HMAC_SIZE bytes in length.
+ // Returns error if the buf argument is NULL or if the values do ot match.
+ Result_t TestHMACValue(const byte_t* buf) const;
+ };
+
+ //---------------------------------------------------------------------------------
+ // frame buffer base class
+ //
+ // The supported essence types are stored using per-frame KLV packetization. The
+ // following class implements essence-neutral functionality for managing a buffer
+ // containing a frame of essence.
+
+ class FrameBuffer
+ {
+ ASDCP_NO_COPY_CONSTRUCT(FrameBuffer);
+
+ protected:
+ byte_t* m_Data; // pointer to memory area containing frame data
+ ui32_t m_Capacity; // size of memory area pointed to by m_Data
+ bool m_OwnMem; // if false, m_Data points to externally allocated memory
+ ui32_t m_Size; // size of frame data in memory area pointed to by m_Data
+ ui32_t m_FrameNumber; // delivery-order frame number
+
+ // It is possible to read raw ciphertext from an encrypted AS-DCP file.
+ // After reading an encrypted AS-DCP file in raw mode, the frame buffer will
+ // contain the encrypted source value portion of the Encrypted Triplet, followed
+ // by the integrity pack, if it exists.
+ // The buffer will begin with the IV and CheckValue, followed by encrypted essence
+ // and optional integrity pack
+ // The SourceLength and PlaintextOffset values from the packet will be held in the
+ // following variables:
+ ui32_t m_SourceLength; // plaintext length (delivered plaintext+decrypted ciphertext)
+ ui32_t m_PlaintextOffset; // offset to first byte of ciphertext
+
+ public:
+ FrameBuffer();
+ virtual ~FrameBuffer();
+
+ // Instructs the object to use an externally allocated buffer. The external
+ // buffer will not be cleaned up by the frame buffer when it exits.
+ // Call with (0,0) to revert to internally allocated buffer.
+ // Returns error if the buf_addr argument is NULL and buf_size is non-zero.
+ Result_t SetData(byte_t* buf_addr, ui32_t buf_size);
+
+ // Sets the size of the internally allocate buffer. Returns RESULT_CAPEXTMEM
+ // if the object is using an externally allocated buffer via SetData();
+ // Resets content size to zero.
+ Result_t Capacity(ui32_t cap);
+
+ // returns the size of the buffer
+ inline ui32_t Capacity() const { return m_Capacity; }
+
+ // returns a const pointer to the essence data
+ inline const byte_t* RoData() const { return m_Data; }
+
+ // returns a non-const pointer to the essence data
+ inline byte_t* Data() { return m_Data; }
+
+ // set the size of the buffer's contents
+ inline ui32_t Size(ui32_t size) { return m_Size = size; }
+
+ // returns the size of the buffer's contents
+ inline ui32_t Size() const { return m_Size; }
+
+ // Sets the absolute frame number of this frame in the file in delivery order.
+ inline void FrameNumber(ui32_t num) { m_FrameNumber = num; }
+
+ // Returns the absolute frame number of this frame in the file in delivery order.
+ inline ui32_t FrameNumber() const { return m_FrameNumber; }
+
+ // Sets the length of the plaintext essence data
+ inline void SourceLength(ui32_t len) { m_SourceLength = len; }
+
+ // When this value is 0 (zero), the buffer contains only plaintext. When it is
+ // non-zero, the buffer contains raw ciphertext and the return value is the length
+ // of the original plaintext.
+ inline ui32_t SourceLength() const { return m_SourceLength; }
+
+ // Sets the offset into the buffer at which encrypted data begins
+ inline void PlaintextOffset(ui32_t ofst) { m_PlaintextOffset = ofst; }
+
+ // Returns offset into buffer of first byte of ciphertext.
+ inline ui32_t PlaintextOffset() const { return m_PlaintextOffset; }
+ };
+
+ //---------------------------------------------------------------------------------
+ // Accessors in the MXFReader and MXFWriter classes below return these types to
+ // provide direct access to MXF metadata structures declared in MXF.h and Metadata.h
+
+ namespace MXF {
+ // #include<Metadata.h> to use these
+ class OP1aHeader;
+ class OPAtomIndexFooter;
+ class RIP;
+ };
+
+ //---------------------------------------------------------------------------------
+ // MPEG2 video elementary stream support
+
+ //
+ namespace MPEG2
+ {
+ // MPEG picture coding type
+ enum FrameType_t {
+ FRAME_U = 0x00, // Unknown
+ FRAME_I = 0x01, // I-Frame
+ FRAME_P = 0x02, // P-Frame
+ FRAME_B = 0x03 // B-Frame
+ };
+
+ // convert FrameType_t to char
+ inline char FrameTypeChar(FrameType_t type)
+ {
+ switch ( type )
+ {
+ case FRAME_I: return 'I';
+ case FRAME_B: return 'B';
+ case FRAME_P: return 'P';
+ default: return 'U';
+ }
+ }
+
+ // Structure represents the metadata elements in the file header's
+ // MPEG2VideoDescriptor object.
+ struct VideoDescriptor
+ {
+ Rational EditRate; //
+ ui32_t FrameRate; //
+ Rational SampleRate; //
+ ui8_t FrameLayout; //
+ ui32_t StoredWidth; //
+ ui32_t StoredHeight; //
+ Rational AspectRatio; //
+ ui32_t ComponentDepth; //
+ ui32_t HorizontalSubsampling; //
+ ui32_t VerticalSubsampling; //
+ ui8_t ColorSiting; //
+ ui8_t CodedContentType; //
+ bool LowDelay; //
+ ui32_t BitRate; //
+ ui8_t ProfileAndLevel; //
+ ui32_t ContainerDuration; //
+ };
+
+ // Print VideoDescriptor to std::ostream
+ std::ostream& operator << (std::ostream& strm, const VideoDescriptor& vdesc);
+ // Print VideoDescriptor to stream, stderr by default.
+ void VideoDescriptorDump(const VideoDescriptor&, FILE* = 0);
+
+ // A container for MPEG frame data.
+ class FrameBuffer : public ASDCP::FrameBuffer
+ {
+ ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
+
+ protected:
+ FrameType_t m_FrameType;
+ ui8_t m_TemporalOffset;
+ bool m_ClosedGOP;
+ bool m_GOPStart;
+
+ public:
+ FrameBuffer() :
+ m_FrameType(FRAME_U), m_TemporalOffset(0),
+ m_ClosedGOP(false), m_GOPStart(false) {}
+
+ FrameBuffer(ui32_t size) :
+ m_FrameType(FRAME_U), m_TemporalOffset(0),
+ m_ClosedGOP(false), m_GOPStart(false)
+ {
+ Capacity(size);
+ }
+
+ virtual ~FrameBuffer() {}
+
+ // Sets the MPEG frame type of the picture data in the frame buffer.
+ inline void FrameType(FrameType_t type) { m_FrameType = type; }
+
+ // Returns the MPEG frame type of the picture data in the frame buffer.
+ inline FrameType_t FrameType() const { return m_FrameType; }
+
+ // Sets the MPEG temporal offset of the picture data in the frame buffer.
+ inline void TemporalOffset(ui8_t offset) { m_TemporalOffset = offset; }
+
+ // Returns the MPEG temporal offset of the picture data in the frame buffer.
+ inline ui8_t TemporalOffset() const { return m_TemporalOffset; }
+
+ // Sets the MPEG GOP 'start' attribute for the frame buffer.
+ inline void GOPStart(bool start) { m_GOPStart = start; }
+
+ // True if the frame in the buffer is the first in the GOP (in transport order)
+ inline bool GOPStart() const { return m_GOPStart; }
+
+ // Sets the MPEG GOP 'closed' attribute for the frame buffer.
+ inline void ClosedGOP(bool closed) { m_ClosedGOP = closed; }
+
+ // Returns true if the frame in the buffer is from a closed GOP, false if
+ // the frame is from an open GOP. Always returns false unless GOPStart()
+ // returns true.
+ inline bool ClosedGOP() const { return m_ClosedGOP; }
+
+ // Print object state to stream, include n bytes of frame data if indicated.
+ // Default stream is stderr.
+ void Dump(FILE* = 0, ui32_t dump_len = 0) const;
+ };
+
+
+ // An object which opens and reads an MPEG2 Video Elementary Stream file. The call to
+ // OpenRead() reads metadata from the file and populates an internal VideoDescriptor object.
+ // Each subsequent call to ReadFrame() reads exactly one frame from the stream into the
+ // given FrameBuffer object.
+ class Parser
+ {
+ class h__Parser;
+ mem_ptr<h__Parser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(Parser);
+
+ public:
+ Parser();
+ virtual ~Parser();
+
+ // Opens the stream for reading, parses enough data to provide a complete
+ // set of stream metadata for the MXFWriter below.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Fill a VideoDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillVideoDescriptor(VideoDescriptor&) const;
+
+ // Rewind the stream to the beginning.
+ Result_t Reset() const;
+
+ // Reads the next sequential frame in the input file and places it in the
+ // frame buffer. Fails if the buffer is too small or the stream is empty.
+ // The frame buffer's PlaintextOffset parameter will be set to the first
+ // data byte of the first slice. Set this value to zero if you want
+ // encrypted headers.
+ Result_t ReadFrame(FrameBuffer&) const;
+ };
+
+ // A class which creates and writes MPEG frame data to an AS-DCP format MXF file.
+ // Not yet implemented
+ class MXFWriter
+ {
+ class h__Writer;
+ mem_ptr<h__Writer> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const std::string& filename, const WriterInfo&,
+ const VideoDescriptor&, ui32_t HeaderSize = 16384);
+
+ // 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.
+ Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // Closes the MXF file, writing the index and revised header.
+ Result_t Finalize();
+ };
+
+ // A class which reads MPEG frame data from an AS-DCP format MXF file.
+ class MXFReader
+ {
+ class h__Reader;
+ mem_ptr<h__Reader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+ MXFReader();
+ virtual ~MXFReader();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill a VideoDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillVideoDescriptor(VideoDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Using the index table read from the footer partition, lookup the frame number
+ // and return the offset into the file at which to read that frame of essence.
+ // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
+ // out of range.
+ Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
+
+ // Calculates the first frame in transport order of the GOP in which the requested
+ // frame is located. Calls ReadFrame() to fetch the frame at the calculated position.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t ReadFrameGOPStart(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Calculates the first frame in transport order of the GOP in which the requested
+ // frame is located. Sets key_frame_number to the number of the frame at the calculated position.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FindFrameGOPStart(ui32_t frame_number, ui32_t& key_frame_number) const;
+
+ // Returns the type of the frame at the given position.
+ // Returns RESULT_INIT if the file is not open or RESULT_RANGE if the index is out of range.
+ Result_t FrameType(ui32_t frame_number, FrameType_t&) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+ } // namespace MPEG2
+
+ //---------------------------------------------------------------------------------
+ //
+
+
+
+ namespace PCM
+ {
+ // The default value of the ChannelFormat element of the AudioDescriptor struct
+ // is CF_NONE. If the value is set to one of the other ChannelFormat_t enum
+ // values, the file's Wave Audio Descriptor will contain a Channel Assignment
+ // element.
+ //
+ // The channel format should be one of (CF_CFG_1, CF_CFG_2, or CF_CFG_3) for
+ // SMPTE 429-2 files. It should normally be CF_NONE for JPEG Interop files, but
+ // the 429-2 may also be used.
+ //
+ enum ChannelFormat_t {
+ CF_NONE,
+ CF_CFG_1, // 5.1 with optional HI/VI
+ CF_CFG_2, // 6.1 (5.1 + center surround) with optional HI/VI
+ CF_CFG_3, // 7.1 (SDDS) with optional HI/VI
+ CF_CFG_4, // Wild Track Format
+ CF_CFG_5, // 7.1 DS with optional HI/VI
+ CF_CFG_6, // ST 377-4 (MCA) labels (see also ASDCP::MXF::decode_mca_string)
+ CF_MAXIMUM
+ };
+
+ struct AudioDescriptor
+ {
+ Rational EditRate; // rate of frame wrapping
+ Rational AudioSamplingRate; // rate of audio sample
+ ui32_t Locked; //
+ ui32_t ChannelCount; // number of channels
+ ui32_t QuantizationBits; // number of bits per single-channel sample
+ ui32_t BlockAlign; // number of bytes ber sample, all channels
+ ui32_t AvgBps; //
+ ui32_t LinkedTrackID; //
+ ui32_t ContainerDuration; // number of frames
+ ChannelFormat_t ChannelFormat; // audio channel arrangement
+ };
+
+ // Print AudioDescriptor to std::ostream
+ std::ostream& operator << (std::ostream& strm, const AudioDescriptor& adesc);
+ // Print debugging information to stream (stderr default)
+ void AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
+
+ // Returns size in bytes of a single sample of data described by ADesc
+ inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
+ {
+ return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
+ }
+
+ // Returns number of samples per frame of data described by ADesc
+ inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
+ {
+ double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
+ return (ui32_t)ceil(tmpd);
+ }
+
+ // Returns the size in bytes of a frame of data described by ADesc
+ inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
+ {
+ return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
+ }
+
+ //
+ class FrameBuffer : public ASDCP::FrameBuffer
+ {
+ public:
+ FrameBuffer() {}
+ FrameBuffer(ui32_t size) { Capacity(size); }
+ virtual ~FrameBuffer() {}
+
+ // Print debugging information to stream (stderr default)
+ void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
+ };
+
+ // An object which opens and reads a WAV file. The call to OpenRead() reads metadata from
+ // the file and populates an internal AudioDescriptor object. Each subsequent call to
+ // ReadFrame() reads exactly one frame from the stream into the given FrameBuffer object.
+ // A "frame" is either 2000 or 2002 samples, depending upon the value of PictureRate.
+ class WAVParser
+ {
+ class h__WAVParser;
+ mem_ptr<h__WAVParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(WAVParser);
+
+ public:
+ WAVParser();
+ virtual ~WAVParser();
+
+ // Opens the stream for reading, parses enough data to provide a complete
+ // set of stream metadata for the MXFWriter below. PictureRate controls
+ // ther frame rate for the MXF frame wrapping option.
+ Result_t OpenRead(const std::string& filename, const Rational& PictureRate) const;
+
+ // Fill an AudioDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillAudioDescriptor(AudioDescriptor&) const;
+
+ // Rewind the stream to the beginning.
+ Result_t Reset() const;
+
+ // Reads the next sequential frame in the input file and places it in the
+ // frame buffer. Fails if the buffer is too small or the stream is empty.
+ Result_t ReadFrame(FrameBuffer&) const;
+ };
+
+
+ //
+ class MXFWriter
+ {
+ class h__Writer;
+ mem_ptr<h__Writer> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const std::string& filename, const WriterInfo&,
+ const AudioDescriptor&, ui32_t HeaderSize = 16384);
+
+ // 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.
+ Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // Closes the MXF file, writing the index and revised header.
+ Result_t Finalize();
+ };
+
+ //
+ class MXFReader
+ {
+ class h__Reader;
+ mem_ptr<h__Reader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+ MXFReader();
+ virtual ~MXFReader();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill an AudioDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillAudioDescriptor(AudioDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Using the index table read from the footer partition, lookup the frame number
+ // and return the offset into the file at which to read that frame of essence.
+ // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
+ // out of range.
+ Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+ } // namespace PCM
+
+ //---------------------------------------------------------------------------------
+ //
+ namespace JP2K
+ {
+ const ui32_t MaxComponents = 3;
+ const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
+ const ui32_t MaxDefaults = 256; // made up
+
+#pragma pack(1)
+ struct ImageComponent_t // ISO 15444-1 Annex A.5.1
+ {
+ ui8_t Ssize;
+ ui8_t XRsize;
+ ui8_t YRsize;
+ };
+
+ struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
+ {
+ ui8_t Scod;
+
+ struct
+ {
+ ui8_t ProgressionOrder;
+ ui8_t NumberOfLayers[sizeof(ui16_t)];
+ ui8_t MultiCompTransform;
+ } SGcod;
+
+ struct
+ {
+ ui8_t DecompositionLevels;
+ ui8_t CodeblockWidth;
+ ui8_t CodeblockHeight;
+ ui8_t CodeblockStyle;
+ ui8_t Transformation;
+ ui8_t PrecinctSize[MaxPrecincts];
+ } SPcod;
+ };
+
+ struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
+ {
+ ui8_t Sqcd;
+ ui8_t SPqcd[MaxDefaults];
+ ui8_t SPqcdLength;
+ };
+#pragma pack()
+
+ struct PictureDescriptor
+ {
+ Rational EditRate;
+ ui32_t ContainerDuration;
+ Rational SampleRate;
+ ui32_t StoredWidth;
+ ui32_t StoredHeight;
+ Rational AspectRatio;
+ ui16_t Rsize;
+ ui32_t Xsize;
+ ui32_t Ysize;
+ ui32_t XOsize;
+ ui32_t YOsize;
+ ui32_t XTsize;
+ ui32_t YTsize;
+ ui32_t XTOsize;
+ ui32_t YTOsize;
+ ui16_t Csize;
+ ImageComponent_t ImageComponents[MaxComponents];
+ CodingStyleDefault_t CodingStyleDefault;
+ QuantizationDefault_t QuantizationDefault;
+ };
+
+ // Print debugging information to std::ostream
+ std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
+ // Print debugging information to stream (stderr default)
+ void PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
+
+ //
+ class FrameBuffer : public ASDCP::FrameBuffer
+ {
+ public:
+ FrameBuffer() {}
+ FrameBuffer(ui32_t size) { Capacity(size); }
+ virtual ~FrameBuffer() {}
+
+ // Print debugging information to stream (stderr default)
+ void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
+ };
+
+
+ // An object which opens and reads a JPEG 2000 codestream file. The file is expected
+ // to contain exactly one complete frame of picture essence as an unwrapped (raw)
+ // ISO/IEC 15444 codestream.
+ class CodestreamParser
+ {
+ class h__CodestreamParser;
+ mem_ptr<h__CodestreamParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
+
+ public:
+ CodestreamParser();
+ virtual ~CodestreamParser();
+
+ // Opens a file for reading, parses enough data to provide a complete
+ // set of stream metadata for the MXFWriter below.
+ // The frame buffer's PlaintextOffset parameter will be set to the first
+ // byte of the data segment. Set this value to zero if you want
+ // encrypted headers.
+ Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
+
+ Result_t OpenReadFrame(const unsigned char * data, unsigned int size, FrameBuffer&) const;
+
+ // Fill a PictureDescriptor struct with the values from the file's codestream.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillPictureDescriptor(PictureDescriptor&) const;
+ };
+
+ // Parses the data in the frame buffer to fill in the picture descriptor. Copies
+ // the offset of the image data into start_of_data. Returns error if the parser fails.
+ Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
+
+ // An object which reads a sequence of files containing JPEG 2000 pictures.
+ class SequenceParser
+ {
+ class h__SequenceParser;
+ mem_ptr<h__SequenceParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
+
+ public:
+ SequenceParser();
+ virtual ~SequenceParser();
+
+ // Opens a directory for reading. The directory is expected to contain one or
+ // more files, each containing the codestream for exactly one picture. The
+ // files must be named such that the frames are in temporal order when sorted
+ // alphabetically by filename. The parser will automatically parse enough data
+ // from the first file to provide a complete set of stream metadata for the
+ // MXFWriter below. If the "pedantic" parameter is given and is true, the
+ // parser will check the metadata for each codestream and fail if a
+ // mismatch is detected.
+ Result_t OpenRead(const std::string& filename, bool pedantic = false) const;
+
+ // Opens a file sequence for reading. The sequence is expected to contain one or
+ // more filenames, each naming a file containing the codestream for exactly one
+ // picture. The parser will automatically parse enough data
+ // from the first file to provide a complete set of stream metadata for the
+ // MXFWriter below. If the "pedantic" parameter is given and is true, the
+ // parser will check the metadata for each codestream and fail if a
+ // mismatch is detected.
+ Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic = false) const;
+
+ // Fill a PictureDescriptor struct with the values from the first file's codestream.
+ // Returns RESULT_INIT if the directory is not open.
+ Result_t FillPictureDescriptor(PictureDescriptor&) const;
+
+ // Rewind the directory to the beginning.
+ Result_t Reset() const;
+
+ // Reads the next sequential frame in the directory and places it in the
+ // frame buffer. Fails if the buffer is too small or the direcdtory
+ // contains no more files.
+ // The frame buffer's PlaintextOffset parameter will be set to the first
+ // byte of the data segment. Set this value to zero if you want
+ // encrypted headers.
+ Result_t ReadFrame(FrameBuffer&) const;
+ };
+
+
+ //
+ class MXFWriter
+ {
+ class h__Writer;
+ mem_ptr<h__Writer> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for writing. The file must not exist unless overwrite is true. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const std::string& filename, const WriterInfo&,
+ const PictureDescriptor&, ui32_t HeaderSize = 16384, bool overwrite = false);
+
+ // Writes a frame of essence to the MXF file. If the optional AESEncContext
+ // argument is present, the essence is encrypted prior to writing.
+ // A MD5 hash of the data that we write is written to hash if it is not 0
+ // Fails if the file is not open, is finalized, or an operating system
+ // error occurs.
+ Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0);
+
+ Result_t FakeWriteFrame(int size);
+
+ // Closes the MXF file, writing the index and revised header.
+ Result_t Finalize();
+
+ // Return the current file offset in the MXF file that we are writing
+ ui64_t Tell() const;
+ };
+
+ //
+ class MXFReader
+ {
+ class h__Reader;
+ mem_ptr<h__Reader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+ MXFReader();
+ virtual ~MXFReader();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill an AudioDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillPictureDescriptor(PictureDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Using the index table read from the footer partition, lookup the frame number
+ // and return the offset into the file at which to read that frame of essence.
+ // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
+ // out of range.
+ Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+
+
+ // Stereoscopic Image support
+ //
+
+ enum StereoscopicPhase_t
+ {
+ SP_LEFT,
+ SP_RIGHT
+ };
+
+ struct SFrameBuffer
+ {
+ JP2K::FrameBuffer Left;
+ JP2K::FrameBuffer Right;
+
+ SFrameBuffer(ui32_t size) {
+ Left.Capacity(size);
+ Right.Capacity(size);
+ }
+ };
+
+ class MXFSWriter
+ {
+ class h__SWriter;
+ mem_ptr<h__SWriter> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
+
+ public:
+ MXFSWriter();
+ virtual ~MXFSWriter();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for writing. The file must not exist unless overwrite is true. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const std::string& filename, const WriterInfo&,
+ const PictureDescriptor&, ui32_t HeaderSize = 16384, bool overwrite = false);
+
+ // Writes a pair of frames 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.
+ Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // 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. Frames must be written in the proper phase (L-R-L-R),
+ // RESULT_SPHASE will be returned if phase is reversed. The first frame
+ // written must be left eye.
+ Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
+ AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0);
+
+ Result_t FakeWriteFrame(int size, StereoscopicPhase_t phase);
+
+ // Closes the MXF file, writing the index and revised header. Returns
+ // RESULT_SPHASE if WriteFrame was called an odd number of times.
+ Result_t Finalize();
+
+ // Return the current file offset in the MXF file that we are writing
+ ui64_t Tell() const;
+ };
+
+ //
+ class MXFSReader
+ {
+ class h__SReader;
+ mem_ptr<h__SReader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
+
+ public:
+ MXFSReader();
+ virtual ~MXFSReader();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill an AudioDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillPictureDescriptor(PictureDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a pair of frames of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, SFrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
+ FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Using the index table read from the footer partition, lookup the frame number
+ // and return the offset into the file at which to read that frame of essence.
+ // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
+ // out of range.
+ Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+ } // namespace JP2K
+
+ //---------------------------------------------------------------------------------
+ //
+ namespace TimedText
+ {
+ enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
+
+ struct TimedTextResourceDescriptor
+ {
+ byte_t ResourceID[UUIDlen];
+ MIMEType_t Type;
+
+ TimedTextResourceDescriptor() : Type(MT_BIN) {}
+ };
+
+ typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
+
+ struct TimedTextDescriptor
+ {
+ Rational EditRate; //
+ ui32_t ContainerDuration;
+ byte_t AssetID[UUIDlen];
+ std::string NamespaceName;
+ std::string EncodingName;
+ ResourceList_t ResourceList;
+
+ TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8
+ };
+
+ // Print debugging information to std::ostream
+ std::ostream& operator << (std::ostream& strm, const TimedTextDescriptor& tinfo);
+ // Print debugging information to stream (stderr default)
+ void DescriptorDump(const TimedTextDescriptor&, FILE* = 0);
+
+ //
+ class FrameBuffer : public ASDCP::FrameBuffer
+ {
+ ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
+
+ protected:
+ byte_t m_AssetID[UUIDlen];
+ std::string m_MIMEType;
+
+ public:
+ FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
+ FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
+ virtual ~FrameBuffer() {}
+
+ inline const byte_t* AssetID() const { return m_AssetID; }
+ inline void AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); }
+ inline const char* MIMEType() const { return m_MIMEType.c_str(); }
+ inline void MIMEType(const std::string& s) { m_MIMEType = s; }
+
+ // Print debugging information to stream (stderr default)
+ void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
+ };
+
+ // An abstract base for a lookup service that returns the resource data
+ // identified by the given ancillary resource id.
+ //
+ class IResourceResolver
+ {
+ public:
+ virtual ~IResourceResolver() {}
+ virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
+ };
+
+ // Resolves resource references by testing the named directory for file names containing
+ // the respective UUID.
+ //
+ class LocalFilenameResolver : public ASDCP::TimedText::IResourceResolver
+ {
+ std::string m_Dirname;
+ ASDCP_NO_COPY_CONSTRUCT(LocalFilenameResolver);
+
+ public:
+ LocalFilenameResolver();
+ virtual ~LocalFilenameResolver();
+ Result_t OpenRead(const std::string& dirname);
+ Result_t ResolveRID(const byte_t* uuid, FrameBuffer& FrameBuf) const;
+ };
+
+ //
+ class DCSubtitleParser
+ {
+ class h__SubtitleParser;
+ mem_ptr<h__SubtitleParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
+
+ public:
+ DCSubtitleParser();
+ virtual ~DCSubtitleParser();
+
+ // Opens an XML file for reading, parses data to provide a complete
+ // set of stream metadata for the MXFWriter below.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Parses an XML document to provide a complete set of stream metadata
+ // for the MXFWriter below. The optional filename argument is used to
+ // initialize the default resource resolver (see ReadAncillaryResource).
+ Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const;
+
+ // Fill a TimedTextDescriptor struct with the values from the file's contents.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
+
+ // Reads the complete Timed Text Resource into the given string.
+ Result_t ReadTimedTextResource(std::string&) const;
+
+ // Reads the Ancillary Resource having the given ID. Fails if the buffer
+ // is too small or the resource does not exist. The optional Resolver
+ // argument can be provided which will be used to retrieve the resource
+ // having a particulat UUID. If a Resolver is not supplied, the default
+ // internal resolver will return the contents of the file having the UUID
+ // as the filename. The filename must exist in the same directory as the
+ // XML file opened with OpenRead().
+ Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
+ const IResourceResolver* Resolver = 0) const;
+ };
+
+ //
+ class MXFWriter
+ {
+ class h__Writer;
+ mem_ptr<h__Writer> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const std::string& filename, const WriterInfo&,
+ const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
+
+ // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
+ // encoded. 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.
+ // This method may only be called once, and it must be called before any
+ // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
+ // conditions are not met.
+ Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
+
+ // Writes an Ancillary Resource 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. RESULT_STATE will be returned if the method is called before
+ // WriteTimedTextResource()
+ Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // Closes the MXF file, writing the index and revised header.
+ Result_t Finalize();
+ };
+
+ //
+ class MXFReader
+ {
+ class h__Reader;
+ mem_ptr<h__Reader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+ MXFReader();
+ virtual ~MXFReader();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill a TimedTextDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads the complete Timed Text Resource into the given string. Fails if the resource
+ // is encrypted and AESDecContext is NULL (use the following method to retrieve the
+ // raw ciphertet block).
+ Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
+ // argument is present, the resource is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Reads the timed-text resource having the given UUID from the MXF file. If the
+ // optional AESEncContext argument is present, the resource is decrypted after
+ // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
+ // the frame buffer will contain the ciphertext frame data. If the HMACContext
+ // argument is not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+ } // namespace TimedText
+
+ //---------------------------------------------------------------------------------
+ //
+ namespace DCData
+ {
+ struct DCDataDescriptor
+ {
+ Rational EditRate; // Sample rate
+ ui32_t ContainerDuration; // number of frames
+ byte_t AssetID[UUIDlen]; // The UUID for the DCData track
+ byte_t DataEssenceCoding[UUIDlen]; // The coding for the data carried
+ };
+
+ // Print DCDataDescriptor to std::ostream
+ std::ostream& operator << (std::ostream& strm, const DCDataDescriptor& ddesc);
+ // Print debugging information to stream (stderr default)
+ void DCDataDescriptorDump(const DCDataDescriptor&, FILE* = 0);
+
+ //
+ class FrameBuffer : public ASDCP::FrameBuffer
+ {
+ public:
+ FrameBuffer() {}
+ FrameBuffer(ui32_t size) { Capacity(size); }
+ virtual ~FrameBuffer() {}
+
+ // Print debugging information to stream (stderr default)
+ void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
+ };
+
+ // An object which opens and reads a DC Data file. The file is expected
+ // to contain exactly one complete frame of DC data essence as an unwrapped (raw)
+ // byte stream.
+ class BytestreamParser
+ {
+ class h__BytestreamParser;
+ mem_ptr<h__BytestreamParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(BytestreamParser);
+
+ public:
+ BytestreamParser();
+ virtual ~BytestreamParser();
+
+ // Opens a file for reading, parses enough data to provide a complete
+ // set of stream metadata for the MXFWriter below.
+ // The frame buffer's PlaintextOffset parameter will be set to the first
+ // byte of the data segment. Set this value to zero if you want
+ // encrypted headers.
+ Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
+
+ // Fill a DCDataDescriptor struct with the values from the file's bytestream.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
+ };
+
+ // An object which reads a sequence of files containing DC Data.
+ class SequenceParser
+ {
+ class h__SequenceParser;
+ mem_ptr<h__SequenceParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
+
+ public:
+ SequenceParser();
+ virtual ~SequenceParser();
+
+ // Opens a directory for reading. The directory is expected to contain one or
+ // more files, each containing the bytestream for exactly one frame. The files
+ // must be named such that the frames are in temporal order when sorted
+ // alphabetically by filename.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Opens a file sequence for reading. The sequence is expected to contain one or
+ // more filenames, each naming a file containing the bytestream for exactly one
+ // frame.
+ Result_t OpenRead(const std::list<std::string>& file_list) const;
+
+ // Fill a DCDataDescriptor struct with default values.
+ // Returns RESULT_INIT if the directory is not open.
+ Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
+
+ // Rewind the directory to the beginning.
+ Result_t Reset() const;
+
+ // Reads the next sequential frame in the directory and places it in the
+ // frame buffer. Fails if the buffer is too small or the direcdtory
+ // contains no more files.
+ // The frame buffer's PlaintextOffset parameter will be set to the first
+ // byte of the data segment. Set this value to zero if you want
+ // encrypted headers.
+ Result_t ReadFrame(FrameBuffer&) const;
+ };
+
+ //
+ class MXFWriter
+ {
+ class h__Writer;
+ mem_ptr<h__Writer> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const std::string& filename, const WriterInfo&,
+ const DCDataDescriptor&, ui32_t HeaderSize = 16384);
+
+ // 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.
+ Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // Closes the MXF file, writing the index and revised header.
+ Result_t Finalize();
+ };
+
+ //
+ class MXFReader
+ {
+ class h__Reader;
+ mem_ptr<h__Reader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+ MXFReader();
+ virtual ~MXFReader();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill a DCDataDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Using the index table read from the footer partition, lookup the frame number
+ // and return the offset into the file at which to read that frame of essence.
+ // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
+ // out of range.
+ Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+
+ } // namespace DCData
+
+ //---------------------------------------------------------------------------------
+ //
+ namespace ATMOS
+ {
+ struct AtmosDescriptor : public DCData::DCDataDescriptor
+ {
+ ui32_t FirstFrame; // Frame number of the frame to align with the FFOA of the picture track
+ ui16_t MaxChannelCount; // Max number of channels in bitstream
+ ui16_t MaxObjectCount; // Max number of objects in bitstream
+ byte_t AtmosID[UUIDlen]; // UUID of Atmos Project
+ ui8_t AtmosVersion; // ATMOS Coder Version used to create bitstream
+ };
+
+ // Print AtmosDescriptor to std::ostream
+ std::ostream& operator << (std::ostream& strm, const AtmosDescriptor& adesc);
+ // Print debugging information to stream (stderr default)
+ void AtmosDescriptorDump(const AtmosDescriptor&, FILE* = 0);
+ // Determine if a file is a raw atmos file
+ bool IsDolbyAtmos(const std::string& filename);
+
+ //
+ class MXFWriter
+ {
+
+ class h__Writer;
+ mem_ptr<h__Writer> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const std::string& filename, const WriterInfo&,
+ const AtmosDescriptor&, ui32_t HeaderSize = 16384);
+
+ // 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.
+ Result_t WriteFrame(const DCData::FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // Closes the MXF file, writing the index and revised header.
+ Result_t Finalize();
+ };
+
+ //
+ class MXFReader
+ {
+ class h__Reader;
+ mem_ptr<h__Reader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+ MXFReader();
+ virtual ~MXFReader();
+
+ // Warning: direct manipulation of MXF structures can interfere
+ // with the normal operation of the wrapper. Caveat emptor!
+ virtual MXF::OP1aHeader& OP1aHeader();
+ virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
+ virtual MXF::RIP& RIP();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const std::string& filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill an AtmosDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillAtmosDescriptor(AtmosDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, DCData::FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Using the index table read from the footer partition, lookup the frame number
+ // and return the offset into the file at which to read that frame of essence.
+ // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
+ // out of range.
+ Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+
+ } // namespace ATMOS
+
+
+
+} // namespace ASDCP
+
+
+#endif // _AS_DCP_H_
+
+//
+// end AS_DCP.h
+//
diff --git a/src/asdcp/KM_error.h b/src/asdcp/KM_error.h
new file mode 100755
index 0000000..8270cc0
--- /dev/null
+++ b/src/asdcp/KM_error.h
@@ -0,0 +1,194 @@
+/*
+Copyright (c) 2004-2015, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file KM_error.h
+ \version $Id$
+ \brief error reporting support
+ */
+
+
+
+#ifndef _KM_ERROR_H_
+#define _KM_ERROR_H_
+
+#include <string>
+
+#define KM_DECLARE_RESULT(sym, i, l) const Result_t RESULT_##sym = Result_t(i, #sym, l);
+
+namespace Kumu
+{
+ // Result code container. Both a signed integer and a text string are stored in the object.
+ // When defining your own codes your choice of integer values is mostly unconstrained, but pay
+ // attention to the numbering in the other libraries that use Kumu. Values between -99 and 99
+ // are reserved for Kumu.
+
+ class Result_t
+ {
+ int value;
+ std::string label, symbol, message;
+ Result_t();
+
+ public:
+ // Return registered Result_t for the given "value" code.
+ static const Result_t& Find(int value);
+
+ // Unregister the Result_t matching the given "value" code. Returns
+ // RESULT_FALSE if "value" does not match a registered Result_t.
+ // Returns RESULT_FAIL if ( value < -99 || value > 99 ) (Kumu core
+ // codes may not be deleted).
+ static Result_t Delete(int value);
+
+ // Iteration through registered result codes, not thread safe.
+ // Get accepts contiguous values from 0 to End() - 1.
+ static unsigned int End();
+ static const Result_t& Get(unsigned int);
+
+ Result_t(int v, const std::string& s, const std::string& l);
+ Result_t(const Result_t& rhs);
+ const Result_t& operator=(const Result_t& rhs);
+ ~Result_t();
+
+ const Result_t operator()(const std::string& message) const;
+ const Result_t operator()(const int& line, const char* filename) const;
+ const Result_t operator()(const std::string& message, const int& line, const char* filename) const;
+
+ inline bool operator==(const Result_t& rhs) const { return value == rhs.value; }
+ inline bool operator!=(const Result_t& rhs) const { return value != rhs.value; }
+ inline bool Success() const { return ! ( value < 0 ); }
+ inline bool Failure() const { return ( value < 0 ); }
+
+ inline int Value() const { return value; }
+ inline operator int() const { return value; }
+ inline const char* Label() const { return label.c_str(); }
+ inline operator const char*() const { return label.c_str(); }
+ inline const char* Symbol() const { return symbol.c_str(); }
+ inline const char* Message() const { return message.c_str(); }
+ };
+
+ KM_DECLARE_RESULT(FALSE, 1, "Successful but not true.");
+ KM_DECLARE_RESULT(OK, 0, "Success.");
+ KM_DECLARE_RESULT(FAIL, -1, "An undefined error was detected.");
+ KM_DECLARE_RESULT(PTR, -2, "An unexpected NULL pointer was given.");
+ KM_DECLARE_RESULT(NULL_STR, -3, "An unexpected empty string was given.");
+ KM_DECLARE_RESULT(ALLOC, -4, "Error allocating memory.");
+ KM_DECLARE_RESULT(PARAM, -5, "Invalid parameter.");
+ KM_DECLARE_RESULT(NOTIMPL, -6, "Unimplemented Feature.");
+ KM_DECLARE_RESULT(SMALLBUF, -7, "The given buffer is too small.");
+ KM_DECLARE_RESULT(INIT, -8, "The object is not yet initialized.");
+ KM_DECLARE_RESULT(NOT_FOUND, -9, "The requested file does not exist on the system.");
+ KM_DECLARE_RESULT(NO_PERM, -10, "Insufficient privilege exists to perform the operation.");
+ KM_DECLARE_RESULT(STATE, -11, "Object state error.");
+ KM_DECLARE_RESULT(CONFIG, -12, "Invalid configuration option detected.");
+ KM_DECLARE_RESULT(FILEOPEN, -13, "File open failure.");
+ KM_DECLARE_RESULT(BADSEEK, -14, "An invalid file location was requested.");
+ KM_DECLARE_RESULT(READFAIL, -15, "File read error.");
+ KM_DECLARE_RESULT(WRITEFAIL, -16, "File write error.");
+ KM_DECLARE_RESULT(ENDOFFILE, -17, "Attempt to read past end of file.");
+ KM_DECLARE_RESULT(FILEEXISTS, -18, "Filename already exists.");
+ KM_DECLARE_RESULT(NOTAFILE, -19, "Filename not found.");
+ KM_DECLARE_RESULT(UNKNOWN, -20, "Unknown result code.");
+ KM_DECLARE_RESULT(DIR_CREATE, -21, "Unable to create directory.");
+ KM_DECLARE_RESULT(NOT_EMPTY, -22, "Unable to delete non-empty directory.");
+ // 23-100 are reserved
+
+} // namespace Kumu
+
+//--------------------------------------------------------------------------------
+// convenience macros
+
+// Convenience macros for managing return values in predicates
+# define KM_SUCCESS(v) (((v) < 0) ? 0 : 1)
+# define KM_FAILURE(v) (((v) < 0) ? 1 : 0)
+
+
+// Returns RESULT_PTR if the given argument is NULL.
+// See Result_t above for an explanation of RESULT_* symbols.
+# define KM_TEST_NULL(p) \
+ if ( (p) == 0 ) { \
+ return Kumu::RESULT_PTR(__LINE__, __FILE__); \
+ }
+
+// Returns RESULT_PTR if the given argument is NULL. See Result_t
+// in WaimeaCore for an explanation of RESULT_* symbols. It then assumes
+// that the argument is a pointer to a string and returns
+// RESULT_NULL_STR if the first character is '\0'.
+//
+# define KM_TEST_NULL_STR(p) \
+ KM_TEST_NULL(p); \
+ if ( (p)[0] == '\0' ) { \
+ return Kumu::RESULT_NULL_STR(__LINE__, __FILE__); \
+ }
+
+// RESULT_STATE is ambiguous. Use these everywhere it is assigned to provide some context
+#define KM_RESULT_STATE_TEST_IMPLICIT() \
+ if ( result == Kumu::RESULT_STATE ) { \
+ Kumu::DefaultLogSink().Error("RESULT_STATE RETURNED at %s (%d)\n", __FILE__, __LINE__); \
+ }
+
+#define KM_RESULT_STATE_TEST_THIS(_this__r_) \
+ if ( _this__r_ == Kumu::RESULT_STATE ) { \
+ Kumu::DefaultLogSink().Error("RESULT_STATE RETURNED at %s (%d)\n", __FILE__, __LINE__); \
+ }
+
+#define KM_RESULT_STATE_HERE() \
+ Kumu::DefaultLogSink().Error("RESULT_STATE RETURNED at %s (%d)\n", __FILE__, __LINE__);
+
+
+
+namespace Kumu
+{
+ // simple tracing mechanism
+ class DTrace_t
+ {
+ DTrace_t();
+
+ protected:
+ const char* m_Label;
+ Result_t* m_Watch;
+ int m_Line;
+ const char* m_File;
+ int m_Sequence;
+
+ public:
+ DTrace_t(const char* Label, Result_t* Watch, int Line, const char* File);
+ ~DTrace_t();
+ };
+}
+
+#ifdef KM_TRACE
+#define WDTRACE(l) DTrace_t __wl__Trace__((l), 0, __LINE__, __FILE__)
+#define WDTRACER(l,r) DTrace_t __wl__Trace__((l), &(r), __LINE__, __FILE__)
+#else
+#define WDTRACE(l)
+#define WDTRACER(l,r)
+#endif
+
+
+#endif // _KM_ERROR_H_
+
+//
+// end KM_error.h
+//
diff --git a/src/asdcp/KM_fileio.h b/src/asdcp/KM_fileio.h
new file mode 100755
index 0000000..1fab636
--- /dev/null
+++ b/src/asdcp/KM_fileio.h
@@ -0,0 +1,388 @@
+/*
+Copyright (c) 2004-2014, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file KM_fileio.h
+ \version $Id$
+ \brief portable file i/o
+ */
+
+#ifndef _KM_FILEIO_H_
+#define _KM_FILEIO_H_
+
+#include <asdcp/KM_util.h>
+#include <string>
+#include <boost/filesystem.hpp>
+#include <openssl/md5.h>
+
+#ifdef KM_WIN32
+# include <io.h>
+#else
+# include <dirent.h>
+# include <unistd.h>
+# include <time.h>
+# include <sys/types.h>
+#include <regex.h>
+#endif
+
+#include <sys/stat.h>
+
+
+
+namespace Kumu
+{
+ class DirScanner
+ {
+ public:
+ DirScanner();
+ Result_t Open(const std::string&);
+ Result_t GetNext(char*);
+ Result_t Close();
+ private:
+ boost::filesystem::directory_iterator _iterator;
+ };
+
+
+ //
+ enum DirectoryEntryType_t {
+ DET_FILE,
+ DET_DIR,
+ DET_DEV,
+ DET_LINK
+ };
+
+ //
+ class DirScannerEx
+ {
+ std::string m_Dirname;
+#ifdef KM_WIN32
+ __int64 m_Handle;
+ struct _finddatai64_t m_FileInfo;
+#else
+ DIR* m_Handle;
+#endif
+
+ KM_NO_COPY_CONSTRUCT(DirScannerEx);
+
+ public:
+
+ DirScannerEx();
+ ~DirScannerEx() { Close(); }
+
+ Result_t Open(const std::string& dirname);
+ Result_t Close();
+
+
+ inline Result_t GetNext(std::string& next_item_name) {
+ DirectoryEntryType_t ft;
+ return GetNext(next_item_name, ft);
+ }
+
+ Result_t GetNext(std::string& next_item_name, DirectoryEntryType_t& next_item_type);
+ };
+
+#ifdef KM_WIN32
+ typedef __int64 fsize_t;
+ typedef __int64 fpos_t;
+ typedef HANDLE FileHandle;
+
+ enum SeekPos_t {
+ SP_BEGIN = FILE_BEGIN,
+ SP_POS = FILE_CURRENT,
+ SP_END = FILE_END
+ };
+#else
+ typedef off_t fsize_t;
+ typedef off_t fpos_t;
+ typedef int FileHandle;
+ const FileHandle INVALID_HANDLE_VALUE = -1L;
+
+ enum SeekPos_t {
+ SP_BEGIN = SEEK_SET,
+ SP_POS = SEEK_CUR,
+ SP_END = SEEK_END
+ };
+#endif
+
+ //
+#ifndef KM_SMALL_FILES_OK
+ template <bool sizecheck> void compile_time_size_checker();
+ template <> inline void compile_time_size_checker<false>() {}
+ //
+ // READ THIS if your compiler is complaining about a previously declared implementation of
+ // compile_time_size_checker(). For example, GCC 4.0.1 looks like this:
+ //
+ // error: 'void Kumu::compile_time_size_checker() [with bool sizecheck = false]' previously declared here
+ //
+ // This is happening because the equality being tested below is false. The reason for this
+ // will depend on your OS, but on Linux it is probably because you have not used -D_FILE_OFFSET_BITS=64
+ // Adding this magic macro to your CFLAGS will get you going again. If you are on a system that
+ // does not support 64-bit files, you can disable this check by using -DKM_SMALL_FILES_OK. You
+ // will then of course be limited to file sizes < 4GB.
+ //
+ template <> inline void compile_time_size_checker<sizeof(Kumu::fsize_t)==sizeof(ui64_t)>() {}
+#endif
+ //
+
+ const ui32_t Kilobyte = 1024;
+ const ui32_t Megabyte = Kilobyte * Kilobyte;
+ const ui32_t Gigabyte = Megabyte * Kilobyte;
+
+ const ui32_t MaxFilePath = Kilobyte;
+
+
+ //------------------------------------------------------------------------------------------
+ // Path Manglers
+ //------------------------------------------------------------------------------------------
+
+ // types
+ typedef std::list<std::string> PathCompList_t; // a list of path components
+ typedef std::list<std::string> PathList_t; // a list of paths
+
+ // tests
+ bool PathExists(const std::string& Path); // true if the path exists in the filesystem
+ bool PathIsFile(const std::string& Path); // true if the path exists in the filesystem and is a file
+ bool PathIsDirectory(const std::string& Path); // true if the path exists in the filesystem and is a directory
+ fsize_t FileSize(const std::string& Path); // returns the size of a regular file, 0 for a directory or device
+ std::string PathCwd();
+ bool PathsAreEquivalent(const std::string& lhs, const std::string& rhs); // true if paths point to the same filesystem entry
+
+ // Returns free space and total space available for the given path
+ Result_t FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space);
+
+ // split and reassemble paths as lists of path components
+ PathCompList_t& PathToComponents(const std::string& Path, PathCompList_t& CList, char separator = '/'); // removes '//'
+ std::string ComponentsToPath(const PathCompList_t& CList, char separator = '/');
+ std::string ComponentsToAbsolutePath(const PathCompList_t& CList, char separator = '/'); // add separator to the front
+ bool PathHasComponents(const std::string& Path, char separator = '/'); // true if paths starts with separator
+
+ bool PathIsAbsolute(const std::string& Path, char separator = '/'); // true if path begins with separator
+ std::string PathMakeAbsolute(const std::string& Path, char separator = '/'); // compute position of relative path using getcwd()
+ std::string PathMakeLocal(const std::string& Path, const std::string& Parent); // remove Parent from front of Path, if it exists
+ std::string PathMakeCanonical(const std::string& Path, char separator = '/'); // remove '.' and '..'
+ bool PathResolveLinks(const std::string& link_path, std::string& resolved_path, char separator = '/');
+
+ // common operations
+ std::string PathBasename(const std::string& Path, char separator = '/'); // returns right-most path element (list back())
+ std::string PathDirname(const std::string& Path, char separator = '/'); // returns everything but the right-most element
+ std::string PathGetExtension(const std::string& Path); // returns everything in the right-most element following the right-most '.'
+ std::string PathSetExtension(const std::string& Path, const std::string& Extension); // empty extension removes '.' as well
+
+ std::string PathJoin(const std::string& Path1, const std::string& Path2, char separator = '/');
+ std::string PathJoin(const std::string& Path1, const std::string& Path2, const std::string& Path3, char separator = '/');
+ std::string PathJoin(const std::string& Path1, const std::string& Path2,
+ const std::string& Path3, const std::string& Path4, char separator = '/');
+
+
+ //------------------------------------------------------------------------------------------
+ // Path Search
+ //------------------------------------------------------------------------------------------
+
+ // An interface for a path matching function, used by FindInPath() and FindInPaths() below
+ //
+ class IPathMatch
+ {
+ public:
+ virtual ~IPathMatch() {}
+ virtual bool Match(const std::string& s) const = 0;
+ };
+
+ // matches any pathname
+ class PathMatchAny : public IPathMatch
+ {
+ public:
+ virtual ~PathMatchAny() {}
+ inline bool Match(const std::string&) const { return true; }
+ };
+
+#ifndef KM_WIN32
+ // matches pathnames using a regular expression
+ class PathMatchRegex : public IPathMatch
+ {
+ regex_t m_regex;
+ PathMatchRegex();
+ const PathMatchRegex& operator=(const PathMatchRegex&);
+
+ public:
+ PathMatchRegex(const std::string& Pattern);
+ PathMatchRegex(const PathMatchRegex&);
+ virtual ~PathMatchRegex();
+ bool Match(const std::string& s) const;
+ };
+
+ // matches pathnames using a Bourne shell glob expression
+ class PathMatchGlob : public IPathMatch
+ {
+ regex_t m_regex;
+ PathMatchGlob();
+ const PathMatchGlob& operator=(const PathMatchGlob&);
+
+ public:
+ PathMatchGlob(const std::string& Pattern);
+ PathMatchGlob(const PathMatchGlob&);
+ virtual ~PathMatchGlob();
+ bool Match(const std::string& s) const;
+ };
+#endif /* !KM_WIN32 */
+
+ // Search all paths in SearchPaths for filenames matching Pattern (no directories are returned).
+ // Put results in FoundPaths. Returns after first find if one_shot is true.
+ PathList_t& FindInPath(const IPathMatch& Pattern, const std::string& SearchDir,
+ PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
+
+ PathList_t& FindInPaths(const IPathMatch& Pattern, const PathList_t& SearchPaths,
+ PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
+
+ std::string GetExecutablePath(const std::string& default_path);
+
+ //------------------------------------------------------------------------------------------
+ // Directory Manipulation
+ //------------------------------------------------------------------------------------------
+
+ // Create a directory, creates intermediate directories as necessary
+ Result_t CreateDirectoriesInPath(const std::string& Path);
+
+ // Delete a file (fails if the path points to a directory)
+ Result_t DeleteFile(const std::string& filename);
+
+ // Recursively remove a file or directory
+ Result_t DeletePath(const std::string& pathname);
+
+ // Remove the path only if it is a directory that is empty.
+ Result_t DeleteDirectoryIfEmpty(const std::string& path);
+
+ //------------------------------------------------------------------------------------------
+ // File I/O Wrappers
+ //------------------------------------------------------------------------------------------
+
+ // Instant IO for strings
+ //
+ // Reads an entire file into a string.
+ Result_t ReadFileIntoString(const std::string& filename, std::string& outString, ui32_t max_size = 8 * Megabyte);
+
+ // Writes a string to a file, overwrites the existing file if present.
+ Result_t WriteStringIntoFile(const std::string& filename, const std::string& inString);
+
+ // Instant IO for archivable objects
+ //
+ // Unarchives a file into an object
+ Result_t ReadFileIntoObject(const std::string& Filename, IArchive& Object, ui32_t max_size = 8 * Kumu::Megabyte);
+
+ // Archives an object into a file
+ Result_t WriteObjectIntoFile(const IArchive& Object, const std::string& Filename);
+
+ // Instant IO for memory buffers
+ //
+ // Unarchives a file into a buffer
+ Result_t ReadFileIntoBuffer(const std::string& Filename, Kumu::ByteString& Buffer,
+ ui32_t max_size = 8 * Kumu::Megabyte);
+
+ // Archives a buffer into a file
+ Result_t WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Filename);
+
+
+ //------------------------------------------------------------------------------------------
+ // File I/O
+ //------------------------------------------------------------------------------------------
+
+ //
+ class FileReader
+ {
+ KM_NO_COPY_CONSTRUCT(FileReader);
+
+ protected:
+ std::string m_Filename;
+ FileHandle m_Handle;
+
+ public:
+ FileReader() : m_Handle(INVALID_HANDLE_VALUE) {}
+ virtual ~FileReader() { Close(); }
+
+ Result_t OpenRead(const std::string&) const; // open the file for reading
+ Result_t Close() const; // close the file
+ fsize_t Size() const; // returns the file's current size
+ Result_t Seek(Kumu::fpos_t = 0, SeekPos_t = SP_BEGIN) const; // move the file pointer
+ Result_t Tell(Kumu::fpos_t* pos) const; // report the file pointer's location
+ Result_t Read(byte_t*, ui32_t, ui32_t* = 0) const; // read a buffer of data
+
+ inline Kumu::fpos_t Tell() const // report the file pointer's location
+ {
+ Kumu::fpos_t tmp_pos;
+ Tell(&tmp_pos);
+ return tmp_pos;
+ }
+
+ inline bool IsOpen() { // returns true if the file is open
+ return (m_Handle != INVALID_HANDLE_VALUE);
+ }
+ };
+
+ //
+ class FileWriter : public FileReader
+ {
+ class h__iovec;
+ mem_ptr<h__iovec> m_IOVec;
+ KM_NO_COPY_CONSTRUCT(FileWriter);
+ bool m_Hashing;
+ MD5_CTX m_MD5Context;
+
+ public:
+ FileWriter();
+ virtual ~FileWriter();
+
+ Result_t OpenWrite(const std::string&); // open a new file, overwrites existing
+ Result_t OpenModify(const std::string&); // open a file for read/write
+
+ // this part of the interface takes advantage of the iovec structure on
+ // platforms that support it. For each call to Writev(const byte_t*, ui32_t, ui32_t*),
+ // the given buffer is added to an internal iovec struct. All items on the list
+ // are written to disk by a call to Writev();
+ Result_t Writev(const byte_t*, ui32_t); // queue buffer for "gather" write
+ Result_t Writev(ui32_t* = 0); // write all queued buffers
+
+ // if you call this while there are unwritten items on the iovec list,
+ // the iovec list will be written to disk before the given buffer,as though
+ // you had called Writev() first.
+ Result_t Write(const byte_t*, ui32_t, ui32_t* = 0); // write buffer to disk
+
+ void StartHashing();
+ void MaybeHash(void const *, int);
+ std::string StopHashing();
+ };
+
+ Result_t CreateDirectoriesInPath(const std::string& Path);
+ Result_t FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space);
+ Result_t DeleteFile(const std::string& filename);
+ Result_t DeletePath(const std::string& pathname);
+
+} // namespace Kumu
+
+
+#endif // _KM_FILEIO_H_
+
+
+//
+// end KM_fileio.h
+//
diff --git a/src/asdcp/KM_memio.h b/src/asdcp/KM_memio.h
new file mode 100755
index 0000000..557b868
--- /dev/null
+++ b/src/asdcp/KM_memio.h
@@ -0,0 +1,254 @@
+/*
+Copyright (c) 2006-2011, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file KM_memio.h
+ \version $Id$
+ \brief abstraction for byte-oriented conversion of integers and objects
+ */
+
+#ifndef _KM_MEMIO_H_
+#define _KM_MEMIO_H_
+
+#include <asdcp/KM_platform.h>
+#include <string>
+#include <cstring>
+
+namespace Kumu
+{
+ class ByteString;
+
+ //
+ class MemIOWriter
+ {
+ KM_NO_COPY_CONSTRUCT(MemIOWriter);
+ MemIOWriter();
+
+ protected:
+ byte_t* m_p;
+ ui32_t m_capacity;
+ ui32_t m_size;
+
+ public:
+ MemIOWriter(byte_t* p, ui32_t c) : m_p(p), m_capacity(c), m_size(0) {
+ assert(m_p); assert(m_capacity);
+ }
+
+ MemIOWriter(ByteString* Buf);
+ ~MemIOWriter() {}
+
+ inline void Reset() { m_size = 0; }
+ inline byte_t* Data() { return m_p; }
+ inline const byte_t* RoData() const { return m_p; }
+ inline byte_t* CurrentData() { return m_p + m_size; }
+ inline ui32_t Length() const { return m_size; }
+ inline ui32_t Remainder() const { return m_capacity - m_size; }
+
+ inline bool AddOffset(ui32_t offset) {
+ if ( ( m_size + offset ) > m_capacity )
+ return false;
+
+ m_size += offset;
+ return true;
+
+ }
+
+ inline bool WriteRaw(const byte_t* p, ui32_t buf_len) {
+ if ( ( m_size + buf_len ) > m_capacity )
+ return false;
+
+ memcpy(m_p + m_size, p, buf_len);
+ m_size += buf_len;
+ return true;
+ }
+
+ bool WriteBER(ui64_t i, ui32_t ber_len);
+
+ inline bool WriteUi8(ui8_t i) {
+ if ( ( m_size + 1 ) > m_capacity )
+ return false;
+
+ *(m_p + m_size) = i;
+ m_size++;
+ return true;
+ }
+
+ inline bool WriteUi16BE(ui16_t i) {
+ if ( ( m_size + sizeof(ui16_t) ) > m_capacity )
+ return false;
+
+ i2p<ui16_t>(KM_i16_BE(i), m_p + m_size);
+ m_size += sizeof(ui16_t);
+ return true;
+ }
+
+ inline bool WriteUi32BE(ui32_t i) {
+ if ( ( m_size + sizeof(ui32_t) ) > m_capacity )
+ return false;
+
+ i2p<ui32_t>(KM_i32_BE(i), m_p + m_size);
+ m_size += sizeof(ui32_t);
+ return true;
+ }
+
+ inline bool WriteUi64BE(ui64_t i) {
+ if ( ( m_size + sizeof(ui64_t) ) > m_capacity )
+ return false;
+
+ i2p<ui64_t>(KM_i64_BE(i), m_p + m_size);
+ m_size += sizeof(ui64_t);
+ return true;
+ }
+
+ inline bool WriteString(const std::string& str) {
+ ui32_t len = static_cast<ui32_t>(str.length());
+ if ( ! WriteUi32BE(len) ) return false;
+ if ( ! WriteRaw((const byte_t*)str.c_str(), len) ) return false;
+ return true;
+ }
+ };
+
+ //
+ class MemIOReader
+ {
+ KM_NO_COPY_CONSTRUCT(MemIOReader);
+ MemIOReader();
+
+ protected:
+ const byte_t* m_p;
+ ui32_t m_capacity;
+ ui32_t m_size; // this is sort of a misnomer, when we are reading it measures offset
+
+ public:
+ MemIOReader(const byte_t* p, ui32_t c) :
+ m_p(p), m_capacity(c), m_size(0) {
+ assert(m_p); assert(m_capacity);
+ }
+
+ MemIOReader(const ByteString* Buf);
+ ~MemIOReader() {}
+
+ inline void Reset() { m_size = 0; }
+ inline const byte_t* Data() const { return m_p; }
+ inline const byte_t* CurrentData() const { return m_p + m_size; }
+ inline ui32_t Offset() const { return m_size; }
+ inline ui32_t Remainder() const { return m_capacity - m_size; }
+
+ inline bool SkipOffset(ui32_t offset) {
+ if ( ( m_size + offset ) > m_capacity )
+ return false;
+
+ m_size += offset;
+ return true;
+ }
+
+ inline bool ReadRaw(byte_t* p, ui32_t buf_len) {
+ if ( ( m_size + buf_len ) > m_capacity )
+ return false;
+
+ memcpy(p, m_p + m_size, buf_len);
+ m_size += buf_len;
+ return true;
+ }
+
+ bool ReadBER(ui64_t* i, ui32_t* ber_len);
+
+ inline bool ReadUi8(ui8_t* i) {
+ assert(i);
+ if ( ( m_size + 1 ) > m_capacity )
+ return false;
+
+ *i = *(m_p + m_size);
+ m_size++;
+ return true;
+ }
+
+ inline bool ReadUi16BE(ui16_t* i) {
+ assert(i);
+ if ( ( m_size + sizeof(ui16_t) ) > m_capacity )
+ return false;
+
+ *i = KM_i16_BE(cp2i<ui16_t>(m_p + m_size));
+ m_size += sizeof(ui16_t);
+ return true;
+ }
+
+ inline bool ReadUi32BE(ui32_t* i) {
+ assert(i);
+ if ( ( m_size + sizeof(ui32_t) ) > m_capacity )
+ return false;
+
+ *i = KM_i32_BE(cp2i<ui32_t>(m_p + m_size));
+ m_size += sizeof(ui32_t);
+ return true;
+ }
+
+ inline bool ReadUi64BE(ui64_t* i) {
+ assert(i);
+ if ( ( m_size + sizeof(ui64_t) ) > m_capacity )
+ return false;
+
+ *i = KM_i64_BE(cp2i<ui64_t>(m_p + m_size));
+ m_size += sizeof(ui64_t);
+ return true;
+ }
+
+ inline bool ReadString(std::string& str)
+ {
+ ui32_t str_length = 0;
+ if ( ! ReadUi32BE(&str_length) ) return false;
+
+ if ( str_length > 0 )
+ {
+ if ( ( m_size + str_length ) > m_capacity ) return false;
+ str.assign((const char*)CurrentData(), str_length);
+ if ( ! SkipOffset(str_length) ) return false;
+ }
+
+ return true;
+ }
+ };
+
+ //
+ inline bool
+ UnarchiveString(MemIOReader& Reader, std::string& str) {
+ return Reader.ReadString(str);
+ }
+
+ //
+ inline bool
+ ArchiveString(MemIOWriter& Writer, const std::string& str)
+ {
+ return Writer.WriteString(str);
+ }
+
+
+} // namespace Kumu
+
+#endif // _KM_MEMIO_H_
+
+//
+// end KM_memio.h
+//
diff --git a/src/asdcp/KM_platform.h b/src/asdcp/KM_platform.h
new file mode 100644
index 0000000..defcd8a
--- /dev/null
+++ b/src/asdcp/KM_platform.h
@@ -0,0 +1,247 @@
+/*
+Copyright (c) 2004-2015, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file KM_platform.h
+ \version $Id$
+ \brief platform portability
+ */
+
+#ifndef _KM_PLATFORM_H_
+# define _KM_PLATFORM_H_
+
+#if defined(__APPLE__) && defined(__MACH__)
+# define KM_MACOSX
+# ifdef __BIG_ENDIAN__
+# define KM_BIG_ENDIAN
+# endif
+# endif
+
+# ifdef KM_WIN32
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# include <windows.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <stdarg.h>
+# pragma warning(disable:4786) // Ignore "identifer > 255 characters" warning
+
+typedef unsigned __int64 ui64_t;
+typedef __int64 i64_t;
+# define i64_C(c) (i64_t)(c)
+# define ui64_C(c) (ui64_t)(c)
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+
+# else // KM_WIN32
+typedef unsigned long long ui64_t;
+typedef long long i64_t;
+# define i64_C(c) c##LL
+# define ui64_C(c) c##ULL
+
+# endif // KM_WIN32
+
+# include <stdio.h>
+# include <assert.h>
+# include <stdlib.h>
+# include <limits.h>
+
+typedef unsigned char byte_t;
+typedef char i8_t;
+typedef unsigned char ui8_t;
+typedef short i16_t;
+typedef unsigned short ui16_t;
+typedef int i32_t;
+typedef unsigned int ui32_t;
+
+
+namespace Kumu
+{
+ inline ui16_t Swap2(ui16_t i)
+ {
+ return ( (i << 8) | (( i & 0xff00) >> 8) );
+ }
+
+ inline ui32_t Swap4(ui32_t i)
+ {
+ return
+ ( (i & 0x000000ffUL) << 24 ) |
+ ( (i & 0xff000000UL) >> 24 ) |
+ ( (i & 0x0000ff00UL) << 8 ) |
+ ( (i & 0x00ff0000UL) >> 8 );
+ }
+
+ inline ui64_t Swap8(ui64_t i)
+ {
+ return
+ ( (i & ui64_C(0x00000000000000FF)) << 56 ) |
+ ( (i & ui64_C(0xFF00000000000000)) >> 56 ) |
+ ( (i & ui64_C(0x000000000000FF00)) << 40 ) |
+ ( (i & ui64_C(0x00FF000000000000)) >> 40 ) |
+ ( (i & ui64_C(0x0000000000FF0000)) << 24 ) |
+ ( (i & ui64_C(0x0000FF0000000000)) >> 24 ) |
+ ( (i & ui64_C(0x00000000FF000000)) << 8 ) |
+ ( (i & ui64_C(0x000000FF00000000)) >> 8 );
+ }
+
+ //
+ template<class T>
+ inline T xmin(T lhs, T rhs) {
+ return (lhs < rhs) ? lhs : rhs;
+ }
+
+ //
+ template<class T>
+ inline T xmax(T lhs, T rhs) {
+ return (lhs > rhs) ? lhs : rhs;
+ }
+
+ //
+ template<class T>
+ inline T xclamp(T v, T l, T h) {
+ if ( v < l ) { return l; }
+ if ( v > h ) { return h; }
+ return v;
+ }
+
+ //
+ template<class T>
+ inline T xabs(T n) {
+ if ( n < 0 ) { return -n; }
+ return n;
+ }
+
+ // read an integer from byte-structured storage
+ template<class T>
+ inline T cp2i(const byte_t* p) { return *(T*)p; }
+
+ // write an integer to byte-structured storage
+ template<class T>
+ inline void i2p(T i, byte_t* p) { *(T*)p = i; }
+
+
+# ifdef KM_BIG_ENDIAN
+# define KM_i16_LE(i) Kumu::Swap2(i)
+# define KM_i32_LE(i) Kumu::Swap4(i)
+# define KM_i64_LE(i) Kumu::Swap8(i)
+# define KM_i16_BE(i) (i)
+# define KM_i32_BE(i) (i)
+# define KM_i64_BE(i) (i)
+# else
+# define KM_i16_LE(i) (i)
+# define KM_i32_LE(i) (i)
+# define KM_i64_LE(i) (i)
+# define KM_i16_BE(i) Kumu::Swap2(i)
+# define KM_i32_BE(i) Kumu::Swap4(i)
+# define KM_i64_BE(i) Kumu::Swap8(i)
+# endif // KM_BIG_ENDIAN
+
+ // A non-reference counting, auto-delete container for internal
+ // member object pointers.
+ template <class T>
+ class mem_ptr
+ {
+ mem_ptr(T&);
+
+ protected:
+ T* m_p; // the thing we point to
+
+ public:
+ mem_ptr() : m_p(0) {}
+ mem_ptr(T* p) : m_p(p) {}
+ ~mem_ptr() { delete m_p; }
+
+ inline T& operator*() const { return *m_p; }
+ inline T* operator->() const { assert(m_p!=0); return m_p; }
+ inline operator T*()const { return m_p; }
+ inline const mem_ptr<T>& operator=(T* p) { this->set(p); return *this; }
+ inline T* set(T* p) { delete m_p; m_p = p; return m_p; }
+ inline T* get() const { return m_p; }
+ inline void release() { m_p = 0; }
+ inline bool empty() const { return m_p == 0; }
+ };
+
+} // namespace Kumu
+
+// Produces copy constructor boilerplate. Allows convenient private
+// declatarion of copy constructors to prevent the compiler from
+// silently manufacturing default methods.
+# define KM_NO_COPY_CONSTRUCT(T) \
+ T(const T&); \
+ T& operator=(const T&)
+
+/*
+// Example
+ class foo
+ {
+ KM_NO_COPY_CONSTRUCT(foo); // accessing private mthods will cause compile time error
+ public:
+ // ...
+ };
+*/
+
+// Produces copy constructor boilerplate. Implements
+// copy and assignment, see example below
+# define KM_EXPLICIT_COPY_CONSTRUCT(T) \
+ T(const T&); \
+ const T& operator=(const T&)
+
+# define KM_EXPLICIT_COPY_CONSTRUCT_IMPL_START(N, T) \
+ void T##_copy_impl(N::T& lhs, const N::T& rhs) \
+ {
+
+#define KM_COPY_ITEM(I) lhs.I = rhs.I;
+
+# define KM_EXPLICIT_COPY_CONSTRUCT_IMPL_END(N, T) \
+ } \
+ N::T::T(const N::T& rhs) { T##_copy_impl(*this, rhs); } \
+ const N::T& N::T::operator=(const N::T& rhs) { T##_copy_impl(*this, rhs); return *this; }
+
+/*
+// Example
+namespace bar {
+ class foo
+ {
+ public:
+ std::string param_a;
+ int param_b;
+
+ KM_EXPLICIT_COPY_CONSTRUCT(foo);
+ // ...
+ };
+}
+
+//
+KM_EXPLICIT_COPY_CONSTRUCT_IMPL_START(bar, foo)
+KM_COPY_ITEM(param_a)
+KM_COPY_ITEM(param_b)
+KM_EXPLICIT_COPY_CONSTRUCT_IMPL_END(bar, foo)
+*/
+
+#endif // _KM_PLATFORM_H_
+
+//
+// KM_platform.h
+//
diff --git a/src/asdcp/KM_prng.h b/src/asdcp/KM_prng.h
new file mode 100755
index 0000000..e2bc3f1
--- /dev/null
+++ b/src/asdcp/KM_prng.h
@@ -0,0 +1,63 @@
+/*
+Copyright (c) 2006-2009, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file KM_prng.h
+ \version $Id$
+ \brief Fortuna pseudo-random number generator
+ */
+
+#ifndef _KM_PRNG_H_
+#define _KM_PRNG_H_
+
+#include <asdcp/KM_util.h>
+
+namespace Kumu
+{
+ class FortunaRNG
+ {
+ KM_NO_COPY_CONSTRUCT(FortunaRNG);
+
+ public:
+ FortunaRNG();
+ ~FortunaRNG();
+ const byte_t* FillRandom(byte_t* buf, ui32_t len);
+ const byte_t* FillRandom(ByteString&);
+ void Reset();
+ };
+
+
+ // key_len must be <= 64 (larger values will be truncated)
+ void Gen_FIPS_186_Value(const byte_t* key_in, ui32_t key_len, byte_t* buf, ui32_t buf_len);
+
+} // namespace Kumu
+
+
+
+#endif // _KM_PRNG_H_
+
+//
+// end KM_prng.h
+//
diff --git a/src/asdcp/KM_tai.h b/src/asdcp/KM_tai.h
new file mode 100644
index 0000000..a126760
--- /dev/null
+++ b/src/asdcp/KM_tai.h
@@ -0,0 +1,107 @@
+/*
+
+THIS IS A SUBSET OF THE FULL LIBTAI. CHANGES HAVE BEEN MADE TO SUIT
+LIBKUMU STYLE AND TYPE CONVENTIONS. ALL BUGS BELONG TO JOHN HURST.
+THE FOLLOWING IS FOR ATTRIBUTION, THANK YOU MR. BERNSTEIN FOR WRITING
+AND DISTRIBUTING SUCH GREAT SOFTWARE:
+
+libtai 0.60, alpha.
+19981013
+Copyright 1998
+D. J. Bernstein, djb@pobox.com
+http://pobox.com/~djb/libtai.html
+
+
+libtai is a library for storing and manipulating dates and times.
+
+libtai supports two time scales: (1) TAI64, covering a few hundred
+billion years with 1-second precision; (2) TAI64NA, covering the same
+period with 1-attosecond precision. Both scales are defined in terms of
+TAI, the current international real time standard.
+
+libtai provides an internal format for TAI64, struct tai, designed for
+fast time manipulations. The tai_pack() and tai_unpack() routines
+convert between struct tai and a portable 8-byte TAI64 storage format.
+libtai provides similar internal and external formats for TAI64NA.
+
+libtai provides struct caldate to store dates in year-month-day form. It
+can convert struct caldate, under the Gregorian calendar, to a modified
+Julian day number for easy date arithmetic.
+
+libtai provides struct caltime to store calendar dates and times along
+with UTC offsets. It can convert from struct tai to struct caltime in
+UTC, accounting for leap seconds, for accurate date and time display. It
+can also convert back from struct caltime to struct tai for user input.
+Its overall UTC-to-TAI conversion speed is 100x better than the usual
+UNIX mktime() implementation.
+
+This version of libtai requires a UNIX system with gettimeofday(). It
+will be easy to port to other operating systems with compilers
+supporting 64-bit arithmetic.
+
+The libtai source code is in the public domain.
+
+*/
+
+ /*! \file KM_tai.h
+ \version $Id$
+ \brief portable time functions
+ */
+
+#ifndef _KUMU_TAI_H_
+#define _KUMU_TAI_H_
+
+#include <asdcp/KM_platform.h>
+
+//
+namespace Kumu
+{
+ namespace TAI
+ {
+ class caltime;
+
+ //
+ struct tai
+ {
+ ui64_t x;
+ inline void add_seconds(i32_t s) { x += s; }
+ inline void add_minutes(i32_t m) { x += m * 60; }
+ inline void add_hours(i32_t h) { x += h * 3600; }
+ inline void add_days(i32_t d) { x += d * 86400; }
+ void now();
+
+ const tai& operator=(const caltime& rhs);
+ };
+
+ //
+ struct caldate
+ {
+ i32_t year;
+ i32_t month;
+ i32_t day;
+ };
+
+ //
+ class caltime
+ {
+ public:
+ caldate date;
+ i32_t hour;
+ i32_t minute;
+ i32_t second;
+ i32_t offset;
+
+ const caltime& operator=(const tai& rhs);
+ };
+
+
+ } // namespace TAI
+
+} // namespace Kumu
+
+
+#endif // _KUMU_TAI_H_
+
+//
+// end KM_tai.h
+//
diff --git a/src/asdcp/KM_util.h b/src/asdcp/KM_util.h
new file mode 100755
index 0000000..409d66e
--- /dev/null
+++ b/src/asdcp/KM_util.h
@@ -0,0 +1,556 @@
+/*
+Copyright (c) 2005-2015, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+ /*! \file KM_util.h
+ \version $Id$
+ \brief Utility functions
+ */
+
+#ifndef _KM_UTIL_H_
+#define _KM_UTIL_H_
+
+#include <asdcp/KM_memio.h>
+#include <asdcp/KM_error.h>
+#include <asdcp/KM_tai.h>
+#include <string.h>
+#include <list>
+
+namespace Kumu
+{
+ extern bool cth_test;
+
+ // The version number declaration and explanation are in ../configure.ac
+ const char* Version();
+
+ // a class that represents the string form of a value
+ template <class T, int SIZE = 16>
+ class IntPrinter : public std::string
+ {
+ KM_NO_COPY_CONSTRUCT(IntPrinter);
+ IntPrinter();
+
+ protected:
+ const char* m_format;
+ char m_strbuf[SIZE];
+
+ public:
+ IntPrinter(const char* format, T value) {
+ assert(format);
+ m_format = format;
+ snprintf(m_strbuf, SIZE, m_format, value);
+ }
+
+ inline operator const char*() { return m_strbuf; }
+ inline const char* c_str() { return m_strbuf; }
+ inline const char* set_value(T value) {
+ snprintf(m_strbuf, SIZE, m_format, value);
+ return m_strbuf;
+ }
+ };
+
+ struct i8Printer : public IntPrinter<i8_t> {
+ i8Printer(i8_t value) : IntPrinter<i8_t>("%hd", value) {}
+ };
+
+ struct ui8Printer : public IntPrinter<ui8_t> {
+ ui8Printer(ui8_t value) : IntPrinter<ui8_t>("%hu", value) {}
+ };
+
+ struct i16Printer : public IntPrinter<i16_t> {
+ i16Printer(i16_t value) : IntPrinter<i16_t>("%hd", value) {}
+ };
+
+ struct ui16Printer : public IntPrinter<ui16_t> {
+ ui16Printer(ui16_t value) : IntPrinter<ui16_t>("%hu", value) {}
+ };
+
+ struct i32Printer : public IntPrinter<i32_t> {
+ i32Printer(i32_t value) : IntPrinter<i32_t>("%d", value) {}
+ };
+
+ struct ui32Printer : public IntPrinter<ui32_t> {
+ ui32Printer(ui32_t value) : IntPrinter<ui32_t>("%u", value) {}
+ };
+
+#ifdef KM_WIN32
+ struct i64Printer : public IntPrinter<i64_t, 32> {
+ i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%I64d", value) {}
+ };
+
+ struct ui64Printer : public IntPrinter<ui64_t, 32> {
+ ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%I64u", value) {}
+ };
+#else
+ struct i64Printer : public IntPrinter<i64_t, 32> {
+ i64Printer(i64_t value) : IntPrinter<i64_t, 32>("%qd", value) {}
+ };
+
+ struct ui64Printer : public IntPrinter<ui64_t, 32> {
+ ui64Printer(ui64_t value) : IntPrinter<ui64_t, 32>("%qu", value) {}
+ };
+#endif
+
+ // Convert NULL-terminated UTF-8 hexadecimal string to binary, returns 0 if
+ // the binary buffer was large enough to hold the result. The output parameter
+ // 'char_count' will contain the length of the converted string. If the output
+ // buffer is too small or any of the pointer arguments are NULL, the subroutine
+ // will return -1 and set 'char_count' to the required buffer size. No data will
+ // be written to 'buf' if the subroutine fails.
+ i32_t hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
+
+ // Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
+ // if the output buffer was large enough to hold the result. If the output buffer
+ // is too small or any of the pointer arguments are NULL, the subroutine will
+ // return 0.
+ //
+ const char* bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
+
+ const char* bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
+
+ // same as above for base64 text
+ i32_t base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count);
+ const char* base64encode(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len);
+
+ // returns the length of a Base64 encoding of a buffer of the given length
+ inline ui32_t base64_encode_length(ui32_t length) {
+ while ( ( length % 3 ) != 0 )
+ length++;
+
+ return ( length / 3 ) * 4;
+ }
+
+ // print buffer contents to a stream as hexadecimal values in numbered
+ // rows of 16-bytes each.
+ //
+ void hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream = 0);
+
+ // Return the length in bytes of a BER encoded value
+ inline ui32_t BER_length(const byte_t* buf)
+ {
+ if ( buf == 0 || (*buf & 0xf0) != 0x80 )
+ return 0;
+
+ return (*buf & 0x0f) + 1;
+ }
+
+ // Return the BER length required to encode value. A return value of zero
+ // indicates a value too large for this library.
+ ui32_t get_BER_length_for_value(ui64_t valuse);
+
+ // read a BER value
+ bool read_BER(const byte_t* buf, ui64_t* val);
+
+ // decode a ber value and compare it to a test value
+ bool read_test_BER(byte_t **buf, ui64_t test_value);
+
+ // create BER encoding of integer value
+ bool write_BER(byte_t* buf, ui64_t val, ui32_t ber_len = 0);
+
+ //----------------------------------------------------------------
+ //
+
+ // an abstract base class that objects implement to serialize state
+ // to and from a binary stream.
+ class IArchive
+ {
+ public:
+ virtual ~IArchive(){}
+ virtual bool HasValue() const = 0;
+ virtual ui32_t ArchiveLength() const = 0;
+ virtual bool Archive(MemIOWriter* Writer) const = 0;
+ virtual bool Unarchive(MemIOReader* Reader) = 0;
+ };
+
+ //
+ template <class T>
+ class ArchivableList : public std::list<T>, public IArchive
+ {
+ public:
+ ArchivableList() {}
+ virtual ~ArchivableList() {}
+
+ bool HasValue() const { return ! this->empty(); }
+
+ ui32_t ArchiveLength() const
+ {
+ ui32_t arch_size = sizeof(ui32_t);
+
+ typename ArchivableList<T>::const_iterator i = this->begin();
+ for ( ; i != this->end(); i++ )
+ arch_size += i->ArchiveLength();
+
+ return arch_size;
+ }
+
+ bool Unarchive(Kumu::MemIOReader* Reader)
+ {
+ if ( Reader == 0 ) return false;
+ ui32_t read_size = 0;
+ if ( ! Reader->ReadUi32BE(&read_size) ) return false;
+ for ( ui32_t i = 0; i < read_size; i++ )
+ {
+ T TmpTP;
+ if ( ! TmpTP.Unarchive(Reader) ) return false;
+ this->push_back(TmpTP);
+ }
+
+ return true;
+ }
+
+ bool Archive(Kumu::MemIOWriter* Writer) const
+ {
+ if ( Writer == 0 ) return false;
+ if ( ! Writer->WriteUi32BE(static_cast<ui32_t>(this->size())) ) return false;
+ typename ArchivableList<T>::const_iterator i = this->begin();
+ for ( ; i != this->end(); i++ )
+ if ( ! i->Archive(Writer) ) return false;
+
+ return true;
+ }
+ };
+
+ // archivable version of std::string
+
+ //
+ class ArchivableString : public std::string, public Kumu::IArchive
+ {
+
+ public:
+ ArchivableString() {}
+ ArchivableString(const char* sz) : std::string(sz) {}
+ ArchivableString(const std::string& s) : std::string(s) {}
+ virtual ~ArchivableString() {}
+
+ bool HasValue() const { return ! this->empty(); }
+ ui32_t ArchiveLength() const { return sizeof(ui32_t) + static_cast<ui32_t>(this->size()); }
+
+ bool Archive(MemIOWriter* Writer) const {
+ if ( Writer == 0 ) return false;
+ return Writer->WriteString(*this);
+ }
+
+ bool Unarchive(MemIOReader* Reader) {
+ if ( Reader == 0 ) return false;
+ return Reader->ReadString(*this);
+ }
+ };
+
+ //
+ typedef Kumu::ArchivableList<ArchivableString> StringList;
+
+ //
+ // the base of all identifier classes, Identifier is not usually used directly
+ // see UUID and SymmetricKey below for more detail.
+ //
+ template <ui32_t SIZE>
+ class Identifier : public IArchive
+ {
+ protected:
+ bool m_HasValue;
+ byte_t m_Value[SIZE];
+
+ public:
+ Identifier() : m_HasValue(false) { memset(m_Value, 0, SIZE); }
+ Identifier(const byte_t* value) : m_HasValue(true) { memcpy(m_Value, value, SIZE); }
+ Identifier(const Identifier& rhs) : IArchive() {
+ m_HasValue = rhs.m_HasValue;
+ memcpy(m_Value, rhs.m_Value, SIZE);
+ }
+
+ virtual ~Identifier() {}
+
+ const Identifier& operator=(const Identifier& rhs) {
+ m_HasValue = rhs.m_HasValue;
+ memcpy(m_Value, rhs.m_Value, SIZE);
+ return *this;
+ }
+
+ inline void Set(const byte_t* value) { m_HasValue = true; memcpy(m_Value, value, SIZE); }
+ inline void Reset() { m_HasValue = false; memset(m_Value, 0, SIZE); }
+ inline const byte_t* Value() const { return m_Value; }
+ inline ui32_t Size() const { return SIZE; }
+
+ inline bool operator<(const Identifier& rhs) const {
+ ui32_t test_size = xmin(rhs.Size(), SIZE);
+
+ for ( ui32_t i = 0; i < test_size; i++ )
+ {
+ if ( m_Value[i] != rhs.m_Value[i] )
+ return m_Value[i] < rhs.m_Value[i];
+ }
+
+ return false;
+ }
+
+ inline bool operator==(const Identifier& rhs) const {
+ if ( rhs.Size() != SIZE ) return false;
+ return ( memcmp(m_Value, rhs.m_Value, SIZE) == 0 );
+ }
+
+ inline bool operator!=(const Identifier& rhs) const {
+ if ( rhs.Size() != SIZE ) return true;
+ return ( memcmp(m_Value, rhs.m_Value, SIZE) != 0 );
+ }
+
+ inline bool DecodeHex(const char* str) {
+ ui32_t char_count;
+ m_HasValue = ( hex2bin(str, m_Value, SIZE, &char_count) == 0 );
+ if ( m_HasValue && char_count != SIZE )
+ m_HasValue = false;
+ return m_HasValue;
+ }
+
+ inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
+ return bin2hex(m_Value, SIZE, buf, buf_len);
+ }
+
+ inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ return EncodeHex(str_buf, buf_len);
+ }
+
+ inline bool DecodeBase64(const char* str) {
+ ui32_t char_count;
+ m_HasValue = ( base64decode(str, m_Value, SIZE, &char_count) == 0 );
+ if ( m_HasValue && char_count != SIZE )
+ m_HasValue = false;
+ return m_HasValue;
+ }
+
+ inline const char* EncodeBase64(char* buf, ui32_t buf_len) const {
+ return base64encode(m_Value, SIZE, buf, buf_len);
+ }
+
+ inline bool HasValue() const { return m_HasValue; }
+
+ inline ui32_t ArchiveLength() const { return SIZE; }
+
+ inline bool Unarchive(Kumu::MemIOReader* Reader) {
+ m_HasValue = Reader->ReadRaw(m_Value, SIZE);
+ return m_HasValue;
+ }
+
+ inline bool Archive(Kumu::MemIOWriter* Writer) const {
+ return Writer->WriteRaw(m_Value, SIZE);
+ }
+ };
+
+
+ // UUID
+ //
+ const ui32_t UUID_Length = 16;
+ class UUID : public Identifier<UUID_Length>
+ {
+ public:
+ UUID() {}
+ UUID(const byte_t* value) : Identifier<UUID_Length>(value) {}
+ UUID(const UUID& rhs) : Identifier<UUID_Length>(rhs) {}
+ virtual ~UUID() {}
+
+ inline const char* EncodeString(char* buf, ui32_t buf_len) const {
+ return bin2UUIDhex(m_Value, Size(), buf, buf_len);
+ }
+
+ inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
+ return bin2UUIDhex(m_Value, Size(), buf, buf_len);
+ }
+ };
+
+ void GenRandomUUID(byte_t* buf); // buf must be UUID_Length or longer
+ void GenRandomValue(UUID&);
+ void ResetTestRNG();
+
+ typedef ArchivableList<UUID> UUIDList;
+
+ // a self-wiping key container
+ //
+ const ui32_t SymmetricKey_Length = 16;
+ const byte_t NilKey[SymmetricKey_Length] = {
+ 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce,
+ 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce, 0xfa, 0xce
+ };
+
+ class SymmetricKey : public Identifier<SymmetricKey_Length>
+ {
+ public:
+ SymmetricKey() {}
+ SymmetricKey(const byte_t* value) : Identifier<SymmetricKey_Length>(value) {}
+ SymmetricKey(const UUID& rhs) : Identifier<SymmetricKey_Length>(rhs) {}
+ virtual ~SymmetricKey() { memcpy(m_Value, NilKey, 16); m_HasValue = false; }
+ };
+
+ void GenRandomValue(SymmetricKey&);
+
+ //
+ // 2004-05-01T13:20:00+00:00
+ const ui32_t DateTimeLen = 25; // the number of chars in the xs:dateTime format (sans milliseconds)
+
+ // UTC time+date representation
+ class Timestamp : public IArchive
+ {
+ TAI::tai m_Timestamp; // always UTC
+ i32_t m_TZOffsetMinutes;
+
+ public:
+ Timestamp();
+ Timestamp(const Timestamp& rhs);
+ Timestamp(const char* datestr);
+ Timestamp(const ui16_t& Year, const ui8_t& Month, const ui8_t& Day);
+ Timestamp(const ui16_t& Year, const ui8_t& Month, const ui8_t& Day,
+ const ui8_t& Hour, const ui8_t& Minute, const ui8_t& Second);
+ virtual ~Timestamp();
+
+ const Timestamp& operator=(const Timestamp& rhs);
+ bool operator<(const Timestamp& rhs) const;
+ bool operator>(const Timestamp& rhs) const;
+ bool operator==(const Timestamp& rhs) const;
+ bool operator!=(const Timestamp& rhs) const;
+
+ // always UTC
+ void GetComponents(ui16_t& Year, ui8_t& Month, ui8_t& Day,
+ ui8_t& Hour, ui8_t& Minute, ui8_t& Second) const;
+ void SetComponents(const ui16_t& Year, const ui8_t& Month, const ui8_t& Day,
+ const ui8_t& Hour, const ui8_t& Minute, const ui8_t& Second);
+
+ // Write the timestamp value to the given buffer in the form 2004-05-01T13:20:00+00:00
+ // returns 0 if the buffer is smaller than DateTimeLen
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
+
+ // decode and set value from string formatted by EncodeString
+ bool DecodeString(const char* datestr);
+
+ // Add the given number of days, hours, minutes, or seconds to the timestamp value.
+ // Values less than zero will cause the timestamp to decrease
+ inline void AddDays(const i32_t& d) { m_Timestamp.add_days(d); }
+ inline void AddHours(const i32_t& h) { m_Timestamp.add_hours(h); }
+ inline void AddMinutes(const i32_t& m) { m_Timestamp.add_minutes(m); }
+ inline void AddSeconds(const i32_t& s) { m_Timestamp.add_seconds(s); }
+
+ // returns false if the requested adjustment is out of range
+ bool SetTZOffsetMinutes(const i32_t& minutes);
+ inline i32_t GetTZOffsetMinutes() const { return m_TZOffsetMinutes; }
+
+ // Return the number of seconds since the Unix epoch UTC (1970-01-01T00:00:00+00:00)
+ ui64_t GetCTime() const;
+
+ // Set internal time to the number of seconds since the Unix epoch UTC
+ void SetCTime(const ui64_t& ctime);
+
+ // Read and write the timestamp (always UTC) value as a byte string having
+ // the following format:
+ // | 16 bits int, big-endian | 8 bits | 8 bits | 8 bits | 8 bits | 8 bits |
+ // | Year A.D | Month(1-12) | Day(1-31) | Hour(0-23) | Minute(0-59) | Second(0-59) |
+ //
+ virtual bool HasValue() const;
+ virtual ui32_t ArchiveLength() const { return 8L; }
+ virtual bool Archive(MemIOWriter* Writer) const;
+ virtual bool Unarchive(MemIOReader* Reader);
+ };
+
+ //
+ class ByteString : public IArchive
+ {
+ KM_NO_COPY_CONSTRUCT(ByteString);
+
+ protected:
+ byte_t* m_Data; // pointer to memory area containing frame data
+ ui32_t m_Capacity; // size of memory area pointed to by m_Data
+ ui32_t m_Length; // length of byte string in memory area pointed to by m_Data
+
+ public:
+ ByteString();
+ ByteString(ui32_t cap);
+ virtual ~ByteString();
+
+ // Sets or resets the size of the internally allocated buffer.
+ Result_t Capacity(ui32_t cap);
+
+ Result_t Append(const ByteString&);
+ Result_t Append(const byte_t* buf, ui32_t buf_len);
+
+ // returns the size of the buffer
+ inline ui32_t Capacity() const { return m_Capacity; }
+
+ // returns a const pointer to the essence data
+ inline const byte_t* RoData() const { assert(m_Data); return m_Data; }
+
+ // returns a non-const pointer to the essence data
+ inline byte_t* Data() { assert(m_Data); return m_Data; }
+
+ // set the length of the buffer's contents
+ inline ui32_t Length(ui32_t l) { return m_Length = l; }
+
+ // returns the length of the buffer's contents
+ inline ui32_t Length() const { return m_Length; }
+
+ // copy the given data into the ByteString, set Length value.
+ // Returns error if the ByteString is too small.
+ Result_t Set(const byte_t* buf, ui32_t buf_len);
+ Result_t Set(const ByteString& Buf);
+
+ inline virtual bool HasValue() const { return m_Length > 0; }
+
+ inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + m_Length; }
+
+ inline virtual bool Archive(MemIOWriter* Writer) const {
+ assert(Writer);
+ if ( ! Writer->WriteUi32BE(m_Length) ) return false;
+ if ( ! Writer->WriteRaw(m_Data, m_Length) ) return false;
+ return true;
+ }
+
+ inline virtual bool Unarchive(MemIOReader* Reader) {
+ assert(Reader);
+ ui32_t tmp_len;
+ if ( ! Reader->ReadUi32BE(&tmp_len) ) return false;
+ if ( KM_FAILURE(Capacity(tmp_len)) ) return false;
+ if ( ! Reader->ReadRaw(m_Data, tmp_len) ) return false;
+ m_Length = tmp_len;
+ return true;
+ }
+ };
+
+ inline void hexdump(const ByteString& buf, FILE* stream = 0) {
+ hexdump(buf.RoData(), buf.Length(), stream);
+ }
+
+ // Locates the first occurrence of the null-terminated string s2 in the string s1, where not more
+ // than n characters are searched. Characters that appear after a `\0' character are not searched.
+ // Reproduced here from BSD for portability.
+ const char *km_strnstr(const char *s1, const char *s2, size_t n);
+
+ // Split the input string into tokens using the given separator. If the separator is not found the
+ // entire string will be returned as a single-item list. Empty items will be recorded for
+ // adjacent instances of the separator. E.g., "/foo//bar/" will return ["", "foo", "", "bar", ""].
+ std::list<std::string> km_token_split(const std::string& str, const std::string& separator);
+
+} // namespace Kumu
+
+
+#endif // _KM_UTIL_H_
+
+//
+// end KM_util.h
+//