2 Copyright (c) 2003-2013, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \brief AS-DCP library, public interface
31 The asdcplib library is a set of file access objects that offer simplified
32 access to files conforming to the standards published by the SMPTE
33 D-Cinema Technology Committee 21DC. The file format, labeled AS-DCP,
34 is described in series of separate documents which include but may not
37 o SMPTE ST 429-2:2011 DCP Operational Constraints
38 o SMPTE ST 429-3:2006 Sound and Picture Track File
39 o SMPTE ST 429-4:2006 MXF JPEG 2000 Application
40 o SMPTE ST 429-5:2009 Timed Text Track File
41 o SMPTE ST 429-6:2006 MXF Track File Essence Encryption
42 o SMPTE ST 429-10:2008 Stereoscopic Picture Track File
43 o SMPTE ST 330:2004 - UMID
44 o SMPTE ST 336:2001 - KLV
45 o SMPTE ST 377-1:2011 - MXF
46 o SMPTE ST 377-4:2012 - MXF Multichannel Audio Labeling Framework
47 o SMPTE ST 390:2011 - MXF OP-Atom
48 o SMPTE ST 379-1:2009 - MXF Generic Container (GC)
49 o SMPTE ST 381-1:2005 - MPEG2 picture in GC
50 o SMPTE ST 422:2006 - JPEG 2000 picture in GC
51 o SMPTE ST 382:2007 - WAV/PCM sound in GC
52 o IETF RFC 2104 - HMAC/SHA1
53 o NIST FIPS 197 - AES (Rijndael) (via OpenSSL)
55 o MXF Interop Track File Specification
56 o MXF Interop Track File Essence Encryption Specification
57 o MXF Interop Operational Constraints Specification
58 - Note: the MXF Interop documents are not formally published.
59 Contact the asdcplib support address to get copies.
61 The following use cases are supported by the library:
63 o Write essence to a plaintext or ciphertext AS-DCP file:
64 MPEG2 Video Elementary Stream
66 JPEG 2000 stereoscopic codestream pairs
68 SMPTE 429-7 Timed Text XML with font and image resources
69 Proposed SMPTE Aux Data track file
70 Proposed Dolby (TM) Atmos track file
72 o Read essence from a plaintext or ciphertext AS-DCP file:
73 MPEG2 Video Elementary Stream
75 JPEG 2000 stereoscopic codestream pairs
77 SMPTE 429-7 Timed Text XML with font and image resources
78 Proposed SMPTE Aux Data track file
79 Proposed Dolby (TM) Atmos track file
81 o Read header metadata from an AS-DCP file
83 This project depends upon the following libraries:
84 - OpenSSL http://www.openssl.org/
85 - Expat http://expat.sourceforge.net/ or
86 Xerces-C http://xerces.apache.org/xerces-c/
87 An XML library is not needed if you don't need support for SMPTE ST 429-5:2009.
94 #include <KM_fileio.h>
103 //--------------------------------------------------------------------------------
104 // common integer types
105 // supply your own by defining ASDCP_NO_BASE_TYPES
107 #ifndef ASDCP_NO_BASE_TYPES
108 typedef unsigned char byte_t;
110 typedef unsigned char ui8_t;
112 typedef unsigned short ui16_t;
114 typedef unsigned int ui32_t;
118 //--------------------------------------------------------------------------------
119 // convenience macros
121 // Convenience macros for managing return values in predicates
122 #define ASDCP_SUCCESS(v) (((v) < 0) ? 0 : 1)
123 #define ASDCP_FAILURE(v) (((v) < 0) ? 1 : 0)
126 // Returns RESULT_PTR if the given argument is NULL.
127 // See Result_t below for an explanation of RESULT_* symbols.
128 #define ASDCP_TEST_NULL(p) \
130 return ASDCP::RESULT_PTR; \
133 // Returns RESULT_PTR if the given argument is NULL. See Result_t
134 // below for an explanation of RESULT_* symbols. It then assumes
135 // that the argument is a pointer to a string and returns
136 // RESULT_NULL_STR if the first character is '\0'.
138 #define ASDCP_TEST_NULL_STR(p) \
139 ASDCP_TEST_NULL(p); \
140 if ( (p)[0] == '\0' ) { \
141 return ASDCP::RESULT_NULL_STR; \
144 // Produces copy constructor boilerplate. Allows convenient private
145 // declatarion of copy constructors to prevent the compiler from
146 // silently manufacturing default methods.
147 #define ASDCP_NO_COPY_CONSTRUCT(T) \
149 T& operator=(const T&)
151 //--------------------------------------------------------------------------------
152 // All library components are defined in the namespace ASDCP
156 // The version number declaration and explanation have moved to ../configure.ac
157 const char* Version();
159 // UUIDs are passed around as strings of UUIDlen bytes
160 const ui32_t UUIDlen = 16;
162 // Encryption keys are passed around as strings of KeyLen bytes
163 const ui32_t KeyLen = 16;
165 //---------------------------------------------------------------------------------
168 using Kumu::Result_t;
170 using Kumu::RESULT_FALSE;
171 using Kumu::RESULT_OK;
172 using Kumu::RESULT_FAIL;
173 using Kumu::RESULT_PTR;
174 using Kumu::RESULT_NULL_STR;
175 using Kumu::RESULT_ALLOC;
176 using Kumu::RESULT_PARAM;
177 using Kumu::RESULT_SMALLBUF;
178 using Kumu::RESULT_INIT;
179 using Kumu::RESULT_NOT_FOUND;
180 using Kumu::RESULT_NO_PERM;
181 using Kumu::RESULT_FILEOPEN;
182 using Kumu::RESULT_BADSEEK;
183 using Kumu::RESULT_READFAIL;
184 using Kumu::RESULT_WRITEFAIL;
185 using Kumu::RESULT_STATE;
186 using Kumu::RESULT_ENDOFFILE;
187 using Kumu::RESULT_CONFIG;
189 KM_DECLARE_RESULT(FORMAT, -101, "The file format is not proper OP-Atom/AS-DCP.");
190 KM_DECLARE_RESULT(RAW_ESS, -102, "Unknown raw essence file type.");
191 KM_DECLARE_RESULT(RAW_FORMAT, -103, "Raw essence format invalid.");
192 KM_DECLARE_RESULT(RANGE, -104, "Frame number out of range.");
193 KM_DECLARE_RESULT(CRYPT_CTX, -105, "AESEncContext required when writing to encrypted file.");
194 KM_DECLARE_RESULT(LARGE_PTO, -106, "Plaintext offset exceeds frame buffer size.");
195 KM_DECLARE_RESULT(CAPEXTMEM, -107, "Cannot resize externally allocated memory.");
196 KM_DECLARE_RESULT(CHECKFAIL, -108, "The check value did not decrypt correctly.");
197 KM_DECLARE_RESULT(HMACFAIL, -109, "HMAC authentication failure.");
198 KM_DECLARE_RESULT(HMAC_CTX, -110, "HMAC context required.");
199 KM_DECLARE_RESULT(CRYPT_INIT, -111, "Error initializing block cipher context.");
200 KM_DECLARE_RESULT(EMPTY_FB, -112, "Empty frame buffer.");
201 KM_DECLARE_RESULT(KLV_CODING, -113, "KLV coding error.");
202 KM_DECLARE_RESULT(SPHASE, -114, "Stereoscopic phase mismatch.");
203 KM_DECLARE_RESULT(SFORMAT, -115, "Rate mismatch, file may contain stereoscopic essence.");
205 //---------------------------------------------------------------------------------
206 // file identification
208 // The file accessors in this library implement a bounded set of essence types.
209 // This list will be expanded when support for new types is added to the library.
211 ESS_UNKNOWN, // the file is not a supported AS-DCP essence container
212 ESS_MPEG2_VES, // the file contains an MPEG video elementary stream
213 ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
214 ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
215 ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
216 ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources
217 ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic)
218 ESS_DCDATA_UNKNOWN, // the file contains one or more D-Cinema Data bytestreams
219 ESS_DCDATA_DOLBY_ATMOS, // the file contains one or more DolbyATMOS bytestreams
223 // Determine the type of essence contained in the given MXF file. RESULT_OK
224 // is returned if the file is successfully opened and contains a valid MXF
225 // stream. If there is an error, the result code will indicate the reason.
226 Result_t EssenceType(const char* filename, EssenceType_t& type);
228 // Determine the type of essence contained in the given raw file. RESULT_OK
229 // is returned if the file is successfully opened and contains a known
230 // stream type. If there is an error, the result code will indicate the reason.
231 Result_t RawEssenceType(const char* filename, EssenceType_t& type);
234 //---------------------------------------------------------------------------------
237 // A simple container for rational numbers.
244 Rational() : Numerator(0), Denominator(0) {}
245 Rational(i32_t n, i32_t d) : Numerator(n), Denominator(d) {}
247 inline double Quotient() const {
248 return (double)Numerator / (double)Denominator;
251 inline bool operator==(const Rational& rhs) const {
252 return ( rhs.Numerator == Numerator && rhs.Denominator == Denominator );
255 inline bool operator!=(const Rational& rhs) const {
256 return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
259 inline bool operator<(const Rational& rhs) {
260 if ( Numerator < rhs.Numerator ) return true;
261 if ( Numerator == rhs.Numerator && Denominator < rhs.Denominator ) return true;
265 inline bool operator>(const Rational& rhs) {
266 if ( Numerator > rhs.Numerator ) return true;
267 if ( Numerator == rhs.Numerator && Denominator > rhs.Denominator ) return true;
272 // common edit rates, use these instead of hard coded constants
273 const Rational EditRate_24 = Rational(24,1);
274 const Rational EditRate_23_98 = Rational(24000,1001); // Not a DCI-compliant value!
275 const Rational EditRate_48 = Rational(48,1);
276 const Rational SampleRate_48k = Rational(48000,1);
277 const Rational SampleRate_96k = Rational(96000,1);
279 // Additional frame rates, see ST 428-11, ST 429-13
280 // These rates are new and not supported by all systems. Do not assume that
281 // a package made using one of these rates will work just anywhere!
282 const Rational EditRate_25 = Rational(25,1);
283 const Rational EditRate_30 = Rational(30,1);
284 const Rational EditRate_50 = Rational(50,1);
285 const Rational EditRate_60 = Rational(60,1);
286 const Rational EditRate_96 = Rational(96,1);
287 const Rational EditRate_100 = Rational(100,1);
288 const Rational EditRate_120 = Rational(120,1);
290 // Archival frame rates, see ST 428-21
291 // These rates are new and not supported by all systems. Do not assume that
292 // a package made using one of these rates will work just anywhere!
293 const Rational EditRate_16 = Rational(16,1);
294 const Rational EditRate_18 = Rational(200,11); // 18.182
295 const Rational EditRate_20 = Rational(20,1);
296 const Rational EditRate_22 = Rational(240,11); // 21.818
299 // Non-reference counting container for internal member objects.
300 // Please do not use this class for any other purpose.
304 T* m_p; // the thing we point to
308 mem_ptr() : m_p(0) {}
309 mem_ptr(T* p) : m_p(p) {}
310 ~mem_ptr() { delete m_p; }
312 inline T& operator*() const { return *m_p; }
313 inline T* operator->() const { return m_p; }
314 inline operator T*()const { return m_p; }
315 inline const mem_ptr<T>& operator=(T* p) { set(p); return *this; }
316 inline T* set(T* p) { delete m_p; m_p = p; return m_p; }
317 inline T* get() const { return m_p; }
318 inline void release() { m_p = 0; }
319 inline bool empty() const { return m_p == 0; }
323 //---------------------------------------------------------------------------------
324 // WriterInfo class - encapsulates writer identification details used for
325 // OpenWrite() calls. Replace these values at runtime to identify your product.
327 // MXF files use SMPTE Universal Labels to identify data items. The set of Labels
328 // in a file is determined by the MXF Operational Pattern and any constraining
329 // documentation. There are currently two flavors of AS-DCP file in use: MXF Interop
330 // (AKA JPEG Interop) and SMPTE. The two differ in the values of three labels:
333 // Interop : 06 0e 2b 34 04 01 01 01 0d 01 02 01 10 00 00 00
334 // SMPTE : 06 0e 2b 34 04 01 01 02 0d 01 02 01 10 00 00 00
337 // Interop : 06 0e 2b 34 02 04 01 07 0d 01 03 01 02 7e 01 00
338 // SMPTE : 06 0e 2b 34 02 04 01 01 0d 01 03 01 02 7e 01 00
340 // GenericDescriptor/SubDescriptors:
341 // Interop : 06 0e 2b 34 01 01 01 02 06 01 01 04 06 10 00 00
342 // SMPTE : 06 0e 2b 34 01 01 01 09 06 01 01 04 06 10 00 00
344 // asdcplib will read any (otherwise valid) file which has any combination of the
345 // above values. When writing files, MXF Interop labels are used by default. To
346 // write a file containing SMPTE labels, replace the default label set value in
347 // the WriterInfo before calling OpenWrite()
361 byte_t ProductUUID[UUIDlen];
362 byte_t AssetUUID[UUIDlen];
363 byte_t ContextID[UUIDlen];
364 byte_t CryptographicKeyID[UUIDlen];
365 bool EncryptedEssence; // true if essence data is (or is going to be) encrypted
366 bool UsesHMAC; // true if HMAC exists or is to be calculated
367 std::string ProductVersion;
368 std::string CompanyName;
369 std::string ProductName;
370 LabelSet_t LabelSetType;
372 WriterInfo() : EncryptedEssence(false), UsesHMAC(false), LabelSetType(LS_MXF_INTEROP)
374 static byte_t default_ProductUUID_Data[UUIDlen] = {
375 0x43, 0x05, 0x9a, 0x1d, 0x04, 0x32, 0x41, 0x01,
376 0xb8, 0x3f, 0x73, 0x68, 0x15, 0xac, 0xf3, 0x1d };
378 memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
379 memset(AssetUUID, 0, UUIDlen);
380 memset(ContextID, 0, UUIDlen);
381 memset(CryptographicKeyID, 0, UUIDlen);
383 ProductVersion = "Unreleased ";
384 ProductVersion += Version();
386 ProductName = "asdcplib";
390 // Print WriterInfo to std::ostream
391 std::ostream& operator << (std::ostream& strm, const WriterInfo& winfo);
392 // Print WriterInfo to stream, stderr by default.
393 void WriterInfoDump(const WriterInfo&, FILE* = 0);
395 //---------------------------------------------------------------------------------
396 // cryptographic support
398 // The following classes define interfaces to Rijndael contexts having the following properties:
400 // o CBC mode with 16 byte block size
401 const ui32_t CBC_KEY_SIZE = 16;
402 const ui32_t CBC_BLOCK_SIZE = 16;
403 const ui32_t HMAC_SIZE = 20;
409 mem_ptr<h__AESContext> m_Context;
410 ASDCP_NO_COPY_CONSTRUCT(AESEncContext);
416 // Initializes Rijndael CBC encryption context.
417 // Returns error if the key argument is NULL.
418 Result_t InitKey(const byte_t* key);
420 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
421 // any number of times for a given key.
422 // Returns error if the i_vec argument is NULL.
423 Result_t SetIVec(const byte_t* i_vec);
424 Result_t GetIVec(byte_t* i_vec) const;
426 // Encrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
427 // Returns error if either argument is NULL.
428 Result_t EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size);
435 mem_ptr<h__AESContext> m_Context;
436 ASDCP_NO_COPY_CONSTRUCT(AESDecContext);
442 // Initializes Rijndael CBC decryption context.
443 // Returns error if the key argument is NULL.
444 Result_t InitKey(const byte_t* key);
446 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
447 // any number of times for a given key.
448 // Returns error if the i_vec argument is NULL.
449 Result_t SetIVec(const byte_t* i_vec);
451 // Decrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
452 // Returns error if either argument is NULL.
453 Result_t DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size);
459 class h__HMACContext;
460 mem_ptr<h__HMACContext> m_Context;
461 ASDCP_NO_COPY_CONSTRUCT(HMACContext);
467 // Initializes HMAC context. The key argument must point to a binary
468 // key that is CBC_KEY_SIZE bytes in length. Returns error if the key
470 Result_t InitKey(const byte_t* key, LabelSet_t);
472 // Reset internal state, allows repeated cycles of Update -> Finalize
475 // Add data to the digest. Returns error if the key argument is NULL or
476 // if the digest has been finalized.
477 Result_t Update(const byte_t* buf, ui32_t buf_len);
479 // Finalize digest. Returns error if the digest has already been finalized.
482 // Writes HMAC value to given buffer. buf must point to a writable area of
483 // memory that is at least HMAC_SIZE bytes in length. Returns error if the
484 // buf argument is NULL or if the digest has not been finalized.
485 Result_t GetHMACValue(byte_t* buf) const;
487 // Tests the given value against the finalized value in the object. buf must
488 // point to a readable area of memory that is at least HMAC_SIZE bytes in length.
489 // Returns error if the buf argument is NULL or if the values do ot match.
490 Result_t TestHMACValue(const byte_t* buf) const;
493 //---------------------------------------------------------------------------------
494 // frame buffer base class
496 // The supported essence types are stored using per-frame KLV packetization. The
497 // following class implements essence-neutral functionality for managing a buffer
498 // containing a frame of essence.
502 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer);
505 byte_t* m_Data; // pointer to memory area containing frame data
506 ui32_t m_Capacity; // size of memory area pointed to by m_Data
507 bool m_OwnMem; // if false, m_Data points to externally allocated memory
508 ui32_t m_Size; // size of frame data in memory area pointed to by m_Data
509 ui32_t m_FrameNumber; // delivery-order frame number
511 // It is possible to read raw ciphertext from an encrypted AS-DCP file.
512 // After reading an encrypted AS-DCP file in raw mode, the frame buffer will
513 // contain the encrypted source value portion of the Encrypted Triplet, followed
514 // by the integrity pack, if it exists.
515 // The buffer will begin with the IV and CheckValue, followed by encrypted essence
516 // and optional integrity pack
517 // The SourceLength and PlaintextOffset values from the packet will be held in the
518 // following variables:
519 ui32_t m_SourceLength; // plaintext length (delivered plaintext+decrypted ciphertext)
520 ui32_t m_PlaintextOffset; // offset to first byte of ciphertext
524 virtual ~FrameBuffer();
526 // Instructs the object to use an externally allocated buffer. The external
527 // buffer will not be cleaned up by the frame buffer when it exits.
528 // Call with (0,0) to revert to internally allocated buffer.
529 // Returns error if the buf_addr argument is NULL and buf_size is non-zero.
530 Result_t SetData(byte_t* buf_addr, ui32_t buf_size);
532 // Sets the size of the internally allocate buffer. Returns RESULT_CAPEXTMEM
533 // if the object is using an externally allocated buffer via SetData();
534 // Resets content size to zero.
535 Result_t Capacity(ui32_t cap);
537 // returns the size of the buffer
538 inline ui32_t Capacity() const { return m_Capacity; }
540 // returns a const pointer to the essence data
541 inline const byte_t* RoData() const { return m_Data; }
543 // returns a non-const pointer to the essence data
544 inline byte_t* Data() { return m_Data; }
546 // set the size of the buffer's contents
547 inline ui32_t Size(ui32_t size) { return m_Size = size; }
549 // returns the size of the buffer's contents
550 inline ui32_t Size() const { return m_Size; }
552 // Sets the absolute frame number of this frame in the file in delivery order.
553 inline void FrameNumber(ui32_t num) { m_FrameNumber = num; }
555 // Returns the absolute frame number of this frame in the file in delivery order.
556 inline ui32_t FrameNumber() const { return m_FrameNumber; }
558 // Sets the length of the plaintext essence data
559 inline void SourceLength(ui32_t len) { m_SourceLength = len; }
561 // When this value is 0 (zero), the buffer contains only plaintext. When it is
562 // non-zero, the buffer contains raw ciphertext and the return value is the length
563 // of the original plaintext.
564 inline ui32_t SourceLength() const { return m_SourceLength; }
566 // Sets the offset into the buffer at which encrypted data begins
567 inline void PlaintextOffset(ui32_t ofst) { m_PlaintextOffset = ofst; }
569 // Returns offset into buffer of first byte of ciphertext.
570 inline ui32_t PlaintextOffset() const { return m_PlaintextOffset; }
573 //---------------------------------------------------------------------------------
574 // Accessors in the MXFReader and MXFWriter classes below return these types to
575 // provide direct access to MXF metadata structures declared in MXF.h and Metadata.h
578 // #include<Metadata.h> to use these
580 class OPAtomIndexFooter;
584 //---------------------------------------------------------------------------------
585 // MPEG2 video elementary stream support
590 // MPEG picture coding type
592 FRAME_U = 0x00, // Unknown
593 FRAME_I = 0x01, // I-Frame
594 FRAME_P = 0x02, // P-Frame
595 FRAME_B = 0x03 // B-Frame
598 // convert FrameType_t to char
599 inline char FrameTypeChar(FrameType_t type)
603 case FRAME_I: return 'I';
604 case FRAME_B: return 'B';
605 case FRAME_P: return 'P';
610 // Structure represents the metadata elements in the file header's
611 // MPEG2VideoDescriptor object.
612 struct VideoDescriptor
614 Rational EditRate; //
616 Rational SampleRate; //
617 ui8_t FrameLayout; //
618 ui32_t StoredWidth; //
619 ui32_t StoredHeight; //
620 Rational AspectRatio; //
621 ui32_t ComponentDepth; //
622 ui32_t HorizontalSubsampling; //
623 ui32_t VerticalSubsampling; //
624 ui8_t ColorSiting; //
625 ui8_t CodedContentType; //
628 ui8_t ProfileAndLevel; //
629 ui32_t ContainerDuration; //
632 // Print VideoDescriptor to std::ostream
633 std::ostream& operator << (std::ostream& strm, const VideoDescriptor& vdesc);
634 // Print VideoDescriptor to stream, stderr by default.
635 void VideoDescriptorDump(const VideoDescriptor&, FILE* = 0);
637 // A container for MPEG frame data.
638 class FrameBuffer : public ASDCP::FrameBuffer
640 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
643 FrameType_t m_FrameType;
644 ui8_t m_TemporalOffset;
650 m_FrameType(FRAME_U), m_TemporalOffset(0),
651 m_ClosedGOP(false), m_GOPStart(false) {}
653 FrameBuffer(ui32_t size) :
654 m_FrameType(FRAME_U), m_TemporalOffset(0),
655 m_ClosedGOP(false), m_GOPStart(false)
660 virtual ~FrameBuffer() {}
662 // Sets the MPEG frame type of the picture data in the frame buffer.
663 inline void FrameType(FrameType_t type) { m_FrameType = type; }
665 // Returns the MPEG frame type of the picture data in the frame buffer.
666 inline FrameType_t FrameType() const { return m_FrameType; }
668 // Sets the MPEG temporal offset of the picture data in the frame buffer.
669 inline void TemporalOffset(ui8_t offset) { m_TemporalOffset = offset; }
671 // Returns the MPEG temporal offset of the picture data in the frame buffer.
672 inline ui8_t TemporalOffset() const { return m_TemporalOffset; }
674 // Sets the MPEG GOP 'start' attribute for the frame buffer.
675 inline void GOPStart(bool start) { m_GOPStart = start; }
677 // True if the frame in the buffer is the first in the GOP (in transport order)
678 inline bool GOPStart() const { return m_GOPStart; }
680 // Sets the MPEG GOP 'closed' attribute for the frame buffer.
681 inline void ClosedGOP(bool closed) { m_ClosedGOP = closed; }
683 // Returns true if the frame in the buffer is from a closed GOP, false if
684 // the frame is from an open GOP. Always returns false unless GOPStart()
686 inline bool ClosedGOP() const { return m_ClosedGOP; }
688 // Print object state to stream, include n bytes of frame data if indicated.
689 // Default stream is stderr.
690 void Dump(FILE* = 0, ui32_t dump_len = 0) const;
694 // An object which opens and reads an MPEG2 Video Elementary Stream file. The call to
695 // OpenRead() reads metadata from the file and populates an internal VideoDescriptor object.
696 // Each subsequent call to ReadFrame() reads exactly one frame from the stream into the
697 // given FrameBuffer object.
701 mem_ptr<h__Parser> m_Parser;
702 ASDCP_NO_COPY_CONSTRUCT(Parser);
708 // Opens the stream for reading, parses enough data to provide a complete
709 // set of stream metadata for the MXFWriter below.
710 Result_t OpenRead(const char* filename) const;
712 // Fill a VideoDescriptor struct with the values from the file's header.
713 // Returns RESULT_INIT if the file is not open.
714 Result_t FillVideoDescriptor(VideoDescriptor&) const;
716 // Rewind the stream to the beginning.
717 Result_t Reset() const;
719 // Reads the next sequential frame in the input file and places it in the
720 // frame buffer. Fails if the buffer is too small or the stream is empty.
721 // The frame buffer's PlaintextOffset parameter will be set to the first
722 // data byte of the first slice. Set this value to zero if you want
723 // encrypted headers.
724 Result_t ReadFrame(FrameBuffer&) const;
727 // A class which creates and writes MPEG frame data to an AS-DCP format MXF file.
728 // Not yet implemented
732 mem_ptr<h__Writer> m_Writer;
733 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
737 virtual ~MXFWriter();
739 // Warning: direct manipulation of MXF structures can interfere
740 // with the normal operation of the wrapper. Caveat emptor!
741 virtual MXF::OP1aHeader& OP1aHeader();
742 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
743 virtual MXF::RIP& RIP();
745 // Open the file for writing. The file must not exist. Returns error if
746 // the operation cannot be completed or if nonsensical data is discovered
747 // in the essence descriptor.
748 Result_t OpenWrite(const char* filename, const WriterInfo&,
749 const VideoDescriptor&, ui32_t HeaderSize = 16384);
751 // Writes a frame of essence to the MXF file. If the optional AESEncContext
752 // argument is present, the essence is encrypted prior to writing.
753 // Fails if the file is not open, is finalized, or an operating system
755 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
757 // Closes the MXF file, writing the index and revised header.
761 // A class which reads MPEG frame data from an AS-DCP format MXF file.
765 mem_ptr<h__Reader> m_Reader;
766 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
770 virtual ~MXFReader();
772 // Warning: direct manipulation of MXF structures can interfere
773 // with the normal operation of the wrapper. Caveat emptor!
774 virtual MXF::OP1aHeader& OP1aHeader();
775 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
776 virtual MXF::RIP& RIP();
778 // Open the file for reading. The file must exist. Returns error if the
779 // operation cannot be completed.
780 Result_t OpenRead(const char* filename) const;
782 // Returns RESULT_INIT if the file is not open.
783 Result_t Close() const;
785 // Fill a VideoDescriptor struct with the values from the file's header.
786 // Returns RESULT_INIT if the file is not open.
787 Result_t FillVideoDescriptor(VideoDescriptor&) const;
789 // Fill a WriterInfo struct with the values from the file's header.
790 // Returns RESULT_INIT if the file is not open.
791 Result_t FillWriterInfo(WriterInfo&) const;
793 // Reads a frame of essence from the MXF file. If the optional AESEncContext
794 // argument is present, the essence is decrypted after reading. If the MXF
795 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
796 // will contain the ciphertext frame data. If the HMACContext argument is
797 // not NULL, the HMAC will be calculated (if the file supports it).
798 // Returns RESULT_INIT if the file is not open, failure if the frame number is
799 // out of range, or if optional decrypt or HAMC operations fail.
800 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
802 // Using the index table read from the footer partition, lookup the frame number
803 // and return the offset into the file at which to read that frame of essence.
804 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
806 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
808 // Calculates the first frame in transport order of the GOP in which the requested
809 // frame is located. Calls ReadFrame() to fetch the frame at the calculated position.
810 // Returns RESULT_INIT if the file is not open.
811 Result_t ReadFrameGOPStart(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
813 // Calculates the first frame in transport order of the GOP in which the requested
814 // frame is located. Sets key_frame_number to the number of the frame at the calculated position.
815 // Returns RESULT_INIT if the file is not open.
816 Result_t FindFrameGOPStart(ui32_t frame_number, ui32_t& key_frame_number) const;
818 // Returns the type of the frame at the given position.
819 // Returns RESULT_INIT if the file is not open or RESULT_RANGE if the index is out of range.
820 Result_t FrameType(ui32_t frame_number, FrameType_t&) const;
822 // Print debugging information to stream
823 void DumpHeaderMetadata(FILE* = 0) const;
824 void DumpIndex(FILE* = 0) const;
828 //---------------------------------------------------------------------------------
835 // The default value of the ChannelFormat element of the AudioDescriptor struct
836 // is CF_NONE. If the value is set to one of the other ChannelFormat_t enum
837 // values, the file's Wave Audio Descriptor will contain a Channel Assignment
840 // The channel format should be one of (CF_CFG_1, CF_CFG_2, or CF_CFG_3) for
841 // SMPTE 429-2 files. It should normally be CF_NONE for JPEG Interop files, but
842 // the 429-2 may also be used.
844 enum ChannelFormat_t {
846 CF_CFG_1, // 5.1 with optional HI/VI
847 CF_CFG_2, // 6.1 (5.1 + center surround) with optional HI/VI
848 CF_CFG_3, // 7.1 (SDDS) with optional HI/VI
849 CF_CFG_4, // Wild Track Format
850 CF_CFG_5, // 7.1 DS with optional HI/VI
854 struct AudioDescriptor
856 Rational EditRate; // rate of frame wrapping
857 Rational AudioSamplingRate; // rate of audio sample
859 ui32_t ChannelCount; // number of channels
860 ui32_t QuantizationBits; // number of bits per single-channel sample
861 ui32_t BlockAlign; // number of bytes ber sample, all channels
863 ui32_t LinkedTrackID; //
864 ui32_t ContainerDuration; // number of frames
865 ChannelFormat_t ChannelFormat; // audio channel arrangement
868 // Print AudioDescriptor to std::ostream
869 std::ostream& operator << (std::ostream& strm, const AudioDescriptor& adesc);
870 // Print debugging information to stream (stderr default)
871 void AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
873 // Returns size in bytes of a single sample of data described by ADesc
874 inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
876 return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
879 // Returns number of samples per frame of data described by ADesc
880 inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
882 double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
883 return (ui32_t)ceil(tmpd);
886 // Returns the size in bytes of a frame of data described by ADesc
887 inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
889 return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
893 class FrameBuffer : public ASDCP::FrameBuffer
897 FrameBuffer(ui32_t size) { Capacity(size); }
898 virtual ~FrameBuffer() {}
900 // Print debugging information to stream (stderr default)
901 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
904 // An object which opens and reads a WAV file. The call to OpenRead() reads metadata from
905 // the file and populates an internal AudioDescriptor object. Each subsequent call to
906 // ReadFrame() reads exactly one frame from the stream into the given FrameBuffer object.
907 // A "frame" is either 2000 or 2002 samples, depending upon the value of PictureRate.
911 mem_ptr<h__WAVParser> m_Parser;
912 ASDCP_NO_COPY_CONSTRUCT(WAVParser);
916 virtual ~WAVParser();
918 // Opens the stream for reading, parses enough data to provide a complete
919 // set of stream metadata for the MXFWriter below. PictureRate controls
920 // ther frame rate for the MXF frame wrapping option.
921 Result_t OpenRead(const char* filename, const Rational& PictureRate) const;
923 // Fill an AudioDescriptor struct with the values from the file's header.
924 // Returns RESULT_INIT if the file is not open.
925 Result_t FillAudioDescriptor(AudioDescriptor&) const;
927 // Rewind the stream to the beginning.
928 Result_t Reset() const;
930 // Reads the next sequential frame in the input file and places it in the
931 // frame buffer. Fails if the buffer is too small or the stream is empty.
932 Result_t ReadFrame(FrameBuffer&) const;
940 mem_ptr<h__Writer> m_Writer;
941 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
945 virtual ~MXFWriter();
947 // Warning: direct manipulation of MXF structures can interfere
948 // with the normal operation of the wrapper. Caveat emptor!
949 virtual MXF::OP1aHeader& OP1aHeader();
950 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
951 virtual MXF::RIP& RIP();
953 // Open the file for writing. The file must not exist. Returns error if
954 // the operation cannot be completed or if nonsensical data is discovered
955 // in the essence descriptor.
956 Result_t OpenWrite(const char* filename, const WriterInfo&,
957 const AudioDescriptor&, ui32_t HeaderSize = 16384);
959 // Writes a frame of essence to the MXF file. If the optional AESEncContext
960 // argument is present, the essence is encrypted prior to writing.
961 // Fails if the file is not open, is finalized, or an operating system
963 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
965 // Closes the MXF file, writing the index and revised header.
973 mem_ptr<h__Reader> m_Reader;
974 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
978 virtual ~MXFReader();
980 // Warning: direct manipulation of MXF structures can interfere
981 // with the normal operation of the wrapper. Caveat emptor!
982 virtual MXF::OP1aHeader& OP1aHeader();
983 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
984 virtual MXF::RIP& RIP();
986 // Open the file for reading. The file must exist. Returns error if the
987 // operation cannot be completed.
988 Result_t OpenRead(const char* filename) const;
990 // Returns RESULT_INIT if the file is not open.
991 Result_t Close() const;
993 // Fill an AudioDescriptor struct with the values from the file's header.
994 // Returns RESULT_INIT if the file is not open.
995 Result_t FillAudioDescriptor(AudioDescriptor&) const;
997 // Fill a WriterInfo struct with the values from the file's header.
998 // Returns RESULT_INIT if the file is not open.
999 Result_t FillWriterInfo(WriterInfo&) const;
1001 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1002 // argument is present, the essence is decrypted after reading. If the MXF
1003 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1004 // will contain the ciphertext frame data. If the HMACContext argument is
1005 // not NULL, the HMAC will be calculated (if the file supports it).
1006 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1007 // out of range, or if optional decrypt or HAMC operations fail.
1008 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1010 // Using the index table read from the footer partition, lookup the frame number
1011 // and return the offset into the file at which to read that frame of essence.
1012 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1014 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1016 // Print debugging information to stream
1017 void DumpHeaderMetadata(FILE* = 0) const;
1018 void DumpIndex(FILE* = 0) const;
1022 //---------------------------------------------------------------------------------
1026 const ui32_t MaxComponents = 3;
1027 const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
1028 const ui32_t MaxDefaults = 256; // made up
1031 struct ImageComponent_t // ISO 15444-1 Annex A.5.1
1038 struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
1044 ui8_t ProgressionOrder;
1045 ui8_t NumberOfLayers[sizeof(ui16_t)];
1046 ui8_t MultiCompTransform;
1051 ui8_t DecompositionLevels;
1052 ui8_t CodeblockWidth;
1053 ui8_t CodeblockHeight;
1054 ui8_t CodeblockStyle;
1055 ui8_t Transformation;
1056 ui8_t PrecinctSize[MaxPrecincts];
1060 struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
1063 ui8_t SPqcd[MaxDefaults];
1068 struct PictureDescriptor
1071 ui32_t ContainerDuration;
1072 Rational SampleRate;
1074 ui32_t StoredHeight;
1075 Rational AspectRatio;
1086 ImageComponent_t ImageComponents[MaxComponents];
1087 CodingStyleDefault_t CodingStyleDefault;
1088 QuantizationDefault_t QuantizationDefault;
1091 // Print debugging information to std::ostream
1092 std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
1093 // Print debugging information to stream (stderr default)
1094 void PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
1097 class FrameBuffer : public ASDCP::FrameBuffer
1101 FrameBuffer(ui32_t size) { Capacity(size); }
1102 virtual ~FrameBuffer() {}
1104 // Print debugging information to stream (stderr default)
1105 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1109 // An object which opens and reads a JPEG 2000 codestream file. The file is expected
1110 // to contain exactly one complete frame of picture essence as an unwrapped (raw)
1111 // ISO/IEC 15444 codestream.
1112 class CodestreamParser
1114 class h__CodestreamParser;
1115 mem_ptr<h__CodestreamParser> m_Parser;
1116 ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
1120 virtual ~CodestreamParser();
1122 // Opens a file for reading, parses enough data to provide a complete
1123 // set of stream metadata for the MXFWriter below.
1124 // The frame buffer's PlaintextOffset parameter will be set to the first
1125 // byte of the data segment. Set this value to zero if you want
1126 // encrypted headers.
1127 Result_t OpenReadFrame(const char* filename, FrameBuffer&) const;
1129 // Fill a PictureDescriptor struct with the values from the file's codestream.
1130 // Returns RESULT_INIT if the file is not open.
1131 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1134 // Parses the data in the frame buffer to fill in the picture descriptor. Copies
1135 // the offset of the image data into start_of_data. Returns error if the parser fails.
1136 Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
1138 // An object which reads a sequence of files containing JPEG 2000 pictures.
1139 class SequenceParser
1141 class h__SequenceParser;
1142 mem_ptr<h__SequenceParser> m_Parser;
1143 ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1147 virtual ~SequenceParser();
1149 // Opens a directory for reading. The directory is expected to contain one or
1150 // more files, each containing the codestream for exactly one picture. The
1151 // files must be named such that the frames are in temporal order when sorted
1152 // alphabetically by filename. The parser will automatically parse enough data
1153 // from the first file to provide a complete set of stream metadata for the
1154 // MXFWriter below. If the "pedantic" parameter is given and is true, the
1155 // parser will check the metadata for each codestream and fail if a
1156 // mismatch is detected.
1157 Result_t OpenRead(const char* filename, bool pedantic = false) const;
1159 // Opens a file sequence for reading. The sequence is expected to contain one or
1160 // more filenames, each naming a file containing the codestream for exactly one
1161 // picture. The parser will automatically parse enough data
1162 // from the first file to provide a complete set of stream metadata for the
1163 // MXFWriter below. If the "pedantic" parameter is given and is true, the
1164 // parser will check the metadata for each codestream and fail if a
1165 // mismatch is detected.
1166 Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic = false) const;
1168 // Fill a PictureDescriptor struct with the values from the first file's codestream.
1169 // Returns RESULT_INIT if the directory is not open.
1170 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1172 // Rewind the directory to the beginning.
1173 Result_t Reset() const;
1175 // Reads the next sequential frame in the directory and places it in the
1176 // frame buffer. Fails if the buffer is too small or the direcdtory
1177 // contains no more files.
1178 // The frame buffer's PlaintextOffset parameter will be set to the first
1179 // byte of the data segment. Set this value to zero if you want
1180 // encrypted headers.
1181 Result_t ReadFrame(FrameBuffer&) const;
1189 mem_ptr<h__Writer> m_Writer;
1190 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1194 virtual ~MXFWriter();
1196 // Warning: direct manipulation of MXF structures can interfere
1197 // with the normal operation of the wrapper. Caveat emptor!
1198 virtual MXF::OP1aHeader& OP1aHeader();
1199 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1200 virtual MXF::RIP& RIP();
1202 // Open the file for writing. The file must not exist. Returns error if
1203 // the operation cannot be completed or if nonsensical data is discovered
1204 // in the essence descriptor.
1205 Result_t OpenWrite(const char* filename, const WriterInfo&,
1206 const PictureDescriptor&, ui32_t HeaderSize = 16384);
1208 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1209 // argument is present, the essence is encrypted prior to writing.
1210 // Fails if the file is not open, is finalized, or an operating system
1212 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1214 // Closes the MXF file, writing the index and revised header.
1215 Result_t Finalize();
1222 mem_ptr<h__Reader> m_Reader;
1223 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1227 virtual ~MXFReader();
1229 // Warning: direct manipulation of MXF structures can interfere
1230 // with the normal operation of the wrapper. Caveat emptor!
1231 virtual MXF::OP1aHeader& OP1aHeader();
1232 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1233 virtual MXF::RIP& RIP();
1235 // Open the file for reading. The file must exist. Returns error if the
1236 // operation cannot be completed.
1237 Result_t OpenRead(const char* filename) const;
1239 // Returns RESULT_INIT if the file is not open.
1240 Result_t Close() const;
1242 // Fill an AudioDescriptor struct with the values from the file's header.
1243 // Returns RESULT_INIT if the file is not open.
1244 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1246 // Fill a WriterInfo struct with the values from the file's header.
1247 // Returns RESULT_INIT if the file is not open.
1248 Result_t FillWriterInfo(WriterInfo&) const;
1250 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1251 // argument is present, the essence is decrypted after reading. If the MXF
1252 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1253 // will contain the ciphertext frame data. If the HMACContext argument is
1254 // not NULL, the HMAC will be calculated (if the file supports it).
1255 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1256 // out of range, or if optional decrypt or HAMC operations fail.
1257 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1259 // Using the index table read from the footer partition, lookup the frame number
1260 // and return the offset into the file at which to read that frame of essence.
1261 // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
1263 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1265 // Print debugging information to stream
1266 void DumpHeaderMetadata(FILE* = 0) const;
1267 void DumpIndex(FILE* = 0) const;
1271 // Stereoscopic Image support
1274 enum StereoscopicPhase_t
1282 JP2K::FrameBuffer Left;
1283 JP2K::FrameBuffer Right;
1285 SFrameBuffer(ui32_t size) {
1286 Left.Capacity(size);
1287 Right.Capacity(size);
1294 mem_ptr<h__SWriter> m_Writer;
1295 ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
1299 virtual ~MXFSWriter();
1301 // Warning: direct manipulation of MXF structures can interfere
1302 // with the normal operation of the wrapper. Caveat emptor!
1303 virtual MXF::OP1aHeader& OP1aHeader();
1304 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1305 virtual MXF::RIP& RIP();
1307 // Open the file for writing. The file must not exist. Returns error if
1308 // the operation cannot be completed or if nonsensical data is discovered
1309 // in the essence descriptor.
1310 Result_t OpenWrite(const char* filename, const WriterInfo&,
1311 const PictureDescriptor&, ui32_t HeaderSize = 16384);
1313 // Writes a pair of frames of essence to the MXF file. If the optional AESEncContext
1314 // argument is present, the essence is encrypted prior to writing.
1315 // Fails if the file is not open, is finalized, or an operating system
1317 Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1319 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1320 // argument is present, the essence is encrypted prior to writing.
1321 // Fails if the file is not open, is finalized, or an operating system
1322 // error occurs. Frames must be written in the proper phase (L-R-L-R),
1323 // RESULT_SPHASE will be returned if phase is reversed. The first frame
1324 // written must be left eye.
1325 Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
1326 AESEncContext* = 0, HMACContext* = 0);
1328 // Closes the MXF file, writing the index and revised header. Returns
1329 // RESULT_SPHASE if WriteFrame was called an odd number of times.
1330 Result_t Finalize();
1337 mem_ptr<h__SReader> m_Reader;
1338 ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
1342 virtual ~MXFSReader();
1344 // Warning: direct manipulation of MXF structures can interfere
1345 // with the normal operation of the wrapper. Caveat emptor!
1346 virtual MXF::OP1aHeader& OP1aHeader();
1347 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1348 virtual MXF::RIP& RIP();
1350 // Open the file for reading. The file must exist. Returns error if the
1351 // operation cannot be completed.
1352 Result_t OpenRead(const char* filename) const;
1354 // Returns RESULT_INIT if the file is not open.
1355 Result_t Close() const;
1357 // Fill an AudioDescriptor struct with the values from the file's header.
1358 // Returns RESULT_INIT if the file is not open.
1359 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1361 // Fill a WriterInfo struct with the values from the file's header.
1362 // Returns RESULT_INIT if the file is not open.
1363 Result_t FillWriterInfo(WriterInfo&) const;
1365 // Reads a pair of frames of essence from the MXF file. If the optional AESEncContext
1366 // argument is present, the essence is decrypted after reading. If the MXF
1367 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1368 // will contain the ciphertext frame data. If the HMACContext argument is
1369 // not NULL, the HMAC will be calculated (if the file supports it).
1370 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1371 // out of range, or if optional decrypt or HAMC operations fail.
1372 Result_t ReadFrame(ui32_t frame_number, SFrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1374 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1375 // argument is present, the essence is decrypted after reading. If the MXF
1376 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1377 // will contain the ciphertext frame data. If the HMACContext argument is
1378 // not NULL, the HMAC will be calculated (if the file supports it).
1379 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1380 // out of range, or if optional decrypt or HAMC operations fail.
1381 Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
1382 FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1384 // Using the index table read from the footer partition, lookup the frame number
1385 // and return the offset into the file at which to read that frame of essence.
1386 // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
1388 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1390 // Print debugging information to stream
1391 void DumpHeaderMetadata(FILE* = 0) const;
1392 void DumpIndex(FILE* = 0) const;
1396 //---------------------------------------------------------------------------------
1400 enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
1402 struct TimedTextResourceDescriptor
1404 byte_t ResourceID[UUIDlen];
1407 TimedTextResourceDescriptor() : Type(MT_BIN) {}
1410 typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
1412 struct TimedTextDescriptor
1414 Rational EditRate; //
1415 ui32_t ContainerDuration;
1416 byte_t AssetID[UUIDlen];
1417 std::string NamespaceName;
1418 std::string EncodingName;
1419 ResourceList_t ResourceList;
1421 TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8
1424 // Print debugging information to std::ostream
1425 std::ostream& operator << (std::ostream& strm, const TimedTextDescriptor& tinfo);
1426 // Print debugging information to stream (stderr default)
1427 void DescriptorDump(const TimedTextDescriptor&, FILE* = 0);
1430 class FrameBuffer : public ASDCP::FrameBuffer
1432 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
1435 byte_t m_AssetID[UUIDlen];
1436 std::string m_MIMEType;
1439 FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
1440 FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
1441 virtual ~FrameBuffer() {}
1443 inline const byte_t* AssetID() const { return m_AssetID; }
1444 inline void AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); }
1445 inline const char* MIMEType() const { return m_MIMEType.c_str(); }
1446 inline void MIMEType(const std::string& s) { m_MIMEType = s; }
1448 // Print debugging information to stream (stderr default)
1449 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1453 class IResourceResolver
1456 virtual ~IResourceResolver() {}
1457 virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
1461 class DCSubtitleParser
1463 class h__SubtitleParser;
1464 mem_ptr<h__SubtitleParser> m_Parser;
1465 ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
1469 virtual ~DCSubtitleParser();
1471 // Opens an XML file for reading, parses data to provide a complete
1472 // set of stream metadata for the MXFWriter below.
1473 Result_t OpenRead(const char* filename) const;
1475 // Parses an XML document to provide a complete set of stream metadata
1476 // for the MXFWriter below. The optional filename argument is used to
1477 // initialize the default resource resolver (see ReadAncillaryResource).
1478 Result_t OpenRead(const std::string& xml_doc, const char* filename = 0) const;
1480 // Fill a TimedTextDescriptor struct with the values from the file's contents.
1481 // Returns RESULT_INIT if the file is not open.
1482 Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1484 // Reads the complete Timed Text Resource into the given string.
1485 Result_t ReadTimedTextResource(std::string&) const;
1487 // Reads the Ancillary Resource having the given ID. Fails if the buffer
1488 // is too small or the resource does not exist. The optional Resolver
1489 // argument can be provided which will be used to retrieve the resource
1490 // having a particulat UUID. If a Resolver is not supplied, the default
1491 // internal resolver will return the contents of the file having the UUID
1492 // as the filename. The filename must exist in the same directory as the
1493 // XML file opened with OpenRead().
1494 Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
1495 const IResourceResolver* Resolver = 0) const;
1502 mem_ptr<h__Writer> m_Writer;
1503 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1507 virtual ~MXFWriter();
1509 // Warning: direct manipulation of MXF structures can interfere
1510 // with the normal operation of the wrapper. Caveat emptor!
1511 virtual MXF::OP1aHeader& OP1aHeader();
1512 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1513 virtual MXF::RIP& RIP();
1515 // Open the file for writing. The file must not exist. Returns error if
1516 // the operation cannot be completed or if nonsensical data is discovered
1517 // in the essence descriptor.
1518 Result_t OpenWrite(const char* filename, const WriterInfo&,
1519 const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
1521 // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
1522 // encoded. If the optional AESEncContext argument is present, the essence
1523 // is encrypted prior to writing. Fails if the file is not open, is finalized,
1524 // or an operating system error occurs.
1525 // This method may only be called once, and it must be called before any
1526 // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
1527 // conditions are not met.
1528 Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
1530 // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
1531 // argument is present, the essence is encrypted prior to writing.
1532 // Fails if the file is not open, is finalized, or an operating system
1533 // error occurs. RESULT_STATE will be returned if the method is called before
1534 // WriteTimedTextResource()
1535 Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1537 // Closes the MXF file, writing the index and revised header.
1538 Result_t Finalize();
1545 mem_ptr<h__Reader> m_Reader;
1546 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1550 virtual ~MXFReader();
1552 // Warning: direct manipulation of MXF structures can interfere
1553 // with the normal operation of the wrapper. Caveat emptor!
1554 virtual MXF::OP1aHeader& OP1aHeader();
1555 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1556 virtual MXF::RIP& RIP();
1558 // Open the file for reading. The file must exist. Returns error if the
1559 // operation cannot be completed.
1560 Result_t OpenRead(const char* filename) const;
1562 // Returns RESULT_INIT if the file is not open.
1563 Result_t Close() const;
1565 // Fill a TimedTextDescriptor struct with the values from the file's header.
1566 // Returns RESULT_INIT if the file is not open.
1567 Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1569 // Fill a WriterInfo struct with the values from the file's header.
1570 // Returns RESULT_INIT if the file is not open.
1571 Result_t FillWriterInfo(WriterInfo&) const;
1573 // Reads the complete Timed Text Resource into the given string. Fails if the resource
1574 // is encrypted and AESDecContext is NULL (use the following method to retrieve the
1575 // raw ciphertet block).
1576 Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
1578 // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
1579 // argument is present, the resource is decrypted after reading. If the MXF
1580 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1581 // will contain the ciphertext frame data. If the HMACContext argument is
1582 // not NULL, the HMAC will be calculated (if the file supports it).
1583 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1584 // out of range, or if optional decrypt or HAMC operations fail.
1585 Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1587 // Reads the timed-text resource having the given UUID from the MXF file. If the
1588 // optional AESEncContext argument is present, the resource is decrypted after
1589 // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
1590 // the frame buffer will contain the ciphertext frame data. If the HMACContext
1591 // argument is not NULL, the HMAC will be calculated (if the file supports it).
1592 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1593 // out of range, or if optional decrypt or HAMC operations fail.
1594 Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1596 // Print debugging information to stream
1597 void DumpHeaderMetadata(FILE* = 0) const;
1598 void DumpIndex(FILE* = 0) const;
1600 } // namespace TimedText
1602 //---------------------------------------------------------------------------------
1606 struct DCDataDescriptor
1608 Rational EditRate; // Sample rate
1609 ui32_t ContainerDuration; // number of frames
1610 byte_t AssetID[UUIDlen]; // The UUID for the DCData track
1611 byte_t DataEssenceCoding[UUIDlen]; // The coding for the data carried
1614 // Print DCDataDescriptor to std::ostream
1615 std::ostream& operator << (std::ostream& strm, const DCDataDescriptor& ddesc);
1616 // Print debugging information to stream (stderr default)
1617 void DCDataDescriptorDump(const DCDataDescriptor&, FILE* = 0);
1620 class FrameBuffer : public ASDCP::FrameBuffer
1624 FrameBuffer(ui32_t size) { Capacity(size); }
1625 virtual ~FrameBuffer() {}
1627 // Print debugging information to stream (stderr default)
1628 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1631 // An object which opens and reads a DC Data file. The file is expected
1632 // to contain exactly one complete frame of DC data essence as an unwrapped (raw)
1634 class BytestreamParser
1636 class h__BytestreamParser;
1637 mem_ptr<h__BytestreamParser> m_Parser;
1638 ASDCP_NO_COPY_CONSTRUCT(BytestreamParser);
1642 virtual ~BytestreamParser();
1644 // Opens a file for reading, parses enough data to provide a complete
1645 // set of stream metadata for the MXFWriter below.
1646 // The frame buffer's PlaintextOffset parameter will be set to the first
1647 // byte of the data segment. Set this value to zero if you want
1648 // encrypted headers.
1649 Result_t OpenReadFrame(const char* filename, FrameBuffer&) const;
1651 // Fill a DCDataDescriptor struct with the values from the file's bytestream.
1652 // Returns RESULT_INIT if the file is not open.
1653 Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1656 // An object which reads a sequence of files containing DC Data.
1657 class SequenceParser
1659 class h__SequenceParser;
1660 mem_ptr<h__SequenceParser> m_Parser;
1661 ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1665 virtual ~SequenceParser();
1667 // Opens a directory for reading. The directory is expected to contain one or
1668 // more files, each containing the bytestream for exactly one frame. The files
1669 // must be named such that the frames are in temporal order when sorted
1670 // alphabetically by filename.
1671 Result_t OpenRead(const char* filename) const;
1673 // Opens a file sequence for reading. The sequence is expected to contain one or
1674 // more filenames, each naming a file containing the bytestream for exactly one
1676 Result_t OpenRead(const std::list<std::string>& file_list) const;
1678 // Fill a DCDataDescriptor struct with default values.
1679 // Returns RESULT_INIT if the directory is not open.
1680 Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1682 // Rewind the directory to the beginning.
1683 Result_t Reset() const;
1685 // Reads the next sequential frame in the directory and places it in the
1686 // frame buffer. Fails if the buffer is too small or the direcdtory
1687 // contains no more files.
1688 // The frame buffer's PlaintextOffset parameter will be set to the first
1689 // byte of the data segment. Set this value to zero if you want
1690 // encrypted headers.
1691 Result_t ReadFrame(FrameBuffer&) const;
1698 mem_ptr<h__Writer> m_Writer;
1699 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1703 virtual ~MXFWriter();
1705 // Warning: direct manipulation of MXF structures can interfere
1706 // with the normal operation of the wrapper. Caveat emptor!
1707 virtual MXF::OP1aHeader& OP1aHeader();
1708 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1709 virtual MXF::RIP& RIP();
1711 // Open the file for writing. The file must not exist. Returns error if
1712 // the operation cannot be completed or if nonsensical data is discovered
1713 // in the essence descriptor.
1714 Result_t OpenWrite(const char* filename, const WriterInfo&,
1715 const DCDataDescriptor&, ui32_t HeaderSize = 16384);
1717 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1718 // argument is present, the essence is encrypted prior to writing.
1719 // Fails if the file is not open, is finalized, or an operating system
1721 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1723 // Closes the MXF file, writing the index and revised header.
1724 Result_t Finalize();
1731 mem_ptr<h__Reader> m_Reader;
1732 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1736 virtual ~MXFReader();
1738 // Warning: direct manipulation of MXF structures can interfere
1739 // with the normal operation of the wrapper. Caveat emptor!
1740 virtual MXF::OP1aHeader& OP1aHeader();
1741 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1742 virtual MXF::RIP& RIP();
1744 // Open the file for reading. The file must exist. Returns error if the
1745 // operation cannot be completed.
1746 Result_t OpenRead(const char* filename) const;
1748 // Returns RESULT_INIT if the file is not open.
1749 Result_t Close() const;
1751 // Fill a DCDataDescriptor struct with the values from the file's header.
1752 // Returns RESULT_INIT if the file is not open.
1753 Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1755 // Fill a WriterInfo struct with the values from the file's header.
1756 // Returns RESULT_INIT if the file is not open.
1757 Result_t FillWriterInfo(WriterInfo&) const;
1759 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1760 // argument is present, the essence is decrypted after reading. If the MXF
1761 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1762 // will contain the ciphertext frame data. If the HMACContext argument is
1763 // not NULL, the HMAC will be calculated (if the file supports it).
1764 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1765 // out of range, or if optional decrypt or HAMC operations fail.
1766 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1768 // Using the index table read from the footer partition, lookup the frame number
1769 // and return the offset into the file at which to read that frame of essence.
1770 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1772 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1774 // Print debugging information to stream
1775 void DumpHeaderMetadata(FILE* = 0) const;
1776 void DumpIndex(FILE* = 0) const;
1779 } // namespace DCData
1781 //---------------------------------------------------------------------------------
1785 struct AtmosDescriptor : public DCData::DCDataDescriptor
1787 ui32_t FirstFrame; // Frame number of the frame to align with the FFOA of the picture track
1788 ui16_t MaxChannelCount; // Max number of channels in bitstream
1789 ui16_t MaxObjectCount; // Max number of objects in bitstream
1790 byte_t AtmosID[UUIDlen]; // UUID of Atmos Project
1791 ui8_t AtmosVersion; // ATMOS Coder Version used to create bitstream
1794 // Print AtmosDescriptor to std::ostream
1795 std::ostream& operator << (std::ostream& strm, const AtmosDescriptor& adesc);
1796 // Print debugging information to stream (stderr default)
1797 void AtmosDescriptorDump(const AtmosDescriptor&, FILE* = 0);
1798 // Determine if a file is a raw atmos file
1799 bool IsDolbyAtmos(const char* filename);
1806 mem_ptr<h__Writer> m_Writer;
1807 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1811 virtual ~MXFWriter();
1813 // Warning: direct manipulation of MXF structures can interfere
1814 // with the normal operation of the wrapper. Caveat emptor!
1815 virtual MXF::OP1aHeader& OP1aHeader();
1816 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1817 virtual MXF::RIP& RIP();
1819 // Open the file for writing. The file must not exist. Returns error if
1820 // the operation cannot be completed or if nonsensical data is discovered
1821 // in the essence descriptor.
1822 Result_t OpenWrite(const char* filename, const WriterInfo&,
1823 const AtmosDescriptor&, ui32_t HeaderSize = 16384);
1825 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1826 // argument is present, the essence is encrypted prior to writing.
1827 // Fails if the file is not open, is finalized, or an operating system
1829 Result_t WriteFrame(const DCData::FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1831 // Closes the MXF file, writing the index and revised header.
1832 Result_t Finalize();
1839 mem_ptr<h__Reader> m_Reader;
1840 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1844 virtual ~MXFReader();
1846 // Warning: direct manipulation of MXF structures can interfere
1847 // with the normal operation of the wrapper. Caveat emptor!
1848 virtual MXF::OP1aHeader& OP1aHeader();
1849 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1850 virtual MXF::RIP& RIP();
1852 // Open the file for reading. The file must exist. Returns error if the
1853 // operation cannot be completed.
1854 Result_t OpenRead(const char* filename) const;
1856 // Returns RESULT_INIT if the file is not open.
1857 Result_t Close() const;
1859 // Fill an AtmosDescriptor struct with the values from the file's header.
1860 // Returns RESULT_INIT if the file is not open.
1861 Result_t FillAtmosDescriptor(AtmosDescriptor&) const;
1863 // Fill a WriterInfo struct with the values from the file's header.
1864 // Returns RESULT_INIT if the file is not open.
1865 Result_t FillWriterInfo(WriterInfo&) const;
1867 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1868 // argument is present, the essence is decrypted after reading. If the MXF
1869 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1870 // will contain the ciphertext frame data. If the HMACContext argument is
1871 // not NULL, the HMAC will be calculated (if the file supports it).
1872 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1873 // out of range, or if optional decrypt or HAMC operations fail.
1874 Result_t ReadFrame(ui32_t frame_number, DCData::FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1876 // Using the index table read from the footer partition, lookup the frame number
1877 // and return the offset into the file at which to read that frame of essence.
1878 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1880 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1882 // Print debugging information to stream
1883 void DumpHeaderMetadata(FILE* = 0) const;
1884 void DumpIndex(FILE* = 0) const;
1887 } // namespace ATMOS
1891 } // namespace ASDCP
1894 #endif // _AS_DCP_H_