/*
-Copyright (c) 2003-2006, John Hurst
+Copyright (c) 2003-2010, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
\version $Id$
\brief AS-DCP library, public interface
-The asdcplib library is a set of wrapper objects that offer simplified
-access to files conforming to the file formats proposed by the SMPTE
-D-Cinema packaging working group DC28.20. The file format, labeled
-AS-DCP, is described in series of separate documents which include but
-may not be limited to:
-
- o AS-DCP Track File Specification
- o AS-DCP Track File Essence Encryption Specification
- o AS-DCP Operational Constraints Specification
+The asdcplib library is a set of file access objects that offer simplified
+access to files conforming to the standards published by the SMPTE
+D-Cinema Technology Committee 21DC. The file format, labeled AS-DCP,
+is described in series of separate documents which include but may not
+be be limited to:
+
+ o SMPTE 429-2-2009 DCP Operational Constraints
+ o SMPTE 429-3-2006 Track File Specification
+ o SMPTE 429-4-2006 JPEG 2000 for D-Cinema
+ o SMPTE 429-5-2009 Timed Text Track File
+ o SMPTE 429-6-2006 Essence Encryption Specification
+ o SMPTE 429-10-2008 Stereoscopic Image Track File
o SMPTE 330M - UMID
o SMPTE 336M - KLV
o SMPTE 377M - MXF
o SMPTE 390M - OP-Atom
o SMPTE 379M - Generic Container
o SMPTE 381M - MPEG2 picture
- o SMPTE XXXM - JPEG 2000 picture
+ o SMPTE 422M - JPEG 2000 picture
o SMPTE 382M - WAV/PCM sound
o IETF RFC 2104 - HMAC/SHA1
o NIST FIPS 197 - AES (Rijndael)
+ o MXF Interop Track File Specification
+ o MXF Interop Track File Essence Encryption Specification
+ o MXF Interop Operational Constraints Specification
+ - Note: the MXF Interop documents are not formally published.
+ Contact the asdcplib support address to get copies.
+
The following use cases are supported by the library:
- o Write a plaintext MPEG2 Video Elementary Stream to a plaintext ASDCP file
- o Write a plaintext MPEG2 Video Elementary Stream to a ciphertext ASDCP file
- o Read a plaintext MPEG2 Video Elementary Stream from a plaintext ASDCP file
- o Read a plaintext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
- o Read a ciphertext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
- o Write one or more plaintext JPEG 2000 codestreams to a plaintext ASDCP file
- o Write one or more plaintext JPEG 2000 codestreams to a ciphertext ASDCP file
- o Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file
- o Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file
- o Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file
- o Write one or more plaintext PCM audio streams to a plaintext ASDCP file
- o Write one or more plaintext PCM audio streams to a ciphertext ASDCP file
- o Read one or more plaintext PCM audio streams from a plaintext ASDCP file
- o Read one or more plaintext PCM audio streams from a ciphertext ASDCP file
- o Read one or more ciphertext PCM audio streams from a ciphertext ASDCP file
- o Read header metadata from an ASDCP file
-
-This project depends upon the following library:
- - OpenSSL http://www.openssl.org/
+ o Write essence to a plaintext or ciphertext AS-DCP file:
+ MPEG2 Video Elementary Stream
+ JPEG 2000 codestreams
+ JPEG 2000 stereoscopic codestream pairs
+ PCM audio streams
+ SMPTE 429-7 Timed Text XML with font and image resources
+ o Read essence from a plaintext or ciphertext AS-DCP file:
+ MPEG2 Video Elementary Stream
+ JPEG 2000 codestreams
+ JPEG 2000 stereoscopic codestream pairs
+ PCM audio streams
+ SMPTE 429-7 Timed Text XML with font and image resources
+
+ o Read header metadata from an AS-DCP file
+
+This project depends upon the following libraries:
+ - OpenSSL http://www.openssl.org/
+ - Expat http://expat.sourceforge.net/ or
+ Xerces-C http://xerces.apache.org/xerces-c/
+ An XML library is not needed if you don't need support for SMPTE 429-5-2009.
*/
-#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>
#include <math.h>
+#include <iosfwd>
+#include <string>
+#include <cstring>
+#include <list>
//--------------------------------------------------------------------------------
// common integer types
T(const T&); \
T& operator=(const T&)
-
//--------------------------------------------------------------------------------
// All library components are defined in the namespace ASDCP
//
namespace ASDCP {
- // The version number consists of three segments: major, API minor, and
- // implementation minor. Whenever a change is made to AS_DCP.h, the API minor
- // version will increment. Changes made to the internal implementation will
- // result in the incrementing of the implementation minor version.
-
- // For example, if asdcplib version 1.0.0 were modified to accomodate changes
- // 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;
+ //
+ // The version number declaration and explanation have moved to ../configure.ac
const char* Version();
// UUIDs are passed around as strings of UUIDlen bytes
// Encryption keys are passed around as strings of KeyLen bytes
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.");
+ const Kumu::Result_t RESULT_SPHASE (-114, "Stereoscopic phase mismatch.");
+ const Kumu::Result_t RESULT_SFORMAT (-115, "Rate mismatch, file may contain stereoscopic essence.");
//---------------------------------------------------------------------------------
// file identification
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_TIMED_TEXT, // the file contains an XML timed text document and one or more resources
+ ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic)
};
// Determine the type of essence contained in the given MXF file. RESULT_OK
inline bool operator!=(const Rational& rhs) const {
return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
}
+
+ inline bool operator<(const Rational& rhs) {
+ if ( Numerator < rhs.Numerator ) return true;
+ if ( Numerator == rhs.Numerator && Denominator < rhs.Denominator ) return true;
+ return false;
+ }
+
+ inline bool operator>(const Rational& rhs) {
+ if ( Numerator > rhs.Numerator ) return true;
+ if ( Numerator == rhs.Numerator && Denominator > rhs.Denominator ) return true;
+ return false;
+ }
};
// common edit rates, use these instead of hard coded constants
const Rational EditRate_24(24,1);
- const Rational EditRate_23_98(24000,1001);
+ const Rational EditRate_23_98(24000,1001); // Not a DCI-compliant value!
const Rational EditRate_48(48,1);
const Rational SampleRate_48k(48000,1);
+ const Rational SampleRate_96k(96000,1);
+
+ // Additional frame rates, see ST 428-11
+ // These rates are new and not supported by all systems. Do not assume that
+ // a package made using on of these rates will work just anywhere!
+ const Rational EditRate_25(25,1);
+ const Rational EditRate_30(30,1);
+ const Rational EditRate_50(50,1);
+ const Rational EditRate_60(60,1);
// Non-reference counting container for internal member objects.
// Please do not use this class for any other purpose.
inline bool empty() const { return m_p == 0; }
};
+
+ //---------------------------------------------------------------------------------
+ // WriterInfo class - encapsulates writer identification details used for
+ // OpenWrite() calls. Replace these values at runtime to identify your product.
+ //
+ // MXF files use SMPTE Universal Labels to identify data items. The set of Labels
+ // in a file is determined by the MXF Operational Pattern and any constraining
+ // documentation. There are currently two flavors of AS-DCP file in use: MXF Interop
+ // (AKA JPEG Interop) and SMPTE. The two differ in the values of three labels:
+ //
+ // OPAtom
+ // Interop : 06 0e 2b 34 04 01 01 01 0d 01 02 01 10 00 00 00
+ // SMPTE : 06 0e 2b 34 04 01 01 02 0d 01 02 01 10 00 00 00
+ //
+ // EKLV Packet:
+ // Interop : 06 0e 2b 34 02 04 01 07 0d 01 03 01 02 7e 01 00
+ // SMPTE : 06 0e 2b 34 02 04 01 01 0d 01 03 01 02 7e 01 00
+ //
+ // GenericDescriptor/SubDescriptors:
+ // Interop : 06 0e 2b 34 01 01 01 02 06 01 01 04 06 10 00 00
+ // SMPTE : 06 0e 2b 34 01 01 01 09 06 01 01 04 06 10 00 00
+ //
+ // asdcplib will read any (otherwise valid) file which has any combination of the
+ // above values. When writing files, MXF Interop labels are used by default. To
+ // write a file containing SMPTE labels, replace the default label set value in
+ // the WriterInfo before calling OpenWrite()
+ //
+ //
+ enum LabelSet_t
+ {
+ LS_MXF_UNKNOWN,
+ LS_MXF_INTEROP,
+ LS_MXF_SMPTE
+ };
+
+ //
+ struct WriterInfo
+ {
+ byte_t ProductUUID[UUIDlen];
+ byte_t AssetUUID[UUIDlen];
+ byte_t ContextID[UUIDlen];
+ byte_t CryptographicKeyID[UUIDlen];
+ bool EncryptedEssence; // true if essence data is (or is going to be) encrypted
+ bool UsesHMAC; // true if HMAC exists or is to be calculated
+ std::string ProductVersion;
+ std::string CompanyName;
+ std::string ProductName;
+ LabelSet_t LabelSetType;
+
+ WriterInfo() : EncryptedEssence(false), UsesHMAC(false), LabelSetType(LS_MXF_INTEROP)
+ {
+ static byte_t default_ProductUUID_Data[UUIDlen] = {
+ 0x43, 0x05, 0x9a, 0x1d, 0x04, 0x32, 0x41, 0x01,
+ 0xb8, 0x3f, 0x73, 0x68, 0x15, 0xac, 0xf3, 0x1d };
+
+ memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
+ memset(AssetUUID, 0, UUIDlen);
+ memset(ContextID, 0, UUIDlen);
+ memset(CryptographicKeyID, 0, UUIDlen);
+
+ ProductVersion = "Unreleased ";
+ ProductVersion += Version();
+ CompanyName = "DCI";
+ ProductName = "asdcplib";
+ }
+ };
+
+ // Print WriterInfo to std::ostream
+ std::ostream& operator << (std::ostream& strm, const WriterInfo& winfo);
+ // Print WriterInfo to stream, stderr by default.
+ void WriterInfoDump(const WriterInfo&, FILE* = 0);
+
//---------------------------------------------------------------------------------
// cryptographic support
// 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);
// Reset internal state, allows repeated cycles of Update -> Finalize
void Reset();
Result_t TestHMACValue(const byte_t* buf) const;
};
- //---------------------------------------------------------------------------------
- // 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
//
ui32_t ContainerDuration; //
};
+ // Print VideoDescriptor to std::ostream
+ std::ostream& operator << (std::ostream& strm, const VideoDescriptor& vdesc);
// Print VideoDescriptor to stream, stderr by default.
void VideoDescriptorDump(const VideoDescriptor&, FILE* = 0);
};
} // namespace MPEG2
+ //---------------------------------------------------------------------------------
//
namespace PCM
{
+ // The default value of the ChannelFormat element of the AudioDescriptor struct
+ // is CF_NONE. If the value is set to one of the other ChannelFormat_t enum
+ // values, the file's Wave Audio Descriptor will contain a Channel Assignment
+ // element.
+ //
+ // The channel format should be one of (CF_CFG_1, CF_CFG_2, or CF_CFG_3) for
+ // SMPTE 429-2 files. It should normally be CF_NONE for JPEG Interop files, but
+ // the 429-2 may also be used.
+ //
+ enum ChannelFormat_t {
+ CF_NONE,
+ CF_CFG_1, // 5.1 with optional HI/VI
+ CF_CFG_2, // 6.1 (5.1 + center surround) with optional HI/VI
+ CF_CFG_3, // 7.1 with optional HI/VI
+ };
+
struct AudioDescriptor
{
- Rational SampleRate; // rate of frame wrapping
+ Rational EditRate; // rate of frame wrapping
Rational AudioSamplingRate; // rate of audio sample
ui32_t Locked; //
ui32_t ChannelCount; // number of channels
ui32_t AvgBps; //
ui32_t LinkedTrackID; //
ui32_t ContainerDuration; // number of frames
+ ChannelFormat_t ChannelFormat; // audio channel arrangement
};
+ // Print AudioDescriptor to std::ostream
+ std::ostream& operator << (std::ostream& strm, const AudioDescriptor& adesc);
// Print debugging information to stream (stderr default)
void AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
// Returns number of samples per frame of data described by ADesc
inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
{
- double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.SampleRate.Quotient();
+ double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
return (ui32_t)ceil(tmpd);
}
};
} // namespace PCM
+ //---------------------------------------------------------------------------------
//
namespace JP2K
{
const ui32_t MaxComponents = 3;
- const ui32_t DefaultCodingDataLength = 64;
+ const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
+ const ui32_t MaxDefaults = 256; // made up
- struct ImageComponent
+#pragma pack(1)
+ struct ImageComponent_t // ISO 15444-1 Annex A.5.1
{
- byte_t Ssize;
- byte_t XRsize;
- byte_t YRsize;
+ ui8_t Ssize;
+ ui8_t XRsize;
+ ui8_t YRsize;
};
+ struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
+ {
+ ui8_t Scod;
+
+ struct
+ {
+ ui8_t ProgressionOrder;
+ ui8_t NumberOfLayers[sizeof(ui16_t)];
+ ui8_t MultiCompTransform;
+ } SGcod;
+
+ struct
+ {
+ ui8_t DecompositionLevels;
+ ui8_t CodeblockWidth;
+ ui8_t CodeblockHeight;
+ ui8_t CodeblockStyle;
+ ui8_t Transformation;
+ ui8_t PrecinctSize[MaxPrecincts];
+ } SPcod;
+ };
+
+ struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
+ {
+ ui8_t Sqcd;
+ ui8_t SPqcd[MaxDefaults];
+ ui8_t SPqcdLength;
+ };
+#pragma pack()
+
struct PictureDescriptor
{
Rational EditRate;
ui32_t XTOsize;
ui32_t YTOsize;
ui16_t Csize;
- ImageComponent ImageComponents[MaxComponents];
- byte_t CodingStyle[DefaultCodingDataLength];
- ui32_t CodingStyleLength;
- byte_t QuantDefault[DefaultCodingDataLength];
- ui32_t QuantDefaultLength;
+ ImageComponent_t ImageComponents[MaxComponents];
+ CodingStyleDefault_t CodingStyleDefault;
+ QuantizationDefault_t QuantizationDefault;
};
+ // Print debugging information to std::ostream
+ std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
// Print debugging information to stream (stderr default)
void PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
Result_t FillPictureDescriptor(PictureDescriptor&) const;
};
+ // Parses the data in the frame buffer to fill in the picture descriptor. Copies
+ // the offset of the image data into start_of_data. Returns error if the parser fails.
+ Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
+
// An object which reads a sequence of files containing JPEG 2000 pictures.
class SequenceParser
{
// mismatch is detected.
Result_t OpenRead(const char* filename, bool pedantic = false) const;
+ // Opens a file sequence for reading. The sequence is expected to contain one or
+ // more filenames, each naming a file containing the codestream for exactly one
+ // picture. The parser will automatically parse enough data
+ // from the first file to provide a complete set of stream metadata for the
+ // MXFWriter below. If the "pedantic" parameter is given and is true, the
+ // parser will check the metadata for each codestream and fail if a
+ // mismatch is detected.
+ Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic = false) const;
+
// Fill a PictureDescriptor struct with the values from the first file's codestream.
// Returns RESULT_INIT if the directory is not open.
Result_t FillPictureDescriptor(PictureDescriptor&) const;
void DumpHeaderMetadata(FILE* = 0) const;
void DumpIndex(FILE* = 0) const;
};
+
+
+ // Stereoscopic Image support
+ //
+
+ enum StereoscopicPhase_t
+ {
+ SP_LEFT,
+ SP_RIGHT
+ };
+
+ struct SFrameBuffer
+ {
+ JP2K::FrameBuffer Left;
+ JP2K::FrameBuffer Right;
+
+ SFrameBuffer(ui32_t size) {
+ Left.Capacity(size);
+ Right.Capacity(size);
+ }
+ };
+
+ class MXFSWriter
+ {
+ class h__SWriter;
+ mem_ptr<h__SWriter> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
+
+ public:
+ MXFSWriter();
+ virtual ~MXFSWriter();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const char* filename, const WriterInfo&,
+ const PictureDescriptor&, ui32_t HeaderSize = 16384);
+
+ // Writes a pair of frames of essence to the MXF file. If the optional AESEncContext
+ // argument is present, the essence is encrypted prior to writing.
+ // Fails if the file is not open, is finalized, or an operating system
+ // error occurs.
+ Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // Writes a frame of essence to the MXF file. If the optional AESEncContext
+ // argument is present, the essence is encrypted prior to writing.
+ // Fails if the file is not open, is finalized, or an operating system
+ // error occurs. Frames must be written in the proper phase (L-R-L-R),
+ // RESULT_SPHASE will be returned if phase is reversed. The first frame
+ // written must be left eye.
+ Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
+ AESEncContext* = 0, HMACContext* = 0);
+
+ // Closes the MXF file, writing the index and revised header. Returns
+ // RESULT_SPHASE if WriteFrame was called an odd number of times.
+ Result_t Finalize();
+ };
+
+ //
+ class MXFSReader
+ {
+ class h__SReader;
+ mem_ptr<h__SReader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
+
+ public:
+ MXFSReader();
+ virtual ~MXFSReader();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const char* filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill an AudioDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillPictureDescriptor(PictureDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads a pair of frames of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, SFrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Reads a frame of essence from the MXF file. If the optional AESEncContext
+ // argument is present, the essence is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
+ FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
} // namespace JP2K
+
+ //---------------------------------------------------------------------------------
+ //
+ namespace TimedText
+ {
+ enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
+
+ struct TimedTextResourceDescriptor
+ {
+ byte_t ResourceID[UUIDlen];
+ MIMEType_t Type;
+
+ TimedTextResourceDescriptor() : Type(MT_BIN) {}
+ };
+
+ typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
+
+ struct TimedTextDescriptor
+ {
+ Rational EditRate; //
+ ui32_t ContainerDuration;
+ byte_t AssetID[UUIDlen];
+ std::string NamespaceName;
+ std::string EncodingName;
+ ResourceList_t ResourceList;
+
+ TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8
+ };
+
+ // Print debugging information to std::ostream
+ std::ostream& operator << (std::ostream& strm, const TimedTextDescriptor& tinfo);
+ // Print debugging information to stream (stderr default)
+ void DescriptorDump(const TimedTextDescriptor&, FILE* = 0);
+
+ //
+ class FrameBuffer : public ASDCP::FrameBuffer
+ {
+ ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
+
+ protected:
+ byte_t m_AssetID[UUIDlen];
+ std::string m_MIMEType;
+
+ public:
+ FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
+ FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
+ virtual ~FrameBuffer() {}
+
+ inline const byte_t* AssetID() const { return m_AssetID; }
+ inline void AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); }
+ inline const char* MIMEType() const { return m_MIMEType.c_str(); }
+ inline void MIMEType(const std::string& s) { m_MIMEType = s; }
+
+ // Print debugging information to stream (stderr default)
+ void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
+ };
+
+ //
+ class IResourceResolver
+ {
+ public:
+ virtual ~IResourceResolver() {}
+ virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
+ };
+
+ //
+ class DCSubtitleParser
+ {
+ class h__SubtitleParser;
+ mem_ptr<h__SubtitleParser> m_Parser;
+ ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
+
+ public:
+ DCSubtitleParser();
+ virtual ~DCSubtitleParser();
+
+ // Opens an XML file for reading, parses data to provide a complete
+ // set of stream metadata for the MXFWriter below.
+ Result_t OpenRead(const char* filename) const;
+
+ // Parses an XML document to provide a complete set of stream metadata
+ // for the MXFWriter below. The optional filename argument is used to
+ // initialize the default resource resolver (see ReadAncillaryResource).
+ Result_t OpenRead(const std::string& xml_doc, const char* filename = 0) const;
+
+ // Fill a TimedTextDescriptor struct with the values from the file's contents.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
+
+ // Reads the complete Timed Text Resource into the given string.
+ Result_t ReadTimedTextResource(std::string&) const;
+
+ // Reads the Ancillary Resource having the given ID. Fails if the buffer
+ // is too small or the resource does not exist. The optional Resolver
+ // argument can be provided which will be used to retrieve the resource
+ // having a particulat UUID. If a Resolver is not supplied, the default
+ // internal resolver will return the contents of the file having the UUID
+ // as the filename. The filename must exist in the same directory as the
+ // XML file opened with OpenRead().
+ Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
+ const IResourceResolver* Resolver = 0) const;
+ };
+
+ //
+ class MXFWriter
+ {
+ class h__Writer;
+ mem_ptr<h__Writer> m_Writer;
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ // Open the file for writing. The file must not exist. Returns error if
+ // the operation cannot be completed or if nonsensical data is discovered
+ // in the essence descriptor.
+ Result_t OpenWrite(const char* filename, const WriterInfo&,
+ const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
+
+ // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
+ // encoded. If the optional AESEncContext argument is present, the essence
+ // is encrypted prior to writing. Fails if the file is not open, is finalized,
+ // or an operating system error occurs.
+ // This method may only be called once, and it must be called before any
+ // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
+ // conditions are not met.
+ Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
+
+ // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
+ // argument is present, the essence is encrypted prior to writing.
+ // Fails if the file is not open, is finalized, or an operating system
+ // error occurs. RESULT_STATE will be returned if the method is called before
+ // WriteTimedTextResource()
+ Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+
+ // Closes the MXF file, writing the index and revised header.
+ Result_t Finalize();
+ };
+
+ //
+ class MXFReader
+ {
+ class h__Reader;
+ mem_ptr<h__Reader> m_Reader;
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+ MXFReader();
+ virtual ~MXFReader();
+
+ // Open the file for reading. The file must exist. Returns error if the
+ // operation cannot be completed.
+ Result_t OpenRead(const char* filename) const;
+
+ // Returns RESULT_INIT if the file is not open.
+ Result_t Close() const;
+
+ // Fill a TimedTextDescriptor struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
+
+ // Fill a WriterInfo struct with the values from the file's header.
+ // Returns RESULT_INIT if the file is not open.
+ Result_t FillWriterInfo(WriterInfo&) const;
+
+ // Reads the complete Timed Text Resource into the given string. Fails if the resource
+ // is encrypted and AESDecContext is NULL (use the following method to retrieve the
+ // raw ciphertet block).
+ Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
+ // argument is present, the resource is decrypted after reading. If the MXF
+ // file is encrypted and the AESDecContext argument is NULL, the frame buffer
+ // will contain the ciphertext frame data. If the HMACContext argument is
+ // not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Reads the timed-text resource having the given UUID from the MXF file. If the
+ // optional AESEncContext argument is present, the resource is decrypted after
+ // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
+ // the frame buffer will contain the ciphertext frame data. If the HMACContext
+ // argument is not NULL, the HMAC will be calculated (if the file supports it).
+ // Returns RESULT_INIT if the file is not open, failure if the frame number is
+ // out of range, or if optional decrypt or HAMC operations fail.
+ Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+ } // namespace TimedText
+
+
} // namespace ASDCP
-#endif // _AS_DCP_H__
+#endif // _AS_DCP_H_
//
// end AS_DCP.h