summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjhurst <jhurst@cinecert.com>2006-04-05 23:03:55 +0000
committerjhurst <>2006-04-05 23:03:55 +0000
commitbfedf725dac9d13f3a02fe69f45c302ab29d2b1e (patch)
tree4a746f759dcb62ebeb6309373e7579d6048f4af6 /src
parentfdf31e0105bf8272a6b7fa9c4039941dff37a271 (diff)
ginormo merge-back with Kumu, SMPTE MIC key and MPEG parser fix
Diffstat (limited to 'src')
-rwxr-xr-xsrc/AS_DCP.cpp387
-rwxr-xr-xsrc/AS_DCP.h245
-rwxr-xr-xsrc/AS_DCP_AES.cpp87
-rwxr-xr-xsrc/AS_DCP_JP2K.cpp24
-rwxr-xr-xsrc/AS_DCP_MPEG2.cpp2
-rwxr-xr-xsrc/AS_DCP_MXF.cpp42
-rwxr-xr-xsrc/AS_DCP_PCM.cpp2
-rwxr-xr-xsrc/AS_DCP_internal.h19
-rwxr-xr-xsrc/Dict.cpp7
-rwxr-xr-xsrc/Index.cpp82
-rwxr-xr-xsrc/JP2K.cpp9
-rwxr-xr-xsrc/JP2K.h31
-rwxr-xr-xsrc/JP2K_Codestream_Parser.cpp10
-rwxr-xr-xsrc/JP2K_Sequence_Parser.cpp9
-rwxr-xr-xsrc/KLV.cpp34
-rwxr-xr-xsrc/KLV.h81
-rwxr-xr-xsrc/KM_error.h117
-rw-r--r--src/KM_fileio.cpp801
-rwxr-xr-xsrc/KM_fileio.h186
-rwxr-xr-xsrc/KM_log.cpp155
-rwxr-xr-xsrc/KM_log.h133
-rwxr-xr-xsrc/KM_memio.h216
-rwxr-xr-xsrc/KM_mutex.h89
-rw-r--r--src/KM_platform.h189
-rwxr-xr-xsrc/KM_prng.cpp214
-rwxr-xr-xsrc/KM_prng.h57
-rwxr-xr-xsrc/KM_util.cpp921
-rwxr-xr-xsrc/KM_util.h392
-rwxr-xr-xsrc/MPEG.cpp118
-rwxr-xr-xsrc/MPEG.h31
-rwxr-xr-xsrc/MPEG2_Parser.cpp93
-rwxr-xr-xsrc/MXF.cpp171
-rwxr-xr-xsrc/MXF.h91
-rwxr-xr-xsrc/MXFTypes.cpp238
-rwxr-xr-xsrc/MXFTypes.h200
-rwxr-xr-xsrc/Metadata.cpp85
-rwxr-xr-xsrc/PCM_Parser.cpp6
-rwxr-xr-xsrc/Wav.cpp61
-rwxr-xr-xsrc/Wav.h9
-rwxr-xr-xsrc/WavFileWriter.h10
-rwxr-xr-xsrc/asdcp-test.cpp124
-rw-r--r--src/blackwave.cpp245
-rwxr-xr-xsrc/h__Reader.cpp26
-rwxr-xr-xsrc/h__Writer.cpp21
-rwxr-xr-xsrc/klvwalk.cpp24
-rwxr-xr-xsrc/wavesplit.cpp369
46 files changed, 5146 insertions, 1317 deletions
diff --git a/src/AS_DCP.cpp b/src/AS_DCP.cpp
index a5187d6..12765c6 100755
--- a/src/AS_DCP.cpp
+++ b/src/AS_DCP.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004-2005, John Hurst
+Copyright (c) 2004-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -29,146 +29,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief AS-DCP library, misc classes and subroutines
*/
-#include <AS_DCP_system.h>
-#include "hex_utils.h"
+#include "AS_DCP_internal.h"
#include <assert.h>
-
-static const ui32_t s_MessageCount = 27;
-static const char* s_ErrorMessages[] =
-{
- "An undefined error was detected.",
- "An unexpected NULL pointer was given.",
- "An unexpected empty string was given.",
- "The given frame buffer is too small.",
- "The object is not yet initialized.",
-
- "The requested file does not exist on the system.",
- "Insufficient privilege exists to perform the operation.",
- "File open error.",
- "The file contains errors or is not OP-Atom/AS-DCP.",
- "An invalid file location was requested.",
-
- "File read error.",
- "File write error.",
- "Unknown raw essence file type.",
- "Raw essence format invalid.",
- "Object state error.",
-
- "Attempt to read past end of file.",
- "Invalid configuration option detected.",
- "Frame number out of range.",
- "AESEncContext required when writing to encrypted file",
- "Plaintext offset exceeds frame buffer size",
-
- "Error allocating memory",
- "Cannot resize externally allocated memory",
- "The check value did not decrypt correctly",
- "HMAC authentication failure",
- "HMAC context required",
-
- "Error initializing block cipher context",
- "Attempted to write an empty frame buffer"
-};
-
-
-//------------------------------------------------------------------------------------------
-
-//
-class StderrLogSink : public ASDCP::ILogSink
-{
-public:
- bool show_info;
- bool show_debug;
-
- StderrLogSink() : show_info(false), show_debug(false) {}
- ~StderrLogSink() {}
-
- void Error(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vLogf(LOG_ERROR, fmt, &args);
- va_end(args);
- }
-
- void Warn(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vLogf(LOG_WARN, fmt, &args);
- va_end(args);
- }
-
- void Info(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vLogf(LOG_INFO, fmt, &args);
- va_end(args);
- }
-
- void Debug(const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vLogf(LOG_DEBUG, fmt, &args);
- va_end(args);
- }
-
- void Logf(ASDCP::ILogSink::LogType_t type, const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- vLogf(type, fmt, &args);
- va_end(args);
- }
-
- void vLogf(ASDCP::ILogSink::LogType_t type, const char* fmt, va_list* list) {
- FILE* stream = stderr;
-
- switch ( type )
- {
- case LOG_ERROR: fputs("Error: ", stream); break;
- case LOG_WARN: fputs("Warning: ", stream); break;
- case LOG_INFO:
- if ( ! show_info ) return;
- fputs("Info: ", stream);
- break;
- case LOG_DEBUG:
- if ( ! show_debug ) return;
- fputs("Debug: ", stream);
- break;
- }
-
- vfprintf(stream, fmt, *list);
- }
-
-} s_StderrLogSink;
-
-//
-static ASDCP::ILogSink* s_DefaultLogSink = 0;
-
-//
-void
-ASDCP::SetDefaultLogSink(ILogSink* Sink)
-{
- s_DefaultLogSink = Sink;
-}
-
-// bootleg entry for debug enthusiasts
-void
-set_debug_mode(bool info_mode, bool debug_mode)
-{
- s_StderrLogSink.show_info = info_mode;
- s_StderrLogSink.show_debug = debug_mode;
-}
-
-// Returns the internal default sink.
-ASDCP::ILogSink&
-ASDCP::DefaultLogSink()
-{
- if ( s_DefaultLogSink == 0 )
- s_DefaultLogSink = &s_StderrLogSink;
-
- return *s_DefaultLogSink;
-}
-
const char*
ASDCP::Version()
{
@@ -178,252 +41,6 @@ ASDCP::Version()
}
-// Returns a pointer to an English language string describing the given result code.
-// If the result code is not a valid member of the Result_t enum, the string
-// "**UNKNOWN**" will be returned.
-const char*
-ASDCP::GetResultString(Result_t result)
-{
- if ( result >= 0 )
- return "No error.";
-
- ui32_t idx = (- result);
-
- if ( idx > s_MessageCount )
- return "**UNKNOWN**";
-
- return s_ErrorMessages[--idx];
-}
-
-
-// convert utf-8 hext string to bin
-i32_t
-ASDCP::hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* conv_size)
-{
- ASDCP_TEST_NULL(str);
- ASDCP_TEST_NULL(buf);
- ASDCP_TEST_NULL(conv_size);
-
- *conv_size = 0;
-
- if ( str[0] == 0 ) // nothing to convert
- return 0;
-
- for ( int j = 0; str[j]; j++ )
- {
- if ( isxdigit(str[j]) )
- (*conv_size)++;
- }
-
- if ( *conv_size & 0x01 ) (*conv_size)++;
- *conv_size /= 2;
-
- if ( *conv_size > buf_len )// maximum possible data size
- return -1;
-
- *conv_size = 0;
-
- int phase = 0; // track high/low nybble
-
- // for each character, fill in the high nybble then the low
- for ( int i = 0; str[i]; i++ )
- {
- if ( ! isxdigit(str[i]) )
- continue;
-
- byte_t val = str[i] - ( isdigit(str[i]) ? 0x30 : ( isupper(str[i]) ? 0x37 : 0x57 ) );
-
- if ( phase == 0 )
- {
- buf[*conv_size] = val << 4;
- phase++;
- }
- else
- {
- buf[*conv_size] |= val;
- phase = 0;
- (*conv_size)++;
- }
- }
-
- return 0;
-}
-
-
-// convert a memory region to a NULL-terminated hexadecimal string
-//
-const char*
-ASDCP::bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
-{
- if ( bin_buf == 0
- || str_buf == 0
- || ((bin_len * 2) + 1) > str_len )
- return 0;
-
- char* p = str_buf;
-
- for ( ui32_t i = 0; i < bin_len; i++ )
- {
- *p = (bin_buf[i] >> 4) & 0x0f;
- *p += *p < 10 ? 0x30 : 0x61 - 10;
- p++;
-
- *p = bin_buf[i] & 0x0f;
- *p += *p < 10 ? 0x30 : 0x61 - 10;
- p++;
- }
-
- *p = '\0';
- return str_buf;
-}
-
-
-// spew a range of bin data as hex
-void
-ASDCP::hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream)
-{
- if ( buf == 0 )
- return;
-
- if ( stream == 0 )
- stream = stderr;
-
- static ui32_t row_len = 16;
- const byte_t* p = buf;
- const byte_t* end_p = p + dump_len;
-
- for ( ui32_t line = 0; p < end_p; line++ )
- {
- fprintf(stream, " %06x: ", line);
- ui32_t i;
- const byte_t* pp;
-
- for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
- fprintf(stream, "%02x ", *pp);
-
- while ( i++ < row_len )
- fputs(" ", stream);
-
- for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
- fputc((isprint(*pp) ? *pp : '.'), stream);
-
- fputc('\n', stream);
- p += row_len;
- }
-}
-
-//------------------------------------------------------------------------------------------
-
-// read a ber value from the buffer and compare with test value.
-// Advances buffer to first character after BER value.
-//
-bool
-ASDCP::read_test_BER(byte_t **buf, ui64_t test_value)
-{
- if ( buf == 0 )
- return false;
-
- if ( ( **buf & 0x80 ) == 0 )
- return false;
-
- ui64_t val = 0;
- ui8_t ber_size = ( **buf & 0x0f ) + 1;
-
- if ( ber_size > 9 )
- return false;
-
- for ( ui8_t i = 1; i < ber_size; i++ )
- {
- if ( (*buf)[i] > 0 )
- val |= (ui64_t)((*buf)[i]) << ( ( ( ber_size - 1 ) - i ) * 8 );
- }
-
- *buf += ber_size;
- return ( val == test_value );
-}
-
-
-//
-bool
-ASDCP::read_BER(const byte_t* buf, ui64_t* val)
-{
- ui8_t ber_size, i;
-
- if ( buf == 0 || val == 0 )
- return false;
-
- if ( ( *buf & 0x80 ) == 0 )
- return false;
-
- *val = 0;
- ber_size = ( *buf & 0x0f ) + 1;
-
- if ( ber_size > 9 )
- return false;
-
- for ( i = 1; i < ber_size; i++ )
- {
- if ( buf[i] > 0 )
- *val |= (ui64_t)buf[i] << ( ( ( ber_size - 1 ) - i ) * 8 );
- }
-
- return true;
-}
-
-
-static const ui64_t ber_masks[9] =
- { ui64_C(0xffffffffffffffff), ui64_C(0xffffffffffffff00),
- ui64_C(0xffffffffffff0000), ui64_C(0xffffffffff000000),
- ui64_C(0xffffffff00000000), ui64_C(0xffffff0000000000),
- ui64_C(0xffff000000000000), ui64_C(0xff00000000000000),
- 0
- };
-
-
-//
-bool
-ASDCP::write_BER(byte_t* buf, ui64_t val, ui32_t ber_len)
-{
- if ( buf == 0 )
- return false;
-
- if ( ber_len == 0 )
- { // calculate default length
- if ( val < 0x01000000L )
- ber_len = 4;
- else if ( val < ui64_C(0x0100000000000000) )
- ber_len = 8;
- else
- ber_len = 9;
- }
- else
- { // sanity check BER length
- if ( ber_len > 9 )
- {
- DefaultLogSink().Error("BER size %lu exceeds maximum size of 9\n", ber_len);
- return false;
- }
-
- if ( val & ber_masks[ber_len - 1] )
- {
- char intbuf[IntBufferLen];
- DefaultLogSink().Error("BER size %lu too small for value %s\n",
- ber_len, ui64sz(val, intbuf));
- return false;
- }
- }
-
- buf[0] = 0x80 + ( ber_len - 1 );
-
- for ( ui32_t i = ber_len - 1; i > 0; i-- )
- {
- buf[i] = (ui8_t)(val & 0xff);
- val >>= 8;
- }
-
- return true;
-}
-
//------------------------------------------------------------------------------------------
//
// frame buffer base class implementation
diff --git a/src/AS_DCP.h b/src/AS_DCP.h
index e65b029..f6574ac 100755
--- a/src/AS_DCP.h
+++ b/src/AS_DCP.h
@@ -72,9 +72,10 @@ This project depends upon the following library:
*/
-#ifndef _AS_DCP_H__
-#define _AS_DCP_H__
+#ifndef _AS_DCP_H_
+#define _AS_DCP_H_
+#include <KM_error.h>
#include <stdio.h>
#include <stdarg.h>
#include <iostream>
@@ -128,7 +129,6 @@ typedef unsigned int ui32_t;
T(const T&); \
T& operator=(const T&)
-
//--------------------------------------------------------------------------------
// All library components are defined in the namespace ASDCP
//
@@ -142,8 +142,8 @@ namespace ASDCP {
// in file format, and if no changes were made to AS_DCP.h, the new version would be
// 1.0.1. If changes were also required in AS_DCP.h, the new version would be 1.1.1.
const ui32_t VERSION_MAJOR = 1;
- const ui32_t VERSION_APIMINOR = 0;
- const ui32_t VERSION_IMPMINOR = 5;
+ const ui32_t VERSION_APIMINOR = 1;
+ const ui32_t VERSION_IMPMINOR = 7;
const char* Version();
// UUIDs are passed around as strings of UUIDlen bytes
@@ -153,75 +153,42 @@ namespace ASDCP {
const ui32_t KeyLen = 16;
//---------------------------------------------------------------------------------
- // message logging
-
- // Error and debug messages will be delivered to an object having this interface.
- // The default implementation sends only LOG_ERROR and LOG_WARN messages to stderr.
- // To receive LOG_INFO or LOG_DEBUG messages, or to send messages somewhere other
- // than stderr, implement this interface and register an instance of your new class
- // by calling SetDefaultLogSink().
- class ILogSink
- {
- public:
- enum LogType_t { LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG };
-
- virtual ~ILogSink() {}
- virtual void Error(const char*, ...) = 0; // receives error messges
- virtual void Warn(const char*, ...) = 0; // receives warning messges
- virtual void Info(const char*, ...) = 0; // receives info messages
- virtual void Debug(const char*, ...) = 0; // receives debug messages
- virtual void Logf(LogType_t, const char*, ...) = 0; // log a formatted string with positional parameters
- virtual void vLogf(LogType_t, const char*, va_list*) = 0; // log a formatted string with a va_list struct
- };
-
- // Sets the internal default sink to the given receiver. If the given value
- // is zero, sets the default sink to the internally allocated stderr sink.
- void SetDefaultLogSink(ILogSink* = 0);
-
- // Returns the internal default sink.
- ILogSink& DefaultLogSink();
-
- //---------------------------------------------------------------------------------
// return values
- // Each method or subroutine in this library that is not void or does not directly
- // return a value will instead return a result code from this enumeration.
- enum Result_t {
- RESULT_FALSE = 1, // successful but negative
- RESULT_OK = 0, // No errors detected
- RESULT_FAIL = -1, // An undefined error was detected
- RESULT_PTR = -2, // An unexpected NULL pointer was given
- RESULT_NULL_STR = -3, // An unexpected empty string was given
- RESULT_SMALLBUF = -4, // The given frame buffer is too small
- RESULT_INIT = -5, // The object is not yet initialized
- RESULT_NOT_FOUND = -6, // The requested file does not exist on the system
- RESULT_NO_PERM = -7, // Insufficient privilege exists to perform the operation
- RESULT_FILEOPEN = -8, // Failure opening file
- RESULT_FORMAT = -9, // The file format is not proper OP-Atom/AS-DCP
- RESULT_BADSEEK = -10, // An invalid file location was requested
- RESULT_READFAIL = -11, // File read error
- RESULT_WRITEFAIL = -12, // File write error
- RESULT_RAW_ESS = -13, // Unknown raw essence file type
- RESULT_RAW_FORMAT = -14, // Raw essence format invalid
- RESULT_STATE = -15, // Object state error
- RESULT_ENDOFFILE = -16, // Attempt to read past end of file
- RESULT_CONFIG = -17, // Invalid configuration option detected
- RESULT_RANGE = -18, // Frame number out of range
- RESULT_CRYPT_CTX = -19, // AESEncContext required when writing to encrypted file
- RESULT_LARGE_PTO = -20, // Plaintext offset exceeds frame buffer size
- RESULT_ALLOC = -21, // Error allocating memory
- RESULT_CAPEXTMEM = -22, // Cannot resize externally allocated memory
- RESULT_CHECKFAIL = -23, // The check value did not decrypt correctly
- RESULT_HMACFAIL = -24, // HMAC authentication failure
- RESULT_HMAC_CTX = -25, // HMAC context required
- RESULT_CRYPT_INIT = -26, // Error initializing block cipher context
- RESULT_EMPTY_FB = -27, // Attempted to write an empty frame buffer
- };
-
- // Returns a pointer to an English language string describing the given result code.
- // If the result code is not a valid member of the Result_t enum, the string
- // "**UNKNOWN**" will be returned.
- const char* GetResultString(Result_t);
+ 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;
+
+ const Kumu::Result_t RESULT_FORMAT (-101, "The file format is not proper OP-Atom/AS-DCP.");
+ const Kumu::Result_t RESULT_RAW_ESS (-102, "Unknown raw essence file type.");
+ const Kumu::Result_t RESULT_RAW_FORMAT (-103, "Raw essence format invalid.");
+ const Kumu::Result_t RESULT_RANGE (-104, "Frame number out of range.");
+ const Kumu::Result_t RESULT_CRYPT_CTX (-105, "AESEncContext required when writing to encrypted file.");
+ const Kumu::Result_t RESULT_LARGE_PTO (-106, "Plaintext offset exceeds frame buffer size.");
+ const Kumu::Result_t RESULT_CAPEXTMEM (-107, "Cannot resize externally allocated memory.");
+ const Kumu::Result_t RESULT_CHECKFAIL (-108, "The check value did not decrypt correctly.");
+ const Kumu::Result_t RESULT_HMACFAIL (-109, "HMAC authentication failure.");
+ const Kumu::Result_t RESULT_HMAC_CTX (-110, "HMAC context required.");
+ const Kumu::Result_t RESULT_CRYPT_INIT (-111, "Error initializing block cipher context.");
+ const Kumu::Result_t RESULT_EMPTY_FB (-112, "Empty frame buffer.");
+ const Kumu::Result_t RESULT_KLV_CODING (-113, "KLV coding error.");
//---------------------------------------------------------------------------------
// file identification
@@ -232,7 +199,10 @@ namespace ASDCP {
ESS_UNKNOWN, // the file is not a supported AS-DCP essence container
ESS_MPEG2_VES, // the file contains an MPEG video elementary stream
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_48k, // the file contains one or more PCM audio pairs
+ ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
+ ESS_UTF8_XML, // the file contains UTF-8 encoded XML data
+ ESS_PNG // the file contains a Portable Network Graphics image
};
// Determine the type of essence contained in the given MXF file. RESULT_OK
@@ -301,6 +271,69 @@ namespace ASDCP {
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
+ // and SMPTE. The two differ only in the values of two labels:
+ //
+ // OP Atom / Interop : 06 0e 2b 34 04 01 01 01 0d 01 02 01 10 00 00 00
+ // OP Atom / SMPTE : 06 0e 2b 34 04 01 01 02 0d 01 02 01 10 00 00 00
+ // and
+ // EKLV Packet / Interop : 06 0e 2b 34 02 04 01 07 0d 01 03 01 02 7e 01 00
+ // EKLV Packet / SMPTE : 06 0e 2b 34 02 04 01 01 0d 01 03 01 02 7e 01 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
+ };
+
+ //
+ 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 stream, stderr by default.
+ void WriterInfoDump(const WriterInfo&, FILE* = 0);
+
//---------------------------------------------------------------------------------
// cryptographic support
@@ -376,7 +409,7 @@ namespace ASDCP {
// 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);
+ Result_t InitKey(const byte_t* key, LabelSet_t = LS_MXF_INTEROP);
// Reset internal state, allows repeated cycles of Update -> Finalize
void Reset();
@@ -400,68 +433,6 @@ namespace ASDCP {
};
//---------------------------------------------------------------------------------
- // 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
- // and SMPTE. The two differ only in the values of two labels:
- //
- // OP Atom / Interop : 06 0e 2b 34 04 01 01 01 0d 01 02 01 10 00 00 00
- // OP Atom / SMPTE : 06 0e 2b 34 04 01 01 02 0d 01 02 01 10 00 00 00
- // and
- // EKLV Packet / Interop : 06 0e 2b 34 02 04 01 07 0d 01 03 01 02 7e 01 00
- // EKLV Packet / SMPTE : 06 0e 2b 34 02 04 01 01 0d 01 03 01 02 7e 01 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
- };
-
- //
- 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 stream, stderr by default.
- void WriterInfoDump(const WriterInfo&, FILE* = 0);
-
- //---------------------------------------------------------------------------------
// frame buffer base class
//
// The supported essence types are stored using per-frame KLV packetization. The
@@ -1103,7 +1074,7 @@ namespace ASDCP {
} // namespace ASDCP
-#endif // _AS_DCP_H__
+#endif // _AS_DCP_H_
//
// end AS_DCP.h
diff --git a/src/AS_DCP_AES.cpp b/src/AS_DCP_AES.cpp
index e21dba1..fc10425 100755
--- a/src/AS_DCP_AES.cpp
+++ b/src/AS_DCP_AES.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004, John Hurst
+Copyright (c) 2004-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include <AS_DCP.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
using namespace ASDCP;
const int KEY_SIZE_BITS = 128;
@@ -39,6 +41,7 @@ const int KEY_SIZE_BITS = 128;
#include <openssl/aes.h>
#include <openssl/sha.h>
+#include <openssl/bn.h>
#include <openssl/err.h>
void
@@ -255,9 +258,76 @@ public:
h__HMACContext() : m_Final(false) {}
~h__HMACContext() {}
- //
+ // SMPTE 429.6 MIC key generation
void SetKey(const byte_t* key)
{
+ // FIPS 186-2 Sec. 3.1 as modified by Change 1, section entitled "General Purpose Random Number Generation"
+ //
+
+ static byte_t t[SHA_DIGEST_LENGTH] = {
+ 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89,
+ 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76,
+ 0xc3, 0xd2, 0xe1, 0xf0
+ };
+
+ byte_t sha_buf0[SHA_DIGEST_LENGTH];
+ byte_t sha_buf1[SHA_DIGEST_LENGTH];
+ SHA_CTX SHA;
+ BN_CTX* ctx1 = BN_CTX_new(); // used by BN_* functions
+ assert(ctx1);
+
+ // create the 2^160 constant
+ BIGNUM c_2powb, c_2, c_160;
+ BN_init(&c_2powb); BN_init(&c_2); BN_init(&c_160);
+ BN_set_word(&c_2, 2);
+ BN_set_word(&c_160, 160);
+ BN_exp(&c_2powb, &c_2, &c_160, ctx1);
+
+ // ROUND 1
+ // step a -- SMPTE 429.6 sets XSEED = 0, so no need to do anything for this step
+ // step b -- (key mod 2^160) is moot because the input value is only 128 bits in length
+
+ // step c -- x = G(t,xkey)
+ SHA1_Init(&SHA);
+ SHA1_Update(&SHA, t, SHA_DIGEST_LENGTH);
+ SHA1_Update(&SHA, key, KeyLen);
+ SHA1_Final(sha_buf0, &SHA);
+
+ // step d ...
+ BIGNUM xkey1, xkey2, x0;
+ BN_init(&xkey1); BN_init(&xkey2); BN_init(&x0);
+
+ BN_bin2bn(key, KeyLen, &xkey1);
+ BN_bin2bn(sha_buf0, SHA_DIGEST_LENGTH, &x0);
+ BN_add_word(&xkey1, 1); // xkey += 1
+ BN_add(&xkey2, &xkey1, &x0); // xkey += x
+ BN_mod(&xkey1, &xkey2, &c_2powb, ctx1); // xkey = xkey mod (2^160)
+
+ // ROUND 2
+ // step a -- SMPTE 429.6 sets XSEED = 0, so no need to do anything for this step
+ // step b -- (key mod 2^160) is moot because xkey1 is the result of the same operation
+
+ byte_t bin_buf[SHA_DIGEST_LENGTH+1]; // we need xkey1 in bin form for use by SHA1_Update
+ ui32_t bin_buf_len = BN_num_bytes(&xkey1);
+ assert(bin_buf_len < SHA_DIGEST_LENGTH+1);
+ BN_bn2bin(&xkey1, bin_buf);
+
+ // step c -- x = G(t,xkey)
+ SHA1_Init(&SHA);
+ SHA1_Update(&SHA, t, SHA_DIGEST_LENGTH);
+ SHA1_Update(&SHA, bin_buf, bin_buf_len);
+ SHA1_Final(sha_buf1, &SHA);
+
+ assert(memcmp(sha_buf1, sha_buf0, SHA_DIGEST_LENGTH) != 0); // are x0 and x1 different?
+
+ BN_CTX_free(ctx1);
+ memcpy(m_key, sha_buf1, KeyLen);
+ Reset();
+ }
+
+ // MXF Interop MIC key generation
+ void SetInteropKey(const byte_t* key)
+ {
static byte_t key_nonce[KeyLen] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
byte_t sha_buf[SHA_DIGEST_LENGTH];
@@ -334,12 +404,21 @@ HMACContext::~HMACContext()
//
Result_t
-HMACContext::InitKey(const byte_t* key)
+HMACContext::InitKey(const byte_t* key, LabelSet_t SetType)
{
ASDCP_TEST_NULL(key);
m_Context = new h__HMACContext;
- m_Context->SetKey(key);
+
+ switch ( SetType )
+ {
+ case LS_MXF_INTEROP: m_Context->SetInteropKey(key); break;
+ case LS_MXF_SMPTE: m_Context->SetKey(key); break;
+ default:
+ m_Context = 0;
+ return RESULT_INIT;
+ }
+
return RESULT_OK;
}
diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp
index f08203a..02d1d91 100755
--- a/src/AS_DCP_JP2K.cpp
+++ b/src/AS_DCP_JP2K.cpp
@@ -92,15 +92,13 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
if ( PDesc.CodingStyleLength )
fprintf(stream, "Default Coding (%lu): %s\n",
PDesc.CodingStyleLength,
- bin2hex(PDesc.CodingStyle, PDesc.CodingStyleLength,
- tmp_buf, tmp_buf_len)
+ Kumu::bin2hex(PDesc.CodingStyle, PDesc.CodingStyleLength, tmp_buf, tmp_buf_len)
);
if ( PDesc.QuantDefaultLength )
fprintf(stream, "Quantization Default (%lu): %s\n",
PDesc.QuantDefaultLength,
- bin2hex(PDesc.QuantDefault, PDesc.QuantDefaultLength,
- tmp_buf, tmp_buf_len)
+ Kumu::bin2hex(PDesc.QuantDefault, PDesc.QuantDefaultLength, tmp_buf, tmp_buf_len)
);
}
@@ -152,7 +150,7 @@ ASDCP::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDe
PDesc.Csize = m_EssenceSubDescriptor->Csize;
// PictureComponentSizing
- ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Size();
+ ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
@@ -161,11 +159,11 @@ ASDCP::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDe
DefaultLogSink().Error("Unexpected PictureComponentSizing size: %lu, should be 17\n", tmp_size);
// CodingStyleDefault
- if ( ( PDesc.CodingStyleLength = m_EssenceSubDescriptor->CodingStyleDefault.Size() ) != 0 )
+ if ( ( PDesc.CodingStyleLength = m_EssenceSubDescriptor->CodingStyleDefault.Length() ) != 0 )
memcpy(PDesc.CodingStyle, m_EssenceSubDescriptor->CodingStyleDefault.RoData(), PDesc.CodingStyleLength);
// QuantizationDefault
- if ( ( PDesc.QuantDefaultLength = m_EssenceSubDescriptor->QuantizationDefault.Size() ) != 0 )
+ if ( ( PDesc.QuantDefaultLength = m_EssenceSubDescriptor->QuantizationDefault.Length() ) != 0 )
memcpy(PDesc.QuantDefault, m_EssenceSubDescriptor->QuantizationDefault.RoData(), PDesc.QuantDefaultLength);
}
@@ -226,7 +224,7 @@ ASDCP::JP2K::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
fputc('\n', stream);
if ( dump_len > 0 )
- hexdump(m_Data, dump_len, stream);
+ Kumu::hexdump(m_Data, dump_len, stream);
}
@@ -368,18 +366,18 @@ ASDCP::JP2K::MXFWriter::h__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDe
const ui32_t tmp_buffer_len = 64;
byte_t tmp_buffer[tmp_buffer_len];
- *(ui32_t*)tmp_buffer = ASDCP_i32_BE(3L); // three components
- *(ui32_t*)(tmp_buffer+4) = ASDCP_i32_BE(3L);
+ *(ui32_t*)tmp_buffer = KM_i32_BE(3L); // three components
+ *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(3L);
memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent) * 3L);
memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, 17);
- m_EssenceSubDescriptor->PictureComponentSizing.Size(17);
+ m_EssenceSubDescriptor->PictureComponentSizing.Length(17);
memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), PDesc.CodingStyle, PDesc.CodingStyleLength);
- m_EssenceSubDescriptor->CodingStyleDefault.Size(PDesc.CodingStyleLength);
+ m_EssenceSubDescriptor->CodingStyleDefault.Length(PDesc.CodingStyleLength);
memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), PDesc.QuantDefault, PDesc.QuantDefaultLength);
- m_EssenceSubDescriptor->QuantizationDefault.Size(PDesc.QuantDefaultLength);
+ m_EssenceSubDescriptor->QuantizationDefault.Length(PDesc.QuantDefaultLength);
return RESULT_OK;
}
diff --git a/src/AS_DCP_MPEG2.cpp b/src/AS_DCP_MPEG2.cpp
index e265848..83f7bbe 100755
--- a/src/AS_DCP_MPEG2.cpp
+++ b/src/AS_DCP_MPEG2.cpp
@@ -273,7 +273,7 @@ ASDCP::MPEG2::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
fputc('\n', stream);
if ( dump_len > 0 )
- hexdump(m_Data, dump_len, stream);
+ Kumu::hexdump(m_Data, dump_len, stream);
}
diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp
index 92f76bb..1c8b6e9 100755
--- a/src/AS_DCP_MXF.cpp
+++ b/src/AS_DCP_MXF.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004-2005, John Hurst
+Copyright (c) 2004-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -29,9 +29,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief AS-DCP library, misc classes and subroutines
*/
+#include <KM_fileio.h>
#include "AS_DCP_internal.h"
-#include "FileIO.h"
-#include "DirScanner.h"
#include "JP2K.h"
#include "Wav.h"
@@ -49,7 +48,7 @@ ASDCP::WriterInfoDump(const WriterInfo& Info, FILE* stream)
char str_buf[40];
- fprintf(stream," ProductUUID: %s\n", bin2hex(Info.ProductUUID, 16, str_buf, 40));
+ fprintf(stream," ProductUUID: %s\n", UUID(Info.ProductUUID).EncodeHex(str_buf, 40));
fprintf(stream,"\
ProductVersion: %s\n\
CompanyName: %s\n\
@@ -64,11 +63,11 @@ ASDCP::WriterInfoDump(const WriterInfo& Info, FILE* stream)
if ( Info.EncryptedEssence )
{
fprintf(stream, " HMAC: %s\n", ( Info.UsesHMAC ? "Yes" : "No"));
- fprintf(stream, " ContextID: %s\n", bin2hex(Info.ContextID, 16, str_buf, 40));
- fprintf(stream, "CryptographicKeyID: %s\n", bin2hex(Info.CryptographicKeyID, 16, str_buf, 40));
+ fprintf(stream, " ContextID: %s\n", UUID(Info.ContextID).EncodeHex(str_buf, 40));
+ fprintf(stream, "CryptographicKeyID: %s\n", UUID(Info.CryptographicKeyID).EncodeHex(str_buf, 40));
}
- fprintf(stream," AssetUUID: %s\n", bin2hex(Info.AssetUUID, 16, str_buf, 40));
+ fprintf(stream," AssetUUID: %s\n", UUID(Info.AssetUUID).EncodeHex(str_buf, 40));
fprintf(stream," Label Set Type: %s\n", ( Info.LabelSetType == LS_MXF_SMPTE ? "SMPTE" :
( Info.LabelSetType == LS_MXF_INTEROP ? "MXF Interop" :
"Unknown" ) ));
@@ -86,13 +85,13 @@ ASDCP::MD_to_WriterInfo(Identification* InfoObj, WriterInfo& Info)
Info.CompanyName = "Unknown Company";
memset(Info.ProductUUID, 0, UUIDlen);
- InfoObj->ProductName.ToString(tmp_str);
+ InfoObj->ProductName.EncodeString(tmp_str, IdentBufferLen);
if ( *tmp_str ) Info.ProductName = tmp_str;
- InfoObj->VersionString.ToString(tmp_str);
+ InfoObj->VersionString.EncodeString(tmp_str, IdentBufferLen);
if ( *tmp_str ) Info.ProductVersion = tmp_str;
- InfoObj->CompanyName.ToString(tmp_str);
+ InfoObj->CompanyName.EncodeString(tmp_str, IdentBufferLen);
if ( *tmp_str ) Info.CompanyName = tmp_str;
memcpy(Info.ProductUUID, InfoObj->ProductUID.Value(), UUIDlen);
@@ -135,7 +134,7 @@ ASDCP::Result_t
ASDCP::EssenceType(const char* filename, EssenceType_t& type)
{
ASDCP_TEST_NULL_STR(filename);
- FileReader Reader;
+ Kumu::FileReader Reader;
OPAtomHeader TestHeader;
Result_t result = Reader.OpenRead(filename);
@@ -163,7 +162,6 @@ ASDCP::EssenceType(const char* filename, EssenceType_t& type)
return result;
}
-
//
ASDCP::Result_t
ASDCP::RawEssenceType(const char* filename, EssenceType_t& type)
@@ -171,11 +169,11 @@ ASDCP::RawEssenceType(const char* filename, EssenceType_t& type)
ASDCP_TEST_NULL_STR(filename);
type = ESS_UNKNOWN;
ASDCP::FrameBuffer FB;
- FileReader Reader;
+ Kumu::FileReader Reader;
ui32_t read_count;
Result_t result = FB.Capacity(Wav::MaxWavHeader); // using Wav max because everything else is much smaller
- if ( ASDCP::PathIsFile(filename) )
+ if ( Kumu::PathIsFile(filename) )
{
result = Reader.OpenRead(filename);
@@ -202,10 +200,10 @@ ASDCP::RawEssenceType(const char* filename, EssenceType_t& type)
type = ESS_PCM_24b_48k;
}
}
- else if ( ASDCP::PathIsDirectory(filename) )
+ else if ( Kumu::PathIsDirectory(filename) )
{
- char next_file[ASDCP_MAX_PATH];
- DirScanner Scanner;
+ char next_file[Kumu::MaxFilePath];
+ Kumu::DirScanner Scanner;
Result_t result = Scanner.Open(filename);
if ( ASDCP_SUCCESS(result) )
@@ -397,7 +395,7 @@ ASDCP::IntegrityPack::CalcValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID,
p += MXF_BER_LENGTH;
// sequence number
- i2p<ui64_t>(ASDCP_i64_BE(sequence), p);
+ Kumu::i2p<ui64_t>(KM_i64_BE(sequence), p);
p += sizeof(ui64_t);
// HMAC length
@@ -429,7 +427,7 @@ ASDCP::IntegrityPack::TestValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID,
byte_t* p = (byte_t*)FB.RoData() + ( FB.Size() - klv_intpack_size );
// test the AssetID length
- if ( ! read_test_BER(&p, UUIDlen) )
+ if ( ! Kumu::read_test_BER(&p, UUIDlen) )
return RESULT_HMACFAIL;
// test the AssetID
@@ -441,10 +439,10 @@ ASDCP::IntegrityPack::TestValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID,
p += UUIDlen;
// test the sequence length
- if ( ! read_test_BER(&p, sizeof(ui64_t)) )
+ if ( ! Kumu::read_test_BER(&p, sizeof(ui64_t)) )
return RESULT_HMACFAIL;
- ui32_t test_sequence = (ui32_t)ASDCP_i64_BE(cp2i<ui64_t>(p));
+ ui32_t test_sequence = (ui32_t)KM_i64_BE(Kumu::cp2i<ui64_t>(p));
// test the sequence value
if ( test_sequence != sequence )
@@ -456,7 +454,7 @@ ASDCP::IntegrityPack::TestValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID,
p += sizeof(ui64_t);
// test the HMAC length
- if ( ! read_test_BER(&p, HMAC_SIZE) )
+ if ( ! Kumu::read_test_BER(&p, HMAC_SIZE) )
return RESULT_HMACFAIL;
// test the HMAC
diff --git a/src/AS_DCP_PCM.cpp b/src/AS_DCP_PCM.cpp
index 8036745..a4f9b5f 100755
--- a/src/AS_DCP_PCM.cpp
+++ b/src/AS_DCP_PCM.cpp
@@ -219,7 +219,7 @@ ASDCP::PCM::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
m_FrameNumber, m_Size);
if ( dump_len )
- hexdump(m_Data, dump_len, stream);
+ Kumu::hexdump(m_Data, dump_len, stream);
}
//------------------------------------------------------------------------------------------
diff --git a/src/AS_DCP_internal.h b/src/AS_DCP_internal.h
index 173540d..4a00ba0 100755
--- a/src/AS_DCP_internal.h
+++ b/src/AS_DCP_internal.h
@@ -29,14 +29,16 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief AS-DCP library, non-public common elements
*/
-#ifndef _AS_DCP_INTERNAL_H__
-#define _AS_DCP_INTERNAL_H__
+#ifndef _AS_DCP_INTERNAL_H_
+#define _AS_DCP_INTERNAL_H_
-#include "AS_DCP_system.h"
+#include <KM_platform.h>
+#include <KM_util.h>
+#include <KM_log.h>
#include "Metadata.h"
-#include "hex_utils.h"
-using namespace std;
+using Kumu::DefaultLogSink;
+// using namespace std;
using namespace ASDCP;
using namespace ASDCP::MXF;
@@ -45,7 +47,6 @@ using namespace ASDCP::MXF;
namespace ASDCP
{
// constant values used to calculate KLV and EKLV packet sizes
-
static const ui32_t klv_cryptinfo_size =
MXF_BER_LENGTH
+ UUIDlen /* ContextID */
@@ -95,7 +96,7 @@ namespace ASDCP
ASDCP_NO_COPY_CONSTRUCT(h__Reader);
public:
- FileReader m_File;
+ Kumu::FileReader m_File;
OPAtomHeader m_HeaderPart;
Partition m_BodyPart;
OPAtomIndexFooter m_FooterPart;
@@ -157,7 +158,7 @@ namespace ASDCP
ASDCP_NO_COPY_CONSTRUCT(h__Writer);
public:
- FileWriter m_File;
+ Kumu::FileWriter m_File;
ui32_t m_HeaderSize;
OPAtomHeader m_HeaderPart;
Partition m_BodyPart;
@@ -220,7 +221,7 @@ namespace ASDCP
} // namespace ASDCP
-#endif // _AS_DCP_INTERNAL_H__
+#endif // _AS_DCP_INTERNAL_H_
//
diff --git a/src/Dict.cpp b/src/Dict.cpp
index fa51fbd..e2aadcb 100755
--- a/src/Dict.cpp
+++ b/src/Dict.cpp
@@ -30,12 +30,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "Mutex.h"
+#include "KM_mutex.h"
#include "KLV.h"
#include "MDD.cpp"
#include <map>
-static ASDCP::Mutex s_Lock;
+static Kumu::Mutex s_Lock;
static bool s_md_init = false;
static std::map<ASDCP::UL, ui32_t> s_md_lookup;
@@ -56,7 +56,8 @@ ASDCP::Dict::FindUL(const byte_t* ul_buf)
{
if ( ! s_md_init )
{
- AutoMutex AL(s_Lock);
+ Kumu::AutoMutex AL(s_Lock);
+
if ( ! s_md_init )
{
for ( ui32_t x = 0; x < s_MDD_Table_size; x++ )
diff --git a/src/Index.cpp b/src/Index.cpp
index 0f243f8..a7bedb1 100755
--- a/src/Index.cpp
+++ b/src/Index.cpp
@@ -60,22 +60,6 @@ ASDCP::MXF::IndexTableSegment::InitFromTLVSet(TLVReader& TLVSet)
if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi8(OBJ_READ_ARGS(IndexTableSegmentBase, PosTableCount));
if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(IndexTableSegment, DeltaEntryArray));
if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(IndexTableSegment, IndexEntryArray));
-
-#if 0
- if ( ASDCP_SUCCESS(result) )
- {
- Batch<IndexEntry>::iterator i;
- ui32_t offset = 0;
- for ( i = IndexEntryArray.begin(); i != IndexEntryArray.end(); i++ )
- {
- if ( (*i).Flags == 0x40 )
- offset = 0;
-
- (*i).KeyFrameOffset = offset++;
- }
- }
-#endif
-
return result;
}
@@ -123,7 +107,7 @@ ASDCP::MXF::IndexTableSegment::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " IndexEditRate = %s\n", IndexEditRate.ToString(identbuf));
+ fprintf(stream, " IndexEditRate = %s\n", IndexEditRate.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " IndexStartPosition = %s\n", i64sz(IndexStartPosition, identbuf));
fprintf(stream, " IndexDuration = %s\n", i64sz(IndexDuration, identbuf));
fprintf(stream, " EditUnitByteCount = %lu\n", EditUnitByteCount);
@@ -150,30 +134,30 @@ ASDCP::MXF::IndexTableSegment::Dump(FILE* stream)
//
const char*
-ASDCP::MXF::IndexTableSegment::DeltaEntry::ToString(char* str_buf) const
+ASDCP::MXF::IndexTableSegment::DeltaEntry::EncodeString(char* str_buf, ui32_t buf_len) const
{
- snprintf(str_buf, IdentBufferLen, "%3i %-3hu %-3lu", PosTableIndex, Slice, ElementData);
+ snprintf(str_buf, buf_len, "%3i %-3hu %-3lu", PosTableIndex, Slice, ElementData);
return str_buf;
}
//
-ASDCP::Result_t
-ASDCP::MXF::IndexTableSegment::DeltaEntry::Unarchive(ASDCP::MemIOReader& Reader)
+bool
+ASDCP::MXF::IndexTableSegment::DeltaEntry::Unarchive(Kumu::MemIOReader* Reader)
{
- Result_t result = Reader.ReadUi8((ui8_t*)&PosTableIndex);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi8(&Slice);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi32BE(&ElementData);
- return result;
+ if ( ! Reader->ReadUi8((ui8_t*)&PosTableIndex) ) return false;
+ if ( ! Reader->ReadUi8(&Slice) ) return false;
+ if ( ! Reader->ReadUi32BE(&ElementData) ) return false;
+ return true;
}
//
-ASDCP::Result_t
-ASDCP::MXF::IndexTableSegment::DeltaEntry::Archive(ASDCP::MemIOWriter& Writer) const
+bool
+ASDCP::MXF::IndexTableSegment::DeltaEntry::Archive(Kumu::MemIOWriter* Writer) const
{
- Result_t result = Writer.WriteUi8((ui8_t)PosTableIndex);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi8(Slice);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi32BE(ElementData);
- return result;
+ if ( ! Writer->WriteUi8((ui8_t)PosTableIndex) ) return false;
+ if ( ! Writer->WriteUi8(Slice) ) return false;
+ if ( ! Writer->WriteUi32BE(ElementData) ) return false;
+ return true;
}
//------------------------------------------------------------------------------------------
@@ -193,7 +177,7 @@ ASDCP::MXF::IndexTableSegment::DeltaEntry::Archive(ASDCP::MemIOWriter& Writer) c
//
const char*
-ASDCP::MXF::IndexTableSegment::IndexEntry::ToString(char* str_buf) const
+ASDCP::MXF::IndexTableSegment::IndexEntry::EncodeString(char* str_buf, ui32_t buf_len) const
{
char intbuf[IntBufferLen];
char txt_flags[6];
@@ -205,33 +189,33 @@ ASDCP::MXF::IndexTableSegment::IndexEntry::ToString(char* str_buf) const
txt_flags[4] = ( (Flags & 0x0f) == 3 ) ? 'B' : ( (Flags & 0x0f) == 2 ) ? 'P' : 'I';
txt_flags[5] = 0;
- snprintf(str_buf, IdentBufferLen, "%3i %-3hu %s %s",
- TemporalOffset, KeyFrameOffset, txt_flags,
- i64sz(StreamOffset, intbuf));
+ snprintf(str_buf, buf_len, "%3i %-3hu %s %s",
+ TemporalOffset, KeyFrameOffset, txt_flags,
+ i64sz(StreamOffset, intbuf));
return str_buf;
}
//
-ASDCP::Result_t
-ASDCP::MXF::IndexTableSegment::IndexEntry::Unarchive(ASDCP::MemIOReader& Reader)
+bool
+ASDCP::MXF::IndexTableSegment::IndexEntry::Unarchive(Kumu::MemIOReader* Reader)
{
- Result_t result = Reader.ReadUi8((ui8_t*)&TemporalOffset);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi8((ui8_t*)&KeyFrameOffset);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi8(&Flags);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi64BE(&StreamOffset);
- return result;
+ if ( ! Reader->ReadUi8((ui8_t*)&TemporalOffset) ) return false;
+ if ( ! Reader->ReadUi8((ui8_t*)&KeyFrameOffset) ) return false;
+ if ( ! Reader->ReadUi8(&Flags) ) return false;
+ if ( ! Reader->ReadUi64BE(&StreamOffset) ) return false;
+ return true;
}
//
-ASDCP::Result_t
-ASDCP::MXF::IndexTableSegment::IndexEntry::Archive(ASDCP::MemIOWriter& Writer) const
+bool
+ASDCP::MXF::IndexTableSegment::IndexEntry::Archive(Kumu::MemIOWriter* Writer) const
{
- Result_t result = Writer.WriteUi8((ui8_t)TemporalOffset);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi8((ui8_t)KeyFrameOffset);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi8(Flags);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi64BE(StreamOffset);
- return result;
+ if ( ! Writer->WriteUi8((ui8_t)TemporalOffset) ) return false;
+ if ( ! Writer->WriteUi8((ui8_t)KeyFrameOffset) ) return false;
+ if ( ! Writer->WriteUi8(Flags) ) return false;
+ if ( ! Writer->WriteUi64BE(StreamOffset) ) return false;
+ return true;
}
diff --git a/src/JP2K.cpp b/src/JP2K.cpp
index 20ec891..ee979ba 100755
--- a/src/JP2K.cpp
+++ b/src/JP2K.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2005, John Hurst
+Copyright (c) 2005-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <JP2K.h>
-#include <hex_utils.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
// when indexed with the second byte of a marker code, this table will procuce one of
@@ -161,7 +162,7 @@ ASDCP::JP2K::Accessor::COM::Dump(FILE* stream)
}
else
{
- hexdump(CommentData(), CommentSize(), stream);
+ Kumu::hexdump(CommentData(), CommentSize(), stream);
}
}
@@ -218,5 +219,5 @@ ASDCP::JP2K::GetMarkerString(Marker_t m)
}
//
-// end
+// end JP2K.cpp
//
diff --git a/src/JP2K.h b/src/JP2K.h
index cff77b2..7e63fd2 100755
--- a/src/JP2K.h
+++ b/src/JP2K.h
@@ -36,8 +36,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define _JP2K_H_
// AS_DCP.h is included only for it's base type definitions.
-#include <AS_DCP_system.h>
-#include <hex_utils.h>
+#include <KM_platform.h>
+#include <KM_util.h>
+#include <AS_DCP.h>
#include <assert.h>
namespace ASDCP
@@ -76,7 +77,7 @@ namespace JP2K
//
class Marker
{
- ASDCP_NO_COPY_CONSTRUCT(Marker);
+ KM_NO_COPY_CONSTRUCT(Marker);
public:
Marker_t m_Type;
@@ -100,7 +101,7 @@ namespace JP2K
class SIZ
{
const byte_t* m_MarkerData;
- ASDCP_NO_COPY_CONSTRUCT(SIZ);
+ KM_NO_COPY_CONSTRUCT(SIZ);
SIZ();
public:
@@ -112,16 +113,16 @@ namespace JP2K
~SIZ() {}
- inline ui16_t Rsize() { return ASDCP_i16_BE(*(ui16_t*)m_MarkerData); }
- inline ui32_t Xsize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 2)); }
- inline ui32_t Ysize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 6)); }
- inline ui32_t XOsize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 10)); }
- inline ui32_t YOsize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 14)); }
- inline ui32_t XTsize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 18)); }
- inline ui32_t YTsize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 22)); }
- inline ui32_t XTOsize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 26)); }
- inline ui32_t YTOsize() { return ASDCP_i32_BE(*(ui32_t*)(m_MarkerData + 30)); }
- inline ui16_t Csize() { return ASDCP_i16_BE(*(ui16_t*)(m_MarkerData + 34)); }
+ inline ui16_t Rsize() { return KM_i16_BE(*(ui16_t*)m_MarkerData); }
+ inline ui32_t Xsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 2)); }
+ inline ui32_t Ysize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 6)); }
+ inline ui32_t XOsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 10)); }
+ inline ui32_t YOsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 14)); }
+ inline ui32_t XTsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 18)); }
+ inline ui32_t YTsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 22)); }
+ inline ui32_t XTOsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 26)); }
+ inline ui32_t YTOsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 30)); }
+ inline ui16_t Csize() { return KM_i16_BE(*(ui16_t*)(m_MarkerData + 34)); }
void ReadComponent(ui32_t index, ImageComponent& IC);
void Dump(FILE* stream = 0);
};
@@ -133,7 +134,7 @@ namespace JP2K
const byte_t* m_MarkerData;
ui32_t m_DataSize;
- ASDCP_NO_COPY_CONSTRUCT(COM);
+ KM_NO_COPY_CONSTRUCT(COM);
COM();
public:
diff --git a/src/JP2K_Codestream_Parser.cpp b/src/JP2K_Codestream_Parser.cpp
index 216827b..700233f 100755
--- a/src/JP2K_Codestream_Parser.cpp
+++ b/src/JP2K_Codestream_Parser.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004, John Hurst
+Copyright (c) 2004-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -29,10 +29,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief AS-DCP library, JPEG 2000 codestream essence reader implementation
*/
+#include <KM_fileio.h>
#include <AS_DCP.h>
-#include <FileIO.h>
#include <JP2K.h>
#include <assert.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
//------------------------------------------------------------------------------------------
@@ -42,7 +44,7 @@ class ASDCP::JP2K::CodestreamParser::h__CodestreamParser
public:
PictureDescriptor m_PDesc;
- FileReader m_File;
+ Kumu::FileReader m_File;
h__CodestreamParser()
{
@@ -61,7 +63,7 @@ public:
if ( ASDCP_SUCCESS(result) )
{
- fsize_t file_size = m_File.Size();
+ Kumu::fsize_t file_size = m_File.Size();
if ( FB.Capacity() < file_size )
{
diff --git a/src/JP2K_Sequence_Parser.cpp b/src/JP2K_Sequence_Parser.cpp
index 8d1b63c..cd93583 100755
--- a/src/JP2K_Sequence_Parser.cpp
+++ b/src/JP2K_Sequence_Parser.cpp
@@ -30,8 +30,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <AS_DCP.h>
-#include <FileIO.h>
-#include <DirScanner.h>
+#include <KM_fileio.h>
#include <list>
#include <string>
#include <algorithm>
@@ -54,8 +53,8 @@ public:
//
Result_t InitFromDirectory(const char* path)
{
- char next_file[ASDCP_MAX_PATH];
- DirScanner Scanner;
+ char next_file[Kumu::MaxFilePath];
+ Kumu::DirScanner Scanner;
Result_t result = Scanner.Open(path);
@@ -139,7 +138,7 @@ ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const char* filename)
CodestreamParser Parser;
FrameBuffer TmpBuffer;
- fsize_t file_size = FileSize((*m_CurrentFile).c_str());
+ Kumu::fsize_t file_size = Kumu::FileSize((*m_CurrentFile).c_str());
if ( file_size == 0 )
result = RESULT_NOT_FOUND;
diff --git a/src/KLV.cpp b/src/KLV.cpp
index 63c1e54..f4a1580 100755
--- a/src/KLV.cpp
+++ b/src/KLV.cpp
@@ -30,7 +30,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "KLV.h"
-#include <hex_utils.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
// This is how much we read when we're reading from a file and we don't know
@@ -69,7 +70,7 @@ ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
return RESULT_FAIL;
}
- ui32_t ber_len = BER_length(buf + SMPTE_UL_LENGTH);
+ ui32_t ber_len = Kumu::BER_length(buf + SMPTE_UL_LENGTH);
if ( ber_len > ( buf_len - SMPTE_UL_LENGTH ) )
{
@@ -79,16 +80,16 @@ ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
if ( ber_len == 0 )
{
- ASDCP::DefaultLogSink().Error("KLV format error, zero BER length not allowed\n");
+ DefaultLogSink().Error("KLV format error, zero BER length not allowed\n");
return RESULT_FAIL;
}
ui64_t tmp_size;
- if ( ! read_BER(buf + SMPTE_UL_LENGTH, &tmp_size) )
+ if ( ! Kumu::read_BER(buf + SMPTE_UL_LENGTH, &tmp_size) )
return RESULT_FAIL;
m_ValueLength = tmp_size;
- m_KLLength = SMPTE_UL_LENGTH + BER_length(buf + SMPTE_UL_LENGTH);
+ m_KLLength = SMPTE_UL_LENGTH + Kumu::BER_length(buf + SMPTE_UL_LENGTH);
m_KeyStart = buf;
m_ValueStart = buf + m_KLLength;
return RESULT_OK;
@@ -116,7 +117,7 @@ ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const byte_t* labe
memcpy(Buffer.Data() + Buffer.Size(), label, SMPTE_UL_LENGTH);
- if ( ! write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
+ if ( ! Kumu::write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
return RESULT_FAIL;
Buffer.Size(Buffer.Size() + kl_length);
@@ -141,7 +142,7 @@ ASDCP::KLVPacket::Dump(FILE* stream, bool show_hex)
fprintf(stream, "\b len: %7lu (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
if ( show_hex && m_ValueLength < 1000 )
- hexdump(m_ValueStart, ASDCP::xmin(m_ValueLength, (ui32_t)64), stream);
+ Kumu::hexdump(m_ValueStart, Kumu::xmin(m_ValueLength, (ui32_t)64), stream);
}
else
{
@@ -151,7 +152,7 @@ ASDCP::KLVPacket::Dump(FILE* stream, bool show_hex)
//
ASDCP::Result_t
-ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader, const byte_t* label)
+ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader, const byte_t* label)
{
Result_t result = KLVFilePacket::InitFromFile(Reader);
@@ -164,7 +165,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader, const byte_t* label
// TODO: refactor to use InitFromBuffer
ASDCP::Result_t
-ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
+ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader)
{
ui32_t read_count;
byte_t tmp_data[tmp_read_size];
@@ -191,7 +192,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
return RESULT_FAIL;
}
- if ( ! read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
+ if ( ! Kumu::read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
{
DefaultLogSink().Error("BER Length decoding error\n");
return RESULT_FAIL;
@@ -199,14 +200,13 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
if ( tmp_size > MAX_KLV_PACKET_LENGTH )
{
- char intbuf[IntBufferLen];
- DefaultLogSink().Error("Packet length %s exceeds internal limit\n",
- ui64sz(tmp_size, intbuf));
+ Kumu::ui64Printer tmp_size_str(tmp_size);
+ DefaultLogSink().Error("Packet length %s exceeds internal limit\n", tmp_size_str.c_str());
return RESULT_FAIL;
}
ui32_t remainder = 0;
- ui32_t ber_len = BER_length(tmp_data + SMPTE_UL_LENGTH);
+ ui32_t ber_len = Kumu::BER_length(tmp_data + SMPTE_UL_LENGTH);
m_KLLength = SMPTE_UL_LENGTH + ber_len;
m_ValueLength = tmp_size;
ui32_t packet_length = m_ValueLength + m_KLLength;
@@ -229,7 +229,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
if ( (remainder = read_count - packet_length) != 0 )
{
DefaultLogSink().Warn("Repositioning pointer for short packet\n");
- ASDCP::fpos_t pos = Reader.Tell();
+ Kumu::fpos_t pos = Reader.Tell();
assert(pos > remainder);
result = Reader.Seek(pos - remainder);
}
@@ -264,12 +264,12 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
//
ASDCP::Result_t
-ASDCP::KLVFilePacket::WriteKLToFile(FileWriter& Writer, const byte_t* label, ui32_t length)
+ASDCP::KLVFilePacket::WriteKLToFile(Kumu::FileWriter& Writer, const byte_t* label, ui32_t length)
{
byte_t buffer[kl_length];
memcpy(buffer, label, SMPTE_UL_LENGTH);
- if ( ! write_BER(buffer+SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
+ if ( ! Kumu::write_BER(buffer+SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
return RESULT_FAIL;
ui32_t write_count;
diff --git a/src/KLV.h b/src/KLV.h
index 9eb230b..9c274bf 100755
--- a/src/KLV.h
+++ b/src/KLV.h
@@ -32,8 +32,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _KLV_H_
#define _KLV_H_
-#include "FileIO.h"
-#include "MemIO.h"
+#include <KM_fileio.h>
+#include <KM_memio.h>
+#include "AS_DCP.h"
#include "MDD.h"
@@ -48,6 +49,30 @@ namespace ASDCP
const ui32_t IdentBufferLen = 128;
+const ui32_t IntBufferLen = 64;
+
+inline const char* i64sz(i64_t i, char* buf)
+{
+ assert(buf);
+#ifdef WIN32
+ snprintf(buf, IntBufferLen, "%I64d", i);
+#else
+ snprintf(buf, IntBufferLen, "%lld", i);
+#endif
+ return buf;
+}
+
+inline const char* ui64sz(ui64_t i, char* buf)
+{
+ assert(buf);
+#ifdef WIN32
+ snprintf(buf, IntBufferLen, "%I64u", i);
+#else
+ snprintf(buf, IntBufferLen, "%llu", i);
+#endif
+ return buf;
+}
+
struct TagValue
{
byte_t a;
@@ -66,21 +91,47 @@ namespace ASDCP
}
};
- //
- class IArchive
+ using Kumu::UUID;
+
+ // Universal Label
+ class UL : public Kumu::Identifier<SMPTE_UL_LENGTH>
{
public:
- virtual ~IArchive() {}
- virtual Result_t Unarchive(ASDCP::MemIOReader& Reader) = 0;
- virtual bool HasValue() const = 0;
- virtual Result_t Archive(ASDCP::MemIOWriter& Writer) const = 0;
+ UL() {}
+ UL(const byte_t* rhs) {
+ assert(rhs);
+ Set(rhs);
+ }
+
+ UL(const UL& rhs) {
+ Set(rhs.m_Value);
+ }
+
+ virtual ~UL() {}
+
+ bool operator==(const UL& rhs) const {
+ return ( memcmp(m_Value, rhs.m_Value, SMPTE_UL_LENGTH) == 0 ) ? true : false;
+ }
+
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
+ };
+
+ // UMID
+ class UMID : public Kumu::Identifier<SMPTE_UMID_LENGTH>
+ {
+ public:
+ UMID() {}
+ UMID(const UMID &rhs) {
+ Set(rhs.m_Value);
+ };
+ virtual ~UMID() {}
+
+ void MakeUMID(int Type);
+ void MakeUMID(int Type, const UUID& ID);
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
};
-} // namespace ASDCP
-#include "Identifier.h"
-namespace ASDCP
-{
//
struct MDDEntry
{
@@ -164,9 +215,9 @@ namespace ASDCP
KLVFilePacket() {}
virtual ~KLVFilePacket() {}
- virtual Result_t InitFromFile(const FileReader&);
- virtual Result_t InitFromFile(const FileReader&, const byte_t* label);
- virtual Result_t WriteKLToFile(FileWriter& Writer, const byte_t* label, ui32_t length);
+ virtual Result_t InitFromFile(const Kumu::FileReader&);
+ virtual Result_t InitFromFile(const Kumu::FileReader&, const byte_t* label);
+ virtual Result_t WriteKLToFile(Kumu::FileWriter& Writer, const byte_t* label, ui32_t length);
};
} // namespace ASDCP
diff --git a/src/KM_error.h b/src/KM_error.h
new file mode 100755
index 0000000..612a92c
--- /dev/null
+++ b/src/KM_error.h
@@ -0,0 +1,117 @@
+/*
+Copyright (c) 2004-2006, 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_
+
+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
+ {
+ long value;
+ const char* label;
+ Result_t();
+
+ public:
+ Result_t(long v, const char* l) : value(v), label(l) {}
+ 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() { return ( value >= 0 ); }
+ inline bool Failure() { return ( value < 0 ); }
+
+ inline long Value() { return value; }
+ inline operator long() const { return value; }
+
+ inline const char* Label() { return label; }
+ inline operator const char*() const { return label; }
+ };
+
+ const Result_t RESULT_FALSE ( 1, "Successful but not true.");
+ const Result_t RESULT_OK ( 0, "Success.");
+ const Result_t RESULT_FAIL (-1, "An undefined error was detected.");
+ const Result_t RESULT_PTR (-2, "An unexpected NULL pointer was given.");
+ const Result_t RESULT_NULL_STR (-3, "An unexpected empty string was given.");
+ const Result_t RESULT_ALLOC (-4, "Error allocating memory.");
+ const Result_t RESULT_PARAM (-5, "Invalid parameter.");
+ const Result_t RESULT_NOTIMPL (-6, "Unimplemented Feature.");
+ const Result_t RESULT_SMALLBUF (-7, "The given buffer is too small.");
+ const Result_t RESULT_INIT (-8, "The object is not yet initialized.");
+ const Result_t RESULT_NOT_FOUND (-9, "The requested file does not exist on the system.");
+ const Result_t RESULT_NO_PERM (-10, "Insufficient privilege exists to perform the operation.");
+ const Result_t RESULT_STATE (-11, "Object state error.");
+ const Result_t RESULT_CONFIG (-12, "Invalid configuration option detected.");
+ const Result_t RESULT_FILEOPEN (-13, "File open failure.");
+ const Result_t RESULT_BADSEEK (-14, "An invalid file location was requested.");
+ const Result_t RESULT_READFAIL (-15, "File read error.");
+ const Result_t RESULT_WRITEFAIL (-16, "File write error.");
+ const Result_t RESULT_ENDOFFILE (-17, "Attempt to read past end of file.");
+ const Result_t RESULT_FILEEXISTS (-18, "Filename already exists.");
+ const Result_t RESULT_NOTAFILE (-19, "Filename not found.");
+} // 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; \
+ }
+
+// 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; \
+ }
+
+#endif // _KM_ERROR_H_
+
+//
+// end KM_error.h
+//
diff --git a/src/KM_fileio.cpp b/src/KM_fileio.cpp
new file mode 100644
index 0000000..1ed32fb
--- /dev/null
+++ b/src/KM_fileio.cpp
@@ -0,0 +1,801 @@
+/*
+Copyright (c) 2004-2006, 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.cpp
+ \version $Id$
+ \brief portable file i/o
+ */
+
+#include <KM_fileio.h>
+#include <KM_log.h>
+#include <fcntl.h>
+#include <assert.h>
+
+using namespace Kumu;
+
+#ifdef KM_WIN32
+typedef struct _stati64 fstat_t;
+
+// AFAIK, there is no iovec equivalent in the win32 API
+struct iovec {
+ char* iov_base; // stupid iovec uses char*
+ int iov_len;
+};
+#else
+#include <sys/uio.h>
+typedef struct stat fstat_t;
+#endif
+
+//
+static Kumu::Result_t
+do_stat(const char* path, fstat_t* stat_info)
+{
+ KM_TEST_NULL_STR(path);
+ KM_TEST_NULL(stat_info);
+
+ Kumu::Result_t result = Kumu::RESULT_OK;
+
+#ifdef KM_WIN32
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+
+ if ( _stati64(path, stat_info) == (__int64)-1 )
+ result = Kumu::RESULT_FILEOPEN;
+
+ ::SetErrorMode( prev );
+#else
+ if ( stat(path, stat_info) == -1L )
+ result = Kumu::RESULT_FILEOPEN;
+
+ if ( stat_info->st_mode & (S_IFREG|S_IFLNK|S_IFDIR) == 0 )
+ result = Kumu::RESULT_FILEOPEN;
+#endif
+
+ return result;
+}
+
+#ifndef KM_WIN32
+
+//
+static Kumu::Result_t
+do_fstat(HANDLE handle, fstat_t* stat_info)
+{
+ KM_TEST_NULL(stat_info);
+
+ Kumu::Result_t result = Kumu::RESULT_OK;
+
+ if ( fstat(handle, stat_info) == -1L )
+ result = Kumu::RESULT_FILEOPEN;
+
+ if ( stat_info->st_mode & (S_IFREG|S_IFLNK|S_IFDIR) == 0 )
+ result = Kumu::RESULT_FILEOPEN;
+
+ return result;
+}
+
+#endif
+
+
+//
+bool
+Kumu::PathIsFile(const char* pathname)
+{
+ assert(pathname);
+ fstat_t info;
+
+ if ( KM_SUCCESS(do_stat(pathname, &info)) )
+ {
+ if ( info.st_mode & S_IFREG )
+ return true;
+ }
+
+ return false;
+}
+
+
+//
+bool
+Kumu::PathIsDirectory(const char* pathname)
+{
+ assert(pathname);
+ fstat_t info;
+
+ if ( KM_SUCCESS(do_stat(pathname, &info)) )
+ {
+ if ( info.st_mode & S_IFDIR )
+ return true;
+ }
+
+ return false;
+}
+
+
+//
+Kumu::fsize_t
+Kumu::FileSize(const char* pathname)
+{
+ assert(pathname);
+ fstat_t info;
+
+ if ( KM_SUCCESS(do_stat(pathname, &info)) )
+ {
+ if ( info.st_mode & S_IFREG )
+ return(info.st_size);
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------------------
+// portable aspects of the file classes
+
+const int IOVecMaxEntries = 32; // we never use more that 3, but that number seems somehow small...
+
+//
+class Kumu::FileWriter::h__iovec
+{
+public:
+ int m_Count;
+ struct iovec m_iovec[IOVecMaxEntries];
+ h__iovec() : m_Count(0) {}
+};
+
+
+
+//
+Kumu::fsize_t
+Kumu::FileReader::Size() const
+{
+#ifdef KM_WIN32
+ return FileSize(m_Filename.c_str());
+#else
+ fstat_t info;
+
+ if ( KM_SUCCESS(do_fstat(m_Handle, &info)) )
+ {
+ if ( info.st_mode & S_IFREG )
+ return(info.st_size);
+ }
+#endif
+
+ return 0;
+}
+
+// these are declared here instead of in the header file
+// because we have a mem_ptr that is managing a hidden class
+Kumu::FileWriter::FileWriter() {}
+Kumu::FileWriter::~FileWriter() {}
+
+//
+Kumu::Result_t
+Kumu::FileWriter::Writev(const byte_t* buf, ui32_t buf_len)
+{
+ assert( ! m_IOVec.empty() );
+ register h__iovec* iov = m_IOVec;
+ KM_TEST_NULL(buf);
+
+ if ( iov->m_Count >= IOVecMaxEntries )
+ {
+ DefaultLogSink().Error("The iovec is full! Only %lu entries allowed before a flush.\n",
+ IOVecMaxEntries);
+ return RESULT_FAIL;
+ }
+
+ iov->m_iovec[iov->m_Count].iov_base = (char*)buf; // stupid iovec uses char*
+ iov->m_iovec[iov->m_Count].iov_len = buf_len;
+ iov->m_Count++;
+
+ return RESULT_OK;
+}
+
+
+#ifdef KM_WIN32
+//------------------------------------------------------------------------------------------
+//
+
+Kumu::Result_t
+Kumu::FileReader::OpenRead(const char* filename) const
+{
+ KM_TEST_NULL_STR(filename);
+ const_cast<FileReader*>(this)->m_Filename = filename;
+
+ // suppress popup window on error
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+
+ const_cast<FileReader*>(this)->m_Handle = ::CreateFile(filename,
+ (GENERIC_READ), // open for reading
+ FILE_SHARE_READ, // share for reading
+ NULL, // no security
+ OPEN_EXISTING, // read
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL // no template file
+ );
+
+ ::SetErrorMode(prev);
+
+ return ( m_Handle == INVALID_HANDLE_VALUE ) ?
+ Kumu::RESULT_FILEOPEN : Kumu::RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Close() const
+{
+ if ( m_Handle == INVALID_HANDLE_VALUE )
+ return Kumu::RESULT_FILEOPEN;
+
+ // suppress popup window on error
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ BOOL result = ::CloseHandle(m_Handle);
+ ::SetErrorMode(prev);
+ const_cast<FileReader*>(this)->m_Handle = INVALID_HANDLE_VALUE;
+
+ return ( result == 0 ) ? Kumu::RESULT_FAIL : Kumu::RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Seek(Kumu::fpos_t position, SeekPos_t whence) const
+{
+ if ( m_Handle == INVALID_HANDLE_VALUE )
+ return Kumu::RESULT_STATE;
+
+ LARGE_INTEGER in;
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ in.QuadPart = position;
+ in.LowPart = ::SetFilePointer(m_Handle, in.LowPart, &in.HighPart, whence);
+ HRESULT LastError = GetLastError();
+ ::SetErrorMode(prev);
+
+ if ( (LastError != NO_ERROR
+ && (in.LowPart == INVALID_SET_FILE_POINTER
+ || in.LowPart == ERROR_NEGATIVE_SEEK )) )
+ return Kumu::RESULT_READFAIL;
+
+ return Kumu::RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Tell(Kumu::fpos_t* pos) const
+{
+ KM_TEST_NULL(pos);
+
+ if ( m_Handle == (HANDLE)-1L )
+ return Kumu::RESULT_FILEOPEN;
+
+ LARGE_INTEGER in;
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ in.QuadPart = (__int64)0;
+ in.LowPart = ::SetFilePointer(m_Handle, in.LowPart, &in.HighPart, FILE_CURRENT);
+ HRESULT LastError = GetLastError();
+ ::SetErrorMode(prev);
+
+ if ( (LastError != NO_ERROR
+ && (in.LowPart == INVALID_SET_FILE_POINTER
+ || in.LowPart == ERROR_NEGATIVE_SEEK )) )
+ return Kumu::RESULT_READFAIL;
+
+ *pos = (Kumu::fpos_t)in.QuadPart;
+ return Kumu::RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Read(byte_t* buf, ui32_t buf_len, ui32_t* read_count) const
+{
+ KM_TEST_NULL(buf);
+ Result_t result = Kumu::RESULT_OK;
+ DWORD tmp_count;
+ ui32_t tmp_int;
+
+ if ( read_count == 0 )
+ read_count = &tmp_int;
+
+ *read_count = 0;
+
+ if ( m_Handle == INVALID_HANDLE_VALUE )
+ return Kumu::RESULT_FILEOPEN;
+
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ if ( ::ReadFile(m_Handle, buf, buf_len, &tmp_count, NULL) == 0 )
+ result = Kumu::RESULT_READFAIL;
+
+ ::SetErrorMode(prev);
+
+ if ( tmp_count == 0 ) /* EOF */
+ result = Kumu::RESULT_ENDOFFILE;
+
+ if ( KM_SUCCESS(result) )
+ *read_count = tmp_count;
+
+ return result;
+}
+
+
+
+//------------------------------------------------------------------------------------------
+//
+
+//
+Kumu::Result_t
+Kumu::FileWriter::OpenWrite(const char* filename)
+{
+ KM_TEST_NULL_STR(filename);
+ m_Filename = filename;
+
+ // suppress popup window on error
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+
+ m_Handle = ::CreateFile(filename,
+ (GENERIC_WRITE|GENERIC_READ), // open for reading
+ FILE_SHARE_READ, // share for reading
+ NULL, // no security
+ CREATE_ALWAYS, // overwrite (beware!)
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL // no template file
+ );
+
+ ::SetErrorMode(prev);
+
+ if ( m_Handle == INVALID_HANDLE_VALUE )
+ return Kumu::RESULT_FILEOPEN;
+
+ m_IOVec = new h__iovec;
+ return Kumu::RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileWriter::Writev(ui32_t* bytes_written)
+{
+ assert( ! m_IOVec.empty() );
+ register h__iovec* iov = m_IOVec;
+ ui32_t tmp_int;
+
+ if ( bytes_written == 0 )
+ bytes_written = &tmp_int;
+
+ if ( m_Handle == INVALID_HANDLE_VALUE )
+ return Kumu::RESULT_STATE;
+
+ *bytes_written = 0;
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ Result_t result = Kumu::RESULT_OK;
+
+ // AFAIK, there is no writev() equivalent in the win32 API
+ for ( register int i = 0; i < iov->m_Count; i++ )
+ {
+ ui32_t tmp_count = 0;
+ BOOL wr_result = ::WriteFile(m_Handle,
+ iov->m_iovec[i].iov_base,
+ iov->m_iovec[i].iov_len,
+ (DWORD*)&tmp_count,
+ NULL);
+
+ if ( wr_result == 0 )
+ {
+ result = Kumu::RESULT_WRITEFAIL;
+ break;
+ }
+
+ assert(iov->m_iovec[i].iov_len == tmp_count);
+ *bytes_written += tmp_count;
+ }
+
+ ::SetErrorMode(prev);
+ iov->m_Count = 0; // error nor not, all is lost
+
+ return result;
+}
+
+//
+Kumu::Result_t
+Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written)
+{
+ KM_TEST_NULL(buf);
+ ui32_t tmp_int;
+
+ if ( bytes_written == 0 )
+ bytes_written = &tmp_int;
+
+ if ( m_Handle == INVALID_HANDLE_VALUE )
+ return Kumu::RESULT_STATE;
+
+ // suppress popup window on error
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ BOOL result = ::WriteFile(m_Handle, buf, buf_len, (DWORD*)bytes_written, NULL);
+ ::SetErrorMode(prev);
+
+ return ( result == 0 ) ? Kumu::RESULT_WRITEFAIL : Kumu::RESULT_OK;
+}
+
+#else // KM_WIN32
+//------------------------------------------------------------------------------------------
+// POSIX
+
+//
+Kumu::Result_t
+Kumu::FileReader::OpenRead(const char* filename) const
+{
+ KM_TEST_NULL_STR(filename);
+ const_cast<FileReader*>(this)->m_Filename = filename;
+ const_cast<FileReader*>(this)->m_Handle = open(filename, O_RDONLY, 0);
+ return ( m_Handle == -1L ) ? RESULT_FILEOPEN : RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Close() const
+{
+ if ( m_Handle == -1L )
+ return RESULT_FILEOPEN;
+
+ close(m_Handle);
+ const_cast<FileReader*>(this)->m_Handle = -1L;
+ return RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Seek(Kumu::fpos_t position, SeekPos_t whence) const
+{
+ if ( m_Handle == -1L )
+ return RESULT_FILEOPEN;
+
+ if ( lseek(m_Handle, position, whence) == -1L )
+ return RESULT_BADSEEK;
+
+ return RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Tell(Kumu::fpos_t* pos) const
+{
+ KM_TEST_NULL(pos);
+
+ if ( m_Handle == -1L )
+ return RESULT_FILEOPEN;
+
+ Kumu::fpos_t tmp_pos;
+
+ if ( (tmp_pos = lseek(m_Handle, 0, SEEK_CUR)) == -1 )
+ return RESULT_READFAIL;
+
+ *pos = tmp_pos;
+ return RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileReader::Read(byte_t* buf, ui32_t buf_len, ui32_t* read_count) const
+{
+ KM_TEST_NULL(buf);
+ i32_t tmp_count = 0;
+ ui32_t tmp_int = 0;
+
+ if ( read_count == 0 )
+ read_count = &tmp_int;
+
+ *read_count = 0;
+
+ if ( m_Handle == -1L )
+ return RESULT_FILEOPEN;
+
+ if ( (tmp_count = read(m_Handle, buf, buf_len)) == -1L )
+ return RESULT_READFAIL;
+
+ *read_count = tmp_count;
+ return (tmp_count == 0 ? RESULT_ENDOFFILE : RESULT_OK);
+}
+
+
+//------------------------------------------------------------------------------------------
+//
+
+//
+Kumu::Result_t
+Kumu::FileWriter::OpenWrite(const char* filename)
+{
+ KM_TEST_NULL_STR(filename);
+ m_Filename = filename;
+ m_Handle = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644);
+
+ if ( m_Handle == -1L )
+ {
+ DefaultLogSink().Error("Error opening file %s: %s\n", filename, strerror(errno));
+ return RESULT_FILEOPEN;
+ }
+
+ m_IOVec = new h__iovec;
+ return RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileWriter::OpenModify(const char* filename)
+{
+ KM_TEST_NULL_STR(filename);
+ m_Filename = filename;
+ m_Handle = open(filename, O_RDWR|O_CREAT, 0644);
+
+ if ( m_Handle == -1L )
+ {
+ DefaultLogSink().Error("Error opening file %s: %s\n", filename, strerror(errno));
+ return RESULT_FILEOPEN;
+ }
+
+ m_IOVec = new h__iovec;
+ return RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileWriter::Writev(ui32_t* bytes_written)
+{
+ assert( ! m_IOVec.empty() );
+ register h__iovec* iov = m_IOVec;
+ ui32_t tmp_int;
+
+ if ( bytes_written == 0 )
+ bytes_written = &tmp_int;
+
+ if ( m_Handle == -1L )
+ return RESULT_STATE;
+
+ int read_size = writev(m_Handle, iov->m_iovec, iov->m_Count);
+
+ if ( read_size == -1L )
+ return RESULT_WRITEFAIL;
+
+ iov->m_Count = 0;
+ *bytes_written = read_size;
+ return RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written)
+{
+ KM_TEST_NULL(buf);
+ ui32_t tmp_int;
+
+ if ( bytes_written == 0 )
+ bytes_written = &tmp_int;
+
+ // TODO: flush iovec
+
+
+ if ( m_Handle == -1L )
+ return RESULT_STATE;
+
+ int read_size = write(m_Handle, buf, buf_len);
+
+ if ( read_size == -1L )
+ return RESULT_WRITEFAIL;
+
+ *bytes_written = read_size;
+ return RESULT_OK;
+}
+
+
+#endif // KM_WIN32
+
+//------------------------------------------------------------------------------------------
+
+
+//
+Kumu::Result_t
+Kumu::ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size)
+{
+ fsize_t fsize = 0;
+ ui32_t read_size;
+ FileReader File;
+ ByteString ReadBuf;
+
+ KM_TEST_NULL_STR(filename);
+
+ Result_t result = File.OpenRead(filename);
+
+ if ( KM_SUCCESS(result) )
+ {
+ fsize = File.Size();
+
+ if ( fsize > max_size )
+ return RESULT_ALLOC;
+
+ result = ReadBuf.Capacity((ui32_t)fsize);
+ }
+
+ if ( KM_SUCCESS(result) )
+ result = File.Read(ReadBuf.Data(), ReadBuf.Capacity(), &read_size);
+
+ if ( KM_SUCCESS(result) )
+ outString.assign((const char*)ReadBuf.RoData(), read_size);
+
+ return result;
+}
+
+
+//------------------------------------------------------------------------------------------
+//
+
+// Win32 directory scanner
+//
+#ifdef KM_WIN32
+
+//
+//
+Result_t
+Kumu::DirScanner::Open(const char* filename)
+{
+ KM_TEST_NULL_STR(filename);
+
+ // we need to append a '*' to read the entire directory
+ ui32_t fn_len = strlen(filename);
+ char* tmp_file = (char*)malloc(fn_len + 8);
+
+ if ( tmp_file == 0 )
+ return RESULT_ALLOC;
+
+ strcpy(tmp_file, filename);
+ char* p = &tmp_file[fn_len] - 1;
+
+ if ( *p != '/' && *p != '\\' )
+ {
+ p++;
+ *p++ = '/';
+ }
+
+ *p++ = '*';
+ *p = 0;
+ // whew...
+
+ m_Handle = _findfirsti64(tmp_file, &m_FileInfo);
+ Result_t result = RESULT_OK;
+
+ if ( m_Handle == -1 )
+ result = RESULT_NOT_FOUND;
+
+ return result;
+}
+
+
+//
+//
+Result_t
+Kumu::DirScanner::Close()
+{
+ if ( m_Handle == -1 )
+ return RESULT_FILEOPEN;
+
+ if ( _findclose((long)m_Handle) == -1 )
+ return RESULT_FAIL;
+
+ m_Handle = -1;
+ return RESULT_OK;
+}
+
+
+// This sets filename param to the same per-instance buffer every time, so
+// the value will change on the next call
+Result_t
+Kumu::DirScanner::GetNext(char* filename)
+{
+ KM_TEST_NULL(filename);
+
+ if ( m_Handle == -1 )
+ return RESULT_FILEOPEN;
+
+ if ( m_FileInfo.name[0] == '\0' )
+ return RESULT_ENDOFFILE;
+
+ strncpy(filename, m_FileInfo.name, MaxFilePath);
+ Result_t result = RESULT_OK;
+
+ if ( _findnexti64((long)m_Handle, &m_FileInfo) == -1 )
+ {
+ m_FileInfo.name[0] = '\0';
+
+ if ( errno != ENOENT )
+ result = RESULT_FAIL;
+ }
+
+ return result;
+}
+
+
+#else // KM_WIN32
+
+// POSIX directory scanner
+
+//
+Result_t
+Kumu::DirScanner::Open(const char* filename)
+{
+ KM_TEST_NULL_STR(filename);
+
+ Result_t result = RESULT_OK;
+
+ if ( ( m_Handle = opendir(filename) ) == NULL )
+ {
+ if ( errno == ENOENT )
+ result = RESULT_ENDOFFILE;
+
+ else
+ result = RESULT_FAIL;
+ }
+
+ return result;
+}
+
+
+//
+Result_t
+Kumu::DirScanner::Close()
+{
+ if ( m_Handle == NULL )
+ return RESULT_FILEOPEN;
+
+ if ( closedir(m_Handle) == -1 )
+ return RESULT_FAIL;
+
+ m_Handle = NULL;
+ return RESULT_OK;
+}
+
+
+//
+Result_t
+Kumu::DirScanner::GetNext(char* filename)
+{
+ KM_TEST_NULL(filename);
+
+ if ( m_Handle == NULL )
+ return RESULT_FILEOPEN;
+
+ struct dirent* entry;
+
+ for (;;)
+ {
+ if ( ( entry = readdir(m_Handle)) == NULL )
+ return RESULT_ENDOFFILE;
+
+ break;
+ }
+
+ strncpy(filename, entry->d_name, MaxFilePath);
+ return RESULT_OK;
+}
+
+
+#endif // KM_WIN32
+
+
+
+//
+// end KM_fileio.cpp
+//
diff --git a/src/KM_fileio.h b/src/KM_fileio.h
new file mode 100755
index 0000000..9c79d49
--- /dev/null
+++ b/src/KM_fileio.h
@@ -0,0 +1,186 @@
+/*
+Copyright (c) 2004-2006, 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 <KM_util.h>
+#include <string>
+
+#ifdef KM_WIN32
+# include <io.h>
+#else
+# include <dirent.h>
+# include <unistd.h>
+# include <time.h>
+# include <sys/types.h>
+#endif
+
+#include <sys/stat.h>
+
+
+
+namespace Kumu
+{
+#ifdef KM_WIN32
+ //
+ class DirScanner
+ {
+ public:
+ __int64 m_Handle;
+ struct _finddatai64_t m_FileInfo;
+
+ DirScanner() {};
+ ~DirScanner() { Close(); }
+ Result_t Open(const char*);
+ Result_t Close();
+ Result_t GetNext(char*);
+ };
+#else // KM_WIN32
+ // POSIX directory scanner
+ //
+ class DirScanner
+ {
+ public:
+ DIR* m_Handle;
+
+ DirScanner() : m_Handle(NULL) {}
+ ~DirScanner() { Close(); }
+
+ Result_t Open(const char*);
+ Result_t Close();
+ Result_t GetNext(char*);
+ };
+#endif // KM_WIN32
+
+#ifdef KM_WIN32
+ typedef __int64 fsize_t;
+ typedef __int64 fpos_t;
+
+ 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 HANDLE;
+ const HANDLE INVALID_HANDLE_VALUE = -1L;
+
+ enum SeekPos_t {
+ SP_BEGIN = SEEK_SET,
+ SP_POS = SEEK_CUR,
+ SP_END = SEEK_END
+ };
+#endif
+
+ const ui32_t Kilobyte = 1024;
+ const ui32_t Megabyte = Kilobyte * Kilobyte;
+ const ui32_t Gigabyte = Megabyte * Kilobyte;
+
+ const ui32_t MaxFilePath = Kilobyte;
+
+ bool PathIsFile(const char* pathname);
+ bool PathIsDirectory(const char* pathname);
+ fsize_t FileSize(const char* pathname);
+
+ // reads an entire file into a string
+ Result_t ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size = 256 * Kilobyte);
+
+ //
+ class FileReader
+ {
+ KM_NO_COPY_CONSTRUCT(FileReader);
+
+ protected:
+ std::string m_Filename;
+ HANDLE m_Handle;
+
+ public:
+ FileReader() : m_Handle(INVALID_HANDLE_VALUE) {}
+ virtual ~FileReader() { Close(); }
+
+ Result_t OpenRead(const char*) 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);
+
+ public:
+ FileWriter();
+ virtual ~FileWriter();
+
+ Result_t OpenWrite(const char*); // open a new file, overwrites existing
+ Result_t OpenModify(const char*); // 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
+ };
+
+} // namespace Kumu
+
+
+#endif // _KM_FILEIO_H_
+
+
+//
+// end KM_fileio.h
+//
diff --git a/src/KM_log.cpp b/src/KM_log.cpp
new file mode 100755
index 0000000..a76df09
--- /dev/null
+++ b/src/KM_log.cpp
@@ -0,0 +1,155 @@
+/*
+Copyright (c) 2004-2006, 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_log.cpp
+ \version $Id$
+ \brief message logging API
+ */
+
+#include <KM_util.h>
+#include <KM_log.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef KM_WIN32
+#define getpid GetCurrentProcessId
+#else
+#include <unistd.h>
+#endif
+
+
+void
+Kumu::StdioLogSink::vLogf(ILogSink::LogType_t type, const char* fmt, va_list* list)
+{
+ AutoMutex L(m_Lock);
+
+ switch ( type )
+ {
+ case LOG_CRIT: fprintf(m_stream, "[%d CRT]: ", getpid()); break;
+ case LOG_ALERT: fprintf(m_stream, "[%d ALR]: ", getpid()); break;
+ case LOG_NOTICE: fprintf(m_stream, "[%d NTC]: ", getpid()); break;
+ case LOG_ERROR: fprintf(m_stream, "[%d ERR]: ", getpid()); break;
+ case LOG_WARN: fprintf(m_stream, "[%d WRN]: ", getpid()); break;
+ case LOG_INFO: fprintf(m_stream, "[%d INF]: ", getpid()); break;
+ case LOG_DEBUG: fprintf(m_stream, "[%d DBG]: ", getpid()); break;
+ default: fprintf(m_stream, "[%d DFL]: ", getpid());
+ }
+
+ vfprintf(m_stream, fmt, *list);
+}
+
+static Kumu::ILogSink* s_DefaultLogSink;
+static Kumu::StdioLogSink s_StderrLogSink;
+
+//
+void
+Kumu::SetDefaultLogSink(ILogSink* Sink)
+{
+ s_DefaultLogSink = Sink;
+}
+
+// Returns the internal default sink.
+Kumu::ILogSink&
+Kumu::DefaultLogSink()
+{
+ if ( s_DefaultLogSink == 0 )
+ s_DefaultLogSink = &s_StderrLogSink;
+
+ return *s_DefaultLogSink;
+}
+
+//---------------------------------------------------------------------------------
+#ifdef KM_WIN32
+
+//
+void
+Kumu::WinDbgLogSink::vLogf(ILogSink::LogType_t type, const char* fmt, va_list* list)
+{
+ AutoMutex L(m_Lock);
+ char msg_buf[MaxLogLength];
+
+ DWORD pid = GetCurrentProcessId();
+
+ switch ( type )
+ {
+ case LOG_CRIT: snprintf(msg_buf, MaxLogLength, "[%d CRT]: ", pid); break;
+ case LOG_ALERT: snprintf(msg_buf, MaxLogLength, "[%d ALR]: ", pid); break;
+ case LOG_NOTICE: snprintf(msg_buf, MaxLogLength, "[%d NTC]: ", pid); break;
+ case LOG_ERROR: snprintf(msg_buf, MaxLogLength, "[%d ERR]: ", pid); break;
+ case LOG_WARN: snprintf(msg_buf, MaxLogLength, "[%d WRN]: ", pid); break;
+ case LOG_INFO: snprintf(msg_buf, MaxLogLength, "[%d INF]: ", pid); break;
+ case LOG_DEBUG: snprintf(msg_buf, MaxLogLength, "[%d DBG]: ", pid); break;
+ default: snprintf(msg_buf, MaxLogLength, "[%d DFL]: ", pid);
+ }
+
+ ui32_t len = strlen(msg_buf);
+ vsnprintf(msg_buf + len, MaxLogLength - len, fmt, *list);
+ msg_buf[MaxLogLength-1] = 0;
+ ::OutputDebugString(msg_buf);
+}
+
+#else
+
+void
+Kumu::StreamLogSink::vLogf(ILogSink::LogType_t type, const char* fmt, va_list* list)
+{
+ AutoMutex L(m_Lock);
+ char msg_buf[MaxLogLength];
+ char ts_buf[MaxLogLength];
+ Timestamp Now;
+
+ switch ( type )
+ {
+ case LOG_CRIT: snprintf(msg_buf, MaxLogLength, "[%s %d CRT]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
+ case LOG_ALERT: snprintf(msg_buf, MaxLogLength, "[%s %d ALR]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
+ case LOG_NOTICE: snprintf(msg_buf, MaxLogLength, "[%s %d NTC]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
+ case LOG_ERROR: snprintf(msg_buf, MaxLogLength, "[%s %d ERR]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
+ case LOG_WARN: snprintf(msg_buf, MaxLogLength, "[%s %d WRN]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
+ case LOG_INFO: snprintf(msg_buf, MaxLogLength, "[%s %d INF]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
+ case LOG_DEBUG: snprintf(msg_buf, MaxLogLength, "[%s %d DBG]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid()); break;
+ default: snprintf(msg_buf, MaxLogLength, "[%s %d DFL]: ",
+ Now.EncodeString(ts_buf, MaxLogLength), getpid());
+ }
+
+ ui32_t len = strlen(msg_buf);
+ vsnprintf(msg_buf + len, MaxLogLength - len, fmt, *list);
+ msg_buf[MaxLogLength-1] = 0;
+ write(m_fd, msg_buf, strlen(msg_buf));
+}
+#endif
+
+
+//
+// end
+//
diff --git a/src/KM_log.h b/src/KM_log.h
new file mode 100755
index 0000000..2bbc330
--- /dev/null
+++ b/src/KM_log.h
@@ -0,0 +1,133 @@
+/*
+Copyright (c) 2004-2006, 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_log.h
+ \version $Id$
+ \brief message logging API
+ */
+
+
+#ifndef _KM_LOG_H_
+#define _KM_LOG_H_
+
+#include <KM_platform.h>
+#include <KM_mutex.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#define LOG_MSG_IMPL(t) va_list args; va_start(args, fmt); vLogf((t), fmt, &args); va_end(args)
+
+
+namespace Kumu
+{
+ // no log message will exceed this length
+ const ui32_t MaxLogLength = 512;
+
+ //---------------------------------------------------------------------------------
+ // message logging
+
+ // Error and debug messages will be delivered to an object having this interface.
+ // The default implementation sends only LOG_ERROR and LOG_WARN messages to stderr.
+ // To receive LOG_INFO or LOG_DEBUG messages, or to send messages somewhere other
+ // than stderr, implement this interface and register an instance of your new class
+ // by calling SetDefaultLogSink().
+ class ILogSink
+ {
+ public:
+ enum LogType_t { LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR,
+ LOG_NOTICE, LOG_ALERT, LOG_CRIT };
+
+ virtual ~ILogSink() {}
+
+ void Critical(const char* fmt, ...) { LOG_MSG_IMPL(LOG_CRIT); }
+ void Alert(const char* fmt, ...) { LOG_MSG_IMPL(LOG_ALERT); }
+ void Notice(const char* fmt, ...) { LOG_MSG_IMPL(LOG_NOTICE); }
+ void Error(const char* fmt, ...) { LOG_MSG_IMPL(LOG_ERROR); }
+ void Warn(const char* fmt, ...) { LOG_MSG_IMPL(LOG_WARN); }
+ void Info(const char* fmt, ...) { LOG_MSG_IMPL(LOG_INFO); }
+ void Debug(const char* fmt, ...) { LOG_MSG_IMPL(LOG_DEBUG); }
+ void Logf(ILogSink::LogType_t type, const char* fmt, ...) { LOG_MSG_IMPL(type); }
+ virtual void vLogf(LogType_t, const char*, va_list*) = 0; // log a formatted string with a va_list struct
+ };
+
+ // Sets the internal default sink to the given receiver. If the given value
+ // is zero, sets the default sink to the internally allocated stderr sink.
+ void SetDefaultLogSink(ILogSink* = 0);
+
+ // Returns the internal default sink.
+ ILogSink& DefaultLogSink();
+
+ //
+ class StdioLogSink : public ILogSink
+ {
+ Mutex m_Lock;
+ FILE* m_stream;
+ KM_NO_COPY_CONSTRUCT(StdioLogSink);
+
+ public:
+ StdioLogSink() : m_stream(stderr) {};
+ StdioLogSink(FILE* stream) : m_stream(stream) {}
+ virtual ~StdioLogSink() {}
+ virtual void vLogf(LogType_t, const char*, va_list*);
+ };
+
+#ifdef KM_WIN32
+ //
+ class WinDbgLogSink : public ILogSink
+ {
+ Mutex m_Lock;
+ KM_NO_COPY_CONSTRUCT(WinDbgLogSink);
+
+ public:
+ WinDbgLogSink() {}
+ virtual ~WinDbgLogSink() {}
+ virtual void vLogf(LogType_t, const char*, va_list*);
+ };
+
+#else
+
+ //
+ class StreamLogSink : public ILogSink
+ {
+ Mutex m_Lock;
+ int m_fd;
+ KM_NO_COPY_CONSTRUCT(StreamLogSink);
+ StreamLogSink();
+
+ public:
+ StreamLogSink(int fd) : m_fd(fd) {}
+ virtual ~StreamLogSink() {}
+ virtual void vLogf(LogType_t, const char*, va_list*);
+ };
+#endif
+
+} // namespace Kumu
+
+#endif // _KM_LOG_H_
+
+//
+// end KM_log.h
+//
diff --git a/src/KM_memio.h b/src/KM_memio.h
new file mode 100755
index 0000000..8416b57
--- /dev/null
+++ b/src/KM_memio.h
@@ -0,0 +1,216 @@
+/*
+Copyright (c) 2006, 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 <KM_platform.h>
+#include <string.h>
+
+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 byte_t* CurrentData() { return m_p + m_size; }
+ inline ui32_t Length() { return m_size; }
+ inline ui32_t Remainder() { 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;
+ }
+ };
+
+ //
+ 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() { return m_p; }
+ inline const byte_t* CurrentData() { return m_p + m_size; }
+ inline ui32_t Offset() { return m_size; }
+ inline ui32_t Remainder() { 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;
+ }
+ };
+
+} // namespace Kumu
+
+#endif // _KM_MEMIO_H_
+
+//
+// end KM_memio.h
+//
diff --git a/src/KM_mutex.h b/src/KM_mutex.h
new file mode 100755
index 0000000..513b504
--- /dev/null
+++ b/src/KM_mutex.h
@@ -0,0 +1,89 @@
+/*
+Copyright (c) 2004-2006, 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_mutex.h
+ \version $Id$
+ \brief platform portability
+ */
+
+#ifndef _KM_MUTEX_H_
+#define _KM_MUTEX_H_
+
+#include <KM_platform.h>
+
+#ifndef KM_WIN32
+# include <pthread.h>
+#endif
+
+namespace Kumu
+{
+#ifdef KM_WIN32
+ class Mutex
+ {
+ CRITICAL_SECTION m_Mutex;
+ KM_NO_COPY_CONSTRUCT(Mutex);
+
+ public:
+ inline Mutex() { ::InitializeCriticalSection(&m_Mutex); }
+ inline ~Mutex() { ::DeleteCriticalSection(&m_Mutex); }
+ inline void Lock() { ::EnterCriticalSection(&m_Mutex); }
+ inline void Unlock() { ::LeaveCriticalSection(&m_Mutex); }
+ };
+#else // KM_WIN32
+ class Mutex
+ {
+ pthread_mutex_t m_Mutex;
+ KM_NO_COPY_CONSTRUCT(Mutex);
+
+ public:
+ inline Mutex() { pthread_mutex_init(&m_Mutex, 0); }
+ inline ~Mutex() { pthread_mutex_destroy(&m_Mutex); }
+ inline void Lock() { pthread_mutex_lock(&m_Mutex); }
+ inline void Unlock() { pthread_mutex_unlock(&m_Mutex); }
+ };
+#endif // KM_WIN32
+
+ // automatic Mutex management within a block -
+ // the mutex is created by the constructor and
+ // released by the destructor
+ class AutoMutex
+ {
+ Mutex& m_Mutex;
+ AutoMutex();
+ KM_NO_COPY_CONSTRUCT(AutoMutex);
+
+ public:
+ AutoMutex(Mutex& Mtx) : m_Mutex(Mtx) { m_Mutex.Lock(); }
+ ~AutoMutex() { m_Mutex.Unlock(); }
+ };
+
+} // namespace Kumu
+
+#endif // _KM_MUTEX_H_
+
+//
+// end KM_mutex.h
+//
diff --git a/src/KM_platform.h b/src/KM_platform.h
new file mode 100644
index 0000000..0c577a1
--- /dev/null
+++ b/src/KM_platform.h
@@ -0,0 +1,189 @@
+/*
+Copyright (c) 2004-2006, 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_
+
+# ifdef __APPLE__
+# 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>
+# 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;
+ }
+
+
+ // 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 { 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; }
+ };
+
+} // 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&)
+
+#endif // _KM_PLATFORM_H_
+
+//
+// KM_platform.h
+//
diff --git a/src/KM_prng.cpp b/src/KM_prng.cpp
new file mode 100755
index 0000000..5e3dd48
--- /dev/null
+++ b/src/KM_prng.cpp
@@ -0,0 +1,214 @@
+/*
+Copyright (c) 2006, 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.cpp
+ \version $Id$
+ \brief Fortuna pseudo-random number generator
+ */
+
+#include <KM_prng.h>
+#include <KM_log.h>
+#include <KM_mutex.h>
+#include <string.h>
+#include <assert.h>
+#include <openssl/aes.h>
+#include <openssl/sha.h>
+
+using namespace Kumu;
+
+
+#ifdef KM_WIN32
+
+// make up a byte by sampling the perf counter LSB
+static byte_t get_perf_byte()
+{
+ LARGE_INTEGER ticks;
+ byte_t retval;
+
+ for ( int i = 0; i < 8; i++ )
+ {
+ QueryPerformanceCounter(&ticks);
+ retval |= (ticks.LowPart & 0x00000001) << i;
+ }
+
+ return retval;
+}
+
+#else // KM_WIN32
+
+#include <KM_fileio.h>
+const char* DEV_URANDOM = "/dev/urandom";
+
+#endif // KM_WIN32
+
+
+const ui32_t RNG_KEY_SIZE = 512UL;
+const ui32_t RNG_KEY_SIZE_BITS = 256UL;
+const ui32_t RNG_BLOCK_SIZE = 16UL;
+const ui32_t MAX_SEQUENCE_LEN = 0x00040000UL;
+
+
+// internal implementation class
+class h__RNG
+{
+ KM_NO_COPY_CONSTRUCT(h__RNG);
+
+public:
+ AES_KEY m_Context;
+ byte_t m_ctr_buf[RNG_BLOCK_SIZE];
+ Mutex m_Lock;
+
+ h__RNG()
+ {
+ memset(m_ctr_buf, 0, RNG_BLOCK_SIZE);
+ byte_t rng_key[RNG_KEY_SIZE];
+
+ { // this block scopes the following AutoMutex so that it will be
+ // released before the call to set_key() below.
+ AutoMutex Lock(m_Lock);
+
+#ifdef KM_WIN32
+ for ( ui32_t i = 0; i < RNG_KEY_SIZE; i++ )
+ rng_key[i] = get_perf_byte();
+
+#else // KM_WIN32
+ // on POSIX systems we simply read some seed from /dev/urandom
+ FileReader URandom;
+
+ Result_t result = URandom.OpenRead(DEV_URANDOM);
+
+ if ( KM_SUCCESS(result) )
+ {
+ ui32_t read_count;
+ result = URandom.Read(rng_key, RNG_KEY_SIZE, &read_count);
+ }
+
+ if ( KM_FAILURE(result) )
+ DefaultLogSink().Error("Error opening random device: %s\n", DEV_URANDOM);
+
+#endif // KM_WIN32
+ } // end AutoMutex context
+
+ set_key(rng_key);
+ }
+
+ //
+ void
+ set_key(const byte_t* key_fodder)
+ {
+ assert(key_fodder);
+ byte_t sha_buf[20];
+ SHA_CTX SHA;
+ SHA1_Init(&SHA);
+
+ SHA1_Update(&SHA, (byte_t*)&m_Context, sizeof(m_Context));
+ SHA1_Update(&SHA, key_fodder, RNG_KEY_SIZE);
+ SHA1_Final(sha_buf, &SHA);
+
+ AutoMutex Lock(m_Lock);
+ AES_set_encrypt_key(sha_buf, RNG_KEY_SIZE_BITS, &m_Context);
+ *(ui32_t*)(m_ctr_buf + 12) = 1;
+ }
+
+ //
+ void
+ fill_rand(byte_t* buf, ui32_t len)
+ {
+ assert(len <= MAX_SEQUENCE_LEN);
+ ui32_t gen_count = 0;
+ AutoMutex Lock(m_Lock);
+
+ while ( gen_count + RNG_BLOCK_SIZE <= len )
+ {
+ AES_encrypt(m_ctr_buf, buf + gen_count, &m_Context);
+ *(ui32_t*)(m_ctr_buf + 12) += 1;
+ gen_count += RNG_BLOCK_SIZE;
+ }
+
+ if ( len != gen_count ) // partial count needed?
+ {
+ byte_t tmp[RNG_BLOCK_SIZE];
+ AES_encrypt(m_ctr_buf, tmp, &m_Context);
+ *(ui32_t*)(m_ctr_buf + 12) += 1;
+ memcpy(buf, tmp, len - gen_count);
+ }
+ }
+};
+
+
+static h__RNG* s_RNG = 0;
+
+
+//------------------------------------------------------------------------------------------
+//
+// public interface
+
+Kumu::FortunaRNG::FortunaRNG()
+{
+ if ( s_RNG == 0 )
+ s_RNG = new h__RNG;
+}
+
+Kumu::FortunaRNG::~FortunaRNG() {}
+
+//
+const byte_t*
+Kumu::FortunaRNG::FillRandom(byte_t* buf, ui32_t len)
+{
+ assert(buf);
+ assert(s_RNG);
+
+ while ( len )
+ {
+ // 2^20 bytes max per seeding, use 2^19 to save
+ // room for generating reseed values
+ ui32_t gen_size = xmin(len, MAX_SEQUENCE_LEN);
+ s_RNG->fill_rand(buf, gen_size);
+ buf += gen_size;
+ len -= gen_size;
+
+ // re-seed the generator
+ byte_t rng_key[RNG_KEY_SIZE];
+ s_RNG->fill_rand(rng_key, RNG_KEY_SIZE);
+ s_RNG->set_key(rng_key);
+ }
+
+ return buf;
+}
+
+//
+const byte_t*
+Kumu::FortunaRNG::FillRandom(Kumu::ByteString& Buffer)
+{
+ FillRandom(Buffer.Data(), Buffer.Capacity());
+ Buffer.Length(Buffer.Capacity());
+ return Buffer.Data();
+}
+
+
+//
+// end KM_prng.cpp
+//
diff --git a/src/KM_prng.h b/src/KM_prng.h
new file mode 100755
index 0000000..f7dfa2b
--- /dev/null
+++ b/src/KM_prng.h
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 2006, 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 <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&);
+ };
+} // namespace Kumu
+
+
+
+#endif // _KM_PRNG_H_
+
+//
+// end KM_prng.h
+//
diff --git a/src/KM_util.cpp b/src/KM_util.cpp
new file mode 100755
index 0000000..c8cbb1c
--- /dev/null
+++ b/src/KM_util.cpp
@@ -0,0 +1,921 @@
+/*
+Copyright (c) 2005-2006, 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.cpp
+ \version $Id$
+ \brief Utility functions
+ */
+
+#include <KM_util.h>
+#include <KM_prng.h>
+#include <KM_memio.h>
+#include <KM_fileio.h>
+#include <KM_log.h>
+#include <ctype.h>
+#include <list>
+#include <string>
+
+//------------------------------------------------------------------------------------------
+
+
+const char fill = '=';
+const char* base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+const byte_t decode_map[] =
+{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
+ 0xff, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+
+// Convert a binary string to NULL-terminated UTF-8 hexadecimal, returns the buffer
+// if the binary 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*
+Kumu::base64encode(const byte_t* buf, ui32_t buf_len, char* strbuf, ui32_t strbuf_len)
+{
+ ui32_t out_char = 0;
+ ui32_t i, block_len, diff;
+
+ if ( buf == 0 || strbuf == 0 )
+ return 0;
+
+ if ( strbuf_len < base64_encode_length(buf_len) + 1 )
+ return 0;
+
+ block_len = buf_len;
+
+ while ( block_len % 3 )
+ block_len--;
+
+ for ( i = 0; i < block_len; i += 3 )
+ {
+ strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
+ strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
+ strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) | ( buf[2] >> 6 ) )];
+ strbuf[out_char++] = base64_chars[( buf[2] & 0x3f )];
+ buf += 3;
+ }
+
+ if ( i < buf_len )
+ {
+ diff = buf_len - i;
+ assert(diff > 0);
+ assert(diff < 3);
+
+ strbuf[out_char++] = base64_chars[( buf[0] >> 2 )];
+
+ if ( diff == 1 )
+ {
+ strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) )];
+ strbuf[out_char++] = fill;
+ }
+ else if ( diff == 2 )
+ {
+ strbuf[out_char++] = base64_chars[( ( ( buf[0] & 0x03 ) << 4 ) | ( buf[1] >> 4 ) )];
+ strbuf[out_char++] = base64_chars[( ( ( buf[1] & 0x0f ) << 2 ) )];
+ }
+
+ strbuf[out_char++] = fill;
+ }
+
+ strbuf[out_char] = 0;
+ return strbuf;;
+}
+
+
+
+
+// Convert NULL-terminated UTF-8 Base64 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
+Kumu::base64decode(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* char_count)
+{
+ register byte_t c = 0, d = 0;
+ register ui32_t phase = 0, i = 0;
+
+ if ( str == 0 || buf == 0 || char_count == 0 )
+ return -1;
+
+ while ( *str != 0 && i < buf_len )
+ {
+ c = decode_map[(int)*str++];
+ if ( c == 0xff ) continue;
+ if ( c == 0xfe ) break;
+
+ switch ( phase++ )
+ {
+ case 0:
+ buf[i++] = c << 2;
+ break;
+
+ case 1:
+ buf[i - 1] |= c >> 4;
+ d = c;
+ break;
+
+ case 2:
+ buf[i++] = ( d << 4 ) | ( c >> 2 );
+ d = c;
+ break;
+
+ case 3:
+ buf[i++] = ( d << 6 ) | c;
+ phase = 0;
+ break;
+ }
+ }
+
+ *char_count = i;
+ return 0;
+}
+
+//------------------------------------------------------------------------------------------
+
+// convert utf-8 hext string to bin
+i32_t
+Kumu::hex2bin(const char* str, byte_t* buf, ui32_t buf_len, ui32_t* conv_size)
+{
+ KM_TEST_NULL(str);
+ KM_TEST_NULL(buf);
+ KM_TEST_NULL(conv_size);
+
+ *conv_size = 0;
+
+ if ( str[0] == 0 ) // nothing to convert
+ return 0;
+
+ for ( int j = 0; str[j]; j++ )
+ {
+ if ( isxdigit(str[j]) )
+ (*conv_size)++;
+ }
+
+ if ( *conv_size & 0x01 ) (*conv_size)++;
+ *conv_size /= 2;
+
+ if ( *conv_size > buf_len )// maximum possible data size
+ return -1;
+
+ *conv_size = 0;
+
+ int phase = 0; // track high/low nybble
+
+ // for each character, fill in the high nybble then the low
+ for ( int i = 0; str[i]; i++ )
+ {
+ if ( ! isxdigit(str[i]) )
+ continue;
+
+ byte_t val = str[i] - ( isdigit(str[i]) ? 0x30 : ( isupper(str[i]) ? 0x37 : 0x57 ) );
+
+ if ( phase == 0 )
+ {
+ buf[*conv_size] = val << 4;
+ phase++;
+ }
+ else
+ {
+ buf[*conv_size] |= val;
+ phase = 0;
+ (*conv_size)++;
+ }
+ }
+
+ return 0;
+}
+
+
+// convert a memory region to a NULL-terminated hexadecimal string
+//
+const char*
+Kumu::bin2hex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
+{
+ if ( bin_buf == 0
+ || str_buf == 0
+ || ((bin_len * 2) + 1) > str_len )
+ return 0;
+
+ char* p = str_buf;
+
+ for ( ui32_t i = 0; i < bin_len; i++ )
+ {
+ *p = (bin_buf[i] >> 4) & 0x0f;
+ *p += *p < 10 ? 0x30 : 0x61 - 10;
+ p++;
+
+ *p = bin_buf[i] & 0x0f;
+ *p += *p < 10 ? 0x30 : 0x61 - 10;
+ p++;
+ }
+
+ *p = '\0';
+ return str_buf;
+}
+
+
+// spew a range of bin data as hex
+void
+Kumu::hexdump(const byte_t* buf, ui32_t dump_len, FILE* stream)
+{
+ if ( buf == 0 )
+ return;
+
+ if ( stream == 0 )
+ stream = stderr;
+
+ static ui32_t row_len = 16;
+ const byte_t* p = buf;
+ const byte_t* end_p = p + dump_len;
+
+ for ( ui32_t line = 0; p < end_p; line++ )
+ {
+ fprintf(stream, " %06x: ", line);
+ ui32_t i;
+ const byte_t* pp;
+
+ for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
+ fprintf(stream, "%02x ", *pp);
+
+ while ( i++ < row_len )
+ fputs(" ", stream);
+
+ for ( pp = p, i = 0; i < row_len && pp < end_p; i++, pp++ )
+ fputc((isprint(*pp) ? *pp : '.'), stream);
+
+ fputc('\n', stream);
+ p += row_len;
+ }
+}
+
+//
+const char*
+Kumu::bin2UUIDhex(const byte_t* bin_buf, ui32_t bin_len, char* str_buf, ui32_t str_len)
+{
+ ui32_t i, j, k;
+
+ if ( str_len < 34 || bin_len != UUID_Length )
+ return 0;
+
+ if ( bin2hex(bin_buf, bin_len, str_buf, str_len) == 0 )
+ return 0;
+
+ // shift the node id
+ for ( k = 19, i = 12; i > 0; i-- )
+ str_buf[k+i+4] = str_buf[k+i];
+
+ // shift the time (mid+hi+clk)
+ for ( k = 15, j = 3; k > 6; k -= 4, j-- )
+ {
+ for ( i = 4; i > 0; i-- )
+ str_buf[k+i+j] = str_buf[k+i];
+ }
+
+ // add in the hyphens and trainling null
+ for ( i = 8; i < 24; i += 5 )
+ str_buf[i] = '-';
+
+ str_buf[36] = 0;
+ return str_buf;
+}
+
+//
+void
+Kumu::GenRandomValue(UUID& ID)
+{
+ byte_t tmp_buf[UUID_Length];
+ GenRandomUUID(tmp_buf);
+ ID.Set(tmp_buf);
+}
+
+//
+void
+Kumu::GenRandomUUID(byte_t* buf)
+{
+ FortunaRNG RNG;
+ RNG.FillRandom(buf, UUID_Length);
+ buf[6] &= 0x0f; // clear bits 4-7
+ buf[6] |= 0x40; // set UUID version
+ buf[8] &= 0x3f; // clear bits 6&7
+ buf[8] |= 0x80; // set bit 7
+}
+
+//
+void
+Kumu::GenRandomValue(SymmetricKey& ID)
+{
+ byte_t tmp_buf[SymmetricKey_Length];
+ FortunaRNG RNG;
+ RNG.FillRandom(tmp_buf, SymmetricKey_Length);
+ ID.Set(tmp_buf);
+}
+
+
+//------------------------------------------------------------------------------------------
+// read a ber value from the buffer and compare with test value.
+// Advances buffer to first character after BER value.
+
+// read a ber value from the buffer and compare with test value.
+// Advances buffer to first character after BER value.
+//
+bool
+Kumu::read_test_BER(byte_t **buf, ui64_t test_value)
+{
+ if ( buf == 0 )
+ return false;
+
+ if ( ( **buf & 0x80 ) == 0 )
+ return false;
+
+ ui64_t val = 0;
+ ui8_t ber_size = ( **buf & 0x0f ) + 1;
+
+ if ( ber_size > 9 )
+ return false;
+
+ for ( ui8_t i = 1; i < ber_size; i++ )
+ {
+ if ( (*buf)[i] > 0 )
+ val |= (ui64_t)((*buf)[i]) << ( ( ( ber_size - 1 ) - i ) * 8 );
+ }
+
+ *buf += ber_size;
+ return ( val == test_value );
+}
+
+
+//
+bool
+Kumu::read_BER(const byte_t* buf, ui64_t* val)
+{
+ ui8_t ber_size, i;
+
+ if ( buf == 0 || val == 0 )
+ return false;
+
+ if ( ( *buf & 0x80 ) == 0 )
+ return false;
+
+ *val = 0;
+ ber_size = ( *buf & 0x0f ) + 1;
+
+ if ( ber_size > 9 )
+ return false;
+
+ for ( i = 1; i < ber_size; i++ )
+ {
+ if ( buf[i] > 0 )
+ *val |= (ui64_t)buf[i] << ( ( ( ber_size - 1 ) - i ) * 8 );
+ }
+
+ return true;
+}
+
+
+static const ui64_t ber_masks[9] =
+ { ui64_C(0xffffffffffffffff), ui64_C(0xffffffffffffff00),
+ ui64_C(0xffffffffffff0000), ui64_C(0xffffffffff000000),
+ ui64_C(0xffffffff00000000), ui64_C(0xffffff0000000000),
+ ui64_C(0xffff000000000000), ui64_C(0xff00000000000000),
+ 0
+ };
+
+
+//
+bool
+Kumu::write_BER(byte_t* buf, ui64_t val, ui32_t ber_len)
+{
+ if ( buf == 0 )
+ return false;
+
+ if ( ber_len == 0 )
+ { // calculate default length
+ if ( val < 0x01000000L )
+ ber_len = 4;
+ else if ( val < ui64_C(0x0100000000000000) )
+ ber_len = 8;
+ else
+ ber_len = 9;
+ }
+ else
+ { // sanity check BER length
+ if ( ber_len > 9 )
+ {
+ DefaultLogSink().Error("BER size %lu exceeds maximum size of 9\n", ber_len);
+ return false;
+ }
+
+ if ( val & ber_masks[ber_len - 1] )
+ {
+ ui64Printer tmp_i(val);
+ DefaultLogSink().Error("BER size %lu too small for value %s\n", tmp_i.c_str());
+ return false;
+ }
+ }
+
+ buf[0] = 0x80 + ( ber_len - 1 );
+
+ for ( ui32_t i = ber_len - 1; i > 0; i-- )
+ {
+ buf[i] = (ui8_t)(val & 0xff);
+ val >>= 8;
+ }
+
+ return true;
+}
+
+
+//------------------------------------------------------------------------------------------
+#ifdef KM_WIN32
+
+#define TIMESTAMP_TO_SYSTIME(ts, t) \
+ (t)->wYear = (ts).Year; /* year */ \
+ (t)->wMonth = (ts).Month; /* month of year (1 - 12) */ \
+ (t)->wDay = (ts).Day; /* day of month (1 - 31) */ \
+ (t)->wHour = (ts).Hour; /* hours (0 - 23) */ \
+ (t)->wMinute = (ts).Minute; /* minutes (0 - 59) */ \
+ (t)->wSecond = (ts).Second; /* seconds (0 - 60) */ \
+ (t)->wDayOfWeek = 0; \
+ (t)->wMilliseconds = 0
+
+#define SYSTIME_TO_TIMESTAMP(t, ts) \
+ (ts).Year = (t)->wYear; /* year */ \
+ (ts).Month = (t)->wMonth; /* month of year (1 - 12) */ \
+ (ts).Day = (t)->wDay; /* day of month (1 - 31) */ \
+ (ts).Hour = (t)->wHour; /* hours (0 - 23) */ \
+ (ts).Minute = (t)->wMinute; /* minutes (0 - 59) */ \
+ (ts).Second = (t)->wSecond; /* seconds (0 - 60) */
+
+//
+Kumu::Timestamp::Timestamp() :
+ Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
+{
+ SYSTEMTIME sys_time;
+ GetSystemTime(&sys_time);
+ SYSTIME_TO_TIMESTAMP(&sys_time, *this);
+}
+
+//
+bool
+Kumu::Timestamp::operator<(const Timestamp& rhs) const
+{
+ SYSTEMTIME lhst, rhst;
+ FILETIME lft, rft;
+
+ TIMESTAMP_TO_SYSTIME(*this, &lhst);
+ TIMESTAMP_TO_SYSTIME(rhs, &rhst);
+ SystemTimeToFileTime(&lhst, &lft);
+ SystemTimeToFileTime(&rhst, &rft);
+ return ( CompareFileTime(&lft, &rft) == -1 );
+}
+
+inline ui64_t
+seconds_to_ns100(ui32_t seconds)
+{
+ return ((ui64_t)seconds * 10000000);
+}
+
+//
+void
+Kumu::Timestamp::AddDays(i32_t days)
+{
+ SYSTEMTIME current_st;
+ FILETIME current_ft;
+ ULARGE_INTEGER current_ul;
+
+ if ( days != 0 )
+ {
+ TIMESTAMP_TO_SYSTIME(*this, &current_st);
+ SystemTimeToFileTime(&current_st, &current_ft);
+ memcpy(&current_ul, &current_ft, sizeof(current_ul));
+ current_ul.QuadPart += ( seconds_to_ns100(86400) * (ui64_t)days );
+ memcpy(&current_ft, &current_ul, sizeof(current_ft));
+ FileTimeToSystemTime(&current_ft, &current_st);
+ SYSTIME_TO_TIMESTAMP(&current_st, *this);
+ }
+}
+
+//
+void
+Kumu::Timestamp::AddHours(i32_t hours)
+{
+ SYSTEMTIME current_st;
+ FILETIME current_ft;
+ ULARGE_INTEGER current_ul;
+
+ if ( hours != 0 )
+ {
+ TIMESTAMP_TO_SYSTIME(*this, &current_st);
+ SystemTimeToFileTime(&current_st, &current_ft);
+ memcpy(&current_ul, &current_ft, sizeof(current_ul));
+ current_ul.QuadPart += ( seconds_to_ns100(3600) * (ui64_t)hours );
+ memcpy(&current_ft, &current_ul, sizeof(current_ft));
+ FileTimeToSystemTime(&current_ft, &current_st);
+ SYSTIME_TO_TIMESTAMP(&current_st, *this);
+ }
+}
+
+#else // KM_WIN32
+
+#include <time.h>
+
+#define TIMESTAMP_TO_TM(ts, t) \
+ (t)->tm_year = (ts).Year - 1900; /* year - 1900 */ \
+ (t)->tm_mon = (ts).Month - 1; /* month of year (0 - 11) */ \
+ (t)->tm_mday = (ts).Day; /* day of month (1 - 31) */ \
+ (t)->tm_hour = (ts).Hour; /* hours (0 - 23) */ \
+ (t)->tm_min = (ts).Minute; /* minutes (0 - 59) */ \
+ (t)->tm_sec = (ts).Second; /* seconds (0 - 60) */
+
+#define TM_TO_TIMESTAMP(t, ts) \
+ (ts).Year = (t)->tm_year + 1900; /* year - 1900 */ \
+ (ts).Month = (t)->tm_mon + 1; /* month of year (0 - 11) */ \
+ (ts).Day = (t)->tm_mday; /* day of month (1 - 31) */ \
+ (ts).Hour = (t)->tm_hour; /* hours (0 - 23) */ \
+ (ts).Minute = (t)->tm_min; /* minutes (0 - 59) */ \
+ (ts).Second = (t)->tm_sec; /* seconds (0 - 60) */
+
+//
+Kumu::Timestamp::Timestamp() :
+ Year(0), Month(0), Day(0), Hour(0), Minute(0), Second(0)
+{
+ time_t t_now = time(0);
+ struct tm* now = gmtime(&t_now);
+ TM_TO_TIMESTAMP(now, *this);
+}
+
+//
+bool
+Kumu::Timestamp::operator<(const Timestamp& rhs) const
+{
+ struct tm lhtm, rhtm;
+ TIMESTAMP_TO_TM(*this, &lhtm);
+ TIMESTAMP_TO_TM(rhs, &rhtm);
+ return ( timegm(&lhtm) < timegm(&rhtm) );
+}
+
+//
+void
+Kumu::Timestamp::AddDays(i32_t days)
+{
+ struct tm current;
+
+ if ( days != 0 )
+ {
+ TIMESTAMP_TO_TM(*this, &current);
+ time_t adj_time = timegm(&current);
+ adj_time += 86400 * days;
+ struct tm* now = gmtime(&adj_time);
+ TM_TO_TIMESTAMP(now, *this);
+ }
+}
+
+//
+void
+Kumu::Timestamp::AddHours(i32_t hours)
+{
+ struct tm current;
+
+ if ( hours != 0 )
+ {
+ TIMESTAMP_TO_TM(*this, &current);
+ time_t adj_time = timegm(&current);
+ adj_time += 3600 * hours;
+ struct tm* now = gmtime(&adj_time);
+ TM_TO_TIMESTAMP(now, *this);
+ }
+}
+
+#endif // KM_WIN32
+
+
+Kumu::Timestamp::Timestamp(const Timestamp& rhs)
+{
+ Year = rhs.Year;
+ Month = rhs.Month;
+ Day = rhs.Day;
+ Hour = rhs.Hour;
+ Minute = rhs.Minute;
+ Second = rhs.Second;
+}
+
+Kumu::Timestamp::~Timestamp()
+{
+}
+
+//
+const Kumu::Timestamp&
+Kumu::Timestamp::operator=(const Timestamp& rhs)
+{
+ Year = rhs.Year;
+ Month = rhs.Month;
+ Day = rhs.Day;
+ Hour = rhs.Hour;
+ Minute = rhs.Minute;
+ Second = rhs.Second;
+ return *this;
+}
+
+//
+bool
+Kumu::Timestamp::operator==(const Timestamp& rhs) const
+{
+ if ( Year == rhs.Year
+ && Month == rhs.Month
+ && Day == rhs.Day
+ && Hour == rhs.Hour
+ && Minute == rhs.Minute
+ && Second == rhs.Second )
+ return true;
+
+ return false;
+}
+
+//
+bool
+Kumu::Timestamp::operator!=(const Timestamp& rhs) const
+{
+ if ( Year != rhs.Year
+ || Month != rhs.Month
+ || Day != rhs.Day
+ || Hour != rhs.Hour
+ || Minute != rhs.Minute
+ || Second != rhs.Second )
+ return true;
+
+ return false;
+}
+
+//
+const char*
+Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const
+{
+ if ( buf_len < ( DateTimeLen + 1 ) )
+ return 0;
+
+ // 2004-05-01T13:20:00-00:00
+ snprintf(str_buf, buf_len,
+ "%04hu-%02hu-%02huT%02hu:%02hu:%02hu-00:00",
+ Year, Month, Day, Hour, Minute, Second);
+
+ return str_buf;
+}
+
+//
+bool
+Kumu::Timestamp::HasValue() const
+{
+ if ( Year || Month || Day || Hour || Minute || Second )
+ return true;
+
+ return false;
+}
+
+//
+bool
+Kumu::Timestamp::Unarchive(MemIOReader* Reader)
+{
+ assert(Reader);
+ if ( ! Reader->ReadUi16BE(&Year) ) return false;
+ if ( ! Reader->ReadRaw(&Month, 6) ) return false;
+ return true;
+}
+
+//
+bool
+Kumu::Timestamp::Archive(MemIOWriter* Writer) const
+{
+ assert(Writer);
+ if ( ! Writer->WriteUi16BE(Year) ) return false;
+ if ( ! Writer->WriteRaw(&Month, 6) ) return false;
+ return true;
+}
+
+#if 0
+//
+bool
+Kumu::UnarchiveString(MemIOReader* Reader, std::string&)
+{
+ assert(Reader);
+ ui32_t str_length;
+ if ( ! Reader->ReadUi32BE(&str_length) ) return false;
+ assign((const char*)Reader->CurrentData(), str_length);
+ if ( ! Reader->SkipOffset(str_length) ) return false;
+ return true;
+}
+
+//
+bool
+Kumu::String::Archive(MemIOWriter* Writer) const
+{
+ assert(Writer);
+ if ( ! Writer->WriteUi32BE(length()) ) return false;
+ if ( ! Writer->WriteRaw((const byte_t*)c_str(), length()) ) return false;
+
+ return true;
+}
+#endif
+
+//------------------------------------------------------------------------------------------
+
+Kumu::MemIOWriter::MemIOWriter(ByteString* Buf)
+ : m_p(0), m_capacity(0), m_size(0)
+{
+ m_p = Buf->Data();
+ m_capacity = Buf->Capacity();
+ assert(m_p); assert(m_capacity);
+}
+
+bool
+Kumu::MemIOWriter:: WriteBER(ui64_t i, ui32_t ber_len)
+{
+ if ( ( m_size + ber_len ) > m_capacity )
+ return false;
+
+ if ( ! write_BER(m_p + m_size, i, ber_len) )
+ return false;
+
+ m_size += ber_len;
+ return true;
+}
+
+
+Kumu::MemIOReader::MemIOReader(const ByteString* Buf)
+ : m_p(0), m_capacity(0), m_size(0)
+{
+ m_p = Buf->RoData();
+ m_capacity = Buf->Capacity();
+ assert(m_p); assert(m_capacity);
+}
+
+bool
+Kumu::MemIOReader::ReadBER(ui64_t* i, ui32_t* ber_len)
+{
+ if ( i == 0 || ber_len == 0 ) return false;
+
+ if ( ( *ber_len = BER_length(m_p + m_size) ) == 0 )
+ return false;
+
+ if ( ( m_size + *ber_len ) > m_capacity )
+ return false;
+
+ if ( ! read_BER(m_p + m_size, i) )
+ return false;
+
+ m_size += *ber_len;
+ return true;
+}
+
+//------------------------------------------------------------------------------------------
+
+Kumu::ByteString::ByteString() : m_Data(0), m_Capacity(0), m_Length(0) {}
+
+Kumu::ByteString::ByteString(ui32_t cap) : m_Data(0), m_Capacity(0), m_Length(0)
+{
+ Capacity(cap);
+}
+
+Kumu::ByteString::~ByteString()
+{
+ if ( m_Data != 0 )
+ free(m_Data);
+}
+
+
+// copy the given data into the ByteString, set Length value.
+// Returns error if the ByteString is too small.
+Kumu::Result_t
+Kumu::ByteString::Set(const byte_t* buf, ui32_t buf_len)
+{
+ if ( m_Capacity < buf_len )
+ return RESULT_ALLOC;
+
+ memcpy(m_Data, buf, buf_len);
+ m_Length = buf_len;
+ return RESULT_OK;
+}
+
+
+// Sets the size of the internally allocate buffer.
+// Resets content length to zero.
+Kumu::Result_t
+Kumu::ByteString::Capacity(ui32_t cap_size)
+{
+ if ( m_Capacity < cap_size )
+ {
+ if ( m_Data != 0 )
+ free(m_Data);
+
+ m_Data = (byte_t*)malloc(cap_size);
+
+ if ( m_Data == 0 )
+ return RESULT_ALLOC;
+
+ m_Capacity = cap_size;
+ m_Length = 0;
+ }
+
+ return RESULT_OK;
+}
+
+//
+Kumu::Result_t
+Kumu::ByteString::Append(const ByteString& Buf)
+{
+ Result_t result = RESULT_OK;
+ ui32_t diff = m_Capacity - m_Length;
+
+ if ( diff < Buf.Length() )
+ result = Capacity(m_Capacity + Buf.Length());
+
+ if ( KM_SUCCESS(result) )
+ {
+ memcpy(m_Data + m_Length, Buf.RoData(), Buf.Length());
+ m_Length += Buf.Length();
+ }
+
+ return result;
+}
+
+//
+Kumu::Result_t
+Kumu::ByteString::Append(const byte_t* buf, ui32_t buf_len)
+{
+ Result_t result = RESULT_OK;
+ ui32_t diff = m_Capacity - m_Length;
+
+ if ( diff < buf_len )
+ result = Capacity(m_Capacity + buf_len);
+
+ if ( KM_SUCCESS(result) )
+ {
+ memcpy(m_Data + m_Length, buf, buf_len);
+ m_Length += buf_len;
+ }
+
+ return result;
+}
+
+
+//
+// end KM_util.cpp
+//
diff --git a/src/KM_util.h b/src/KM_util.h
new file mode 100755
index 0000000..a27296b
--- /dev/null
+++ b/src/KM_util.h
@@ -0,0 +1,392 @@
+/*
+Copyright (c) 2005-2006, 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 <KM_memio.h>
+#include <KM_error.h>
+#include <string.h>
+#include <string>
+
+namespace Kumu
+{
+
+ template <class T, int SIZE = 16>
+ class IntPrinter : public std::string
+ {
+ protected:
+ IntPrinter();
+ char m_strbuf[SIZE];
+
+ public:
+ inline const char* c_str() { return m_strbuf; }
+
+ IntPrinter(const char* format, T value) {
+ snprintf(m_strbuf, SIZE, format, value);
+ }
+ };
+
+ 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 binary 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;
+ }
+
+ // 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);
+
+ //----------------------------------------------------------------
+ //
+
+ class IArchive
+ {
+ public:
+ virtual ~IArchive(){}
+ virtual bool HasValue() const = 0;
+ virtual bool Archive(MemIOWriter* Writer) const = 0;
+ virtual bool Unarchive(MemIOReader* Reader) = 0;
+ };
+
+
+ //
+ // the base of all identifier classes
+ 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) : m_HasValue(true) { memcpy(m_Value, rhs.m_Value, SIZE); }
+ virtual ~Identifier() {}
+
+ const Identifier& operator=(const Identifier& rhs) {
+ m_HasValue = true;
+ 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 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;
+ if ( hex2bin(str, m_Value, SIZE, &char_count) != 0 )
+ return false;
+
+ m_HasValue = true;
+ return true;
+ }
+
+ 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;
+ if ( base64decode(str, m_Value, SIZE, &char_count) != 0 )
+ return false;
+
+ m_HasValue = true;
+ return true;
+ }
+
+ inline const char* EncodeBase64(char* buf, ui32_t buf_len) const
+ {
+ return base64encode(m_Value, SIZE, buf, buf_len);
+ }
+
+ inline virtual bool HasValue() const { return m_HasValue; }
+
+ inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( ! Reader->ReadRaw(m_Value, SIZE) ) return false;
+ m_HasValue = true;
+ return true;
+ }
+
+ inline virtual 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* EncodeHex(char* buf, ui32_t buf_len) const {
+ return bin2UUIDhex(m_Value, Size(), buf, buf_len);
+ }
+ };
+
+ void GenRandomUUID(byte_t* buf);
+ void GenRandomValue(UUID&);
+
+ // 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
+ {
+ public:
+ ui16_t Year;
+ ui8_t Month;
+ ui8_t Day;
+ ui8_t Hour;
+ ui8_t Minute;
+ ui8_t Second;
+
+ Timestamp();
+ Timestamp(const Timestamp& rhs);
+ Timestamp(const char* datestr);
+ 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;
+
+ // 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
+ Result_t SetFromString(const char* datestr);
+
+ // add the given number of days or hours to the timestamp value. Values less than zero
+ // will cause the value to decrease
+ void AddDays(i32_t);
+ void AddHours(i32_t);
+
+ // Read and write the timestamp value as a byte string
+ virtual bool HasValue() const;
+ virtual bool Archive(MemIOWriter* Writer) const;
+ virtual bool Unarchive(MemIOReader* Reader);
+ };
+
+ //
+ class ByteString
+ {
+ 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 the size of the internally allocated buffer.
+ // Resets content Size to zero.
+ 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 { return m_Data; }
+
+ // returns a non-const pointer to the essence data
+ inline byte_t* 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);
+ };
+
+} // namespace Kumu
+
+
+#endif // _KM_UTIL_H_
+
+//
+// end KM_util.h
+//
diff --git a/src/MPEG.cpp b/src/MPEG.cpp
index 0f60a8f..0c4e49c 100755
--- a/src/MPEG.cpp
+++ b/src/MPEG.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2005, John Hurst
+Copyright (c) 2005-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <MPEG.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
// walk a buffer stopping at the end of the buffer or the end of a VES
// start code '00 00 01'. If successful, returns address of first byte
@@ -103,9 +105,9 @@ public:
h__StreamState() : m_State(ST_IDLE) {}
~h__StreamState() {}
- void Goto_START_HEADER() { m_State = ST_START_HEADER; }
- void Goto_IN_HEADER() { m_State = ST_IN_HEADER; }
- void Goto_IDLE() { m_State = ST_IDLE; }
+ void Goto_START_HEADER() { m_State = ST_START_HEADER; }
+ void Goto_IN_HEADER() { m_State = ST_IN_HEADER; }
+ void Goto_IDLE() { m_State = ST_IDLE; }
bool Test_IDLE() { return m_State == ST_IDLE; }
bool Test_START_HEADER() { return m_State == ST_START_HEADER; }
bool Test_IN_HEADER() { return m_State == ST_IN_HEADER; }
@@ -115,7 +117,7 @@ public:
ASDCP::MPEG2::VESParser::VESParser() :
- m_Delegate(0), m_HBufLen(0), m_ZeroCount(0), m_Partial(false)
+ m_Delegate(0), m_HBufLen(0), m_ZeroCount(0)
{
m_State = new h__StreamState;
}
@@ -139,7 +141,6 @@ ASDCP::MPEG2::VESParser::Reset()
m_State->Goto_IDLE();
m_HBufLen = 0;
m_ZeroCount = 0;
- m_Partial = false;
}
//
@@ -149,17 +150,18 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len)
ASDCP_TEST_NULL(buf);
ASDCP_TEST_NULL(m_Delegate);
- Result_t result;
- const byte_t* end_p = buf + buf_len;
- const byte_t* run_pos = buf; // track runs of uninteresting data as a position and count
- ui32_t run_len = 0;
+ Result_t result = RESULT_OK;
+ register const byte_t* end_p = buf + buf_len;
+ register const byte_t* run_pos = buf; // track runs of uninteresting data using a position and count
+ register ui32_t run_len = 0;
// search for MPEG2 headers
// copy interesting data to a buffer and pass to delegate for processing
- for ( const byte_t* p = buf; p < end_p; p++ )
+ for ( register const byte_t* p = buf; p < end_p; p++ )
{
if ( m_State->Test_IN_HEADER() )
{
+ assert(run_len==0);
m_HBuf[m_HBufLen++] = *p;
assert(m_HBufLen < VESHeaderBufSize);
}
@@ -170,8 +172,44 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len)
if ( m_State->Test_START_HEADER() ) // *p is a start code
{
- // Do we already have a header? We need to flush it...
- if ( m_HBufLen > 0)
+ if ( m_HBufLen == 0) // not already collecting a header
+ {
+ m_HBuf[0] = m_HBuf[1] = 0; m_HBuf[2] = 1; m_HBuf[3] = *p;
+
+ // is this one we want?
+ if ( *p == PIC_START || *p == SEQ_START || *p == EXT_START || *p == GOP_START )
+ {
+ m_HBufLen = 4;
+ m_State->Goto_IN_HEADER();
+
+ switch ( run_len )
+ {
+ case 1: // we suppressed writing 001 when exiting from the last call
+ case 4: // we have exactly 001x
+ break;
+ case 2: // we have 1x
+ case 3: // we have 01x
+ m_Delegate->Data(this, run_pos, (run_len == 2 ? -2 : -1));
+ break;
+
+ default:
+ m_Delegate->Data(this, run_pos, run_len - 4);
+ }
+
+ run_len = 0;
+ }
+ else
+ {
+ m_State->Goto_IDLE();
+
+ if ( run_len == 1 ) // did we suppress writing 001 when exiting from the last call?
+ {
+ m_Delegate->Data(this, m_HBuf, 4);
+ run_len = 0;
+ }
+ }
+ }
+ else // currently collecting a header, requires a flush before handling
{
m_HBufLen -= 3; // remove the current partial start code
@@ -189,48 +227,38 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len)
result = RESULT_RAW_FORMAT;
}
- // the next run starts with the start code that got us here
- run_len = 4;
- run_pos = p-3;
- m_HBufLen = 0;
-
// Parser handlers return RESULT_FALSE to teriminate without error
if ( result != RESULT_OK )
{
m_State->Goto_IDLE();
return result;
}
- }
-
- // all headers start with this same start code: 00 00 01 xx
- m_HBuf[0] = m_HBuf[1] = 0; m_HBuf[2] = 1; m_HBuf[3] = *p;
+
+ m_HBuf[0] = m_HBuf[1] = 0; m_HBuf[2] = 1; m_HBuf[3] = *p; // 001x
+ run_len = 0;
- // is this a header we want?
- if ( *p == PIC_START || *p == SEQ_START || *p == EXT_START || *p == GOP_START )
- {
- // we're starting a new header, flush the current run
- if ( run_len > 4 )
+ // is this a header we want?
+ if ( *p == PIC_START || *p == SEQ_START || *p == EXT_START || *p == GOP_START )
{
- m_Delegate->Data(this, run_pos, run_len - 4);
- run_len = 0;
+ m_HBufLen = 4;
+ m_State->Goto_IN_HEADER();
}
+ else
+ {
+ m_HBufLen = 0;
+ m_State->Goto_IDLE();
- m_Partial = false;
- m_HBufLen = 4;
- m_State->Goto_IN_HEADER();
- }
- else
- {
- if ( *p == FIRST_SLICE )
- result = m_Delegate->Slice(this);
+ if ( *p >= FIRST_SLICE && *p <= LAST_SLICE )
+ {
+ result = m_Delegate->Slice(this, *p);
- if ( m_Partial )
- {
- m_Partial = false;
- m_Delegate->Data(this, m_HBuf, 3);
+ if ( result != RESULT_OK )
+ return result;
+ }
+
+ m_Delegate->Data(this, m_HBuf, 4);
+ run_pos = p+1;
}
-
- m_State->Goto_IDLE();
}
}
else if ( *p == 0 )
@@ -248,9 +276,9 @@ ASDCP::MPEG2::VESParser::Parse(const byte_t* buf, ui32_t buf_len)
if ( run_len > 0 )
{
- if ( m_State->Test_START_HEADER() )
+ if ( m_State->Test_START_HEADER() && run_len != 0 )
{
- m_Partial = true; // 'partial' means we have a partial header in progress
+ assert(run_len > 2);
run_len -= 3;
}
diff --git a/src/MPEG.h b/src/MPEG.h
index c4de827..61cb1c3 100755
--- a/src/MPEG.h
+++ b/src/MPEG.h
@@ -29,10 +29,11 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief MPEG2 VES parser interface
*/
-#ifndef _ASDCP_MPEG_H_
-#define _ASDCP_MPEG_H_
+#ifndef _MPEG_H_
+#define _MPEG_H_
-#include <AS_DCP_system.h>
+#include <KM_platform.h>
+#include "AS_DCP.h"
#include <stdio.h>
#include <assert.h>
@@ -48,6 +49,7 @@ namespace ASDCP
EXT_START = 0xb5,
GOP_START = 0xb8,
FIRST_SLICE = 0x01,
+ LAST_SLICE = 0xaf,
INVALID = 0xff
};
@@ -90,7 +92,7 @@ namespace ASDCP
class VESParser
{
class h__StreamState;
- mem_ptr<h__StreamState> m_State;
+ Kumu::mem_ptr<h__StreamState> m_State;
VESParserDelegate* m_Delegate;
ui32_t m_HBufLen; // temp space for partial header contents
@@ -106,7 +108,7 @@ namespace ASDCP
void SetDelegate(VESParserDelegate*); // you must call this before Parse()
Result_t Parse(const byte_t*, ui32_t); // call repeatedly
- void Reset(); // resets the internal state machine and counters
+ void Reset(); // resets the internal state machine and counters, return to the top of the file
};
// Parser Event Delegate Interface
@@ -114,7 +116,7 @@ namespace ASDCP
// Create a concrete subclass and give it to the parser by calling SetDelegate().
// The respective method will be called when a header of the named type is found.
// Handler methods should return RESULT_OK to continue processing or RESULT_FALSE
- // to stop without error.
+ // to terminate parsing without signaling an error.
//
class VESParserDelegate
{
@@ -122,17 +124,20 @@ namespace ASDCP
virtual ~VESParserDelegate() {}
// header handlers
- virtual Result_t Picture(VESParser*, const byte_t*, ui32_t) = 0;
+ virtual Result_t Picture(VESParser* Caller, const byte_t* header_buf, ui32_t header_len) = 0;
virtual Result_t Extension(VESParser*, const byte_t*, ui32_t) = 0;
virtual Result_t Sequence(VESParser*, const byte_t*, ui32_t) = 0;
virtual Result_t GOP(VESParser*, const byte_t*, ui32_t) = 0;
// this is not a header handler, it is a signal that actual picture data
// has started. All Slice data is reported via the Data() method.
- virtual Result_t Slice(VESParser*) = 0;
+ virtual Result_t Slice(VESParser*, byte_t slice_id) = 0;
// Any data not given to the header handlers above is reported here
- virtual Result_t Data(VESParser*, const byte_t*, ui32_t) = 0;
+ // This method may be called with a value of -1 or -2. This will happen
+ // when processing a start code that has one or two leading zeros
+ // in the preceding buffer
+ virtual Result_t Data(VESParser*, const byte_t*, i32_t) = 0;
};
@@ -141,7 +146,9 @@ namespace ASDCP
//
// For use within parser delegate methods. The constructor expects a pointer to a buffer
// containing two zero bytes, a one byte, a start code and some number of header bytes.
- // They are not documented further as they should be self-explanatory.
+ // They are not documented further as it is hoped that they are self-explanatory.
+
+ //
namespace Accessor
{
// decoding tables
@@ -169,7 +176,7 @@ namespace ASDCP
};
//
- class SequenceEx
+ class SequenceEx // tension
{
const byte_t* m_p;
ASDCP_NO_COPY_CONSTRUCT(SequenceEx);
@@ -230,7 +237,7 @@ namespace ASDCP
} // namespace ASDCP
-#endif // ASDCP_MPEG_H_
+#endif // _MPEG_H_
//
// end MPEG.h
diff --git a/src/MPEG2_Parser.cpp b/src/MPEG2_Parser.cpp
index f6e0089..af7396f 100755
--- a/src/MPEG2_Parser.cpp
+++ b/src/MPEG2_Parser.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004, John Hurst
+Copyright (c) 2004-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -29,14 +29,17 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief AS-DCP library, MPEG2 raw essence reader implementation
*/
-#include <FileIO.h>
+#include <KM_fileio.h>
#include <MPEG.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
+
using namespace ASDCP;
using namespace ASDCP::MPEG2;
// data will be read from a VES file in chunks of this size
-const ui32_t VESReadSize = 4096;
+const ui32_t VESReadSize = 4 * Kumu::Kilobyte;
//------------------------------------------------------------------------------------------
@@ -59,11 +62,11 @@ class h__ParserState
ASDCP_NO_COPY_CONSTRUCT(h__ParserState);
public:
- h__ParserState() : m_State(::ST_INIT) {}
+ h__ParserState() : m_State(ST_INIT) {}
~h__ParserState() {}
- bool Test_SLICE() { return m_State == ST_SLICE; }
- void Reset() { m_State = ST_INIT; }
+ inline bool Test_SLICE() { return m_State == ST_SLICE; }
+ inline void Reset() { m_State = ST_INIT; }
//
inline Result_t Goto_SEQ()
@@ -75,6 +78,7 @@ class h__ParserState
return RESULT_OK;
}
+ DefaultLogSink().Error("SEQ follows 0x%02x\n", m_State);
return RESULT_STATE;
}
@@ -90,6 +94,7 @@ class h__ParserState
return RESULT_OK;
}
+ DefaultLogSink().Error("Slice follows 0x%02x\n", m_State);
return RESULT_STATE;
}
@@ -107,23 +112,25 @@ class h__ParserState
return RESULT_OK;
}
+ DefaultLogSink().Error("PIC follows 0x%02x\n", m_State);
return RESULT_STATE;
}
//
inline Result_t Goto_GOP()
- {
- switch ( m_State )
- {
- case ST_EXT:
- case ST_SEQ:
- m_State = ST_GOP;
- return RESULT_OK;
- }
-
- return RESULT_STATE;
- }
+ {
+ switch ( m_State )
+ {
+ case ST_EXT:
+ case ST_SEQ:
+ m_State = ST_GOP;
+ return RESULT_OK;
+ }
+
+ DefaultLogSink().Error("GOP follows 0x%02x\n", m_State);
+ return RESULT_STATE;
+ }
//
inline Result_t Goto_EXT()
@@ -138,6 +145,7 @@ class h__ParserState
return RESULT_OK;
}
+ DefaultLogSink().Error("EXT follows 0x%02x\n", m_State);
return RESULT_STATE;
}
};
@@ -216,8 +224,8 @@ public:
Result_t GOP(VESParser*, const byte_t*, ui32_t) { return RESULT_FALSE; }
Result_t Picture(VESParser*, const byte_t*, ui32_t) { return RESULT_FALSE; }
- Result_t Slice(VESParser*) { return RESULT_FALSE; }
- Result_t Data(VESParser*, const byte_t*, ui32_t) { return RESULT_OK; }
+ Result_t Slice(VESParser*, byte_t) { return RESULT_FALSE; }
+ Result_t Data(VESParser*, const byte_t*, i32_t) { return RESULT_OK; }
};
@@ -258,7 +266,7 @@ public:
m_PlaintextOffset = 0;
m_FrameType = FRAME_U;
m_State.Reset();
- }
+ }
Result_t Sequence(VESParser*, const byte_t* b, ui32_t s)
{
@@ -287,10 +295,15 @@ public:
return m_State.Goto_PIC();
}
- Result_t Slice(VESParser*)
+ Result_t Slice(VESParser*, byte_t slice_id)
{
- m_PlaintextOffset = m_FrameSize;
- return m_State.Goto_SLICE();
+ if ( slice_id == FIRST_SLICE )
+ {
+ m_PlaintextOffset = m_FrameSize;
+ return m_State.Goto_SLICE();
+ }
+
+ return m_State.Test_SLICE() ? RESULT_OK : RESULT_FAIL;
}
Result_t Extension(VESParser*, const byte_t* b, ui32_t s)
@@ -308,7 +321,7 @@ public:
return m_State.Goto_GOP();
}
- Result_t Data(VESParser*, const byte_t* b, ui32_t s)
+ Result_t Data(VESParser*, const byte_t* b, i32_t s)
{
m_FrameSize += s;
return RESULT_OK;
@@ -324,13 +337,12 @@ public:
// - any frame that begins with a picture header is either an I, B or P frame
// and is assumed to contain a complete picture header and picture data
-
class ASDCP::MPEG2::Parser::h__Parser
{
StreamParams m_ParamsDelegate;
FrameParser m_ParserDelegate;
VESParser m_Parser;
- FileReader m_FileReader;
+ Kumu::FileReader m_FileReader;
ui32_t m_FrameNumber;
bool m_EOF;
ASDCP::MPEG2::FrameBuffer m_TmpBuffer;
@@ -387,9 +399,9 @@ ASDCP::MPEG2::Parser::h__Parser::OpenRead(const char* filename)
// Since no one complained and that's the easiest thing to implement,
// I have left it that way. Let me know if you want to be able to
// locate the first GOP in the stream.
- if ( p[0] != 0 || p[1] != 0 || p[2] != 1 )
+ if ( p[0] != 0 || p[1] != 0 || p[2] != 1 || ! ( p[3] == SEQ_START || p[3] == PIC_START ) )
{
- DefaultLogSink().Error("Frame buffer does not begin with a start code.\n");
+ DefaultLogSink().Error("Frame buffer does not begin with a PIC or SEQ start code.\n");
return RESULT_RAW_FORMAT;
}
@@ -412,8 +424,8 @@ ASDCP::MPEG2::Parser::h__Parser::OpenRead(const char* filename)
m_FileReader.Close();
}
- return result;
-}
+ return result;}
+
//
//
@@ -434,6 +446,7 @@ ASDCP::MPEG2::Parser::h__Parser::ReadFrame(FrameBuffer& FB)
// the input file is exhausted. The partial next frame is cached for the
// next call.
m_ParserDelegate.Reset();
+ m_Parser.Reset();
if ( m_TmpBuffer.Size() > 0 )
{
@@ -443,7 +456,7 @@ ASDCP::MPEG2::Parser::h__Parser::ReadFrame(FrameBuffer& FB)
m_TmpBuffer.Size(0);
}
- while ( ! m_ParserDelegate.m_CompletePicture && ASDCP_SUCCESS(result) )
+ while ( ! m_ParserDelegate.m_CompletePicture && result == RESULT_OK )
{
if ( FB.Capacity() < ( write_offset + VESReadSize ) )
{
@@ -454,7 +467,7 @@ ASDCP::MPEG2::Parser::h__Parser::ReadFrame(FrameBuffer& FB)
result = m_FileReader.Read(FB.Data() + write_offset, VESReadSize, &read_count);
- if ( result == RESULT_ENDOFFILE )
+ if ( result == RESULT_ENDOFFILE || read_count == 0 )
{
m_EOF = true;
@@ -471,6 +484,7 @@ ASDCP::MPEG2::Parser::h__Parser::ReadFrame(FrameBuffer& FB)
if ( m_EOF )
break;
}
+ assert(m_ParserDelegate.m_FrameSize <= write_offset);
if ( ASDCP_SUCCESS(result)
&& m_ParserDelegate.m_FrameSize < write_offset )
@@ -478,21 +492,20 @@ ASDCP::MPEG2::Parser::h__Parser::ReadFrame(FrameBuffer& FB)
assert(m_TmpBuffer.Size() == 0);
ui32_t diff = write_offset - m_ParserDelegate.m_FrameSize;
assert(diff <= m_TmpBuffer.Capacity());
+
memcpy(m_TmpBuffer.Data(), FB.RoData() + m_ParserDelegate.m_FrameSize, diff);
m_TmpBuffer.Size(diff);
}
-#ifndef NDEBUG
if ( ASDCP_SUCCESS(result) )
{
const byte_t* p = FB.RoData();
- if ( p[0] != 0 || p[1] != 0 || p[2] != 1 )
- {
- DefaultLogSink().Error("Parsed frame buffer does not begin with a start code.\n");
- return RESULT_RAW_FORMAT;
- }
+ if ( p[0] != 0 || p[1] != 0 || p[2] != 1 || ! ( p[3] == SEQ_START || p[3] == PIC_START ) )
+ {
+ DefaultLogSink().Error("Frame buffer does not begin with a PIC or SEQ start code.\n");
+ return RESULT_RAW_FORMAT;
+ }
}
-#endif
if ( ASDCP_SUCCESS(result) )
{
@@ -573,5 +586,5 @@ ASDCP::MPEG2::Parser::FillVideoDescriptor(VideoDescriptor& VDesc) const
}
//
-// end AS_DCP_MPEG2_Parser.cpp
+// end MPEG2_Parser.cpp
//
diff --git a/src/MXF.cpp b/src/MXF.cpp
index ed16cab..ab30389 100755
--- a/src/MXF.cpp
+++ b/src/MXF.cpp
@@ -30,8 +30,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "MXF.h"
-#include "hex_utils.h"
-
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
//------------------------------------------------------------------------------------------
//
@@ -40,12 +40,12 @@ const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH;
//
ASDCP::Result_t
-ASDCP::MXF::SeekToRIP(const ASDCP::FileReader& Reader)
+ASDCP::MXF::SeekToRIP(const Kumu::FileReader& Reader)
{
- ASDCP::fpos_t end_pos;
+ Kumu::fpos_t end_pos;
// go to the end - 4 bytes
- Result_t result = Reader.Seek(0, ASDCP::SP_END);
+ Result_t result = Reader.Seek(0, Kumu::SP_END);
if ( ASDCP_SUCCESS(result) )
result = Reader.Tell(&end_pos);
@@ -72,7 +72,7 @@ ASDCP::MXF::SeekToRIP(const ASDCP::FileReader& Reader)
if ( ASDCP_SUCCESS(result) )
{
- rip_size = ASDCP_i32_BE(cp2i<ui32_t>(intbuf));
+ rip_size = KM_i32_BE(Kumu::cp2i<ui32_t>(intbuf));
if ( rip_size > end_pos ) // RIP can't be bigger than the file
return RESULT_FAIL;
@@ -87,14 +87,14 @@ ASDCP::MXF::SeekToRIP(const ASDCP::FileReader& Reader)
//
ASDCP::Result_t
-ASDCP::MXF::RIP::InitFromFile(const ASDCP::FileReader& Reader)
+ASDCP::MXF::RIP::InitFromFile(const Kumu::FileReader& Reader)
{
Result_t result = KLVFilePacket::InitFromFile(Reader, Dict::ul(MDD_RandomIndexMetadata));
if ( ASDCP_SUCCESS(result) )
{
- MemIOReader MemRDR(m_ValueStart, m_ValueLength - 4);
- result = PairArray.Unarchive(MemRDR);
+ Kumu::MemIOReader MemRDR(m_ValueStart, m_ValueLength - 4);
+ result = PairArray.Unarchive(&MemRDR) ? RESULT_OK : RESULT_KLV_CODING;
}
if ( ASDCP_FAILURE(result) )
@@ -105,7 +105,7 @@ ASDCP::MXF::RIP::InitFromFile(const ASDCP::FileReader& Reader)
//
ASDCP::Result_t
-ASDCP::MXF::RIP::WriteToFile(ASDCP::FileWriter& Writer)
+ASDCP::MXF::RIP::WriteToFile(Kumu::FileWriter& Writer)
{
ASDCP::FrameBuffer Buffer;
ui32_t RIPSize = ( PairArray.size() * (sizeof(ui32_t) + sizeof(ui64_t)) ) + 4;
@@ -116,14 +116,15 @@ ASDCP::MXF::RIP::WriteToFile(ASDCP::FileWriter& Writer)
if ( ASDCP_SUCCESS(result) )
{
- MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity());
- result = PairArray.Archive(MemWRT);
-
- if ( ASDCP_SUCCESS(result) )
- MemWRT.WriteUi32BE(RIPSize + 20);
+ result = RESULT_KLV_CODING;
- if ( ASDCP_SUCCESS(result) )
- Buffer.Size(MemWRT.Size());
+ Kumu::MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity());
+ if ( PairArray.Archive(&MemWRT) )
+ if ( MemWRT.WriteUi32BE(RIPSize + 20) )
+ {
+ Buffer.Size(MemWRT.Length());
+ result = RESULT_OK;
+ }
}
if ( ASDCP_SUCCESS(result) )
@@ -215,14 +216,14 @@ ASDCP::MXF::Partition::AddChildObject(InterchangeObject* Object)
{
assert(Object);
UUID TmpID;
- TmpID.GenRandomValue();
+ Kumu::GenRandomValue(TmpID);
Object->InstanceUID = TmpID;
m_PacketList->AddPacket(Object);
}
//
ASDCP::Result_t
-ASDCP::MXF::Partition::InitFromFile(const ASDCP::FileReader& Reader)
+ASDCP::MXF::Partition::InitFromFile(const Kumu::FileReader& Reader)
{
Result_t result = KLVFilePacket::InitFromFile(Reader);
// test the UL
@@ -230,20 +231,23 @@ ASDCP::MXF::Partition::InitFromFile(const ASDCP::FileReader& Reader)
if ( ASDCP_SUCCESS(result) )
{
- MemIOReader MemRDR(m_ValueStart, m_ValueLength);
- result = MemRDR.ReadUi16BE(&MajorVersion);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi16BE(&MinorVersion);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&KAGSize);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&ThisPartition);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&PreviousPartition);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&FooterPartition);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&HeaderByteCount);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&IndexByteCount);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&IndexSID);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&BodyOffset);
- if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&BodySID);
- if ( ASDCP_SUCCESS(result) ) result = OperationalPattern.Unarchive(MemRDR);
- if ( ASDCP_SUCCESS(result) ) result = EssenceContainers.Unarchive(MemRDR);
+ Kumu::MemIOReader MemRDR(m_ValueStart, m_ValueLength);
+ result = RESULT_KLV_CODING;
+
+ if ( MemRDR.ReadUi16BE(&MajorVersion) )
+ if ( MemRDR.ReadUi16BE(&MinorVersion) )
+ if ( MemRDR.ReadUi32BE(&KAGSize) )
+ if ( MemRDR.ReadUi64BE(&ThisPartition) )
+ if ( MemRDR.ReadUi64BE(&PreviousPartition) )
+ if ( MemRDR.ReadUi64BE(&FooterPartition) )
+ if ( MemRDR.ReadUi64BE(&HeaderByteCount) )
+ if ( MemRDR.ReadUi64BE(&IndexByteCount) )
+ if ( MemRDR.ReadUi32BE(&IndexSID) )
+ if ( MemRDR.ReadUi64BE(&BodyOffset) )
+ if ( MemRDR.ReadUi32BE(&BodySID) )
+ if ( OperationalPattern.Unarchive(&MemRDR) )
+ if ( EssenceContainers.Unarchive(&MemRDR) )
+ result = RESULT_OK;
}
if ( ASDCP_FAILURE(result) )
@@ -254,28 +258,32 @@ ASDCP::MXF::Partition::InitFromFile(const ASDCP::FileReader& Reader)
//
ASDCP::Result_t
-ASDCP::MXF::Partition::WriteToFile(ASDCP::FileWriter& Writer, UL& PartitionLabel)
+ASDCP::MXF::Partition::WriteToFile(Kumu::FileWriter& Writer, UL& PartitionLabel)
{
ASDCP::FrameBuffer Buffer;
Result_t result = Buffer.Capacity(1024);
if ( ASDCP_SUCCESS(result) )
{
- MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity());
- result = MemWRT.WriteUi16BE(MajorVersion);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi16BE(MinorVersion);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(KAGSize);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(ThisPartition);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(PreviousPartition);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(FooterPartition);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(HeaderByteCount);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(IndexByteCount);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(IndexSID);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(BodyOffset);
- if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(BodySID);
- if ( ASDCP_SUCCESS(result) ) result = OperationalPattern.Archive(MemWRT);
- if ( ASDCP_SUCCESS(result) ) result = EssenceContainers.Archive(MemWRT);
- if ( ASDCP_SUCCESS(result) ) Buffer.Size(MemWRT.Size());
+ Kumu::MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity());
+ result = RESULT_KLV_CODING;
+ if ( MemWRT.WriteUi16BE(MajorVersion) )
+ if ( MemWRT.WriteUi16BE(MinorVersion) )
+ if ( MemWRT.WriteUi32BE(KAGSize) )
+ if ( MemWRT.WriteUi64BE(ThisPartition) )
+ if ( MemWRT.WriteUi64BE(PreviousPartition) )
+ if ( MemWRT.WriteUi64BE(FooterPartition) )
+ if ( MemWRT.WriteUi64BE(HeaderByteCount) )
+ if ( MemWRT.WriteUi64BE(IndexByteCount) )
+ if ( MemWRT.WriteUi32BE(IndexSID) )
+ if ( MemWRT.WriteUi64BE(BodyOffset) )
+ if ( MemWRT.WriteUi32BE(BodySID) )
+ if ( OperationalPattern.Archive(&MemWRT) )
+ if ( EssenceContainers.Archive(&MemWRT) )
+ {
+ Buffer.Size(MemWRT.Length());
+ result = RESULT_OK;
+ }
}
if ( ASDCP_SUCCESS(result) )
@@ -310,7 +318,6 @@ void
ASDCP::MXF::Partition::Dump(FILE* stream)
{
char identbuf[IdentBufferLen];
- char intbuf[IntBufferLen];
if ( stream == 0 )
stream = stderr;
@@ -319,15 +326,15 @@ ASDCP::MXF::Partition::Dump(FILE* stream)
fprintf(stream, " MajorVersion = %hu\n", MajorVersion);
fprintf(stream, " MinorVersion = %hu\n", MinorVersion);
fprintf(stream, " KAGSize = %lu\n", KAGSize);
- fprintf(stream, " ThisPartition = %s\n", ui64sz(ThisPartition, intbuf));
- fprintf(stream, " PreviousPartition = %s\n", ui64sz(PreviousPartition, intbuf));
- fprintf(stream, " FooterPartition = %s\n", ui64sz(FooterPartition, intbuf));
- fprintf(stream, " HeaderByteCount = %s\n", ui64sz(HeaderByteCount, intbuf));
- fprintf(stream, " IndexByteCount = %s\n", ui64sz(IndexByteCount, intbuf));
+ fprintf(stream, " ThisPartition = %s\n", ui64sz(ThisPartition, identbuf));
+ fprintf(stream, " PreviousPartition = %s\n", ui64sz(PreviousPartition, identbuf));
+ fprintf(stream, " FooterPartition = %s\n", ui64sz(FooterPartition, identbuf));
+ fprintf(stream, " HeaderByteCount = %s\n", ui64sz(HeaderByteCount, identbuf));
+ fprintf(stream, " IndexByteCount = %s\n", ui64sz(IndexByteCount, identbuf));
fprintf(stream, " IndexSID = %lu\n", IndexSID);
- fprintf(stream, " BodyOffset = %s\n", ui64sz(BodyOffset, intbuf));
+ fprintf(stream, " BodyOffset = %s\n", ui64sz(BodyOffset, identbuf));
fprintf(stream, " BodySID = %lu\n", BodySID);
- fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.ToString(identbuf));
+ fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.EncodeString(identbuf, IdentBufferLen));
fputs("Essence Containers:\n", stream); EssenceContainers.Dump(stream, false);
fputs("==========================================================================\n", stream);
@@ -372,8 +379,8 @@ ASDCP::MXF::Primer::InitFromBuffer(const byte_t* p, ui32_t l)
if ( ASDCP_SUCCESS(result) )
{
- MemIOReader MemRDR(m_ValueStart, m_ValueLength);
- result = LocalTagEntryBatch.Unarchive(MemRDR);
+ Kumu::MemIOReader MemRDR(m_ValueStart, m_ValueLength);
+ result = LocalTagEntryBatch.Unarchive(&MemRDR) ? RESULT_OK : RESULT_KLV_CODING;
}
if ( ASDCP_SUCCESS(result) )
@@ -390,7 +397,7 @@ ASDCP::MXF::Primer::InitFromBuffer(const byte_t* p, ui32_t l)
//
ASDCP::Result_t
-ASDCP::MXF::Primer::WriteToFile(ASDCP::FileWriter& Writer)
+ASDCP::MXF::Primer::WriteToFile(Kumu::FileWriter& Writer)
{
ASDCP::FrameBuffer Buffer;
Result_t result = Buffer.Capacity(128*1024);
@@ -409,12 +416,12 @@ ASDCP::Result_t
ASDCP::MXF::Primer::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
{
ASDCP::FrameBuffer LocalTagBuffer;
- MemIOWriter MemWRT(Buffer.Data() + kl_length, Buffer.Capacity() - kl_length);
- Result_t result = LocalTagEntryBatch.Archive(MemWRT);
+ Kumu::MemIOWriter MemWRT(Buffer.Data() + kl_length, Buffer.Capacity() - kl_length);
+ Result_t result = LocalTagEntryBatch.Archive(&MemWRT) ? RESULT_OK : RESULT_KLV_CODING;
if ( ASDCP_SUCCESS(result) )
{
- ui32_t packet_length = MemWRT.Size();
+ ui32_t packet_length = MemWRT.Length();
result = WriteKLToBuffer(Buffer, Dict::ul(MDD_Primer), packet_length);
if ( ASDCP_SUCCESS(result) )
@@ -498,7 +505,7 @@ ASDCP::MXF::Primer::Dump(FILE* stream)
for ( ; i != LocalTagEntryBatch.end(); i++ )
{
const MDDEntry* Entry = Dict::FindUL((*i).UL.Value());
- fprintf(stream, " %s %s\n", (*i).ToString(identbuf), (Entry ? Entry->name : "Unknown"));
+ fprintf(stream, " %s %s\n", (*i).EncodeString(identbuf, IdentBufferLen), (Entry ? Entry->name : "Unknown"));
}
fputs("==========================================================================\n", stream);
@@ -568,13 +575,13 @@ ASDCP::MXF::Preface::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " %22s = %s\n", "LastModifiedDate", LastModifiedDate.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "LastModifiedDate", LastModifiedDate.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %hu\n", "Version", Version);
fprintf(stream, " %22s = %lu\n", "ObjectModelVersion", ObjectModelVersion);
- fprintf(stream, " %22s = %s\n", "PrimaryPackage", PrimaryPackage.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "PrimaryPackage", PrimaryPackage.EncodeHex(identbuf, IdentBufferLen));
fprintf(stream, " %22s:\n", "Identifications"); Identifications.Dump(stream);
- fprintf(stream, " %22s = %s\n", "ContentStorage", ContentStorage.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "OperationalPattern", OperationalPattern.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "ContentStorage", ContentStorage.EncodeHex(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "OperationalPattern", OperationalPattern.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s:\n", "EssenceContainers"); EssenceContainers.Dump(stream);
fprintf(stream, " %22s:\n", "DMSchemes"); DMSchemes.Dump(stream);
}
@@ -587,7 +594,7 @@ ASDCP::MXF::OPAtomHeader::~OPAtomHeader() {}
//
ASDCP::Result_t
-ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader)
+ASDCP::MXF::OPAtomHeader::InitFromFile(const Kumu::FileReader& Reader)
{
m_HasRIP = false;
Result_t result = SeekToRIP(Reader);
@@ -637,18 +644,16 @@ ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader)
if ( ASDCP_SUCCESS(result) )
result = Partition::InitFromFile(Reader); // test UL and OP
- Partition::Dump();
-
// is it really OP-Atom?
UL OPAtomUL(Dict::ul(MDD_OPAtom));
UL InteropOPAtomUL(Dict::ul(MDD_MXFInterop_OPAtom));
if ( ! ( OperationalPattern == OPAtomUL || OperationalPattern == InteropOPAtomUL ) )
{
- char strbuf[IntBufferLen];
+ char strbuf[IdentBufferLen];
const MDDEntry* Entry = Dict::FindUL(OperationalPattern.Value());
if ( Entry == 0 )
- DefaultLogSink().Warn("Operational pattern is not OP-Atom: %s\n", OperationalPattern.ToString(strbuf));
+ DefaultLogSink().Warn("Operational pattern is not OP-Atom: %s\n", OperationalPattern.EncodeString(strbuf, IdentBufferLen));
else
DefaultLogSink().Warn("Operational pattern is not OP-Atom: %s\n", Entry->name);
}
@@ -760,7 +765,7 @@ ASDCP::MXF::OPAtomHeader::GetSourcePackage()
//
ASDCP::Result_t
-ASDCP::MXF::OPAtomHeader::WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderSize)
+ASDCP::MXF::OPAtomHeader::WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderSize)
{
if ( m_Preface == 0 )
return RESULT_STATE;
@@ -808,9 +813,9 @@ ASDCP::MXF::OPAtomHeader::WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderSi
// KLV Fill
if ( ASDCP_SUCCESS(result) )
{
- ASDCP::fpos_t pos = Writer.Tell();
+ Kumu::fpos_t pos = Writer.Tell();
- if ( pos > (ASDCP::fpos_t)HeaderByteCount )
+ if ( pos > (Kumu::fpos_t)HeaderByteCount )
{
char intbuf[IntBufferLen];
DefaultLogSink().Error("Header size %s exceeds specified value %lu\n",
@@ -884,7 +889,7 @@ ASDCP::MXF::OPAtomIndexFooter::~OPAtomIndexFooter() {}
ASDCP::Result_t
-ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const ASDCP::FileReader& Reader)
+ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const Kumu::FileReader& Reader)
{
Result_t result = Partition::InitFromFile(Reader); // test UL and OP
@@ -936,7 +941,7 @@ ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const ASDCP::FileReader& Reader)
//
ASDCP::Result_t
-ASDCP::MXF::OPAtomIndexFooter::WriteToFile(ASDCP::FileWriter& Writer, ui64_t duration)
+ASDCP::MXF::OPAtomIndexFooter::WriteToFile(Kumu::FileWriter& Writer, ui64_t duration)
{
ASDCP::FrameBuffer FooterBuffer;
ui32_t footer_size = m_PacketList->m_List.size() * MaxIndexSegmentSize; // segment-count * max-segment-size
@@ -1059,7 +1064,7 @@ ASDCP::MXF::OPAtomIndexFooter::SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t s
//
void
-ASDCP::MXF::OPAtomIndexFooter::SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, fpos_t offset)
+ASDCP::MXF::OPAtomIndexFooter::SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset)
{
assert(lookup);
m_Lookup = lookup;
@@ -1132,7 +1137,7 @@ ASDCP::Result_t
ASDCP::MXF::InterchangeObject::InitFromBuffer(const byte_t* p, ui32_t l)
{
ASDCP_TEST_NULL(p);
- Result_t result;
+ Result_t result = RESULT_FALSE;
if ( m_Typeinfo == 0 )
{
@@ -1164,7 +1169,7 @@ ASDCP::MXF::InterchangeObject::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
if ( ASDCP_SUCCESS(result) )
{
- ui32_t packet_length = MemWRT.Size();
+ ui32_t packet_length = MemWRT.Length();
result = WriteKLToBuffer(Buffer, m_Typeinfo->ul, packet_length);
if ( ASDCP_SUCCESS(result) )
@@ -1182,8 +1187,8 @@ ASDCP::MXF::InterchangeObject::Dump(FILE* stream)
fputc('\n', stream);
KLVPacket::Dump(stream, false);
- fprintf(stream, " InstanceUID = %s\n", InstanceUID.ToString(identbuf));
- fprintf(stream, " GenerationUID = %s\n", GenerationUID.ToString(identbuf));
+ fprintf(stream, " InstanceUID = %s\n", InstanceUID.EncodeHex(identbuf, IdentBufferLen));
+ fprintf(stream, " GenerationUID = %s\n", GenerationUID.EncodeHex(identbuf, IdentBufferLen));
}
//
diff --git a/src/MXF.h b/src/MXF.h
index 27f3b3e..da7b92f 100755
--- a/src/MXF.h
+++ b/src/MXF.h
@@ -41,7 +41,7 @@ namespace ASDCP
class InterchangeObject;
// seek an open file handle to the start of the RIP KLV packet
- Result_t SeekToRIP(const FileReader&);
+ Result_t SeekToRIP(const Kumu::FileReader&);
//
class RIP : public ASDCP::KLVFilePacket
@@ -50,7 +50,7 @@ namespace ASDCP
public:
//
- class Pair : public IArchive
+ class Pair : public Kumu::IArchive
{
public:
ui32_t BodySID;
@@ -58,33 +58,28 @@ namespace ASDCP
Pair() : BodySID(0), ByteOffset(0) {}
Pair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {}
+ virtual ~Pair() {}
ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); }
- inline const char* ToString(char* str_buf) const {
- char intbuf[IntBufferLen];
- snprintf(str_buf, IdentBufferLen, "%-6lu: %s", BodySID, ui64sz(ByteOffset, intbuf));
+ inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ Kumu::ui64Printer offset_str(ByteOffset);
+ snprintf(str_buf, buf_len, "%-6lu: %s", BodySID, offset_str.c_str());
return str_buf;
}
- inline Result_t Unarchive(ASDCP::MemIOReader& Reader) {
- Result_t result = Reader.ReadUi32BE(&BodySID);
-
- if ( ASDCP_SUCCESS(result) )
- result = Reader.ReadUi64BE(&ByteOffset);
-
- return result;
+ inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( ! Reader->ReadUi32BE(&BodySID) ) return false;
+ if ( ! Reader->ReadUi64BE(&ByteOffset) ) return false;
+ return true;
}
- inline bool HasValue() const { return true; }
+ inline virtual bool HasValue() const { return true; }
- inline Result_t Archive(ASDCP::MemIOWriter& Writer) const {
- Result_t result = Writer.WriteUi32BE(BodySID);
-
- if ( ASDCP_SUCCESS(result) )
- result = Writer.WriteUi64BE(ByteOffset);
-
- return result;
+ inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi32BE(BodySID) ) return false;
+ if ( ! Writer->WriteUi64BE(ByteOffset) ) return false;
+ return true;
}
};
@@ -92,15 +87,15 @@ namespace ASDCP
RIP() {}
virtual ~RIP() {}
- virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
- virtual Result_t WriteToFile(ASDCP::FileWriter& Writer);
+ virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+ virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
virtual void Dump(FILE* = 0);
};
//
class Partition : public ASDCP::KLVFilePacket
- {
+ {
ASDCP_NO_COPY_CONSTRUCT(Partition);
protected:
@@ -125,8 +120,8 @@ namespace ASDCP
Partition();
virtual ~Partition();
virtual void AddChildObject(InterchangeObject*);
- virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
- virtual Result_t WriteToFile(ASDCP::FileWriter& Writer, UL& PartitionLabel);
+ virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+ virtual Result_t WriteToFile(Kumu::FileWriter& Writer, UL& PartitionLabel);
virtual ui32_t ArchiveSize(); // returns the size of the archived structure
virtual void Dump(FILE* = 0);
};
@@ -148,24 +143,22 @@ namespace ASDCP
TagValue Tag;
ASDCP::UL UL;
- inline const char* ToString(char* str_buf) const {
- snprintf(str_buf, IdentBufferLen, "%02x %02x: ", Tag.a, Tag.b);
- UL.ToString(str_buf + strlen(str_buf));
+ inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ snprintf(str_buf, buf_len, "%02x %02x: ", Tag.a, Tag.b);
+ UL.EncodeString(str_buf + strlen(str_buf), buf_len - strlen(str_buf));
return str_buf;
}
- inline Result_t Unarchive(ASDCP::MemIOReader& Reader) {
- Result_t result = Reader.ReadUi8(&Tag.a);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi8(&Tag.b);
- if ( ASDCP_SUCCESS(result) ) result = UL.Unarchive(Reader);
- return result;
+ inline bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( ! Reader->ReadUi8(&Tag.a) ) return false;
+ if ( ! Reader->ReadUi8(&Tag.b) ) return false;
+ return UL.Unarchive(Reader);
}
- inline Result_t Archive(ASDCP::MemIOWriter& Writer) const {
- Result_t result = Writer.WriteUi8(Tag.a);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi8(Tag.b);
- if ( ASDCP_SUCCESS(result) ) result = UL.Archive(Writer);
- return result;
+ inline bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi8(Tag.a) ) return false;
+ if ( ! Writer->WriteUi8(Tag.b) ) return false;
+ return UL.Archive(Writer);
}
};
@@ -180,7 +173,7 @@ namespace ASDCP
virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
- virtual Result_t WriteToFile(ASDCP::FileWriter& Writer);
+ virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
virtual void Dump(FILE* = 0);
};
@@ -253,9 +246,9 @@ namespace ASDCP
ui32_t ElementData;
DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
- Result_t Unarchive(ASDCP::MemIOReader& Reader);
- Result_t Archive(ASDCP::MemIOWriter& Writer) const;
- const char* ToString(char* str_buf) const;
+ bool Unarchive(Kumu::MemIOReader* Reader);
+ bool Archive(Kumu::MemIOWriter* Writer) const;
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
};
//
@@ -270,9 +263,9 @@ namespace ASDCP
// Array<Rational> PosTable;
IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {}
- Result_t Unarchive(ASDCP::MemIOReader& Reader);
- Result_t Archive(ASDCP::MemIOWriter& Writer) const;
- const char* ToString(char* str_buf) const;
+ bool Unarchive(Kumu::MemIOReader* Reader);
+ bool Archive(Kumu::MemIOWriter* Writer) const;
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
};
Rational IndexEditRate;
@@ -315,8 +308,8 @@ namespace ASDCP
OPAtomHeader();
virtual ~OPAtomHeader();
- virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
- virtual Result_t WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderLength = 16384);
+ virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+ virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
virtual void Dump(FILE* = 0);
virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
Identification* GetIdentification();
@@ -339,8 +332,8 @@ namespace ASDCP
OPAtomIndexFooter();
virtual ~OPAtomIndexFooter();
- virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
- virtual Result_t WriteToFile(ASDCP::FileWriter& Writer, ui64_t duration);
+ virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+ virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
virtual void Dump(FILE* = 0);
virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&);
diff --git a/src/MXFTypes.cpp b/src/MXFTypes.cpp
index 111d493..c2352fd 100755
--- a/src/MXFTypes.cpp
+++ b/src/MXFTypes.cpp
@@ -29,19 +29,51 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief MXF objects
*/
+#include <KM_prng.h>
#include "MXFTypes.h"
-#include "FortunaRNG.h"
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
//------------------------------------------------------------------------------------------
//
+const char*
+ASDCP::UL::EncodeString(char* str_buf, ui32_t buf_len) const
+{
+ if ( buf_len > 38 ) // room for dotted notation?
+ {
+ snprintf(str_buf, buf_len,
+ "%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x",
+ m_Value[0], m_Value[1], m_Value[2], m_Value[3],
+ m_Value[4], m_Value[5], m_Value[6], m_Value[7],
+ m_Value[8], m_Value[9], m_Value[10], m_Value[11],
+ m_Value[12], m_Value[13], m_Value[14], m_Value[15]
+ );
+
+ return str_buf;
+ }
+ else if ( buf_len > 32 ) // room for compact?
+ {
+ snprintf(str_buf, buf_len,
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ m_Value[0], m_Value[1], m_Value[2], m_Value[3],
+ m_Value[4], m_Value[5], m_Value[6], m_Value[7],
+ m_Value[8], m_Value[9], m_Value[10], m_Value[11],
+ m_Value[12], m_Value[13], m_Value[14], m_Value[15]
+ );
+
+ return str_buf;
+ }
+
+ return 0;
+}
//
void
ASDCP::UMID::MakeUMID(int Type)
{
UUID AssetID;
- AssetID.GenRandomValue();
+ Kumu::GenRandomValue(AssetID);
MakeUMID(Type, AssetID);
}
@@ -69,11 +101,11 @@ ASDCP::UMID::MakeUMID(int Type, const UUID& AssetID)
// Write the timestamp value to the given buffer in the form 2004-05-01 13:20:00.000
// returns 0 if the buffer is smaller than DateTimeLen
const char*
-ASDCP::UMID::ToString(char* str_buf) const
+ASDCP::UMID::EncodeString(char* str_buf, ui32_t buf_len) const
{
assert(str_buf);
- snprintf(str_buf, IdentBufferLen, "[%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x],%02x,%02x,%02x,%02x,",
+ snprintf(str_buf, buf_len, "[%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x],%02x,%02x,%02x,%02x,",
m_Value[0], m_Value[1], m_Value[2], m_Value[3],
m_Value[4], m_Value[5], m_Value[6], m_Value[7],
m_Value[8], m_Value[9], m_Value[10], m_Value[11],
@@ -85,7 +117,7 @@ ASDCP::UMID::ToString(char* str_buf) const
if ( ( m_Value[8] & 0x80 ) == 0 )
{
// half-swapped UL, use [bbaa9988.ddcc.ffee.00010203.04050607]
- snprintf(str_buf + offset, IdentBufferLen - offset,
+ snprintf(str_buf + offset, buf_len - offset,
"[%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x]",
m_Value[24], m_Value[25], m_Value[26], m_Value[27],
m_Value[28], m_Value[29], m_Value[30], m_Value[31],
@@ -96,7 +128,7 @@ ASDCP::UMID::ToString(char* str_buf) const
else
{
// UUID, use {00112233-4455-6677-8899-aabbccddeeff}
- snprintf(str_buf + offset, IdentBufferLen - offset,
+ snprintf(str_buf + offset, buf_len - offset,
"{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
m_Value[16], m_Value[17], m_Value[18], m_Value[19],
m_Value[20], m_Value[21], m_Value[22], m_Value[23],
@@ -108,20 +140,6 @@ ASDCP::UMID::ToString(char* str_buf) const
return str_buf;
}
-//
-void
-ASDCP::UUID::GenRandomValue()
-{
- FortunaRNG RNG;
- RNG.FillRandom(m_Value, UUIDlen);
- m_Value[6] &= 0x0f; // clear bits 4-7
- m_Value[6] |= 0x40; // set UUID version
- m_Value[8] &= 0x3f; // clear bits 6&7
- m_Value[8] |= 0x80; // set bit 7
- m_HasValue = true;
-}
-
-
//------------------------------------------------------------------------------------------
//
@@ -135,7 +153,7 @@ ASDCP::MXF::UTF16String::operator=(const char* sz)
}
else
{
- ui32_t len = xmin((ui32_t)strlen(sz), (IdentBufferLen - 1));
+ ui32_t len = Kumu::xmin((ui32_t)strlen(sz), (IdentBufferLen - 1));
m_length = len;
memcpy(m_buffer, sz, m_length);
m_buffer[m_length] = 0;
@@ -146,11 +164,11 @@ ASDCP::MXF::UTF16String::operator=(const char* sz)
//
-ASDCP::Result_t
-ASDCP::MXF::UTF16String::Unarchive(ASDCP::MemIOReader& Reader)
+bool
+ASDCP::MXF::UTF16String::Unarchive(Kumu::MemIOReader* Reader)
{
- const byte_t* p = Reader.CurrentData();
- m_length = Reader.Remainder();
+ const byte_t* p = Reader->CurrentData();
+ m_length = Reader->Remainder();
assert(m_length % 2 == 0);
m_length /= 2;
assert(IdentBufferLen >= m_length);
@@ -161,23 +179,23 @@ ASDCP::MXF::UTF16String::Unarchive(ASDCP::MemIOReader& Reader)
m_buffer[i] = 0;
- Reader.SkipOffset(m_length*2);
- return RESULT_OK;
+ Reader->SkipOffset(m_length*2);
+ return true;
}
//
-ASDCP::Result_t
-ASDCP::MXF::UTF16String::Archive(ASDCP::MemIOWriter& Writer) const
+bool
+ASDCP::MXF::UTF16String::Archive(Kumu::MemIOWriter* Writer) const
{
- byte_t* p = Writer.Data() + Writer.Size();
+ byte_t* p = Writer->Data() + Writer->Length();
ui32_t i = 0;
memset(p, 0, (m_length*2)+2);
for ( i = 0; i < m_length; i++ )
p[(i*2)+1] = m_buffer[i];
- Writer.AddOffset(m_length * 2);
- return RESULT_OK;
+ Writer->AddOffset(m_length * 2);
+ return true;
}
@@ -274,7 +292,7 @@ ASDCP::MXF::Timestamp::AddHours(i32_t hours)
}
}
-#else // WM_WIN32
+#else // KM_WIN32
#include <time.h>
@@ -345,7 +363,7 @@ ASDCP::MXF::Timestamp::AddHours(i32_t hours)
}
}
-#endif // WM_WIN32
+#endif // KM_WIN32
ASDCP::MXF::Timestamp::Timestamp(const Timestamp& rhs)
@@ -407,11 +425,11 @@ ASDCP::MXF::Timestamp::operator!=(const Timestamp& rhs) const
//
const char*
-ASDCP::MXF::Timestamp::ToString(char* str_buf) const
+ASDCP::MXF::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const
{
// 2004-05-01 13:20:00.000
- snprintf(str_buf, IntBufferLen,
- "%04hu-%02hu-%02hu %02hu:%02hu:%02hu.000",
+ snprintf(str_buf, buf_len,
+ "%04hu-%02hu-%02hu %02hu:%02hu:%02hu.000",
Year, Month, Day, Hour, Minute, Second, Tick);
return str_buf;
@@ -430,26 +448,18 @@ ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* Prime
TagValue Tag;
ui16_t pkt_len = 0;
- result = MemIOReader::ReadUi8(&Tag.a);
-
- if ( ASDCP_SUCCESS(result) )
- result = MemIOReader::ReadUi8(&Tag.b);
-
- if ( ASDCP_SUCCESS(result) )
- result = MemIOReader::ReadUi16BE(&pkt_len);
-
- if ( ASDCP_SUCCESS(result) )
- {
- m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
- result = SkipOffset(pkt_len);
- }
-
- if ( ASDCP_FAILURE(result) )
- {
- DefaultLogSink().Error("Malformed Set\n");
- m_ElementMap.clear();
- break;
- }
+ if ( MemIOReader::ReadUi8(&Tag.a) )
+ if ( MemIOReader::ReadUi8(&Tag.b) )
+ if ( MemIOReader::ReadUi16BE(&pkt_len) )
+ {
+ m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
+ if ( SkipOffset(pkt_len) )
+ continue;;
+ }
+
+ DefaultLogSink().Error("Malformed Set\n");
+ m_ElementMap.clear();
+ result = RESULT_KLV_CODING;
}
}
@@ -469,8 +479,8 @@ ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
{
if ( Entry.tag.a == 0 )
{
- DefaultLogSink().Info("No such UL in this TL list: %s (%02x %02x)\n",
- Entry.name, Entry.tag.a, Entry.tag.b);
+ // DefaultLogSink().Debug("No such UL in this TL list: %s (%02x %02x)\n",
+ // Entry.name, Entry.tag.a, Entry.tag.b);
return false;
}
@@ -486,20 +496,20 @@ ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
return true;
}
- DefaultLogSink().Info("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
+ // DefaultLogSink().Debug("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
return false;
}
//
ASDCP::Result_t
-ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, IArchive* Object)
+ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, Kumu::IArchive* Object)
{
ASDCP_TEST_NULL(Object);
if ( FindTL(Entry) )
{
if ( m_size < m_capacity ) // don't try to unarchive an empty item
- return Object->Unarchive(*this);
+ return Object->Unarchive(this) ? RESULT_OK : RESULT_KLV_CODING;
}
return RESULT_FALSE;
@@ -512,7 +522,7 @@ ASDCP::MXF::TLVReader::ReadUi8(const MDDEntry& Entry, ui8_t* value)
ASDCP_TEST_NULL(value);
if ( FindTL(Entry) )
- return MemIOReader::ReadUi8(value);
+ return MemIOReader::ReadUi8(value) ? RESULT_OK : RESULT_KLV_CODING;
return RESULT_FALSE;
}
@@ -524,7 +534,7 @@ ASDCP::MXF::TLVReader::ReadUi16(const MDDEntry& Entry, ui16_t* value)
ASDCP_TEST_NULL(value);
if ( FindTL(Entry) )
- return MemIOReader::ReadUi16BE(value);
+ return MemIOReader::ReadUi16BE(value) ? RESULT_OK : RESULT_KLV_CODING;
return RESULT_FALSE;
}
@@ -536,7 +546,7 @@ ASDCP::MXF::TLVReader::ReadUi32(const MDDEntry& Entry, ui32_t* value)
ASDCP_TEST_NULL(value);
if ( FindTL(Entry) )
- return MemIOReader::ReadUi32BE(value);
+ return MemIOReader::ReadUi32BE(value) ? RESULT_OK : RESULT_KLV_CODING;
return RESULT_FALSE;
}
@@ -548,7 +558,7 @@ ASDCP::MXF::TLVReader::ReadUi64(const MDDEntry& Entry, ui64_t* value)
ASDCP_TEST_NULL(value);
if ( FindTL(Entry) )
- return MemIOReader::ReadUi64BE(value);
+ return MemIOReader::ReadUi64BE(value) ? RESULT_OK : RESULT_KLV_CODING;
return RESULT_FALSE;
}
@@ -580,15 +590,14 @@ ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
return RESULT_FAIL;
}
- Result_t result = MemIOWriter::WriteUi8(TmpTag.a);
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi8(TmpTag.b);
-
- return result;
+ if ( ! MemIOWriter::WriteUi8(TmpTag.a) ) return RESULT_KLV_CODING;
+ if ( ! MemIOWriter::WriteUi8(TmpTag.b) ) return RESULT_KLV_CODING;
+ return RESULT_OK;
}
//
ASDCP::Result_t
-ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, IArchive* Object)
+ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, Kumu::IArchive* Object)
{
ASDCP_TEST_NULL(Object);
@@ -600,19 +609,12 @@ ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, IArchive* Object)
// write a temp length
byte_t* l_p = CurrentData();
- if ( ASDCP_SUCCESS(result) )
- MemIOWriter::WriteUi16BE(0);
+ if ( ! MemIOWriter::WriteUi16BE(0) ) return RESULT_KLV_CODING;
- if ( ASDCP_SUCCESS(result) )
- {
- ui32_t before = Size();
- result = Object->Archive(*this);
-
- if ( ASDCP_SUCCESS(result) )
- i2p<ui16_t>(ASDCP_i16_BE( Size() - before), l_p);
- }
-
- return result;
+ ui32_t before = Length();
+ if ( ! Object->Archive(this) ) return RESULT_KLV_CODING;
+ Kumu::i2p<ui16_t>(KM_i16_BE( Length() - before), l_p);
+ return RESULT_OK;
}
//
@@ -621,8 +623,13 @@ ASDCP::MXF::TLVWriter::WriteUi8(const MDDEntry& Entry, ui8_t* value)
{
ASDCP_TEST_NULL(value);
Result_t result = WriteTag(Entry);
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui8_t));
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi8(*value);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ if ( ! MemIOWriter::WriteUi16BE(sizeof(ui8_t)) ) return RESULT_KLV_CODING;
+ if ( ! MemIOWriter::WriteUi8(*value) ) return RESULT_KLV_CODING;
+ }
+
return result;
}
@@ -632,8 +639,13 @@ ASDCP::MXF::TLVWriter::WriteUi16(const MDDEntry& Entry, ui16_t* value)
{
ASDCP_TEST_NULL(value);
Result_t result = WriteTag(Entry);
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui16_t));
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(*value);
+
+ if ( KM_SUCCESS(result) )
+ {
+ if ( ! MemIOWriter::WriteUi16BE(sizeof(ui16_t)) ) return RESULT_KLV_CODING;
+ if ( ! MemIOWriter::WriteUi16BE(*value) ) return RESULT_KLV_CODING;
+ }
+
return result;
}
@@ -643,8 +655,13 @@ ASDCP::MXF::TLVWriter::WriteUi32(const MDDEntry& Entry, ui32_t* value)
{
ASDCP_TEST_NULL(value);
Result_t result = WriteTag(Entry);
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui32_t));
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi32BE(*value);
+
+ if ( KM_SUCCESS(result) )
+ {
+ if ( ! MemIOWriter::WriteUi16BE(sizeof(ui32_t)) ) return RESULT_KLV_CODING;
+ if ( ! MemIOWriter::WriteUi32BE(*value) ) return RESULT_KLV_CODING;
+ }
+
return result;
}
@@ -654,8 +671,13 @@ ASDCP::MXF::TLVWriter::WriteUi64(const MDDEntry& Entry, ui64_t* value)
{
ASDCP_TEST_NULL(value);
Result_t result = WriteTag(Entry);
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui64_t));
- if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi64BE(*value);
+
+ if ( KM_SUCCESS(result) )
+ {
+ if ( ! MemIOWriter::WriteUi16BE(sizeof(ui64_t)) ) return RESULT_KLV_CODING;
+ if ( ! MemIOWriter::WriteUi64BE(*value) ) return RESULT_KLV_CODING;
+ }
+
return result;
}
@@ -673,39 +695,31 @@ ASDCP::MXF::Raw::~Raw()
}
//
-ASDCP::Result_t
-ASDCP::MXF::Raw::Unarchive(ASDCP::MemIOReader& Reader)
+bool
+ASDCP::MXF::Raw::Unarchive(Kumu::MemIOReader* Reader)
{
- ui32_t payload_size = Reader.Remainder();
-
- if ( payload_size == 0 )
- return RESULT_OK;
+ ui32_t payload_size = Reader->Remainder();
+ if ( payload_size == 0 ) return false;
+ if ( KM_FAILURE(Capacity(payload_size)) ) return false;
- Result_t result = Capacity(payload_size);
-
- if ( ASDCP_SUCCESS(result) )
- {
- memcpy(Data(), Reader.CurrentData(), payload_size);
- Size(payload_size);
- }
-
- return result;
+ memcpy(Data(), Reader->CurrentData(), payload_size);
+ Length(payload_size);
+ return true;
}
//
-ASDCP::Result_t
-ASDCP::MXF::Raw::Archive(ASDCP::MemIOWriter& Writer) const
+bool
+ASDCP::MXF::Raw::Archive(Kumu::MemIOWriter* Writer) const
{
- return Writer.WriteRaw(RoData(), Size());
+ return Writer->WriteRaw(RoData(), Length());
}
//
const char*
-ASDCP::MXF::Raw::ToString(char* str_buf) const
+ASDCP::MXF::Raw::EncodeString(char* str_buf, ui32_t buf_len) const
{
*str_buf = 0;
- bin2hex(RoData(), Size(), str_buf, IdentBufferLen);
- snprintf(str_buf, IdentBufferLen, "%s\n", str_buf);
+ Kumu::bin2hex(RoData(), Length(), str_buf, buf_len);
return str_buf;
}
diff --git a/src/MXFTypes.h b/src/MXFTypes.h
index e78b55c..5bb8ca4 100755
--- a/src/MXFTypes.h
+++ b/src/MXFTypes.h
@@ -54,7 +54,7 @@ namespace ASDCP
typedef std::map<TagValue, ItemInfo> TagMap;
//
- class TLVReader : public ASDCP::MemIOReader
+ class TLVReader : public Kumu::MemIOReader
{
TagMap m_ElementMap;
@@ -66,7 +66,7 @@ namespace ASDCP
public:
TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* = 0);
- Result_t ReadObject(const MDDEntry&, IArchive*);
+ Result_t ReadObject(const MDDEntry&, Kumu::IArchive*);
Result_t ReadUi8(const MDDEntry&, ui8_t*);
Result_t ReadUi16(const MDDEntry&, ui16_t*);
Result_t ReadUi32(const MDDEntry&, ui32_t*);
@@ -74,7 +74,7 @@ namespace ASDCP
};
//
- class TLVWriter : public ASDCP::MemIOWriter
+ class TLVWriter : public Kumu::MemIOWriter
{
TagMap m_ElementMap;
@@ -86,7 +86,7 @@ namespace ASDCP
public:
TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* = 0);
- Result_t WriteObject(const MDDEntry&, IArchive*);
+ Result_t WriteObject(const MDDEntry&, Kumu::IArchive*);
Result_t WriteUi8(const MDDEntry&, ui8_t*);
Result_t WriteUi16(const MDDEntry&, ui16_t*);
Result_t WriteUi32(const MDDEntry&, ui32_t*);
@@ -95,58 +95,55 @@ namespace ASDCP
//
template <class T>
- class Batch : public std::vector<T>, public IArchive
+ class Batch : public std::vector<T>, public Kumu::IArchive
{
public:
Batch() {}
~Batch() {}
//
- Result_t Unarchive(ASDCP::MemIOReader& Reader) {
+ virtual bool Unarchive(Kumu::MemIOReader* Reader) {
ui32_t ItemCount, ItemSize;
- Result_t result = Reader.ReadUi32BE(&ItemCount);
-
- if ( ASDCP_SUCCESS(result) )
- result = Reader.ReadUi32BE(&ItemSize);
+ if ( ! Reader->ReadUi32BE(&ItemCount) ) return false;
+ if ( ! Reader->ReadUi32BE(&ItemSize) ) return false;
if ( ( ItemCount > 65536 ) || ( ItemSize > 1024 ) )
- return RESULT_FAIL;
+ return false;
- for ( ui32_t i = 0; i < ItemCount && ASDCP_SUCCESS(result); i++ )
+ bool result = true;
+ for ( ui32_t i = 0; i < ItemCount && result; i++ )
{
T Tmp;
result = Tmp.Unarchive(Reader);
- if ( ASDCP_SUCCESS(result) )
+ if ( result )
push_back(Tmp);
}
return result;
}
- inline bool HasValue() const { return ! this->empty(); }
+ inline virtual bool HasValue() const { return ! this->empty(); }
//
- Result_t Archive(ASDCP::MemIOWriter& Writer) const {
- Result_t result = Writer.WriteUi32BE(size());
- byte_t* p = Writer.CurrentData();
-
- if ( ASDCP_SUCCESS(result) )
- result = Writer.WriteUi32BE(0);
+ virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi32BE(this->size()) ) return false;
+ byte_t* p = Writer->CurrentData();
- if ( ASDCP_FAILURE(result) || this->empty() )
- return result;
+ if ( ! Writer->WriteUi32BE(0) ) return false;
+ if ( this->empty() ) return true;
typename std::vector<T>::const_iterator l_i = this->begin();
assert(l_i != this->end());
- ui32_t ItemSize = Writer.Remainder();
- result = (*l_i).Archive(Writer);
- ItemSize -= Writer.Remainder();
- i2p<ui32_t>(ASDCP_i32_BE(ItemSize), p);
+ ui32_t ItemSize = Writer->Remainder();
+ if ( ! (*l_i).Archive(Writer) ) return false;
+ ItemSize -= Writer->Remainder();
+ Kumu::i2p<ui32_t>(KM_i32_BE(ItemSize), p);
l_i++;
- for ( ; l_i != this->end() && ASDCP_SUCCESS(result); l_i++ )
+ bool result = true;
+ for ( ; l_i != this->end() && result; l_i++ )
result = (*l_i).Archive(Writer);
return result;
@@ -162,39 +159,41 @@ namespace ASDCP
typename std::vector<T>::iterator i = this->begin();
for ( ; i != this->end(); i++ )
- fprintf(stream, " %s\n", (*i).ToString(identbuf));
+ fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
}
};
//
template <class T>
- class Array : public std::list<T>, public IArchive
+ class Array : public std::list<T>, public Kumu::IArchive
{
public:
Array() {}
~Array() {}
//
- Result_t Unarchive(ASDCP::MemIOReader& Reader)
+ virtual bool Unarchive(Kumu::MemIOReader* Reader)
{
- while ( Reader.Remainder() > 0 )
+ bool result = true;
+
+ while ( Reader->Remainder() > 0 && result )
{
T Tmp;
- Tmp.Unarchive(Reader);
+ result = Tmp.Unarchive(Reader);
push_back(Tmp);
}
- return RESULT_OK;
+ return result;
}
- inline bool HasValue() const { return ! this->empty(); }
+ inline virtual bool HasValue() const { return ! this->empty(); }
//
- Result_t Archive(ASDCP::MemIOWriter& Writer) const {
- Result_t result = RESULT_OK;
+ virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ bool result = true;
typename std::list<T>::const_iterator l_i = this->begin();
- for ( ; l_i != this->end() && ASDCP_SUCCESS(result); l_i++ )
+ for ( ; l_i != this->end() && result; l_i++ )
result = (*l_i).Archive(Writer);
return result;
@@ -210,12 +209,12 @@ namespace ASDCP
typename std::list<T>::iterator i = this->begin();
for ( ; i != this->end(); i++ )
- fprintf(stream, " %s\n", (*i).ToString(identbuf));
+ fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
}
};
//
- class Timestamp : public IArchive
+ class Timestamp : public Kumu::IArchive
{
public:
ui16_t Year;
@@ -246,33 +245,27 @@ namespace ASDCP
// Write the timestamp value to the given buffer in the form 2004-05-01 13:20:00.000
// returns 0 if the buffer is smaller than DateTimeLen
- const char* ToString(char* str_buf) const;
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
//
- inline Result_t Unarchive(ASDCP::MemIOReader& Reader) {
- Result_t result = Reader.ReadUi16BE(&Year);
-
- if ( ASDCP_SUCCESS(result) )
- result = Reader.ReadRaw(&Month, 6);
-
- return result;
+ inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( ! Reader->ReadUi16BE(&Year) ) return false;
+ if ( ! Reader->ReadRaw(&Month, 6) ) return false;
+ return true;
}
- inline bool HasValue() const { return true; }
+ inline virtual bool HasValue() const { return true; }
//
- inline Result_t Archive(ASDCP::MemIOWriter& Writer) const {
- Result_t result = Writer.WriteUi16BE(Year);
-
- if ( ASDCP_SUCCESS(result) )
- result = Writer.WriteRaw(&Month, 6);
-
- return result;
+ inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi16BE(Year) ) return false;
+ if ( ! Writer->WriteRaw(&Month, 6) ) return false;
+ return true;
}
};
//
- class UTF16String : public IArchive
+ class UTF16String : public Kumu::IArchive
{
ui16_t m_length;
char m_buffer[IdentBufferLen];
@@ -285,18 +278,19 @@ namespace ASDCP
const UTF16String& operator=(const char*);
//
- const char* ToString(char* str_buf) const {
- strncpy(str_buf, m_buffer, m_length+1);
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ strncpy(str_buf, m_buffer, Kumu::xmin(buf_len, ((ui32_t)m_length+1)));
+ str_buf[buf_len-1] = 0;
return str_buf;
}
- Result_t Unarchive(ASDCP::MemIOReader& Reader);
- inline bool HasValue() const { return m_length > 0; }
- Result_t Archive(ASDCP::MemIOWriter& Writer) const;
+ virtual bool Unarchive(Kumu::MemIOReader* Reader);
+ inline virtual bool HasValue() const { return m_length > 0; }
+ virtual bool Archive(Kumu::MemIOWriter* Writer) const;
};
//
- class Rational : public ASDCP::Rational, public IArchive
+ class Rational : public ASDCP::Rational, public Kumu::IArchive
{
public:
Rational() {}
@@ -325,34 +319,28 @@ namespace ASDCP
}
//
- const char* ToString(char* str_buf) const {
- snprintf(str_buf, IdentBufferLen, "%lu/%lu", Numerator, Denominator);
+ inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ snprintf(str_buf, buf_len, "%lu/%lu", Numerator, Denominator);
return str_buf;
}
- Result_t Unarchive(ASDCP::MemIOReader& Reader) {
- Result_t result = Reader.ReadUi32BE((ui32_t*)&Numerator);
-
- if ( ASDCP_SUCCESS(result) )
- result = Reader.ReadUi32BE((ui32_t*)&Denominator);
-
- return result;
+ inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( ! Reader->ReadUi32BE((ui32_t*)&Numerator) ) return false;
+ if ( ! Reader->ReadUi32BE((ui32_t*)&Denominator) ) return false;
+ return true;
}
- inline bool HasValue() const { return true; }
+ inline virtual bool HasValue() const { return true; }
- Result_t Archive(ASDCP::MemIOWriter& Writer) const {
- Result_t result = Writer.WriteUi32BE((ui32_t)Numerator);
-
- if ( ASDCP_SUCCESS(result) )
- result = Writer.WriteUi32BE((ui32_t)Denominator);
-
- return result;
+ inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi32BE((ui32_t)Numerator) ) return false;
+ if ( ! Writer->WriteUi32BE((ui32_t)Denominator) ) return false;
+ return true;
}
};
//
- class VersionType : public IArchive
+ class VersionType : public Kumu::IArchive
{
ASDCP_NO_COPY_CONSTRUCT(VersionType);
@@ -368,40 +356,36 @@ namespace ASDCP
~VersionType() {}
void Dump(FILE* = 0);
- const char* ToString(char* str_buf) const {
- snprintf(str_buf, IdentBufferLen, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, Release);
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+ snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, Release);
return str_buf;
}
- Result_t Unarchive(ASDCP::MemIOReader& Reader) {
- Result_t result = Reader.ReadUi16BE(&Major);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi16BE(&Minor);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi16BE(&Patch);
- if ( ASDCP_SUCCESS(result) ) result = Reader.ReadUi16BE(&Build);
- if ( ASDCP_SUCCESS(result) )
- {
- ui16_t tmp_release;
- result = Reader.ReadUi16BE(&tmp_release);
- Release = (Release_t)tmp_release;
- }
-
- return result;
+ virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+ if ( ! Reader->ReadUi16BE(&Major) ) return false;
+ if ( ! Reader->ReadUi16BE(&Minor) ) return false;
+ if ( ! Reader->ReadUi16BE(&Patch) ) return false;
+ if ( ! Reader->ReadUi16BE(&Build) ) return false;
+ ui16_t tmp_release;
+ if ( ! Reader->ReadUi16BE(&tmp_release) ) return false;
+ Release = (Release_t)tmp_release;
+ return true;
}
- inline bool HasValue() const { return true; }
+ inline virtual bool HasValue() const { return true; }
- Result_t Archive(ASDCP::MemIOWriter& Writer) const {
- Result_t result = Writer.WriteUi16BE(Major);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi16BE(Minor);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi16BE(Patch);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi16BE(Build);
- if ( ASDCP_SUCCESS(result) ) result = Writer.WriteUi16BE((ui16_t)(Release & 0x0000ffffL));
- return result;
+ virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+ if ( ! Writer->WriteUi16BE(Major) ) return false;
+ if ( ! Writer->WriteUi16BE(Minor) ) return false;
+ if ( ! Writer->WriteUi16BE(Patch) ) return false;
+ if ( ! Writer->WriteUi16BE(Build) ) return false;
+ if ( ! Writer->WriteUi16BE((ui16_t)(Release & 0x0000ffffL)) ) return false;
+ return true;
}
};
//
- class Raw : public ASDCP::FrameBuffer, public IArchive
+ class Raw : public Kumu::ByteString, public Kumu::IArchive
{
ASDCP_NO_COPY_CONSTRUCT(Raw);
@@ -410,10 +394,10 @@ namespace ASDCP
~Raw();
//
- Result_t Unarchive(ASDCP::MemIOReader& Reader);
- inline bool HasValue() const { return Size() > 0; }
- Result_t Archive(ASDCP::MemIOWriter& Writer) const;
- const char* ToString(char* str_buf) const;
+ virtual bool Unarchive(Kumu::MemIOReader* Reader);
+ inline virtual bool HasValue() const { return Length() > 0; }
+ virtual bool Archive(Kumu::MemIOWriter* Writer) const;
+ const char* EncodeString(char* str_buf, ui32_t buf_len) const;
};
} // namespace MXF
diff --git a/src/Metadata.cpp b/src/Metadata.cpp
index d4cc819..3290b1b 100755
--- a/src/Metadata.cpp
+++ b/src/Metadata.cpp
@@ -30,9 +30,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <KM_mutex.h>
#include "Metadata.h"
-#include "Mutex.h"
-#include "hex_utils.h"
const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH;
@@ -71,24 +70,24 @@ typedef std::map<ASDCP::UL, FLT_t>::iterator FLi_t;
class FactoryList : public std::map<ASDCP::UL, FLT_t>
{
- ASDCP::Mutex m_Lock;
+ Kumu::Mutex m_Lock;
public:
FactoryList() {}
~FactoryList() {}
bool Empty() {
- ASDCP::AutoMutex BlockLock(m_Lock);
+ Kumu::AutoMutex BlockLock(m_Lock);
return empty();
}
FLi_t Find(const byte_t* label) {
- ASDCP::AutoMutex BlockLock(m_Lock);
+ Kumu::AutoMutex BlockLock(m_Lock);
return find(label);
}
FLi_t End() {
- ASDCP::AutoMutex BlockLock(m_Lock);
+ Kumu::AutoMutex BlockLock(m_Lock);
return end();
}
@@ -220,15 +219,15 @@ ASDCP::MXF::Identification::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " %22s = %s\n", "ThisGenerationUID", ThisGenerationUID.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "CompanyName", CompanyName.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "ProductName", ProductName.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "ProductVersion", ProductVersion.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "VersionString", VersionString.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "ProductUID", ProductUID.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "ModificationDate", ModificationDate.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "ToolkitVersion", ToolkitVersion.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "Platform", Platform.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "ThisGenerationUID", ThisGenerationUID.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "CompanyName", CompanyName.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "ProductName", ProductName.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "ProductVersion", ProductVersion.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "VersionString", VersionString.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "ProductUID", ProductUID.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "ModificationDate", ModificationDate.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "ToolkitVersion", ToolkitVersion.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "Platform", Platform.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -339,7 +338,7 @@ ASDCP::MXF::EssenceContainerData::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " %22s = %s\n", "LinkedPackageUID", LinkedPackageUID.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "LinkedPackageUID", LinkedPackageUID.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %d\n", "IndexSID", IndexSID);
fprintf(stream, " %22s = %d\n", "BodySID", BodySID);
}
@@ -400,10 +399,10 @@ ASDCP::MXF::GenericPackage::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " %22s = %s\n", "PackageUID", PackageUID.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "Name", Name.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "PackageCreationDate", PackageCreationDate.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "PackageModifiedDate", PackageModifiedDate.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "PackageUID", PackageUID.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "Name", Name.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "PackageCreationDate", PackageCreationDate.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "PackageModifiedDate", PackageModifiedDate.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s:\n", "Tracks");
Tracks.Dump(stream);
}
@@ -489,7 +488,7 @@ ASDCP::MXF::SourcePackage::Dump(FILE* stream)
stream = stderr;
GenericPackage::Dump(stream);
- fprintf(stream, " %22s = %s\n", "Descriptor", Descriptor.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "Descriptor", Descriptor.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -548,8 +547,8 @@ ASDCP::MXF::GenericTrack::Dump(FILE* stream)
InterchangeObject::Dump(stream);
fprintf(stream, " %22s = %d\n", "TrackID", TrackID);
fprintf(stream, " %22s = %d\n", "TrackNumber", TrackNumber);
- fprintf(stream, " %22s = %s\n", "TrackName", TrackName.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "Sequence", Sequence.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "TrackName", TrackName.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "Sequence", Sequence.EncodeString(identbuf, IdentBufferLen));
}
@@ -635,7 +634,7 @@ ASDCP::MXF::Track::Dump(FILE* stream)
stream = stderr;
GenericTrack::Dump(stream);
- fprintf(stream, " %22s = %s\n", "EditRate", EditRate.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "EditRate", EditRate.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %s\n", "Origin", i64sz(Origin, identbuf));
}
@@ -689,7 +688,7 @@ ASDCP::MXF::StructuralComponent::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " %22s = %s\n", "DataDefinition", DataDefinition.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "DataDefinition", DataDefinition.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %s\n", "Duration", i64sz(Duration, identbuf));
}
@@ -783,7 +782,7 @@ ASDCP::MXF::SourceClip::Dump(FILE* stream)
StructuralComponent::Dump(stream);
fprintf(stream, " %22s = %s\n", "StartPosition", i64sz(StartPosition, identbuf));
- fprintf(stream, " %22s = %s\n", "SourcePackageID", SourcePackageID.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "SourcePackageID", SourcePackageID.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %d\n", "SourceTrackID", SourceTrackID);
}
@@ -942,10 +941,10 @@ ASDCP::MXF::FileDescriptor::Dump(FILE* stream)
GenericDescriptor::Dump(stream);
fprintf(stream, " %22s = %d\n", "LinkedTrackID", LinkedTrackID);
- fprintf(stream, " %22s = %s\n", "SampleRate", SampleRate.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "SampleRate", SampleRate.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %s\n", "ContainerDuration", i64sz(ContainerDuration, identbuf));
- fprintf(stream, " %22s = %s\n", "EssenceContainer", EssenceContainer.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "Codec", Codec.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "EssenceContainer", EssenceContainer.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "Codec", Codec.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -1006,7 +1005,7 @@ ASDCP::MXF::GenericSoundEssenceDescriptor::Dump(FILE* stream)
stream = stderr;
FileDescriptor::Dump(stream);
- fprintf(stream, " %22s = %s\n", "AudioSamplingRate", AudioSamplingRate.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "AudioSamplingRate", AudioSamplingRate.EncodeString(identbuf, IdentBufferLen));
fprintf(stream, " %22s = %d\n", "Locked", Locked);
fprintf(stream, " %22s = %d\n", "AudioRefLevel", AudioRefLevel);
fprintf(stream, " %22s = %d\n", "ChannelCount", ChannelCount);
@@ -1128,7 +1127,7 @@ ASDCP::MXF::GenericPictureEssenceDescriptor::Dump(FILE* stream)
fprintf(stream, " %22s = %d\n", "FrameLayout", FrameLayout);
fprintf(stream, " %22s = %d\n", "StoredWidth", StoredWidth);
fprintf(stream, " %22s = %d\n", "StoredHeight", StoredHeight);
- fprintf(stream, " %22s = %s\n", "AspectRatio", AspectRatio.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "AspectRatio", AspectRatio.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -1267,9 +1266,9 @@ ASDCP::MXF::JPEG2000PictureSubDescriptor::Dump(FILE* stream)
fprintf(stream, " %22s = %d\n", "XTOsize", XTOsize);
fprintf(stream, " %22s = %d\n", "YTOsize", YTOsize);
fprintf(stream, " %22s = %d\n", "Csize", Csize);
- fprintf(stream, " %22s = %s\n", "PictureComponentSizing", PictureComponentSizing.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "CodingStyleDefault", CodingStyleDefault.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "QuantizationDefault", QuantizationDefault.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "PictureComponentSizing", PictureComponentSizing.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "CodingStyleDefault", CodingStyleDefault.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "QuantizationDefault", QuantizationDefault.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -1445,8 +1444,8 @@ ASDCP::MXF::DMSegment::Dump(FILE* stream)
InterchangeObject::Dump(stream);
fprintf(stream, " %22s = %s\n", "EventStartPosition", i64sz(EventStartPosition, identbuf));
- fprintf(stream, " %22s = %s\n", "EventComment", EventComment.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "DMFramework", DMFramework.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "EventComment", EventComment.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "DMFramework", DMFramework.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -1497,7 +1496,7 @@ ASDCP::MXF::CryptographicFramework::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " %22s = %s\n", "ContextSR", ContextSR.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "ContextSR", ContextSR.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -1556,11 +1555,11 @@ ASDCP::MXF::CryptographicContext::Dump(FILE* stream)
stream = stderr;
InterchangeObject::Dump(stream);
- fprintf(stream, " %22s = %s\n", "ContextID", ContextID.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "SourceEssenceContainer", SourceEssenceContainer.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "CipherAlgorithm", CipherAlgorithm.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "MICAlgorithm", MICAlgorithm.ToString(identbuf));
- fprintf(stream, " %22s = %s\n", "CryptographicKeyID", CryptographicKeyID.ToString(identbuf));
+ fprintf(stream, " %22s = %s\n", "ContextID", ContextID.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "SourceEssenceContainer", SourceEssenceContainer.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "CipherAlgorithm", CipherAlgorithm.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "MICAlgorithm", MICAlgorithm.EncodeString(identbuf, IdentBufferLen));
+ fprintf(stream, " %22s = %s\n", "CryptographicKeyID", CryptographicKeyID.EncodeString(identbuf, IdentBufferLen));
}
//
@@ -1580,5 +1579,5 @@ ASDCP::MXF::CryptographicContext::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
}
//
-// end MXF.cpp
+// end Metadata.cpp
//
diff --git a/src/PCM_Parser.cpp b/src/PCM_Parser.cpp
index 331bebf..f3e32db 100755
--- a/src/PCM_Parser.cpp
+++ b/src/PCM_Parser.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004, John Hurst
+Copyright (c) 2004-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -31,6 +31,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <Wav.h>
#include <assert.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
using namespace ASDCP;
using namespace ASDCP::PCM;
@@ -42,7 +44,7 @@ using namespace ASDCP::Wav;
//
class ASDCP::PCM::WAVParser::h__WAVParser
{
- FileReader m_FileReader;
+ Kumu::FileReader m_FileReader;
bool m_EOF;
ui32_t m_DataStart;
ui32_t m_DataLength;
diff --git a/src/Wav.cpp b/src/Wav.cpp
index ce64a78..92bd5e7 100755
--- a/src/Wav.cpp
+++ b/src/Wav.cpp
@@ -30,8 +30,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Wav.h"
-#include "hex_utils.h"
#include <assert.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
const ui32_t SimpleWavHeaderLength = 46;
@@ -69,7 +70,7 @@ ASDCP::Wav::SimpleWaveHeader::FillADesc(ASDCP::PCM::AudioDescriptor& ADesc, ASDC
//
ASDCP::Result_t
-ASDCP::Wav::SimpleWaveHeader::WriteToFile(ASDCP::FileWriter& OutFile) const
+ASDCP::Wav::SimpleWaveHeader::WriteToFile(Kumu::FileWriter& OutFile) const
{
ui32_t write_count;
byte_t tmp_header[SimpleWavHeaderLength];
@@ -87,26 +88,26 @@ ASDCP::Wav::SimpleWaveHeader::WriteToFile(ASDCP::FileWriter& OutFile) const
ui32_t RIFF_len = data_len + SimpleWavHeaderLength - 8;
memcpy(p, &FCC_RIFF, sizeof(fourcc)); p += 4;
- *((ui32_t*)p) = ASDCP_i32_LE(RIFF_len); p += 4;
+ *((ui32_t*)p) = KM_i32_LE(RIFF_len); p += 4;
memcpy(p, &FCC_WAVE, sizeof(fourcc)); p += 4;
memcpy(p, &FCC_fmt_, sizeof(fourcc)); p += 4;
- *((ui32_t*)p) = ASDCP_i32_LE(fmt_len); p += 4;
- *((ui16_t*)p) = ASDCP_i16_LE(format); p += 2;
- *((ui16_t*)p) = ASDCP_i16_LE(nchannels); p += 2;
- *((ui32_t*)p) = ASDCP_i32_LE(samplespersec); p += 4;
- *((ui32_t*)p) = ASDCP_i32_LE(avgbps); p += 4;
- *((ui16_t*)p) = ASDCP_i16_LE(blockalign); p += 2;
- *((ui16_t*)p) = ASDCP_i16_LE(bitspersample); p += 2;
- *((ui16_t*)p) = ASDCP_i16_LE(cbsize); p += 2;
+ *((ui32_t*)p) = KM_i32_LE(fmt_len); p += 4;
+ *((ui16_t*)p) = KM_i16_LE(format); p += 2;
+ *((ui16_t*)p) = KM_i16_LE(nchannels); p += 2;
+ *((ui32_t*)p) = KM_i32_LE(samplespersec); p += 4;
+ *((ui32_t*)p) = KM_i32_LE(avgbps); p += 4;
+ *((ui16_t*)p) = KM_i16_LE(blockalign); p += 2;
+ *((ui16_t*)p) = KM_i16_LE(bitspersample); p += 2;
+ *((ui16_t*)p) = KM_i16_LE(cbsize); p += 2;
memcpy(p, &FCC_data, sizeof(fourcc)); p += 4;
- *((ui32_t*)p) = ASDCP_i32_LE(data_len); p += 4;
+ *((ui32_t*)p) = KM_i32_LE(data_len); p += 4;
return OutFile.Write(tmp_header, SimpleWavHeaderLength, &write_count);
}
//
ASDCP::Result_t
-ASDCP::Wav::SimpleWaveHeader::ReadFromFile(const ASDCP::FileReader& InFile, ui32_t* data_start)
+ASDCP::Wav::SimpleWaveHeader::ReadFromFile(const Kumu::FileReader& InFile, ui32_t* data_start)
{
ui32_t read_count = 0;
ui32_t local_data_start = 0;
@@ -140,7 +141,7 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
return RESULT_RAW_FORMAT;
}
- ui32_t RIFF_len = ASDCP_i32_LE(*(ui32_t*)p); p += 4;
+ ui32_t RIFF_len = KM_i32_LE(*(ui32_t*)p); p += 4;
fourcc test_WAVE(p); p += 4;
if ( test_WAVE != FCC_WAVE )
@@ -154,7 +155,7 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
while ( p < end_p )
{
test_fcc = fourcc(p); p += 4;
- ui32_t chunk_size = ASDCP_i32_LE(*(ui32_t*)p); p += 4;
+ ui32_t chunk_size = KM_i32_LE(*(ui32_t*)p); p += 4;
if ( test_fcc == FCC_data )
{
@@ -171,7 +172,7 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
if ( test_fcc == FCC_fmt_ )
{
- ui16_t format = ASDCP_i16_LE(*(ui16_t*)p); p += 2;
+ ui16_t format = KM_i16_LE(*(ui16_t*)p); p += 2;
if ( format != 1 )
{
@@ -179,11 +180,11 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
return RESULT_RAW_FORMAT;
}
- nchannels = ASDCP_i16_LE(*(ui16_t*)p); p += 2;
- samplespersec = ASDCP_i32_LE(*(ui32_t*)p); p += 4;
- avgbps = ASDCP_i32_LE(*(ui32_t*)p); p += 4;
- blockalign = ASDCP_i16_LE(*(ui16_t*)p); p += 2;
- bitspersample = ASDCP_i16_LE(*(ui16_t*)p); p += 2;
+ nchannels = KM_i16_LE(*(ui16_t*)p); p += 2;
+ samplespersec = KM_i32_LE(*(ui32_t*)p); p += 4;
+ avgbps = KM_i32_LE(*(ui32_t*)p); p += 4;
+ blockalign = KM_i16_LE(*(ui16_t*)p); p += 2;
+ bitspersample = KM_i16_LE(*(ui16_t*)p); p += 2;
p += chunk_size - 16;
}
else
@@ -230,7 +231,7 @@ Rat_to_extended(ASDCP::Rational rate, byte_t* buf)
value <<= 1;
}
- *(ui32_t*)(buf+2) = ASDCP_i32_BE(value);
+ *(ui32_t*)(buf+2) = KM_i32_BE(value);
}
//
@@ -238,7 +239,7 @@ ASDCP::Rational
extended_to_Rat(const byte_t* buf)
{
ui32_t last = 0;
- ui32_t mantissa = ASDCP_i32_BE(*(ui32_t*)(buf+2));
+ ui32_t mantissa = KM_i32_BE(*(ui32_t*)(buf+2));
byte_t exp = 30 - *(buf+1);
@@ -271,7 +272,7 @@ ASDCP::AIFF::SimpleAIFFHeader::FillADesc(ASDCP::PCM::AudioDescriptor& ADesc, ASD
//
ASDCP::Result_t
-ASDCP::AIFF::SimpleAIFFHeader::ReadFromFile(const ASDCP::FileReader& InFile, ui32_t* data_start)
+ASDCP::AIFF::SimpleAIFFHeader::ReadFromFile(const Kumu::FileReader& InFile, ui32_t* data_start)
{
ui32_t read_count = 0;
ui32_t local_data_start = 0;
@@ -306,7 +307,7 @@ ASDCP::AIFF::SimpleAIFFHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
return RESULT_RAW_FORMAT;
}
- ui32_t RIFF_len = ASDCP_i32_BE(*(ui32_t*)p); p += 4;
+ ui32_t RIFF_len = KM_i32_BE(*(ui32_t*)p); p += 4;
fourcc test_AIFF(p); p += 4;
if ( test_AIFF != FCC_AIFF )
@@ -320,13 +321,13 @@ ASDCP::AIFF::SimpleAIFFHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
while ( p < end_p )
{
test_fcc = fourcc(p); p += 4;
- ui32_t chunk_size = ASDCP_i32_BE(*(ui32_t*)p); p += 4;
+ ui32_t chunk_size = KM_i32_BE(*(ui32_t*)p); p += 4;
if ( test_fcc == FCC_COMM )
{
- numChannels = ASDCP_i16_BE(*(ui16_t*)p); p += 2;
- numSampleFrames = ASDCP_i32_BE(*(ui32_t*)p); p += 4;
- sampleSize = ASDCP_i16_BE(*(ui16_t*)p); p += 2;
+ numChannels = KM_i16_BE(*(ui16_t*)p); p += 2;
+ numSampleFrames = KM_i32_BE(*(ui32_t*)p); p += 4;
+ sampleSize = KM_i16_BE(*(ui16_t*)p); p += 2;
memcpy(sampleRate, p, 10);
p += 10;
}
@@ -338,7 +339,7 @@ ASDCP::AIFF::SimpleAIFFHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
return RESULT_RAW_FORMAT;
}
- ui32_t offset = ASDCP_i32_BE(*(ui32_t*)p); p += 4;
+ ui32_t offset = KM_i32_BE(*(ui32_t*)p); p += 4;
p += 4; // blockSize;
data_len = chunk_size - 8;
diff --git a/src/Wav.h b/src/Wav.h
index efd99c0..bd890ce 100755
--- a/src/Wav.h
+++ b/src/Wav.h
@@ -32,7 +32,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _WAV_H_
#define _WAV_H_
-#include <FileIO.h>
+#include <KM_fileio.h>
+#include <AS_DCP.h>
namespace ASDCP
{
@@ -73,7 +74,7 @@ namespace ASDCP
}
Result_t ReadFromBuffer(const byte_t* buf, ui32_t buf_len, ui32_t* data_start);
- Result_t ReadFromFile(const ASDCP::FileReader& InFile, ui32_t* data_start);
+ Result_t ReadFromFile(const Kumu::FileReader& InFile, ui32_t* data_start);
void FillADesc(ASDCP::PCM::AudioDescriptor& ADesc, Rational PictureRate) const;
};
@@ -108,8 +109,8 @@ namespace ASDCP
SimpleWaveHeader(ASDCP::PCM::AudioDescriptor& ADesc);
Result_t ReadFromBuffer(const byte_t* buf, ui32_t buf_len, ui32_t* data_start);
- Result_t ReadFromFile(const ASDCP::FileReader& InFile, ui32_t* data_start);
- Result_t WriteToFile(ASDCP::FileWriter& OutFile) const;
+ Result_t ReadFromFile(const Kumu::FileReader& InFile, ui32_t* data_start);
+ Result_t WriteToFile(Kumu::FileWriter& OutFile) const;
void FillADesc(ASDCP::PCM::AudioDescriptor& ADesc, Rational PictureRate) const;
};
diff --git a/src/WavFileWriter.h b/src/WavFileWriter.h
index 40d23ba..b246f3c 100755
--- a/src/WavFileWriter.h
+++ b/src/WavFileWriter.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2005, John Hurst
+Copyright (c) 2005-2006, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\brief demux and write PCM data to WAV file(s)
*/
-#include <FileIO.h>
+#include <KM_fileio.h>
#include <Wav.h>
#include <list>
@@ -40,7 +40,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class WavFileWriter
{
ASDCP::PCM::AudioDescriptor m_ADesc;
- std::list<ASDCP::FileWriter*> m_OutFile;
+ std::list<Kumu::FileWriter*> m_OutFile;
ASDCP_NO_COPY_CONSTRUCT(WavFileWriter);
public:
@@ -73,7 +73,7 @@ class WavFileWriter
for ( ui32_t i = 0; i < file_count && ASDCP_SUCCESS(result); i++ )
{
snprintf(filename, 256, "%s_%lu.wav", file_root, (i + 1));
- m_OutFile.push_back(new ASDCP::FileWriter);
+ m_OutFile.push_back(new Kumu::FileWriter);
result = m_OutFile.back()->OpenWrite(filename);
if ( ASDCP_SUCCESS(result) )
@@ -91,7 +91,7 @@ class WavFileWriter
{
ui32_t write_count;
ASDCP::Result_t result = ASDCP::RESULT_OK;
- std::list<ASDCP::FileWriter*>::iterator fi;
+ std::list<Kumu::FileWriter*>::iterator fi;
assert(! m_OutFile.empty());
ui32_t sample_size = ASDCP::PCM::CalcSampleSize(m_ADesc);
diff --git a/src/asdcp-test.cpp b/src/asdcp-test.cpp
index c048a30..50a02ef 100755
--- a/src/asdcp-test.cpp
+++ b/src/asdcp-test.cpp
@@ -50,11 +50,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <assert.h>
-#include <FileIO.h>
+#include <KM_fileio.h>
+#include <KM_prng.h>
#include <PCMParserList.h>
#include <WavFileWriter.h>
-#include <hex_utils.h>
-#include <AS_DCP_UUID.h>
#include <MXF.h>
#include <Metadata.h>
@@ -138,46 +137,46 @@ USAGE: %s [-i [-H, -n]|-c <filename> [-p <rate>, -e, -M, -R]|-x <root-name> [-m]
fprintf(stream, "\
Major modes:\n\
- -i - show file info\n\
- -c <filename> - create AS-DCP file from input(s)\n\
- -x <root-name> - extract essence from AS-DCP file to named file(s)\n\
- -g - generate a random 16 byte value to stdout\n\
- -u - generate a random UUID value to stdout\n\
+ -i - Show file info\n\
+ -c <filename> - Create AS-DCP file from input(s)\n\
+ -x <root-name> - Extract essence from AS-DCP file to named file(s)\n\
+ -g - Generate a random 16 byte value to stdout\n\
+ -u - Generate a random UUID value to stdout\n\
-G - Perform GOP start lookup test on MPEG file\n\
- -V - show version\n\
- -h - show help\n\
+ -V - Show version\n\
+ -h - Show help\n\
\n");
fprintf(stream, "\
Security Options:\n\
- -j <key-id-str> - write key ID instead of creating a random value\n\
- -k <key-string> - use key for ciphertext operations\n\
- -e - encrypt MPEG or JP2K headers (default)\n\
- -E - do not encrypt MPEG or JP2K headers\n\
- -M - do not create HMAC values when writing\n\
+ -j <key-id-str> - Write key ID instead of creating a random value\n\
+ -k <key-string> - Use key for ciphertext operations\n\
+ -e - Encrypt MPEG or JP2K headers (default)\n\
+ -E - Do not encrypt MPEG or JP2K headers\n\
+ -M - Do not create HMAC values when writing\n\
-m - verify HMAC values when reading\n\
\n");
fprintf(stream, "\
Read/Write Options:\n\
-b <buf-size> - Size (in bytes) of the picture frame buffer, default: 2097152 (2MB)\n\
- -f <frame-num> - starting frame number, default 0\n\
- -d <duration> - number of frames to process, default all\n\
+ -f <frame-num> - Starting frame number, default 0\n\
+ -d <duration> - Number of frames to process, default all\n\
-p <rate> - fps of picture when wrapping PCM or JP2K:, use one of [23|24|48], 24 is default\n\
-L - Write SMPTE UL values instead of MXF Interop\n\
-R - Repeat the first frame over the entire file (picture essence only, requires -c, -d)\n\
-S - Split Wave essence to stereo WAV files during extract (default = multichannel WAV)\n\
- -W - read input file only, do not write source file\n\
+ -W - Read input file only, do not write source file\n\
\n");
fprintf(stream, "\
Info Options:\n\
- -H - show MXF header metadata, used with option -i\n\
- -n - show index, used with option -i\n\
+ -H - Show MXF header metadata, used with option -i\n\
+ -n - Show index, used with option -i\n\
\n\
Other Options:\n\
- -s <number> - number of bytes of frame buffer to be dumped as hex to stderr (use with -v)\n\
- -v - verbose, show extra detail during run\n\
+ -s <number> - Number of bytes of frame buffer to be dumped as hex to stderr (use with -v)\n\
+ -v - Verbose, show extra detail during run\n\
\n\
NOTES: o There is no option grouping, all options must be distinct arguments.\n\
o All option arguments must be separated from the option by whitespace.\n\
@@ -296,7 +295,7 @@ public:
TEST_EXTRA_ARG(i, 'k');
{
ui32_t length;
- hex2bin(argv[i], key_value, KeyLen, &length);
+ Kumu::hex2bin(argv[i], key_value, KeyLen, &length);
if ( length != KeyLen )
{
@@ -310,7 +309,7 @@ public:
TEST_EXTRA_ARG(i, 'j');
{
ui32_t length;
- hex2bin(argv[i], key_id_value, UUIDlen, &length);
+ Kumu::hex2bin(argv[i], key_id_value, UUIDlen, &length);
if ( length != UUIDlen )
{
@@ -402,7 +401,7 @@ write_MPEG2_file(CommandOptions& Options)
MPEG2::MXFWriter Writer;
MPEG2::VideoDescriptor VDesc;
byte_t IV_buf[CBC_BLOCK_SIZE];
- FortunaRNG RNG;
+ Kumu::FortunaRNG RNG;
// set up essence parser
Result_t result = Parser.OpenRead(Options.filenames[0]);
@@ -424,18 +423,18 @@ write_MPEG2_file(CommandOptions& Options)
if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
{
WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
- GenRandomUUID(RNG, Info.AssetUUID);
+ Kumu::GenRandomUUID(Info.AssetUUID);
if ( Options.use_smpte_labels )
{
- Info.LabelSetType = LS_MXF_INTEROP;
+ Info.LabelSetType = LS_MXF_SMPTE;
fprintf(stderr, "ATTENTION! Writing SMPTE Universal Labels\n");
}
// configure encryption
if( Options.key_flag )
{
- GenRandomUUID(RNG, Info.ContextID);
+ Kumu::GenRandomUUID(Info.ContextID);
Info.EncryptedEssence = true;
if ( Options.key_id_flag )
@@ -453,7 +452,7 @@ write_MPEG2_file(CommandOptions& Options)
{
Info.UsesHMAC = true;
HMAC = new HMACContext;
- result = HMAC->InitKey(Options.key_value);
+ result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
}
}
@@ -517,7 +516,7 @@ read_MPEG2_file(CommandOptions& Options)
HMACContext* HMAC = 0;
MPEG2::MXFReader Reader;
MPEG2::FrameBuffer FrameBuffer(Options.fb_size);
- FileWriter OutFile;
+ Kumu::FileWriter OutFile;
ui32_t frame_count = 0;
Result_t result = Reader.OpenRead(Options.filenames[0]);
@@ -555,7 +554,7 @@ read_MPEG2_file(CommandOptions& Options)
if ( Info.UsesHMAC )
{
HMAC = new HMACContext;
- result = HMAC->InitKey(Options.key_value);
+ result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
}
else
{
@@ -649,8 +648,8 @@ write_JP2K_file(CommandOptions& Options)
JP2K::FrameBuffer FrameBuffer(Options.fb_size);
JP2K::PictureDescriptor PDesc;
JP2K::SequenceParser Parser;
- byte_t IV_buf[CBC_BLOCK_SIZE];
- FortunaRNG RNG;
+ byte_t IV_buf[CBC_BLOCK_SIZE];
+ Kumu::FortunaRNG RNG;
// set up essence parser
Result_t result = Parser.OpenRead(Options.filenames[0]);
@@ -673,18 +672,18 @@ write_JP2K_file(CommandOptions& Options)
if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
{
WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
- GenRandomUUID(RNG, Info.AssetUUID);
+ Kumu::GenRandomUUID(Info.AssetUUID);
if ( Options.use_smpte_labels )
{
- Info.LabelSetType = LS_MXF_INTEROP;
+ Info.LabelSetType = LS_MXF_SMPTE;
fprintf(stderr, "ATTENTION! Writing SMPTE Universal Labels\n");
}
// configure encryption
if( Options.key_flag )
{
- GenRandomUUID(RNG, Info.ContextID);
+ Kumu::GenRandomUUID(Info.ContextID);
Info.EncryptedEssence = true;
if ( Options.key_id_flag )
@@ -702,7 +701,7 @@ write_JP2K_file(CommandOptions& Options)
{
Info.UsesHMAC = true;
HMAC = new HMACContext;
- result = HMAC->InitKey(Options.key_value);
+ result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
}
}
@@ -796,7 +795,7 @@ read_JP2K_file(CommandOptions& Options)
if ( Info.UsesHMAC )
{
HMAC = new HMACContext;
- result = HMAC->InitKey(Options.key_value);
+ result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
}
else
{
@@ -815,7 +814,7 @@ read_JP2K_file(CommandOptions& Options)
if ( ASDCP_SUCCESS(result) )
{
- FileWriter OutFile;
+ Kumu::FileWriter OutFile;
char filename[256];
ui32_t write_count;
snprintf(filename, 256, "%s%06lu.j2c", Options.file_root, i);
@@ -842,15 +841,15 @@ read_JP2K_file(CommandOptions& Options)
Result_t
write_PCM_file(CommandOptions& Options)
{
- AESEncContext* Context = 0;
- HMACContext* HMAC = 0;
- PCMParserList Parser;
- PCM::MXFWriter Writer;
- PCM::FrameBuffer FrameBuffer;
+ AESEncContext* Context = 0;
+ HMACContext* HMAC = 0;
+ PCMParserList Parser;
+ PCM::MXFWriter Writer;
+ PCM::FrameBuffer FrameBuffer;
PCM::AudioDescriptor ADesc;
- Rational PictureRate = Options.PictureRate();
- byte_t IV_buf[CBC_BLOCK_SIZE];
- FortunaRNG RNG;
+ Rational PictureRate = Options.PictureRate();
+ byte_t IV_buf[CBC_BLOCK_SIZE];
+ Kumu::FortunaRNG RNG;
// set up essence parser
Result_t result = Parser.OpenRead(Options.file_count, Options.filenames, PictureRate);
@@ -876,18 +875,18 @@ write_PCM_file(CommandOptions& Options)
if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag )
{
WriterInfo Info = s_MyInfo; // fill in your favorite identifiers here
- GenRandomUUID(RNG, Info.AssetUUID);
+ Kumu::GenRandomUUID(Info.AssetUUID);
if ( Options.use_smpte_labels )
{
- Info.LabelSetType = LS_MXF_INTEROP;
+ Info.LabelSetType = LS_MXF_SMPTE;
fprintf(stderr, "ATTENTION! Writing SMPTE Universal Labels\n");
}
// configure encryption
if( Options.key_flag )
{
- GenRandomUUID(RNG, Info.ContextID);
+ Kumu::GenRandomUUID(Info.ContextID);
Info.EncryptedEssence = true;
if ( Options.key_id_flag )
@@ -905,7 +904,7 @@ write_PCM_file(CommandOptions& Options)
{
Info.UsesHMAC = true;
HMAC = new HMACContext;
- result = HMAC->InitKey(Options.key_value);
+ result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
}
}
@@ -1006,7 +1005,7 @@ read_PCM_file(CommandOptions& Options)
return RESULT_FAIL;
}
- last_frame = xmin(Options.start_frame + last_frame, ADesc.ContainerDuration);
+ last_frame = Kumu::xmin(Options.start_frame + last_frame, ADesc.ContainerDuration);
}
ADesc.ContainerDuration = last_frame - Options.start_frame;
@@ -1026,7 +1025,7 @@ read_PCM_file(CommandOptions& Options)
if ( Info.UsesHMAC )
{
HMAC = new HMACContext;
- result = HMAC->InitKey(Options.key_value);
+ result = HMAC->InitKey(Options.key_value, Info.LabelSetType);
}
else
{
@@ -1165,7 +1164,7 @@ show_file_info(CommandOptions& Options)
else
{
fprintf(stderr, "File is not AS-DCP: %s\n", Options.filenames[0]);
- FileReader Reader;
+ Kumu::FileReader Reader;
MXF::OPAtomHeader TestHeader;
result = Reader.OpenRead(Options.filenames[0]);
@@ -1226,22 +1225,19 @@ main(int argc, const char** argv)
}
else if ( Options.genkey_flag )
{
- FortunaRNG RNG;
+ Kumu::FortunaRNG RNG;
byte_t bin_buf[KeyLen];
char str_buf[40];
RNG.FillRandom(bin_buf, KeyLen);
- printf("%s\n", bin2hex(bin_buf, KeyLen, str_buf, 40));
+ printf("%s\n", Kumu::bin2hex(bin_buf, KeyLen, str_buf, 40));
}
else if ( Options.genid_flag )
{
- FortunaRNG RNG;
- byte_t bin_buf[KeyLen];
+ UUID TmpID;
+ Kumu::GenRandomValue(TmpID);
char str_buf[40];
-
- GenRandomUUID(RNG, bin_buf);
- bin2hex(bin_buf, KeyLen, str_buf, 40);
- printf("%s\n", hyphenate_UUID(str_buf, 40));
+ printf("%s\n", TmpID.EncodeHex(str_buf, 40));
}
else if ( Options.extract_flag )
{
@@ -1305,13 +1301,13 @@ main(int argc, const char** argv)
}
}
- if ( result != RESULT_OK )
+ if ( ASDCP_FAILURE(result) )
{
fputs("Program stopped on error.\n", stderr);
if ( result != RESULT_FAIL )
{
- fputs(GetResultString(result), stderr);
+ fputs(result, stderr);
fputc('\n', stderr);
}
diff --git a/src/blackwave.cpp b/src/blackwave.cpp
new file mode 100644
index 0000000..c84774f
--- /dev/null
+++ b/src/blackwave.cpp
@@ -0,0 +1,245 @@
+/*
+Copyright (c) 2005, 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 wavsplit.cpp
+ \version $Id$
+ \brief Black WAV file generator
+*/
+
+#include "Wav.h"
+#include <assert.h>
+
+using namespace ASDCP;
+
+//------------------------------------------------------------------------------------------
+//
+// command line option parser class
+
+static const char* PACKAGE = "wavsplit"; // program name for messages
+
+// Macros used to test command option data state.
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \
+ { \
+ fprintf(stderr, "Argument not found for option %c.\n", (c)); \
+ return; \
+ }
+//
+void
+banner(FILE* stream = stderr)
+{
+ fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2005-2006 John Hurst\n\n\
+wavesplit is part of asdcplib.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+ PACKAGE, ASDCP::Version(), PACKAGE);
+}
+
+//
+void
+usage(FILE* stream = stderr)
+{
+ fprintf(stream, "\
+USAGE: %s [-v|-h[-d]] <filename>\n\
+\n\
+ -V - Show version\n\
+ -h - Show help\n\
+ -d <duration> - Number of 2k-sample frames to process, default 1440\n\
+\n\
+Other Options:\n\
+ -v - Verbose, show extra detail during run\n\
+\n\
+ NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+ o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE);
+}
+
+//
+//
+class CommandOptions
+{
+ CommandOptions();
+
+public:
+ bool error_flag; // true if the given options are in error or not complete
+ bool verbose_flag; // true if the verbose option was selected
+ bool version_flag; // true if the version display option was selected
+ bool help_flag; // true if the help display option was selected
+ ui32_t duration; // number of frames to be processed
+ const char* filename; // filename prefix for files written by the extract mode
+
+ CommandOptions(int argc, const char** argv) :
+ error_flag(true), verbose_flag(false), version_flag(false), help_flag(false),
+ duration(1440), filename(0)
+ {
+ for ( int i = 1; i < argc; i++ )
+ {
+ if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+ {
+ switch ( argv[i][1] )
+ {
+ case 'V': version_flag = true; break;
+ case 'h': help_flag = true; break;
+ case 'v': verbose_flag = true; break;
+
+ case 'd':
+ TEST_EXTRA_ARG(i, 'd');
+ duration = atoi(argv[i]); // TODO: test for negative value, should use strtol()
+ break;
+
+ default:
+ fprintf(stderr, "Unrecognized option: %c\n", argv[i][1]);
+ return;
+ }
+ }
+ else
+ {
+ if ( filename )
+ {
+ fprintf(stderr, "Unexpected extra filename.\n");
+ return;
+ }
+
+ filename = argv[i];
+ }
+ }
+
+ if ( filename == 0 )
+ {
+ fputs("Output filename required.\n", stderr);
+ return;
+ }
+
+ error_flag = false;
+ }
+};
+
+
+//
+//
+Result_t
+make_black_wav_file(CommandOptions& Options)
+{
+ PCM::FrameBuffer FrameBuffer;
+ PCM::AudioDescriptor ADesc;
+
+ ADesc.SampleRate = Rational(24,1);
+ ADesc.AudioSamplingRate = ASDCP::SampleRate_48k;
+ ADesc.Locked = 0;
+ ADesc.ChannelCount = 1;
+ ADesc.QuantizationBits = 24;
+ ADesc.BlockAlign = 18;
+ ADesc.AvgBps = 86400;
+ ADesc.LinkedTrackID = 1;
+ ADesc.ContainerDuration = Options.duration;
+
+ // fill the frame buffer with a frame (2000 samples) of black
+ FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc));
+ memset(FrameBuffer.Data(), 0, FrameBuffer.Capacity());
+ FrameBuffer.Size(FrameBuffer.Capacity());
+
+ if ( 1 ) // Options.verbose_flag )
+ {
+ fprintf(stderr, "48Khz PCM Audio, %s fps (%lu spf)\n", "24",
+ PCM::CalcSamplesPerFrame(ADesc));
+ fputs("AudioDescriptor:\n", stderr);
+ PCM::AudioDescriptorDump(ADesc);
+ }
+
+ // set up output file
+ Kumu::FileWriter OutFile;
+ Result_t result = OutFile.OpenWrite(Options.filename);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ Wav::SimpleWaveHeader WavHeader(ADesc);
+ result = WavHeader.WriteToFile(OutFile);
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ui32_t write_count = 0;
+ ui32_t duration = 0;
+
+ while ( ASDCP_SUCCESS(result) && (duration++ < Options.duration) )
+ {
+ result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count);
+ }
+
+ if ( result == RESULT_ENDOFFILE )
+ result = RESULT_OK;
+ }
+
+ return RESULT_OK;
+}
+
+
+//
+int
+main(int argc, const char** argv)
+{
+ Result_t result = RESULT_OK;
+ CommandOptions Options(argc, argv);
+
+ if ( Options.help_flag )
+ {
+ usage();
+ return 0;
+ }
+
+ if ( Options.error_flag )
+ return 3;
+
+ if ( Options.version_flag )
+ banner();
+
+ else
+ result = make_black_wav_file(Options);
+
+ if ( result != RESULT_OK )
+ {
+ fputs("Program stopped on error.\n", stderr);
+
+ if ( result != RESULT_FAIL )
+ {
+ fputs(result, stderr);
+ fputc('\n', stderr);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+//
diff --git a/src/h__Reader.cpp b/src/h__Reader.cpp
index 7851953..268f308 100755
--- a/src/h__Reader.cpp
+++ b/src/h__Reader.cpp
@@ -112,15 +112,11 @@ ASDCP::h__Reader::OpenMXFRead(const char* filename)
// partition and read off the partition pack
if ( m_HeaderPart.m_RIP.PairArray.size() == 3 )
{
- fprintf(stderr, "Three part!\n");
Array<RIP::Pair>::iterator r_i = m_HeaderPart.m_RIP.PairArray.begin();
r_i++;
m_File.Seek((*r_i).ByteOffset);
result = m_BodyPart.InitFromFile(m_File);
- m_BodyPart.Dump();
- // TODO: check the partition pack to make sure it is
- // really a body with a single essence container
}
m_EssenceStart = m_File.Tell();
@@ -163,7 +159,7 @@ public:
inline const ui64_t Length() { return m_ValueLength; }
inline const ui64_t KLLength() { return m_KLLength; }
- Result_t ReadKLFromFile(ASDCP::FileReader& Reader)
+ Result_t ReadKLFromFile(Kumu::FileReader& Reader)
{
ui32_t read_count;
ui32_t header_length = SMPTE_UL_LENGTH + MXF_BER_LENGTH;
@@ -197,7 +193,7 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
// get frame position and go read the frame's key and length
Result_t result = RESULT_OK;
KLReader Reader;
- ASDCP::fpos_t FilePosition = m_EssenceStart + TmpEntry.StreamOffset;
+ Kumu::fpos_t FilePosition = m_EssenceStart + TmpEntry.StreamOffset;
if ( FilePosition != m_LastPosition )
{
@@ -244,7 +240,7 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
byte_t* ess_p = m_CtFrameBuf.Data();
// read context ID length
- if ( ! read_test_BER(&ess_p, UUIDlen) )
+ if ( ! Kumu::read_test_BER(&ess_p, UUIDlen) )
return RESULT_FORMAT;
// test the context ID
@@ -256,14 +252,14 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
ess_p += UUIDlen;
// read PlaintextOffset length
- if ( ! read_test_BER(&ess_p, sizeof(ui64_t)) )
+ if ( ! Kumu::read_test_BER(&ess_p, sizeof(ui64_t)) )
return RESULT_FORMAT;
- ui32_t PlaintextOffset = (ui32_t)ASDCP_i64_BE(cp2i<ui64_t>(ess_p));
+ ui32_t PlaintextOffset = (ui32_t)KM_i64_BE(Kumu::cp2i<ui64_t>(ess_p));
ess_p += sizeof(ui64_t);
// read essence UL length
- if ( ! read_test_BER(&ess_p, SMPTE_UL_LENGTH) )
+ if ( ! Kumu::read_test_BER(&ess_p, SMPTE_UL_LENGTH) )
return RESULT_FORMAT;
// test essence UL
@@ -272,7 +268,7 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
char strbuf[IntBufferLen];
const MDDEntry* Entry = Dict::FindUL(Key.Value());
if ( Entry == 0 )
- DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Key.ToString(strbuf));
+ DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Key.EncodeString(strbuf, IntBufferLen));
else
DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Entry->name);
return RESULT_FORMAT;
@@ -280,10 +276,10 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
ess_p += SMPTE_UL_LENGTH;
// read SourceLength length
- if ( ! read_test_BER(&ess_p, sizeof(ui64_t)) )
+ if ( ! Kumu::read_test_BER(&ess_p, sizeof(ui64_t)) )
return RESULT_FORMAT;
- ui32_t SourceLength = (ui32_t)ASDCP_i64_BE(cp2i<ui64_t>(ess_p));
+ ui32_t SourceLength = (ui32_t)KM_i64_BE(Kumu::cp2i<ui64_t>(ess_p));
ess_p += sizeof(ui64_t);
assert(SourceLength);
@@ -296,7 +292,7 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
ui32_t esv_length = calc_esv_length(SourceLength, PlaintextOffset);
// read ESV length
- if ( ! read_test_BER(&ess_p, esv_length) )
+ if ( ! Kumu::read_test_BER(&ess_p, esv_length) )
{
DefaultLogSink().Error("read_test_BER did not return %lu\n", esv_length);
return RESULT_FORMAT;
@@ -377,7 +373,7 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
char strbuf[IntBufferLen];
const MDDEntry* Entry = Dict::FindUL(Key.Value());
if ( Entry == 0 )
- DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Key.ToString(strbuf));
+ DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Key.EncodeString(strbuf, IntBufferLen));
else
DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Entry->name);
return RESULT_FORMAT;
diff --git a/src/h__Writer.cpp b/src/h__Writer.cpp
index 1449748..7d874c0 100755
--- a/src/h__Writer.cpp
+++ b/src/h__Writer.cpp
@@ -30,7 +30,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "AS_DCP_internal.h"
-#include "MemIO.h"
#include "KLV.h"
using namespace ASDCP;
@@ -120,7 +119,7 @@ ASDCP::h__Writer::WriteMXFHeader(const std::string& PackageLabel, const UL& Wrap
m_HeaderPart.AddChildObject(Ident);
m_HeaderPart.m_Preface->Identifications.push_back(Ident->InstanceUID);
- Ident->ThisGenerationUID.GenRandomValue();
+ Kumu::GenRandomValue(Ident->ThisGenerationUID);
Ident->CompanyName = m_Info.CompanyName.c_str();
Ident->ProductName = m_Info.ProductName.c_str();
Ident->VersionString = m_Info.ProductVersion.c_str();
@@ -315,11 +314,11 @@ Result_t
ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
AESEncContext* Ctx, HMACContext* HMAC)
{
- Result_t result;
+ Result_t result = RESULT_OK;
IntegrityPack IntPack;
byte_t overhead[128];
- MemIOWriter Overhead(overhead, 128);
+ Kumu::MemIOWriter Overhead(overhead, 128);
if ( FrameBuf.Size() == 0 )
{
@@ -371,12 +370,12 @@ ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte
Overhead.WriteUi64BE(FrameBuf.Size()); // write SourceLength
Overhead.WriteBER(m_CtFrameBuf.Size(), MXF_BER_LENGTH); // write ESV length
- result = m_File.Writev(Overhead.Data(), Overhead.Size());
+ result = m_File.Writev(Overhead.Data(), Overhead.Length());
}
if ( ASDCP_SUCCESS(result) )
{
- m_StreamOffset += Overhead.Size();
+ m_StreamOffset += Overhead.Length();
// write encrypted source value
result = m_File.Writev((byte_t*)m_CtFrameBuf.RoData(), m_CtFrameBuf.Size());
}
@@ -386,7 +385,7 @@ ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte
m_StreamOffset += m_CtFrameBuf.Size();
byte_t hmoverhead[512];
- MemIOWriter HMACOverhead(hmoverhead, 512);
+ Kumu::MemIOWriter HMACOverhead(hmoverhead, 512);
// write the HMAC
if ( m_Info.UsesHMAC )
@@ -400,21 +399,21 @@ ASDCP::h__Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf, const byte
}
// write HMAC
- result = m_File.Writev(HMACOverhead.Data(), HMACOverhead.Size());
- m_StreamOffset += HMACOverhead.Size();
+ result = m_File.Writev(HMACOverhead.Data(), HMACOverhead.Length());
+ m_StreamOffset += HMACOverhead.Length();
}
}
else
{
Overhead.WriteRaw((byte_t*)EssenceUL, SMPTE_UL_LENGTH);
Overhead.WriteBER(FrameBuf.Size(), MXF_BER_LENGTH);
- result = m_File.Writev(Overhead.Data(), Overhead.Size());
+ result = m_File.Writev(Overhead.Data(), Overhead.Length());
if ( ASDCP_SUCCESS(result) )
result = m_File.Writev((byte_t*)FrameBuf.RoData(), FrameBuf.Size());
if ( ASDCP_SUCCESS(result) )
- m_StreamOffset += Overhead.Size() + FrameBuf.Size();
+ m_StreamOffset += Overhead.Length() + FrameBuf.Size();
}
if ( ASDCP_SUCCESS(result) )
diff --git a/src/klvwalk.cpp b/src/klvwalk.cpp
index b5b3cea..395aa54 100755
--- a/src/klvwalk.cpp
+++ b/src/klvwalk.cpp
@@ -31,7 +31,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AS_DCP.h"
#include "MXF.h"
-#include "hex_utils.h"
+#include <KM_log.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -40,15 +40,14 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/stat.h>
using namespace ASDCP;
+using Kumu::DefaultLogSink;
+
+const char* PACKAGE = "klvwalk";
//------------------------------------------------------------------------------------------
//
-// There is no header file thet defines this function.
-// You just have to know it's there...
-void set_debug_mode(bool info_mode, bool debug_mode);
-
int
main(int argc, char** argv)
@@ -56,19 +55,24 @@ main(int argc, char** argv)
Result_t result = RESULT_OK;
bool read_mxf = false;
int arg_i = 1;
- set_debug_mode(true, true);
- if ( strcmp(argv[1], "-r") == 0 )
+ if ( argc > arg_i && strcmp(argv[1], "-r") == 0 )
{
read_mxf = true;
arg_i++;
}
+ if ( argc - arg_i != 1 )
+ {
+ fprintf(stderr, "usage: %s [-r] <infile>\n", PACKAGE);
+ return 1;
+ }
+
fprintf(stderr, "Opening file %s\n", argv[arg_i]);
if ( read_mxf )
{
- ASDCP::FileReader Reader;
+ Kumu::FileReader Reader;
ASDCP::MXF::OPAtomHeader Header;
result = Reader.OpenRead(argv[arg_i]);
@@ -95,7 +99,7 @@ main(int argc, char** argv)
}
else // dump klv
{
- ASDCP::FileReader Reader;
+ Kumu::FileReader Reader;
KLVFilePacket KP;
result = Reader.OpenRead(argv[arg_i]);
@@ -119,7 +123,7 @@ main(int argc, char** argv)
if ( result != RESULT_FAIL )
{
- fputs(GetResultString(result), stderr);
+ fputs(result, stderr);
fputc('\n', stderr);
}
diff --git a/src/wavesplit.cpp b/src/wavesplit.cpp
new file mode 100755
index 0000000..2a40e1e
--- /dev/null
+++ b/src/wavesplit.cpp
@@ -0,0 +1,369 @@
+/*
+Copyright (c) 2005-2006, 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 wavesplit.cpp
+ \version $Id$
+ \brief WAV file splitter
+*/
+
+#include <AS_DCP.h>
+#include <WavFileWriter.h>
+#include <assert.h>
+
+using namespace ASDCP;
+
+//------------------------------------------------------------------------------------------
+//
+// command line option parser class
+
+static const char* PACKAGE = "wavesplit"; // program name for messages
+
+// Macros used to test command option data state.
+
+// True if a major mode has already been selected.
+#define TEST_MAJOR_MODE() ( create_flag )
+
+// Causes the caller to return if a major mode has already been selected,
+// otherwise sets the given flag.
+#define TEST_SET_MAJOR_MODE(f) if ( TEST_MAJOR_MODE() ) \
+ { \
+ fputs("Conflicting major mode, choose one of -(ic)).\n", stderr); \
+ return; \
+ } \
+ (f) = true;
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c) if ( ++i >= argc || argv[(i)][0] == '-' ) \
+ { \
+ fprintf(stderr, "Argument not found for option %c.\n", (c)); \
+ return; \
+ }
+//
+void
+banner(FILE* stream = stderr)
+{
+ fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2005-2006 John Hurst\n\n\
+wavesplit is part of asdcplib.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+ PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
+
+//
+void
+usage(FILE* stream = stderr)
+{
+ fprintf(stream, "\
+USAGE: %s [-i|-c <root-name> [-v]] <filename>\n\
+\n\
+Major modes:\n\
+ -c <root-name> - Create a WAV file for each channel in the input file (default is two channel files)\n\
+ -V - Show version\n\
+ -h - Show help\n\
+\n\
+Read/Write Options:\n\
+ -f <frame-num> - Starting frame number, default 0\n\
+ -d <duration> - Number of frames to process, default all\n\
+ -v - Print extra info while processing\n\
+\n\
+ NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+ o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE);
+}
+
+//
+//
+class CommandOptions
+{
+ CommandOptions();
+
+public:
+ bool error_flag; // true if the given options are in error or not complete
+ bool create_flag; // true if the file create mode was selected
+ bool version_flag; // true if the version display option was selected
+ bool help_flag; // true if the help display option was selected
+ bool verbose_flag; // true for extra info during procesing
+ ui32_t start_frame; // frame number to begin processing
+ ui32_t duration; // number of frames to be processed
+ const char* file_root; // filename prefix for files written by the extract mode
+ const char* filename; // filename to be processed
+
+ CommandOptions(int argc, const char** argv) :
+ error_flag(true), create_flag(false),
+ version_flag(false), help_flag(false), start_frame(0),
+ duration(0xffffffff), file_root(0), filename(0)
+ {
+ for ( int i = 1; i < argc; i++ )
+ {
+ if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+ {
+ switch ( argv[i][1] )
+ {
+ case 'V': version_flag = true; break;
+ case 'h': help_flag = true; break;
+ case 'c':
+ TEST_SET_MAJOR_MODE(create_flag);
+ TEST_EXTRA_ARG(i, 'c');
+ file_root = argv[i];
+ break;
+
+ case 'f':
+ TEST_EXTRA_ARG(i, 'f');
+ start_frame = atoi(argv[i]); // TODO: test for negative value, should use strtol()
+ break;
+
+ case 'd':
+ TEST_EXTRA_ARG(i, 'd');
+ duration = atoi(argv[i]); // TODO: test for negative value, should use strtol()
+ break;
+
+ default:
+ fprintf(stderr, "Unrecognized option: %c\n", argv[i][1]);
+ return;
+ }
+ }
+ else
+ {
+ if ( filename )
+ {
+ fprintf(stderr, "Unexpected extra filename.\n");
+ return;
+ }
+
+ filename = argv[i];
+ }
+ }
+
+ if ( TEST_MAJOR_MODE() )
+ {
+ if ( filename == 0 )
+ {
+ fputs("Input filename required.\n", stderr);
+ return;
+ }
+ }
+
+ if ( ! TEST_MAJOR_MODE() && ! help_flag && ! version_flag )
+ {
+ fputs("No operation selected (use one of -(ic) or -h for help).\n", stderr);
+ return;
+ }
+
+ error_flag = false;
+ }
+};
+
+
+//
+//
+void
+split_buffer(ui32_t sample_size, PCM::FrameBuffer& FrameBuffer,
+ PCM::FrameBuffer& L_FrameBuffer, PCM::FrameBuffer& R_FrameBuffer)
+{
+ assert((FrameBuffer.Size() % 2) == 0);
+ byte_t* p = FrameBuffer.Data();
+ byte_t* end_p = p + FrameBuffer.Size();
+ byte_t* lp = L_FrameBuffer.Data();
+ byte_t* rp = R_FrameBuffer.Data();
+
+ for ( ; p < end_p; )
+ {
+ memcpy(lp, p, sample_size);
+ lp += sample_size;
+ p += sample_size;
+ memcpy(rp, p, sample_size);
+ rp += sample_size;
+ p += sample_size;
+ }
+
+ L_FrameBuffer.Size(L_FrameBuffer.Capacity());
+ R_FrameBuffer.Size(R_FrameBuffer.Capacity());
+}
+
+
+//
+//
+Result_t
+split_wav_file(CommandOptions& Options)
+{
+ PCM::FrameBuffer FrameBuffer;
+ PCM::FrameBuffer L_FrameBuffer;
+ PCM::FrameBuffer R_FrameBuffer;
+ PCM::AudioDescriptor ADesc;
+ Rational PictureRate = EditRate_24;
+ PCM::WAVParser Parser;
+
+ // set up essence parser
+ Result_t result = Parser.OpenRead(Options.filename, PictureRate);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ Parser.FillAudioDescriptor(ADesc);
+
+ ADesc.SampleRate = PictureRate;
+ ui32_t fb_size = PCM::CalcFrameBufferSize(ADesc);
+ assert((fb_size % 2) == 0);
+ FrameBuffer.Capacity(fb_size);
+ L_FrameBuffer.Capacity(fb_size/2);
+ R_FrameBuffer.Capacity(fb_size/2);
+
+ if ( Options.verbose_flag )
+ {
+ fprintf(stderr, "48Khz PCM Audio, %s fps (%lu spf)\n", "24",
+ PCM::CalcSamplesPerFrame(ADesc));
+ fputs("AudioDescriptor:\n", stderr);
+ PCM::AudioDescriptorDump(ADesc);
+ }
+
+ ADesc.ChannelCount = 1;
+ }
+
+ // set up output files
+ Kumu::FileWriter L_OutFile;
+ Kumu::FileWriter R_OutFile;
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ char filename[256];
+ sprintf(filename, "%s_l.wav", Options.file_root);
+ result = L_OutFile.OpenWrite(filename);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ sprintf(filename, "%s_r.wav", Options.file_root);
+ result = R_OutFile.OpenWrite(filename);
+ }
+ }
+
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ Wav::SimpleWaveHeader WavHeader(ADesc);
+ result = WavHeader.WriteToFile(L_OutFile);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = WavHeader.WriteToFile(R_OutFile);
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ui32_t write_count = 0;
+ ui32_t duration = 0;
+
+ while ( ASDCP_SUCCESS(result) && (duration++ < Options.duration) )
+ {
+ result = Parser.ReadFrame(FrameBuffer);
+
+ if ( FrameBuffer.Size() != FrameBuffer.Capacity() )
+ {
+ fprintf(stderr, "WARNING: Last frame read was short, PCM input is possibly not frame aligned.\n");
+ fprintf(stderr, "Expecting %lu bytes, got %lu.\n", FrameBuffer.Capacity(), FrameBuffer.Size());
+ result = RESULT_ENDOFFILE;
+ continue;
+ }
+
+ if ( Options.verbose_flag )
+ FrameBuffer.Dump(stderr);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ split_buffer(PCM::CalcSampleSize(ADesc), FrameBuffer, L_FrameBuffer, R_FrameBuffer);
+ result = L_OutFile.Write(L_FrameBuffer.Data(), L_FrameBuffer.Size(), &write_count);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = R_OutFile.Write(R_FrameBuffer.Data(), R_FrameBuffer.Size(), &write_count);
+ }
+ }
+
+ if ( result == RESULT_ENDOFFILE )
+ result = RESULT_OK;
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ADesc.ContainerDuration = duration;
+ Wav::SimpleWaveHeader WavHeader(ADesc);
+ L_OutFile.Seek();
+
+ if ( ASDCP_SUCCESS(result) )
+ result = R_OutFile.Seek();
+
+ if ( ASDCP_SUCCESS(result) )
+ result = WavHeader.WriteToFile(L_OutFile);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = WavHeader.WriteToFile(R_OutFile);
+ }
+ }
+
+ return RESULT_OK;
+}
+
+
+//
+int
+main(int argc, const char** argv)
+{
+ Result_t result = RESULT_OK;
+ CommandOptions Options(argc, argv);
+
+ if ( Options.help_flag )
+ {
+ usage();
+ return 0;
+ }
+
+ if ( Options.error_flag )
+ return 3;
+
+ if ( Options.version_flag )
+ banner();
+
+ if ( Options.create_flag )
+ result = split_wav_file(Options);
+
+ if ( result != RESULT_OK )
+ {
+ fputs("Program stopped on error.\n", stderr);
+
+ if ( result != RESULT_FAIL )
+ {
+ fputs(result, stderr);
+ fputc('\n', stderr);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+
+//