diff options
| author | Carl Hetherington <cth@carlh.net> | 2016-01-05 15:32:10 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2016-01-05 15:32:10 +0000 |
| commit | 3ec4338ce90ea0549409312f24f8b28c07a5d2da (patch) | |
| tree | 09aaaff66dd860abbeacc20793145e1a27f4defd /asdcplib/src/AS_DCP.h | |
| parent | 342aad2ddf893aaaafa9a2c9980579d2dc4ec125 (diff) | |
asdcplib 2.5.11
Diffstat (limited to 'asdcplib/src/AS_DCP.h')
| -rwxr-xr-x | asdcplib/src/AS_DCP.h | 557 |
1 files changed, 459 insertions, 98 deletions
diff --git a/asdcplib/src/AS_DCP.h b/asdcplib/src/AS_DCP.h index eb2ce6e6..9e9702fc 100755 --- a/asdcplib/src/AS_DCP.h +++ b/asdcplib/src/AS_DCP.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2012, John Hurst +Copyright (c) 2003-2014, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -25,13 +25,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*! \file AS_DCP.h - \version $Id: AS_DCP.h,v 1.43 2012/02/02 01:58:43 jhurst Exp $ + \version $Id: AS_DCP.h,v 1.52 2015/04/21 03:55:31 jhurst Exp $ \brief AS-DCP library, public interface The asdcplib library is a set of file access objects that offer simplified access to files conforming to the standards published by the SMPTE D-Cinema Technology Committee 21DC. The file format, labeled AS-DCP, -is described in series of separate documents which include but may not +is described in a series of documents which includes but may not be be limited to: o SMPTE ST 429-2:2011 DCP Operational Constraints @@ -40,8 +40,10 @@ be be limited to: o SMPTE ST 429-5:2009 Timed Text Track File o SMPTE ST 429-6:2006 MXF Track File Essence Encryption o SMPTE ST 429-10:2008 Stereoscopic Picture Track File + o SMPTE ST 429-14:2008 Aux Data Track File o SMPTE ST 330:2004 - UMID o SMPTE ST 336:2001 - KLV + o SMPTE ST 377:2004 - MXF (old version, required) o SMPTE ST 377-1:2011 - MXF o SMPTE ST 377-4:2012 - MXF Multichannel Audio Labeling Framework o SMPTE ST 390:2011 - MXF OP-Atom @@ -61,18 +63,14 @@ be be limited to: The following use cases are supported by the library: 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 + Aux Data (frame-wrapped synchronous blob) + Proposed Dolby (TM) Atmos track file o Read header metadata from an AS-DCP file @@ -87,7 +85,7 @@ This project depends upon the following libraries: #define _AS_DCP_H_ #include <KM_error.h> -#include <KM_platform.h> +#include <KM_fileio.h> #include <stdio.h> #include <stdarg.h> #include <math.h> @@ -204,24 +202,38 @@ namespace ASDCP { // The file accessors in this library implement a bounded set of essence types. // This list will be expanded when support for new types is added to the library. enum EssenceType_t { - ESS_UNKNOWN, // the file is not a supported AS-DCP 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_96k, // the file contains one or more PCM audio pairs - ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources - ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic) + ESS_UNKNOWN, // the file is not a supported AS-DCP of AS-02 essence container + + // + ESS_MPEG2_VES, // the file contains an MPEG-2 video elementary stream + + // d-cinema essence types + ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams + ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs + ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs + ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources + ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic) + ESS_DCDATA_UNKNOWN, // the file contains one or more D-Cinema Data bytestreams + ESS_DCDATA_DOLBY_ATMOS, // the file contains one or more DolbyATMOS bytestreams + + // IMF essence types + ESS_AS02_JPEG_2000, // the file contains one or more JPEG 2000 codestreams + ESS_AS02_PCM_24b_48k, // the file contains one or more PCM audio pairs, clip wrapped + ESS_AS02_PCM_24b_96k, // the file contains one or more PCM audio pairs, clip wrapped + ESS_AS02_TIMED_TEXT, // the file contains a TTML document and zero or more resources + + ESS_MAX }; // Determine the type of essence contained in the given MXF file. RESULT_OK // is returned if the file is successfully opened and contains a valid MXF // stream. If there is an error, the result code will indicate the reason. - Result_t EssenceType(const char* filename, EssenceType_t& type); + Result_t EssenceType(const std::string& filename, EssenceType_t& type); // Determine the type of essence contained in the given raw file. RESULT_OK // is returned if the file is successfully opened and contains a known // stream type. If there is an error, the result code will indicate the reason. - Result_t RawEssenceType(const char* filename, EssenceType_t& type); + Result_t RawEssenceType(const std::string& filename, EssenceType_t& type); //--------------------------------------------------------------------------------- @@ -254,7 +266,7 @@ namespace ASDCP { 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; @@ -262,6 +274,16 @@ namespace ASDCP { } }; + // Encodes a rational number as a string having a single delimiter character between + // numerator and denominator. Retuns the buffer pointer to allow convenient in-line use. + const char* EncodeRational(const Rational&, char* str_buf, ui32_t buf_len, char delimiter = ' '); + + // Decodes a rational number havng a single non-digit delimiter character between + // the numerator and denominator. Returns false if the string does not contain + // the expected syntax. + bool DecodeRational(const char* str_rat, Rational&); + + // common edit rates, use these instead of hard coded constants const Rational EditRate_24 = Rational(24,1); const Rational EditRate_23_98 = Rational(24000,1001); // Not a DCI-compliant value! @@ -280,6 +302,15 @@ namespace ASDCP { const Rational EditRate_100 = Rational(100,1); const Rational EditRate_120 = Rational(120,1); + // Archival frame rates, see ST 428-21 + // These rates are new and not supported by all systems. Do not assume that + // a package made using one of these rates will work just anywhere! + const Rational EditRate_16 = Rational(16,1); + const Rational EditRate_18 = Rational(200,11); // 18.182 + const Rational EditRate_20 = Rational(20,1); + const Rational EditRate_22 = Rational(240,11); // 21.818 + + // Non-reference counting container for internal member objects. // Please do not use this class for any other purpose. template <class T> @@ -335,7 +366,8 @@ namespace ASDCP { { LS_MXF_UNKNOWN, LS_MXF_INTEROP, - LS_MXF_SMPTE + LS_MXF_SMPTE, + LS_MAX }; // @@ -357,7 +389,7 @@ namespace ASDCP { 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); @@ -399,7 +431,7 @@ namespace ASDCP { // Initializes Rijndael CBC encryption context. // Returns error if the key argument is NULL. Result_t InitKey(const byte_t* key); - + // Initializes 16 byte CBC Initialization Vector. This operation may be performed // any number of times for a given key. // Returns error if the i_vec argument is NULL. @@ -559,8 +591,9 @@ namespace ASDCP { namespace MXF { // #include<Metadata.h> to use these - class OPAtomHeader; + class OP1aHeader; class OPAtomIndexFooter; + class RIP; }; //--------------------------------------------------------------------------------- @@ -593,22 +626,22 @@ namespace ASDCP { // MPEG2VideoDescriptor object. struct VideoDescriptor { - Rational EditRate; // - ui32_t FrameRate; // - Rational SampleRate; // - ui8_t FrameLayout; // - ui32_t StoredWidth; // - ui32_t StoredHeight; // - Rational AspectRatio; // - ui32_t ComponentDepth; // - ui32_t HorizontalSubsampling; // - ui32_t VerticalSubsampling; // - ui8_t ColorSiting; // - ui8_t CodedContentType; // - bool LowDelay; // - ui32_t BitRate; // - ui8_t ProfileAndLevel; // - ui32_t ContainerDuration; // + Rational EditRate; // + ui32_t FrameRate; // + Rational SampleRate; // + ui8_t FrameLayout; // + ui32_t StoredWidth; // + ui32_t StoredHeight; // + Rational AspectRatio; // + ui32_t ComponentDepth; // + ui32_t HorizontalSubsampling; // + ui32_t VerticalSubsampling; // + ui8_t ColorSiting; // + ui8_t CodedContentType; // + bool LowDelay; // + ui32_t BitRate; // + ui8_t ProfileAndLevel; // + ui32_t ContainerDuration; // }; // Print VideoDescriptor to std::ostream @@ -638,7 +671,7 @@ namespace ASDCP { { Capacity(size); } - + virtual ~FrameBuffer() {} // Sets the MPEG frame type of the picture data in the frame buffer. @@ -689,7 +722,7 @@ namespace ASDCP { // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Fill a VideoDescriptor struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. @@ -720,13 +753,14 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const VideoDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext @@ -752,12 +786,13 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -779,6 +814,12 @@ namespace ASDCP { // out of range, or if optional decrypt or HAMC operations fail. Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + // Using the index table read from the footer partition, lookup the frame number + // and return the offset into the file at which to read that frame of essence. + // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is + // out of range. + Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const; + // Calculates the first frame in transport order of the GOP in which the requested // frame is located. Calls ReadFrame() to fetch the frame at the calculated position. // Returns RESULT_INIT if the file is not open. @@ -822,18 +863,20 @@ namespace ASDCP { CF_CFG_3, // 7.1 (SDDS) with optional HI/VI CF_CFG_4, // Wild Track Format CF_CFG_5, // 7.1 DS with optional HI/VI + CF_CFG_6, // ST 377-4 (MCA) labels (see also ASDCP::MXF::decode_mca_string) + CF_MAXIMUM }; struct AudioDescriptor { Rational EditRate; // rate of frame wrapping Rational AudioSamplingRate; // rate of audio sample - ui32_t Locked; // + ui32_t Locked; // ui32_t ChannelCount; // number of channels ui32_t QuantizationBits; // number of bits per single-channel sample ui32_t BlockAlign; // number of bytes ber sample, all channels - ui32_t AvgBps; // - ui32_t LinkedTrackID; // + ui32_t AvgBps; // + ui32_t LinkedTrackID; // ui32_t ContainerDuration; // number of frames ChannelFormat_t ChannelFormat; // audio channel arrangement }; @@ -869,7 +912,7 @@ namespace ASDCP { FrameBuffer() {} FrameBuffer(ui32_t size) { Capacity(size); } virtual ~FrameBuffer() {} - + // Print debugging information to stream (stderr default) void Dump(FILE* = 0, ui32_t dump_bytes = 0) const; }; @@ -891,7 +934,7 @@ namespace ASDCP { // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. PictureRate controls // ther frame rate for the MXF frame wrapping option. - Result_t OpenRead(const char* filename, const Rational& PictureRate) const; + Result_t OpenRead(const std::string& filename, const Rational& PictureRate) const; // Fill an AudioDescriptor struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. @@ -919,13 +962,14 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const AudioDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext @@ -951,12 +995,13 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -978,6 +1023,12 @@ namespace ASDCP { // out of range, or if optional decrypt or HAMC operations fail. Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + // Using the index table read from the footer partition, lookup the frame number + // and return the offset into the file at which to read that frame of essence. + // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is + // out of range. + Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const; + // Print debugging information to stream void DumpHeaderMetadata(FILE* = 0) const; void DumpIndex(FILE* = 0) const; @@ -1010,7 +1061,7 @@ namespace ASDCP { ui8_t NumberOfLayers[sizeof(ui16_t)]; ui8_t MultiCompTransform; } SGcod; - + struct { ui8_t DecompositionLevels; @@ -1065,7 +1116,7 @@ namespace ASDCP { FrameBuffer() {} FrameBuffer(ui32_t size) { Capacity(size); } virtual ~FrameBuffer() {} - + // Print debugging information to stream (stderr default) void Dump(FILE* = 0, ui32_t dump_bytes = 0) const; }; @@ -1089,9 +1140,7 @@ namespace ASDCP { // The frame buffer's PlaintextOffset parameter will be set to the first // byte of the data segment. Set this value to zero if you want // encrypted headers. - Result_t OpenReadFrame(const char* filename, FrameBuffer&) const; - - Result_t OpenReadFrame(const unsigned char * data, unsigned int size, FrameBuffer&) const; + Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const; // Fill a PictureDescriptor struct with the values from the file's codestream. // Returns RESULT_INIT if the file is not open. @@ -1119,16 +1168,16 @@ namespace ASDCP { // alphabetically by filename. The parser will automatically parse enough data // from the first file to provide a complete set of stream metadata for the // MXFWriter below. If the "pedantic" parameter is given and is true, the - // parser will check the metadata for each codestream and fail if a + // parser will check the metadata for each codestream and fail if a // mismatch is detected. - Result_t OpenRead(const char* filename, bool pedantic = false) const; + Result_t OpenRead(const std::string& filename, bool pedantic = false) const; // Opens a file sequence for reading. The sequence is expected to contain one or // more filenames, each naming a file containing the codestream for exactly one // picture. The parser will automatically parse enough data // from the first file to provide a complete set of stream metadata for the // MXFWriter below. If the "pedantic" parameter is given and is true, the - // parser will check the metadata for each codestream and fail if a + // 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; @@ -1162,29 +1211,24 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); - // Open the file for writing. The file must not exist unless overwrite is true. Returns error if + // 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, bool overwrite); + Result_t OpenWrite(const std::string& filename, const WriterInfo&, + const PictureDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext // argument is present, the essence is encrypted prior to writing. - // A MD5 hash of the data that we write is written to hash if it is not 0 // Fails if the file is not open, is finalized, or an operating system // error occurs. - Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0); - - Result_t FakeWriteFrame(int size); + Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); // Closes the MXF file, writing the index and revised header. Result_t Finalize(); - - // Return the current file offset in the MXF file that we are writing - ui64_t Tell() const; }; // @@ -1200,12 +1244,13 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1227,6 +1272,12 @@ namespace ASDCP { // out of range, or if optional decrypt or HAMC operations fail. Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + // Using the index table read from the footer partition, lookup the frame number + // and return the offset into the file at which to read that frame of essence. + // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is + // out of range. + Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const; + // Print debugging information to stream void DumpHeaderMetadata(FILE* = 0) const; void DumpIndex(FILE* = 0) const; @@ -1241,7 +1292,7 @@ namespace ASDCP { SP_LEFT, SP_RIGHT }; - + struct SFrameBuffer { JP2K::FrameBuffer Left; @@ -1265,14 +1316,15 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); - // Open the file for writing. The file must not exist unless overwrite is true. Returns error if + // 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, bool overwrite); + Result_t OpenWrite(const std::string& 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. @@ -1287,16 +1339,11 @@ namespace ASDCP { // RESULT_SPHASE will be returned if phase is reversed. The first frame // written must be left eye. Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase, - AESEncContext* = 0, HMACContext* = 0, std::string* hash = 0); + AESEncContext* = 0, HMACContext* = 0); - Result_t FakeWriteFrame(int size, StereoscopicPhase_t phase); - // Closes the MXF file, writing the index and revised header. Returns // RESULT_SPHASE if WriteFrame was called an odd number of times. Result_t Finalize(); - - // Return the current file offset in the MXF file that we are writing - ui64_t Tell() const; }; // @@ -1312,12 +1359,13 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1349,6 +1397,12 @@ namespace ASDCP { Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + // Using the index table read from the footer partition, lookup the frame number + // and return the offset into the file at which to read that frame of essence. + // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is + // out of range. + Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const; + // Print debugging information to stream void DumpHeaderMetadata(FILE* = 0) const; void DumpIndex(FILE* = 0) const; @@ -1364,7 +1418,7 @@ namespace ASDCP { struct TimedTextResourceDescriptor { byte_t ResourceID[UUIDlen]; - MIMEType_t Type; + MIMEType_t Type; TimedTextResourceDescriptor() : Type(MT_BIN) {} }; @@ -1373,7 +1427,7 @@ namespace ASDCP { struct TimedTextDescriptor { - Rational EditRate; // + Rational EditRate; // ui32_t ContainerDuration; byte_t AssetID[UUIDlen]; std::string NamespaceName; @@ -1401,7 +1455,7 @@ namespace ASDCP { 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(); } @@ -1411,6 +1465,8 @@ namespace ASDCP { void Dump(FILE* = 0, ui32_t dump_bytes = 0) const; }; + // An abstract base for a lookup service that returns the resource data + // identified by the given ancillary resource id. // class IResourceResolver { @@ -1419,6 +1475,21 @@ namespace ASDCP { virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID }; + // Resolves resource references by testing the named directory for file names containing + // the respective UUID. + // + class LocalFilenameResolver : public ASDCP::TimedText::IResourceResolver + { + std::string m_Dirname; + ASDCP_NO_COPY_CONSTRUCT(LocalFilenameResolver); + + public: + LocalFilenameResolver(); + virtual ~LocalFilenameResolver(); + Result_t OpenRead(const std::string& dirname); + Result_t ResolveRID(const byte_t* uuid, FrameBuffer& FrameBuf) const; + }; + // class DCSubtitleParser { @@ -1432,12 +1503,12 @@ namespace ASDCP { // 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; + Result_t OpenRead(const std::string& filename) const; // Parses an XML document to provide a complete set of stream metadata // for the MXFWriter below. The optional filename argument is used to // initialize the default resource resolver (see ReadAncillaryResource). - Result_t OpenRead(const std::string& xml_doc, const char* filename = 0) const; + Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const; // Fill a TimedTextDescriptor struct with the values from the file's contents. // Returns RESULT_INIT if the file is not open. @@ -1470,13 +1541,14 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const TimedTextDescriptor&, ui32_t HeaderSize = 16384); // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8 @@ -1512,12 +1584,13 @@ namespace ASDCP { // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! - virtual MXF::OPAtomHeader& OPAtomHeader(); + virtual MXF::OP1aHeader& OP1aHeader(); virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1559,6 +1632,294 @@ namespace ASDCP { }; } // namespace TimedText + //--------------------------------------------------------------------------------- + // + namespace DCData + { + struct DCDataDescriptor + { + Rational EditRate; // Sample rate + ui32_t ContainerDuration; // number of frames + byte_t AssetID[UUIDlen]; // The UUID for the DCData track + byte_t DataEssenceCoding[UUIDlen]; // The coding for the data carried + }; + + // Print DCDataDescriptor to std::ostream + std::ostream& operator << (std::ostream& strm, const DCDataDescriptor& ddesc); + // Print debugging information to stream (stderr default) + void DCDataDescriptorDump(const DCDataDescriptor&, FILE* = 0); + + // + class FrameBuffer : public ASDCP::FrameBuffer + { + public: + FrameBuffer() {} + FrameBuffer(ui32_t size) { Capacity(size); } + virtual ~FrameBuffer() {} + + // Print debugging information to stream (stderr default) + void Dump(FILE* = 0, ui32_t dump_bytes = 0) const; + }; + + // An object which opens and reads a DC Data file. The file is expected + // to contain exactly one complete frame of DC data essence as an unwrapped (raw) + // byte stream. + class BytestreamParser + { + class h__BytestreamParser; + mem_ptr<h__BytestreamParser> m_Parser; + ASDCP_NO_COPY_CONSTRUCT(BytestreamParser); + + public: + BytestreamParser(); + virtual ~BytestreamParser(); + + // Opens a file for reading, parses enough data to provide a complete + // set of stream metadata for the MXFWriter below. + // The frame buffer's PlaintextOffset parameter will be set to the first + // byte of the data segment. Set this value to zero if you want + // encrypted headers. + Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const; + + // Fill a DCDataDescriptor struct with the values from the file's bytestream. + // Returns RESULT_INIT if the file is not open. + Result_t FillDCDataDescriptor(DCDataDescriptor&) const; + }; + + // An object which reads a sequence of files containing DC Data. + class SequenceParser + { + class h__SequenceParser; + mem_ptr<h__SequenceParser> m_Parser; + ASDCP_NO_COPY_CONSTRUCT(SequenceParser); + + public: + SequenceParser(); + virtual ~SequenceParser(); + + // Opens a directory for reading. The directory is expected to contain one or + // more files, each containing the bytestream for exactly one frame. The files + // must be named such that the frames are in temporal order when sorted + // alphabetically by filename. + Result_t OpenRead(const std::string& filename) const; + + // Opens a file sequence for reading. The sequence is expected to contain one or + // more filenames, each naming a file containing the bytestream for exactly one + // frame. + Result_t OpenRead(const std::list<std::string>& file_list) const; + + // Fill a DCDataDescriptor struct with default values. + // Returns RESULT_INIT if the directory is not open. + Result_t FillDCDataDescriptor(DCDataDescriptor&) const; + + // Rewind the directory to the beginning. + Result_t Reset() const; + + // Reads the next sequential frame in the directory and places it in the + // frame buffer. Fails if the buffer is too small or the direcdtory + // contains no more files. + // The frame buffer's PlaintextOffset parameter will be set to the first + // byte of the data segment. Set this value to zero if you want + // encrypted headers. + Result_t ReadFrame(FrameBuffer&) const; + }; + + // + class MXFWriter + { + class h__Writer; + mem_ptr<h__Writer> m_Writer; + ASDCP_NO_COPY_CONSTRUCT(MXFWriter); + + public: + MXFWriter(); + virtual ~MXFWriter(); + + // Warning: direct manipulation of MXF structures can interfere + // with the normal operation of the wrapper. Caveat emptor! + virtual MXF::OP1aHeader& OP1aHeader(); + virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); + + // Open the file for writing. The file must not exist. Returns error if + // the operation cannot be completed or if nonsensical data is discovered + // in the essence descriptor. + Result_t OpenWrite(const std::string& filename, const WriterInfo&, + const DCDataDescriptor&, ui32_t HeaderSize = 16384); + + // Writes a frame of essence to the MXF file. If the optional AESEncContext + // argument is present, the essence is encrypted prior to writing. + // Fails if the file is not open, is finalized, or an operating system + // error occurs. + Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); + + // Closes the MXF file, writing the index and revised header. + Result_t Finalize(); + }; + + // + class MXFReader + { + class h__Reader; + mem_ptr<h__Reader> m_Reader; + ASDCP_NO_COPY_CONSTRUCT(MXFReader); + + public: + MXFReader(); + virtual ~MXFReader(); + + // Warning: direct manipulation of MXF structures can interfere + // with the normal operation of the wrapper. Caveat emptor! + virtual MXF::OP1aHeader& OP1aHeader(); + virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); + + // Open the file for reading. The file must exist. Returns error if the + // operation cannot be completed. + Result_t OpenRead(const std::string& filename) const; + + // Returns RESULT_INIT if the file is not open. + Result_t Close() const; + + // Fill a DCDataDescriptor struct with the values from the file's header. + // Returns RESULT_INIT if the file is not open. + Result_t FillDCDataDescriptor(DCDataDescriptor&) const; + + // Fill a WriterInfo struct with the values from the file's header. + // Returns RESULT_INIT if the file is not open. + Result_t FillWriterInfo(WriterInfo&) const; + + // Reads a frame of essence from the MXF file. If the optional AESEncContext + // argument is present, the essence is decrypted after reading. If the MXF + // file is encrypted and the AESDecContext argument is NULL, the frame buffer + // will contain the ciphertext frame data. If the HMACContext argument is + // not NULL, the HMAC will be calculated (if the file supports it). + // Returns RESULT_INIT if the file is not open, failure if the frame number is + // out of range, or if optional decrypt or HAMC operations fail. + Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + + // Using the index table read from the footer partition, lookup the frame number + // and return the offset into the file at which to read that frame of essence. + // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is + // out of range. + Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const; + + // Print debugging information to stream + void DumpHeaderMetadata(FILE* = 0) const; + void DumpIndex(FILE* = 0) const; + }; + + } // namespace DCData + + //--------------------------------------------------------------------------------- + // + namespace ATMOS + { + struct AtmosDescriptor : public DCData::DCDataDescriptor + { + ui32_t FirstFrame; // Frame number of the frame to align with the FFOA of the picture track + ui16_t MaxChannelCount; // Max number of channels in bitstream + ui16_t MaxObjectCount; // Max number of objects in bitstream + byte_t AtmosID[UUIDlen]; // UUID of Atmos Project + ui8_t AtmosVersion; // ATMOS Coder Version used to create bitstream + }; + + // Print AtmosDescriptor to std::ostream + std::ostream& operator << (std::ostream& strm, const AtmosDescriptor& adesc); + // Print debugging information to stream (stderr default) + void AtmosDescriptorDump(const AtmosDescriptor&, FILE* = 0); + // Determine if a file is a raw atmos file + bool IsDolbyAtmos(const std::string& filename); + + // + class MXFWriter + { + + class h__Writer; + mem_ptr<h__Writer> m_Writer; + ASDCP_NO_COPY_CONSTRUCT(MXFWriter); + + public: + MXFWriter(); + virtual ~MXFWriter(); + + // Warning: direct manipulation of MXF structures can interfere + // with the normal operation of the wrapper. Caveat emptor! + virtual MXF::OP1aHeader& OP1aHeader(); + virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); + + // Open the file for writing. The file must not exist. Returns error if + // the operation cannot be completed or if nonsensical data is discovered + // in the essence descriptor. + Result_t OpenWrite(const std::string& filename, const WriterInfo&, + const AtmosDescriptor&, ui32_t HeaderSize = 16384); + + // Writes a frame of essence to the MXF file. If the optional AESEncContext + // argument is present, the essence is encrypted prior to writing. + // Fails if the file is not open, is finalized, or an operating system + // error occurs. + Result_t WriteFrame(const DCData::FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); + + // Closes the MXF file, writing the index and revised header. + Result_t Finalize(); + }; + + // + class MXFReader + { + class h__Reader; + mem_ptr<h__Reader> m_Reader; + ASDCP_NO_COPY_CONSTRUCT(MXFReader); + + public: + MXFReader(); + virtual ~MXFReader(); + + // Warning: direct manipulation of MXF structures can interfere + // with the normal operation of the wrapper. Caveat emptor! + virtual MXF::OP1aHeader& OP1aHeader(); + virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter(); + virtual MXF::RIP& RIP(); + + // Open the file for reading. The file must exist. Returns error if the + // operation cannot be completed. + Result_t OpenRead(const std::string& filename) const; + + // Returns RESULT_INIT if the file is not open. + Result_t Close() const; + + // Fill an AtmosDescriptor struct with the values from the file's header. + // Returns RESULT_INIT if the file is not open. + Result_t FillAtmosDescriptor(AtmosDescriptor&) const; + + // Fill a WriterInfo struct with the values from the file's header. + // Returns RESULT_INIT if the file is not open. + Result_t FillWriterInfo(WriterInfo&) const; + + // Reads a frame of essence from the MXF file. If the optional AESEncContext + // argument is present, the essence is decrypted after reading. If the MXF + // file is encrypted and the AESDecContext argument is NULL, the frame buffer + // will contain the ciphertext frame data. If the HMACContext argument is + // not NULL, the HMAC will be calculated (if the file supports it). + // Returns RESULT_INIT if the file is not open, failure if the frame number is + // out of range, or if optional decrypt or HAMC operations fail. + Result_t ReadFrame(ui32_t frame_number, DCData::FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + + // Using the index table read from the footer partition, lookup the frame number + // and return the offset into the file at which to read that frame of essence. + // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is + // out of range. + Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const; + + // Print debugging information to stream + void DumpHeaderMetadata(FILE* = 0) const; + void DumpIndex(FILE* = 0) const; + }; + + } // namespace ATMOS + + } // namespace ASDCP |
