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 of AS-02 essence container
214 ESS_MPEG2_VES, // the file contains an MPEG-2 video elementary stream
216 // d-cinema essence types
217 ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
218 ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
219 ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
220 ESS_TIMED_TEXT, // the file contains an XML timed text document and one or more resources
221 ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic)
222 ESS_DCDATA_UNKNOWN, // the file contains one or more D-Cinema Data bytestreams
223 ESS_DCDATA_DOLBY_ATMOS, // the file contains one or more DolbyATMOS bytestreams
226 ESS_AS02_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
227 ESS_AS02_PCM_24b_48k, // the file contains one or more PCM audio pairs, clip wrapped
228 ESS_AS02_PCM_24b_96k, // the file contains one or more PCM audio pairs, clip wrapped
229 ESS_AS02_TIMED_TEXT, // the file contains a TTML document and zero or more resources
234 // Determine the type of essence contained in the given MXF file. RESULT_OK
235 // is returned if the file is successfully opened and contains a valid MXF
236 // stream. If there is an error, the result code will indicate the reason.
237 Result_t EssenceType(const std::string& filename, EssenceType_t& type);
239 // Determine the type of essence contained in the given raw file. RESULT_OK
240 // is returned if the file is successfully opened and contains a known
241 // stream type. If there is an error, the result code will indicate the reason.
242 Result_t RawEssenceType(const std::string& filename, EssenceType_t& type);
245 //---------------------------------------------------------------------------------
248 // A simple container for rational numbers.
255 Rational() : Numerator(0), Denominator(0) {}
256 Rational(i32_t n, i32_t d) : Numerator(n), Denominator(d) {}
258 inline double Quotient() const {
259 return (double)Numerator / (double)Denominator;
262 inline bool operator==(const Rational& rhs) const {
263 return ( rhs.Numerator == Numerator && rhs.Denominator == Denominator );
266 inline bool operator!=(const Rational& rhs) const {
267 return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
270 inline bool operator<(const Rational& rhs) {
271 if ( Numerator < rhs.Numerator ) return true;
272 if ( Numerator == rhs.Numerator && Denominator < rhs.Denominator ) return true;
276 inline bool operator>(const Rational& rhs) {
277 if ( Numerator > rhs.Numerator ) return true;
278 if ( Numerator == rhs.Numerator && Denominator > rhs.Denominator ) return true;
283 // common edit rates, use these instead of hard coded constants
284 const Rational EditRate_24 = Rational(24,1);
285 const Rational EditRate_23_98 = Rational(24000,1001); // Not a DCI-compliant value!
286 const Rational EditRate_48 = Rational(48,1);
287 const Rational SampleRate_48k = Rational(48000,1);
288 const Rational SampleRate_96k = Rational(96000,1);
290 // Additional frame rates, see ST 428-11, ST 429-13
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_25 = Rational(25,1);
294 const Rational EditRate_30 = Rational(30,1);
295 const Rational EditRate_50 = Rational(50,1);
296 const Rational EditRate_60 = Rational(60,1);
297 const Rational EditRate_96 = Rational(96,1);
298 const Rational EditRate_100 = Rational(100,1);
299 const Rational EditRate_120 = Rational(120,1);
301 // Archival frame rates, see ST 428-21
302 // These rates are new and not supported by all systems. Do not assume that
303 // a package made using one of these rates will work just anywhere!
304 const Rational EditRate_16 = Rational(16,1);
305 const Rational EditRate_18 = Rational(200,11); // 18.182
306 const Rational EditRate_20 = Rational(20,1);
307 const Rational EditRate_22 = Rational(240,11); // 21.818
310 // Non-reference counting container for internal member objects.
311 // Please do not use this class for any other purpose.
315 T* m_p; // the thing we point to
319 mem_ptr() : m_p(0) {}
320 mem_ptr(T* p) : m_p(p) {}
321 ~mem_ptr() { delete m_p; }
323 inline T& operator*() const { return *m_p; }
324 inline T* operator->() const { return m_p; }
325 inline operator T*()const { return m_p; }
326 inline const mem_ptr<T>& operator=(T* p) { set(p); return *this; }
327 inline T* set(T* p) { delete m_p; m_p = p; return m_p; }
328 inline T* get() const { return m_p; }
329 inline void release() { m_p = 0; }
330 inline bool empty() const { return m_p == 0; }
334 //---------------------------------------------------------------------------------
335 // WriterInfo class - encapsulates writer identification details used for
336 // OpenWrite() calls. Replace these values at runtime to identify your product.
338 // MXF files use SMPTE Universal Labels to identify data items. The set of Labels
339 // in a file is determined by the MXF Operational Pattern and any constraining
340 // documentation. There are currently two flavors of AS-DCP file in use: MXF Interop
341 // (AKA JPEG Interop) and SMPTE. The two differ in the values of three labels:
344 // Interop : 06 0e 2b 34 04 01 01 01 0d 01 02 01 10 00 00 00
345 // SMPTE : 06 0e 2b 34 04 01 01 02 0d 01 02 01 10 00 00 00
348 // Interop : 06 0e 2b 34 02 04 01 07 0d 01 03 01 02 7e 01 00
349 // SMPTE : 06 0e 2b 34 02 04 01 01 0d 01 03 01 02 7e 01 00
351 // GenericDescriptor/SubDescriptors:
352 // Interop : 06 0e 2b 34 01 01 01 02 06 01 01 04 06 10 00 00
353 // SMPTE : 06 0e 2b 34 01 01 01 09 06 01 01 04 06 10 00 00
355 // asdcplib will read any (otherwise valid) file which has any combination of the
356 // above values. When writing files, MXF Interop labels are used by default. To
357 // write a file containing SMPTE labels, replace the default label set value in
358 // the WriterInfo before calling OpenWrite()
372 byte_t ProductUUID[UUIDlen];
373 byte_t AssetUUID[UUIDlen];
374 byte_t ContextID[UUIDlen];
375 byte_t CryptographicKeyID[UUIDlen];
376 bool EncryptedEssence; // true if essence data is (or is going to be) encrypted
377 bool UsesHMAC; // true if HMAC exists or is to be calculated
378 std::string ProductVersion;
379 std::string CompanyName;
380 std::string ProductName;
381 LabelSet_t LabelSetType;
383 WriterInfo() : EncryptedEssence(false), UsesHMAC(false), LabelSetType(LS_MXF_INTEROP)
385 static byte_t default_ProductUUID_Data[UUIDlen] = {
386 0x43, 0x05, 0x9a, 0x1d, 0x04, 0x32, 0x41, 0x01,
387 0xb8, 0x3f, 0x73, 0x68, 0x15, 0xac, 0xf3, 0x1d };
389 memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
390 memset(AssetUUID, 0, UUIDlen);
391 memset(ContextID, 0, UUIDlen);
392 memset(CryptographicKeyID, 0, UUIDlen);
394 ProductVersion = "Unreleased ";
395 ProductVersion += Version();
397 ProductName = "asdcplib";
401 // Print WriterInfo to std::ostream
402 std::ostream& operator << (std::ostream& strm, const WriterInfo& winfo);
403 // Print WriterInfo to stream, stderr by default.
404 void WriterInfoDump(const WriterInfo&, FILE* = 0);
406 //---------------------------------------------------------------------------------
407 // cryptographic support
409 // The following classes define interfaces to Rijndael contexts having the following properties:
411 // o CBC mode with 16 byte block size
412 const ui32_t CBC_KEY_SIZE = 16;
413 const ui32_t CBC_BLOCK_SIZE = 16;
414 const ui32_t HMAC_SIZE = 20;
420 mem_ptr<h__AESContext> m_Context;
421 ASDCP_NO_COPY_CONSTRUCT(AESEncContext);
427 // Initializes Rijndael CBC encryption context.
428 // Returns error if the key argument is NULL.
429 Result_t InitKey(const byte_t* key);
431 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
432 // any number of times for a given key.
433 // Returns error if the i_vec argument is NULL.
434 Result_t SetIVec(const byte_t* i_vec);
435 Result_t GetIVec(byte_t* i_vec) const;
437 // Encrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
438 // Returns error if either argument is NULL.
439 Result_t EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size);
446 mem_ptr<h__AESContext> m_Context;
447 ASDCP_NO_COPY_CONSTRUCT(AESDecContext);
453 // Initializes Rijndael CBC decryption context.
454 // Returns error if the key argument is NULL.
455 Result_t InitKey(const byte_t* key);
457 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
458 // any number of times for a given key.
459 // Returns error if the i_vec argument is NULL.
460 Result_t SetIVec(const byte_t* i_vec);
462 // Decrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
463 // Returns error if either argument is NULL.
464 Result_t DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size);
470 class h__HMACContext;
471 mem_ptr<h__HMACContext> m_Context;
472 ASDCP_NO_COPY_CONSTRUCT(HMACContext);
478 // Initializes HMAC context. The key argument must point to a binary
479 // key that is CBC_KEY_SIZE bytes in length. Returns error if the key
481 Result_t InitKey(const byte_t* key, LabelSet_t);
483 // Reset internal state, allows repeated cycles of Update -> Finalize
486 // Add data to the digest. Returns error if the key argument is NULL or
487 // if the digest has been finalized.
488 Result_t Update(const byte_t* buf, ui32_t buf_len);
490 // Finalize digest. Returns error if the digest has already been finalized.
493 // Writes HMAC value to given buffer. buf must point to a writable area of
494 // memory that is at least HMAC_SIZE bytes in length. Returns error if the
495 // buf argument is NULL or if the digest has not been finalized.
496 Result_t GetHMACValue(byte_t* buf) const;
498 // Tests the given value against the finalized value in the object. buf must
499 // point to a readable area of memory that is at least HMAC_SIZE bytes in length.
500 // Returns error if the buf argument is NULL or if the values do ot match.
501 Result_t TestHMACValue(const byte_t* buf) const;
504 //---------------------------------------------------------------------------------
505 // frame buffer base class
507 // The supported essence types are stored using per-frame KLV packetization. The
508 // following class implements essence-neutral functionality for managing a buffer
509 // containing a frame of essence.
513 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer);
516 byte_t* m_Data; // pointer to memory area containing frame data
517 ui32_t m_Capacity; // size of memory area pointed to by m_Data
518 bool m_OwnMem; // if false, m_Data points to externally allocated memory
519 ui32_t m_Size; // size of frame data in memory area pointed to by m_Data
520 ui32_t m_FrameNumber; // delivery-order frame number
522 // It is possible to read raw ciphertext from an encrypted AS-DCP file.
523 // After reading an encrypted AS-DCP file in raw mode, the frame buffer will
524 // contain the encrypted source value portion of the Encrypted Triplet, followed
525 // by the integrity pack, if it exists.
526 // The buffer will begin with the IV and CheckValue, followed by encrypted essence
527 // and optional integrity pack
528 // The SourceLength and PlaintextOffset values from the packet will be held in the
529 // following variables:
530 ui32_t m_SourceLength; // plaintext length (delivered plaintext+decrypted ciphertext)
531 ui32_t m_PlaintextOffset; // offset to first byte of ciphertext
535 virtual ~FrameBuffer();
537 // Instructs the object to use an externally allocated buffer. The external
538 // buffer will not be cleaned up by the frame buffer when it exits.
539 // Call with (0,0) to revert to internally allocated buffer.
540 // Returns error if the buf_addr argument is NULL and buf_size is non-zero.
541 Result_t SetData(byte_t* buf_addr, ui32_t buf_size);
543 // Sets the size of the internally allocate buffer. Returns RESULT_CAPEXTMEM
544 // if the object is using an externally allocated buffer via SetData();
545 // Resets content size to zero.
546 Result_t Capacity(ui32_t cap);
548 // returns the size of the buffer
549 inline ui32_t Capacity() const { return m_Capacity; }
551 // returns a const pointer to the essence data
552 inline const byte_t* RoData() const { return m_Data; }
554 // returns a non-const pointer to the essence data
555 inline byte_t* Data() { return m_Data; }
557 // set the size of the buffer's contents
558 inline ui32_t Size(ui32_t size) { return m_Size = size; }
560 // returns the size of the buffer's contents
561 inline ui32_t Size() const { return m_Size; }
563 // Sets the absolute frame number of this frame in the file in delivery order.
564 inline void FrameNumber(ui32_t num) { m_FrameNumber = num; }
566 // Returns the absolute frame number of this frame in the file in delivery order.
567 inline ui32_t FrameNumber() const { return m_FrameNumber; }
569 // Sets the length of the plaintext essence data
570 inline void SourceLength(ui32_t len) { m_SourceLength = len; }
572 // When this value is 0 (zero), the buffer contains only plaintext. When it is
573 // non-zero, the buffer contains raw ciphertext and the return value is the length
574 // of the original plaintext.
575 inline ui32_t SourceLength() const { return m_SourceLength; }
577 // Sets the offset into the buffer at which encrypted data begins
578 inline void PlaintextOffset(ui32_t ofst) { m_PlaintextOffset = ofst; }
580 // Returns offset into buffer of first byte of ciphertext.
581 inline ui32_t PlaintextOffset() const { return m_PlaintextOffset; }
584 //---------------------------------------------------------------------------------
585 // Accessors in the MXFReader and MXFWriter classes below return these types to
586 // provide direct access to MXF metadata structures declared in MXF.h and Metadata.h
589 // #include<Metadata.h> to use these
591 class OPAtomIndexFooter;
595 //---------------------------------------------------------------------------------
596 // MPEG2 video elementary stream support
601 // MPEG picture coding type
603 FRAME_U = 0x00, // Unknown
604 FRAME_I = 0x01, // I-Frame
605 FRAME_P = 0x02, // P-Frame
606 FRAME_B = 0x03 // B-Frame
609 // convert FrameType_t to char
610 inline char FrameTypeChar(FrameType_t type)
614 case FRAME_I: return 'I';
615 case FRAME_B: return 'B';
616 case FRAME_P: return 'P';
621 // Structure represents the metadata elements in the file header's
622 // MPEG2VideoDescriptor object.
623 struct VideoDescriptor
625 Rational EditRate; //
627 Rational SampleRate; //
628 ui8_t FrameLayout; //
629 ui32_t StoredWidth; //
630 ui32_t StoredHeight; //
631 Rational AspectRatio; //
632 ui32_t ComponentDepth; //
633 ui32_t HorizontalSubsampling; //
634 ui32_t VerticalSubsampling; //
635 ui8_t ColorSiting; //
636 ui8_t CodedContentType; //
639 ui8_t ProfileAndLevel; //
640 ui32_t ContainerDuration; //
643 // Print VideoDescriptor to std::ostream
644 std::ostream& operator << (std::ostream& strm, const VideoDescriptor& vdesc);
645 // Print VideoDescriptor to stream, stderr by default.
646 void VideoDescriptorDump(const VideoDescriptor&, FILE* = 0);
648 // A container for MPEG frame data.
649 class FrameBuffer : public ASDCP::FrameBuffer
651 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
654 FrameType_t m_FrameType;
655 ui8_t m_TemporalOffset;
661 m_FrameType(FRAME_U), m_TemporalOffset(0),
662 m_ClosedGOP(false), m_GOPStart(false) {}
664 FrameBuffer(ui32_t size) :
665 m_FrameType(FRAME_U), m_TemporalOffset(0),
666 m_ClosedGOP(false), m_GOPStart(false)
671 virtual ~FrameBuffer() {}
673 // Sets the MPEG frame type of the picture data in the frame buffer.
674 inline void FrameType(FrameType_t type) { m_FrameType = type; }
676 // Returns the MPEG frame type of the picture data in the frame buffer.
677 inline FrameType_t FrameType() const { return m_FrameType; }
679 // Sets the MPEG temporal offset of the picture data in the frame buffer.
680 inline void TemporalOffset(ui8_t offset) { m_TemporalOffset = offset; }
682 // Returns the MPEG temporal offset of the picture data in the frame buffer.
683 inline ui8_t TemporalOffset() const { return m_TemporalOffset; }
685 // Sets the MPEG GOP 'start' attribute for the frame buffer.
686 inline void GOPStart(bool start) { m_GOPStart = start; }
688 // True if the frame in the buffer is the first in the GOP (in transport order)
689 inline bool GOPStart() const { return m_GOPStart; }
691 // Sets the MPEG GOP 'closed' attribute for the frame buffer.
692 inline void ClosedGOP(bool closed) { m_ClosedGOP = closed; }
694 // Returns true if the frame in the buffer is from a closed GOP, false if
695 // the frame is from an open GOP. Always returns false unless GOPStart()
697 inline bool ClosedGOP() const { return m_ClosedGOP; }
699 // Print object state to stream, include n bytes of frame data if indicated.
700 // Default stream is stderr.
701 void Dump(FILE* = 0, ui32_t dump_len = 0) const;
705 // An object which opens and reads an MPEG2 Video Elementary Stream file. The call to
706 // OpenRead() reads metadata from the file and populates an internal VideoDescriptor object.
707 // Each subsequent call to ReadFrame() reads exactly one frame from the stream into the
708 // given FrameBuffer object.
712 mem_ptr<h__Parser> m_Parser;
713 ASDCP_NO_COPY_CONSTRUCT(Parser);
719 // Opens the stream for reading, parses enough data to provide a complete
720 // set of stream metadata for the MXFWriter below.
721 Result_t OpenRead(const std::string& filename) const;
723 // Fill a VideoDescriptor struct with the values from the file's header.
724 // Returns RESULT_INIT if the file is not open.
725 Result_t FillVideoDescriptor(VideoDescriptor&) const;
727 // Rewind the stream to the beginning.
728 Result_t Reset() const;
730 // Reads the next sequential frame in the input file and places it in the
731 // frame buffer. Fails if the buffer is too small or the stream is empty.
732 // The frame buffer's PlaintextOffset parameter will be set to the first
733 // data byte of the first slice. Set this value to zero if you want
734 // encrypted headers.
735 Result_t ReadFrame(FrameBuffer&) const;
738 // A class which creates and writes MPEG frame data to an AS-DCP format MXF file.
739 // Not yet implemented
743 mem_ptr<h__Writer> m_Writer;
744 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
748 virtual ~MXFWriter();
750 // Warning: direct manipulation of MXF structures can interfere
751 // with the normal operation of the wrapper. Caveat emptor!
752 virtual MXF::OP1aHeader& OP1aHeader();
753 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
754 virtual MXF::RIP& RIP();
756 // Open the file for writing. The file must not exist. Returns error if
757 // the operation cannot be completed or if nonsensical data is discovered
758 // in the essence descriptor.
759 Result_t OpenWrite(const std::string& filename, const WriterInfo&,
760 const VideoDescriptor&, ui32_t HeaderSize = 16384);
762 // Writes a frame of essence to the MXF file. If the optional AESEncContext
763 // argument is present, the essence is encrypted prior to writing.
764 // Fails if the file is not open, is finalized, or an operating system
766 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
768 // Closes the MXF file, writing the index and revised header.
772 // A class which reads MPEG frame data from an AS-DCP format MXF file.
776 mem_ptr<h__Reader> m_Reader;
777 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
781 virtual ~MXFReader();
783 // Warning: direct manipulation of MXF structures can interfere
784 // with the normal operation of the wrapper. Caveat emptor!
785 virtual MXF::OP1aHeader& OP1aHeader();
786 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
787 virtual MXF::RIP& RIP();
789 // Open the file for reading. The file must exist. Returns error if the
790 // operation cannot be completed.
791 Result_t OpenRead(const std::string& filename) const;
793 // Returns RESULT_INIT if the file is not open.
794 Result_t Close() const;
796 // Fill a VideoDescriptor struct with the values from the file's header.
797 // Returns RESULT_INIT if the file is not open.
798 Result_t FillVideoDescriptor(VideoDescriptor&) const;
800 // Fill a WriterInfo struct with the values from the file's header.
801 // Returns RESULT_INIT if the file is not open.
802 Result_t FillWriterInfo(WriterInfo&) const;
804 // Reads a frame of essence from the MXF file. If the optional AESEncContext
805 // argument is present, the essence is decrypted after reading. If the MXF
806 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
807 // will contain the ciphertext frame data. If the HMACContext argument is
808 // not NULL, the HMAC will be calculated (if the file supports it).
809 // Returns RESULT_INIT if the file is not open, failure if the frame number is
810 // out of range, or if optional decrypt or HAMC operations fail.
811 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
813 // Using the index table read from the footer partition, lookup the frame number
814 // and return the offset into the file at which to read that frame of essence.
815 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
817 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
819 // Calculates the first frame in transport order of the GOP in which the requested
820 // frame is located. Calls ReadFrame() to fetch the frame at the calculated position.
821 // Returns RESULT_INIT if the file is not open.
822 Result_t ReadFrameGOPStart(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
824 // Calculates the first frame in transport order of the GOP in which the requested
825 // frame is located. Sets key_frame_number to the number of the frame at the calculated position.
826 // Returns RESULT_INIT if the file is not open.
827 Result_t FindFrameGOPStart(ui32_t frame_number, ui32_t& key_frame_number) const;
829 // Returns the type of the frame at the given position.
830 // Returns RESULT_INIT if the file is not open or RESULT_RANGE if the index is out of range.
831 Result_t FrameType(ui32_t frame_number, FrameType_t&) const;
833 // Print debugging information to stream
834 void DumpHeaderMetadata(FILE* = 0) const;
835 void DumpIndex(FILE* = 0) const;
839 //---------------------------------------------------------------------------------
846 // The default value of the ChannelFormat element of the AudioDescriptor struct
847 // is CF_NONE. If the value is set to one of the other ChannelFormat_t enum
848 // values, the file's Wave Audio Descriptor will contain a Channel Assignment
851 // The channel format should be one of (CF_CFG_1, CF_CFG_2, or CF_CFG_3) for
852 // SMPTE 429-2 files. It should normally be CF_NONE for JPEG Interop files, but
853 // the 429-2 may also be used.
855 enum ChannelFormat_t {
857 CF_CFG_1, // 5.1 with optional HI/VI
858 CF_CFG_2, // 6.1 (5.1 + center surround) with optional HI/VI
859 CF_CFG_3, // 7.1 (SDDS) with optional HI/VI
860 CF_CFG_4, // Wild Track Format
861 CF_CFG_5, // 7.1 DS with optional HI/VI
862 CF_CFG_6, // ST 377-4 (MCA) labels (see also ASDCP::MXF::decode_mca_string)
866 struct AudioDescriptor
868 Rational EditRate; // rate of frame wrapping
869 Rational AudioSamplingRate; // rate of audio sample
871 ui32_t ChannelCount; // number of channels
872 ui32_t QuantizationBits; // number of bits per single-channel sample
873 ui32_t BlockAlign; // number of bytes ber sample, all channels
875 ui32_t LinkedTrackID; //
876 ui32_t ContainerDuration; // number of frames
877 ChannelFormat_t ChannelFormat; // audio channel arrangement
880 // Print AudioDescriptor to std::ostream
881 std::ostream& operator << (std::ostream& strm, const AudioDescriptor& adesc);
882 // Print debugging information to stream (stderr default)
883 void AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
885 // Returns size in bytes of a single sample of data described by ADesc
886 inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
888 return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
891 // Returns number of samples per frame of data described by ADesc
892 inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
894 double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
895 return (ui32_t)ceil(tmpd);
898 // Returns the size in bytes of a frame of data described by ADesc
899 inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
901 return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
905 class FrameBuffer : public ASDCP::FrameBuffer
909 FrameBuffer(ui32_t size) { Capacity(size); }
910 virtual ~FrameBuffer() {}
912 // Print debugging information to stream (stderr default)
913 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
916 // An object which opens and reads a WAV file. The call to OpenRead() reads metadata from
917 // the file and populates an internal AudioDescriptor object. Each subsequent call to
918 // ReadFrame() reads exactly one frame from the stream into the given FrameBuffer object.
919 // A "frame" is either 2000 or 2002 samples, depending upon the value of PictureRate.
923 mem_ptr<h__WAVParser> m_Parser;
924 ASDCP_NO_COPY_CONSTRUCT(WAVParser);
928 virtual ~WAVParser();
930 // Opens the stream for reading, parses enough data to provide a complete
931 // set of stream metadata for the MXFWriter below. PictureRate controls
932 // ther frame rate for the MXF frame wrapping option.
933 Result_t OpenRead(const std::string& filename, const Rational& PictureRate) const;
935 // Fill an AudioDescriptor struct with the values from the file's header.
936 // Returns RESULT_INIT if the file is not open.
937 Result_t FillAudioDescriptor(AudioDescriptor&) const;
939 // Rewind the stream to the beginning.
940 Result_t Reset() const;
942 // Reads the next sequential frame in the input file and places it in the
943 // frame buffer. Fails if the buffer is too small or the stream is empty.
944 Result_t ReadFrame(FrameBuffer&) const;
952 mem_ptr<h__Writer> m_Writer;
953 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
957 virtual ~MXFWriter();
959 // Warning: direct manipulation of MXF structures can interfere
960 // with the normal operation of the wrapper. Caveat emptor!
961 virtual MXF::OP1aHeader& OP1aHeader();
962 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
963 virtual MXF::RIP& RIP();
965 // Open the file for writing. The file must not exist. Returns error if
966 // the operation cannot be completed or if nonsensical data is discovered
967 // in the essence descriptor.
968 Result_t OpenWrite(const std::string& filename, const WriterInfo&,
969 const AudioDescriptor&, ui32_t HeaderSize = 16384);
971 // Writes a frame of essence to the MXF file. If the optional AESEncContext
972 // argument is present, the essence is encrypted prior to writing.
973 // Fails if the file is not open, is finalized, or an operating system
975 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
977 // Closes the MXF file, writing the index and revised header.
985 mem_ptr<h__Reader> m_Reader;
986 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
990 virtual ~MXFReader();
992 // Warning: direct manipulation of MXF structures can interfere
993 // with the normal operation of the wrapper. Caveat emptor!
994 virtual MXF::OP1aHeader& OP1aHeader();
995 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
996 virtual MXF::RIP& RIP();
998 // Open the file for reading. The file must exist. Returns error if the
999 // operation cannot be completed.
1000 Result_t OpenRead(const std::string& filename) const;
1002 // Returns RESULT_INIT if the file is not open.
1003 Result_t Close() const;
1005 // Fill an AudioDescriptor struct with the values from the file's header.
1006 // Returns RESULT_INIT if the file is not open.
1007 Result_t FillAudioDescriptor(AudioDescriptor&) const;
1009 // Fill a WriterInfo struct with the values from the file's header.
1010 // Returns RESULT_INIT if the file is not open.
1011 Result_t FillWriterInfo(WriterInfo&) const;
1013 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1014 // argument is present, the essence is decrypted after reading. If the MXF
1015 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1016 // will contain the ciphertext frame data. If the HMACContext argument is
1017 // not NULL, the HMAC will be calculated (if the file supports it).
1018 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1019 // out of range, or if optional decrypt or HAMC operations fail.
1020 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1022 // Using the index table read from the footer partition, lookup the frame number
1023 // and return the offset into the file at which to read that frame of essence.
1024 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1026 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1028 // Print debugging information to stream
1029 void DumpHeaderMetadata(FILE* = 0) const;
1030 void DumpIndex(FILE* = 0) const;
1034 //---------------------------------------------------------------------------------
1038 const ui32_t MaxComponents = 3;
1039 const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
1040 const ui32_t MaxDefaults = 256; // made up
1043 struct ImageComponent_t // ISO 15444-1 Annex A.5.1
1050 struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
1056 ui8_t ProgressionOrder;
1057 ui8_t NumberOfLayers[sizeof(ui16_t)];
1058 ui8_t MultiCompTransform;
1063 ui8_t DecompositionLevels;
1064 ui8_t CodeblockWidth;
1065 ui8_t CodeblockHeight;
1066 ui8_t CodeblockStyle;
1067 ui8_t Transformation;
1068 ui8_t PrecinctSize[MaxPrecincts];
1072 struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
1075 ui8_t SPqcd[MaxDefaults];
1080 struct PictureDescriptor
1083 ui32_t ContainerDuration;
1084 Rational SampleRate;
1086 ui32_t StoredHeight;
1087 Rational AspectRatio;
1098 ImageComponent_t ImageComponents[MaxComponents];
1099 CodingStyleDefault_t CodingStyleDefault;
1100 QuantizationDefault_t QuantizationDefault;
1103 // Print debugging information to std::ostream
1104 std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
1105 // Print debugging information to stream (stderr default)
1106 void PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
1109 class FrameBuffer : public ASDCP::FrameBuffer
1113 FrameBuffer(ui32_t size) { Capacity(size); }
1114 virtual ~FrameBuffer() {}
1116 // Print debugging information to stream (stderr default)
1117 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1121 // An object which opens and reads a JPEG 2000 codestream file. The file is expected
1122 // to contain exactly one complete frame of picture essence as an unwrapped (raw)
1123 // ISO/IEC 15444 codestream.
1124 class CodestreamParser
1126 class h__CodestreamParser;
1127 mem_ptr<h__CodestreamParser> m_Parser;
1128 ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
1132 virtual ~CodestreamParser();
1134 // Opens a file for reading, parses enough data to provide a complete
1135 // set of stream metadata for the MXFWriter below.
1136 // The frame buffer's PlaintextOffset parameter will be set to the first
1137 // byte of the data segment. Set this value to zero if you want
1138 // encrypted headers.
1139 Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
1141 // Fill a PictureDescriptor struct with the values from the file's codestream.
1142 // Returns RESULT_INIT if the file is not open.
1143 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1146 // Parses the data in the frame buffer to fill in the picture descriptor. Copies
1147 // the offset of the image data into start_of_data. Returns error if the parser fails.
1148 Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
1150 // An object which reads a sequence of files containing JPEG 2000 pictures.
1151 class SequenceParser
1153 class h__SequenceParser;
1154 mem_ptr<h__SequenceParser> m_Parser;
1155 ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1159 virtual ~SequenceParser();
1161 // Opens a directory for reading. The directory is expected to contain one or
1162 // more files, each containing the codestream for exactly one picture. The
1163 // files must be named such that the frames are in temporal order when sorted
1164 // alphabetically by filename. The parser will automatically parse enough data
1165 // from the first file to provide a complete set of stream metadata for the
1166 // MXFWriter below. If the "pedantic" parameter is given and is true, the
1167 // parser will check the metadata for each codestream and fail if a
1168 // mismatch is detected.
1169 Result_t OpenRead(const std::string& filename, bool pedantic = false) const;
1171 // Opens a file sequence for reading. The sequence is expected to contain one or
1172 // more filenames, each naming a file containing the codestream for exactly one
1173 // picture. The parser will automatically parse enough data
1174 // from the first file to provide a complete set of stream metadata for the
1175 // MXFWriter below. If the "pedantic" parameter is given and is true, the
1176 // parser will check the metadata for each codestream and fail if a
1177 // mismatch is detected.
1178 Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic = false) const;
1180 // Fill a PictureDescriptor struct with the values from the first file's codestream.
1181 // Returns RESULT_INIT if the directory is not open.
1182 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1184 // Rewind the directory to the beginning.
1185 Result_t Reset() const;
1187 // Reads the next sequential frame in the directory and places it in the
1188 // frame buffer. Fails if the buffer is too small or the direcdtory
1189 // contains no more files.
1190 // The frame buffer's PlaintextOffset parameter will be set to the first
1191 // byte of the data segment. Set this value to zero if you want
1192 // encrypted headers.
1193 Result_t ReadFrame(FrameBuffer&) const;
1201 mem_ptr<h__Writer> m_Writer;
1202 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1206 virtual ~MXFWriter();
1208 // Warning: direct manipulation of MXF structures can interfere
1209 // with the normal operation of the wrapper. Caveat emptor!
1210 virtual MXF::OP1aHeader& OP1aHeader();
1211 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1212 virtual MXF::RIP& RIP();
1214 // Open the file for writing. The file must not exist. Returns error if
1215 // the operation cannot be completed or if nonsensical data is discovered
1216 // in the essence descriptor.
1217 Result_t OpenWrite(const std::string& filename, const WriterInfo&,
1218 const PictureDescriptor&, ui32_t HeaderSize = 16384);
1220 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1221 // argument is present, the essence is encrypted prior to writing.
1222 // Fails if the file is not open, is finalized, or an operating system
1224 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1226 // Closes the MXF file, writing the index and revised header.
1227 Result_t Finalize();
1234 mem_ptr<h__Reader> m_Reader;
1235 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1239 virtual ~MXFReader();
1241 // Warning: direct manipulation of MXF structures can interfere
1242 // with the normal operation of the wrapper. Caveat emptor!
1243 virtual MXF::OP1aHeader& OP1aHeader();
1244 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1245 virtual MXF::RIP& RIP();
1247 // Open the file for reading. The file must exist. Returns error if the
1248 // operation cannot be completed.
1249 Result_t OpenRead(const std::string& filename) const;
1251 // Returns RESULT_INIT if the file is not open.
1252 Result_t Close() const;
1254 // Fill an AudioDescriptor struct with the values from the file's header.
1255 // Returns RESULT_INIT if the file is not open.
1256 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1258 // Fill a WriterInfo struct with the values from the file's header.
1259 // Returns RESULT_INIT if the file is not open.
1260 Result_t FillWriterInfo(WriterInfo&) const;
1262 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1263 // argument is present, the essence is decrypted after reading. If the MXF
1264 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1265 // will contain the ciphertext frame data. If the HMACContext argument is
1266 // not NULL, the HMAC will be calculated (if the file supports it).
1267 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1268 // out of range, or if optional decrypt or HAMC operations fail.
1269 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1271 // Using the index table read from the footer partition, lookup the frame number
1272 // and return the offset into the file at which to read that frame of essence.
1273 // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
1275 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1277 // Print debugging information to stream
1278 void DumpHeaderMetadata(FILE* = 0) const;
1279 void DumpIndex(FILE* = 0) const;
1283 // Stereoscopic Image support
1286 enum StereoscopicPhase_t
1294 JP2K::FrameBuffer Left;
1295 JP2K::FrameBuffer Right;
1297 SFrameBuffer(ui32_t size) {
1298 Left.Capacity(size);
1299 Right.Capacity(size);
1306 mem_ptr<h__SWriter> m_Writer;
1307 ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
1311 virtual ~MXFSWriter();
1313 // Warning: direct manipulation of MXF structures can interfere
1314 // with the normal operation of the wrapper. Caveat emptor!
1315 virtual MXF::OP1aHeader& OP1aHeader();
1316 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1317 virtual MXF::RIP& RIP();
1319 // Open the file for writing. The file must not exist. Returns error if
1320 // the operation cannot be completed or if nonsensical data is discovered
1321 // in the essence descriptor.
1322 Result_t OpenWrite(const std::string& filename, const WriterInfo&,
1323 const PictureDescriptor&, ui32_t HeaderSize = 16384);
1325 // Writes a pair of frames of essence to the MXF file. If the optional AESEncContext
1326 // argument is present, the essence is encrypted prior to writing.
1327 // Fails if the file is not open, is finalized, or an operating system
1329 Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1331 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1332 // argument is present, the essence is encrypted prior to writing.
1333 // Fails if the file is not open, is finalized, or an operating system
1334 // error occurs. Frames must be written in the proper phase (L-R-L-R),
1335 // RESULT_SPHASE will be returned if phase is reversed. The first frame
1336 // written must be left eye.
1337 Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
1338 AESEncContext* = 0, HMACContext* = 0);
1340 // Closes the MXF file, writing the index and revised header. Returns
1341 // RESULT_SPHASE if WriteFrame was called an odd number of times.
1342 Result_t Finalize();
1349 mem_ptr<h__SReader> m_Reader;
1350 ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
1354 virtual ~MXFSReader();
1356 // Warning: direct manipulation of MXF structures can interfere
1357 // with the normal operation of the wrapper. Caveat emptor!
1358 virtual MXF::OP1aHeader& OP1aHeader();
1359 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1360 virtual MXF::RIP& RIP();
1362 // Open the file for reading. The file must exist. Returns error if the
1363 // operation cannot be completed.
1364 Result_t OpenRead(const std::string& filename) const;
1366 // Returns RESULT_INIT if the file is not open.
1367 Result_t Close() const;
1369 // Fill an AudioDescriptor struct with the values from the file's header.
1370 // Returns RESULT_INIT if the file is not open.
1371 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1373 // Fill a WriterInfo struct with the values from the file's header.
1374 // Returns RESULT_INIT if the file is not open.
1375 Result_t FillWriterInfo(WriterInfo&) const;
1377 // Reads a pair of frames of essence from the MXF file. If the optional AESEncContext
1378 // argument is present, the essence is decrypted after reading. If the MXF
1379 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1380 // will contain the ciphertext frame data. If the HMACContext argument is
1381 // not NULL, the HMAC will be calculated (if the file supports it).
1382 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1383 // out of range, or if optional decrypt or HAMC operations fail.
1384 Result_t ReadFrame(ui32_t frame_number, SFrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1386 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1387 // argument is present, the essence is decrypted after reading. If the MXF
1388 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1389 // will contain the ciphertext frame data. If the HMACContext argument is
1390 // not NULL, the HMAC will be calculated (if the file supports it).
1391 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1392 // out of range, or if optional decrypt or HAMC operations fail.
1393 Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
1394 FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1396 // Using the index table read from the footer partition, lookup the frame number
1397 // and return the offset into the file at which to read that frame of essence.
1398 // Returns RESULT_INIT if the file is not open, and RESULT_FRAME if the frame number is
1400 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1402 // Print debugging information to stream
1403 void DumpHeaderMetadata(FILE* = 0) const;
1404 void DumpIndex(FILE* = 0) const;
1408 //---------------------------------------------------------------------------------
1412 enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
1414 struct TimedTextResourceDescriptor
1416 byte_t ResourceID[UUIDlen];
1419 TimedTextResourceDescriptor() : Type(MT_BIN) {}
1422 typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
1424 struct TimedTextDescriptor
1426 Rational EditRate; //
1427 ui32_t ContainerDuration;
1428 byte_t AssetID[UUIDlen];
1429 std::string NamespaceName;
1430 std::string EncodingName;
1431 ResourceList_t ResourceList;
1433 TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8
1436 // Print debugging information to std::ostream
1437 std::ostream& operator << (std::ostream& strm, const TimedTextDescriptor& tinfo);
1438 // Print debugging information to stream (stderr default)
1439 void DescriptorDump(const TimedTextDescriptor&, FILE* = 0);
1442 class FrameBuffer : public ASDCP::FrameBuffer
1444 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
1447 byte_t m_AssetID[UUIDlen];
1448 std::string m_MIMEType;
1451 FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
1452 FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
1453 virtual ~FrameBuffer() {}
1455 inline const byte_t* AssetID() const { return m_AssetID; }
1456 inline void AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); }
1457 inline const char* MIMEType() const { return m_MIMEType.c_str(); }
1458 inline void MIMEType(const std::string& s) { m_MIMEType = s; }
1460 // Print debugging information to stream (stderr default)
1461 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1464 // An abstract base for a lookup service that returns the resource data
1465 // identified by the given ancillary resource id.
1467 class IResourceResolver
1470 virtual ~IResourceResolver() {}
1471 virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
1474 // Resolves resource references by testing the named directory for file names containing
1475 // the respective UUID.
1477 class LocalFilenameResolver : public ASDCP::TimedText::IResourceResolver
1479 std::string m_Dirname;
1480 ASDCP_NO_COPY_CONSTRUCT(LocalFilenameResolver);
1483 LocalFilenameResolver();
1484 Result_t OpenRead(const std::string& dirname);
1485 Result_t ResolveRID(const byte_t* uuid, FrameBuffer& FrameBuf) const;
1489 class DCSubtitleParser
1491 class h__SubtitleParser;
1492 mem_ptr<h__SubtitleParser> m_Parser;
1493 ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
1497 virtual ~DCSubtitleParser();
1499 // Opens an XML file for reading, parses data to provide a complete
1500 // set of stream metadata for the MXFWriter below.
1501 Result_t OpenRead(const std::string& filename) const;
1503 // Parses an XML document to provide a complete set of stream metadata
1504 // for the MXFWriter below. The optional filename argument is used to
1505 // initialize the default resource resolver (see ReadAncillaryResource).
1506 Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const;
1508 // Fill a TimedTextDescriptor struct with the values from the file's contents.
1509 // Returns RESULT_INIT if the file is not open.
1510 Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1512 // Reads the complete Timed Text Resource into the given string.
1513 Result_t ReadTimedTextResource(std::string&) const;
1515 // Reads the Ancillary Resource having the given ID. Fails if the buffer
1516 // is too small or the resource does not exist. The optional Resolver
1517 // argument can be provided which will be used to retrieve the resource
1518 // having a particulat UUID. If a Resolver is not supplied, the default
1519 // internal resolver will return the contents of the file having the UUID
1520 // as the filename. The filename must exist in the same directory as the
1521 // XML file opened with OpenRead().
1522 Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
1523 const IResourceResolver* Resolver = 0) const;
1530 mem_ptr<h__Writer> m_Writer;
1531 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1535 virtual ~MXFWriter();
1537 // Warning: direct manipulation of MXF structures can interfere
1538 // with the normal operation of the wrapper. Caveat emptor!
1539 virtual MXF::OP1aHeader& OP1aHeader();
1540 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1541 virtual MXF::RIP& RIP();
1543 // Open the file for writing. The file must not exist. Returns error if
1544 // the operation cannot be completed or if nonsensical data is discovered
1545 // in the essence descriptor.
1546 Result_t OpenWrite(const std::string& filename, const WriterInfo&,
1547 const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
1549 // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
1550 // encoded. If the optional AESEncContext argument is present, the essence
1551 // is encrypted prior to writing. Fails if the file is not open, is finalized,
1552 // or an operating system error occurs.
1553 // This method may only be called once, and it must be called before any
1554 // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
1555 // conditions are not met.
1556 Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
1558 // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
1559 // argument is present, the essence is encrypted prior to writing.
1560 // Fails if the file is not open, is finalized, or an operating system
1561 // error occurs. RESULT_STATE will be returned if the method is called before
1562 // WriteTimedTextResource()
1563 Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1565 // Closes the MXF file, writing the index and revised header.
1566 Result_t Finalize();
1573 mem_ptr<h__Reader> m_Reader;
1574 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1578 virtual ~MXFReader();
1580 // Warning: direct manipulation of MXF structures can interfere
1581 // with the normal operation of the wrapper. Caveat emptor!
1582 virtual MXF::OP1aHeader& OP1aHeader();
1583 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1584 virtual MXF::RIP& RIP();
1586 // Open the file for reading. The file must exist. Returns error if the
1587 // operation cannot be completed.
1588 Result_t OpenRead(const std::string& filename) const;
1590 // Returns RESULT_INIT if the file is not open.
1591 Result_t Close() const;
1593 // Fill a TimedTextDescriptor struct with the values from the file's header.
1594 // Returns RESULT_INIT if the file is not open.
1595 Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1597 // Fill a WriterInfo struct with the values from the file's header.
1598 // Returns RESULT_INIT if the file is not open.
1599 Result_t FillWriterInfo(WriterInfo&) const;
1601 // Reads the complete Timed Text Resource into the given string. Fails if the resource
1602 // is encrypted and AESDecContext is NULL (use the following method to retrieve the
1603 // raw ciphertet block).
1604 Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
1606 // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
1607 // argument is present, the resource is decrypted after reading. If the MXF
1608 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1609 // will contain the ciphertext frame data. If the HMACContext argument is
1610 // not NULL, the HMAC will be calculated (if the file supports it).
1611 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1612 // out of range, or if optional decrypt or HAMC operations fail.
1613 Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1615 // Reads the timed-text resource having the given UUID from the MXF file. If the
1616 // optional AESEncContext argument is present, the resource is decrypted after
1617 // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
1618 // the frame buffer will contain the ciphertext frame data. If the HMACContext
1619 // argument is not NULL, the HMAC will be calculated (if the file supports it).
1620 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1621 // out of range, or if optional decrypt or HAMC operations fail.
1622 Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1624 // Print debugging information to stream
1625 void DumpHeaderMetadata(FILE* = 0) const;
1626 void DumpIndex(FILE* = 0) const;
1628 } // namespace TimedText
1630 //---------------------------------------------------------------------------------
1634 struct DCDataDescriptor
1636 Rational EditRate; // Sample rate
1637 ui32_t ContainerDuration; // number of frames
1638 byte_t AssetID[UUIDlen]; // The UUID for the DCData track
1639 byte_t DataEssenceCoding[UUIDlen]; // The coding for the data carried
1642 // Print DCDataDescriptor to std::ostream
1643 std::ostream& operator << (std::ostream& strm, const DCDataDescriptor& ddesc);
1644 // Print debugging information to stream (stderr default)
1645 void DCDataDescriptorDump(const DCDataDescriptor&, FILE* = 0);
1648 class FrameBuffer : public ASDCP::FrameBuffer
1652 FrameBuffer(ui32_t size) { Capacity(size); }
1653 virtual ~FrameBuffer() {}
1655 // Print debugging information to stream (stderr default)
1656 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1659 // An object which opens and reads a DC Data file. The file is expected
1660 // to contain exactly one complete frame of DC data essence as an unwrapped (raw)
1662 class BytestreamParser
1664 class h__BytestreamParser;
1665 mem_ptr<h__BytestreamParser> m_Parser;
1666 ASDCP_NO_COPY_CONSTRUCT(BytestreamParser);
1670 virtual ~BytestreamParser();
1672 // Opens a file for reading, parses enough data to provide a complete
1673 // set of stream metadata for the MXFWriter below.
1674 // The frame buffer's PlaintextOffset parameter will be set to the first
1675 // byte of the data segment. Set this value to zero if you want
1676 // encrypted headers.
1677 Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const;
1679 // Fill a DCDataDescriptor struct with the values from the file's bytestream.
1680 // Returns RESULT_INIT if the file is not open.
1681 Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1684 // An object which reads a sequence of files containing DC Data.
1685 class SequenceParser
1687 class h__SequenceParser;
1688 mem_ptr<h__SequenceParser> m_Parser;
1689 ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1693 virtual ~SequenceParser();
1695 // Opens a directory for reading. The directory is expected to contain one or
1696 // more files, each containing the bytestream for exactly one frame. The files
1697 // must be named such that the frames are in temporal order when sorted
1698 // alphabetically by filename.
1699 Result_t OpenRead(const std::string& filename) const;
1701 // Opens a file sequence for reading. The sequence is expected to contain one or
1702 // more filenames, each naming a file containing the bytestream for exactly one
1704 Result_t OpenRead(const std::list<std::string>& file_list) const;
1706 // Fill a DCDataDescriptor struct with default values.
1707 // Returns RESULT_INIT if the directory is not open.
1708 Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1710 // Rewind the directory to the beginning.
1711 Result_t Reset() const;
1713 // Reads the next sequential frame in the directory and places it in the
1714 // frame buffer. Fails if the buffer is too small or the direcdtory
1715 // contains no more files.
1716 // The frame buffer's PlaintextOffset parameter will be set to the first
1717 // byte of the data segment. Set this value to zero if you want
1718 // encrypted headers.
1719 Result_t ReadFrame(FrameBuffer&) const;
1726 mem_ptr<h__Writer> m_Writer;
1727 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1731 virtual ~MXFWriter();
1733 // Warning: direct manipulation of MXF structures can interfere
1734 // with the normal operation of the wrapper. Caveat emptor!
1735 virtual MXF::OP1aHeader& OP1aHeader();
1736 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1737 virtual MXF::RIP& RIP();
1739 // Open the file for writing. The file must not exist. Returns error if
1740 // the operation cannot be completed or if nonsensical data is discovered
1741 // in the essence descriptor.
1742 Result_t OpenWrite(const std::string& filename, const WriterInfo&,
1743 const DCDataDescriptor&, ui32_t HeaderSize = 16384);
1745 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1746 // argument is present, the essence is encrypted prior to writing.
1747 // Fails if the file is not open, is finalized, or an operating system
1749 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1751 // Closes the MXF file, writing the index and revised header.
1752 Result_t Finalize();
1759 mem_ptr<h__Reader> m_Reader;
1760 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1764 virtual ~MXFReader();
1766 // Warning: direct manipulation of MXF structures can interfere
1767 // with the normal operation of the wrapper. Caveat emptor!
1768 virtual MXF::OP1aHeader& OP1aHeader();
1769 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1770 virtual MXF::RIP& RIP();
1772 // Open the file for reading. The file must exist. Returns error if the
1773 // operation cannot be completed.
1774 Result_t OpenRead(const std::string& filename) const;
1776 // Returns RESULT_INIT if the file is not open.
1777 Result_t Close() const;
1779 // Fill a DCDataDescriptor struct with the values from the file's header.
1780 // Returns RESULT_INIT if the file is not open.
1781 Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1783 // Fill a WriterInfo struct with the values from the file's header.
1784 // Returns RESULT_INIT if the file is not open.
1785 Result_t FillWriterInfo(WriterInfo&) const;
1787 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1788 // argument is present, the essence is decrypted after reading. If the MXF
1789 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1790 // will contain the ciphertext frame data. If the HMACContext argument is
1791 // not NULL, the HMAC will be calculated (if the file supports it).
1792 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1793 // out of range, or if optional decrypt or HAMC operations fail.
1794 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1796 // Using the index table read from the footer partition, lookup the frame number
1797 // and return the offset into the file at which to read that frame of essence.
1798 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1800 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1802 // Print debugging information to stream
1803 void DumpHeaderMetadata(FILE* = 0) const;
1804 void DumpIndex(FILE* = 0) const;
1807 } // namespace DCData
1809 //---------------------------------------------------------------------------------
1813 struct AtmosDescriptor : public DCData::DCDataDescriptor
1815 ui32_t FirstFrame; // Frame number of the frame to align with the FFOA of the picture track
1816 ui16_t MaxChannelCount; // Max number of channels in bitstream
1817 ui16_t MaxObjectCount; // Max number of objects in bitstream
1818 byte_t AtmosID[UUIDlen]; // UUID of Atmos Project
1819 ui8_t AtmosVersion; // ATMOS Coder Version used to create bitstream
1822 // Print AtmosDescriptor to std::ostream
1823 std::ostream& operator << (std::ostream& strm, const AtmosDescriptor& adesc);
1824 // Print debugging information to stream (stderr default)
1825 void AtmosDescriptorDump(const AtmosDescriptor&, FILE* = 0);
1826 // Determine if a file is a raw atmos file
1827 bool IsDolbyAtmos(const std::string& filename);
1834 mem_ptr<h__Writer> m_Writer;
1835 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1839 virtual ~MXFWriter();
1841 // Warning: direct manipulation of MXF structures can interfere
1842 // with the normal operation of the wrapper. Caveat emptor!
1843 virtual MXF::OP1aHeader& OP1aHeader();
1844 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1845 virtual MXF::RIP& RIP();
1847 // Open the file for writing. The file must not exist. Returns error if
1848 // the operation cannot be completed or if nonsensical data is discovered
1849 // in the essence descriptor.
1850 Result_t OpenWrite(const std::string& filename, const WriterInfo&,
1851 const AtmosDescriptor&, ui32_t HeaderSize = 16384);
1853 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1854 // argument is present, the essence is encrypted prior to writing.
1855 // Fails if the file is not open, is finalized, or an operating system
1857 Result_t WriteFrame(const DCData::FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1859 // Closes the MXF file, writing the index and revised header.
1860 Result_t Finalize();
1867 mem_ptr<h__Reader> m_Reader;
1868 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1872 virtual ~MXFReader();
1874 // Warning: direct manipulation of MXF structures can interfere
1875 // with the normal operation of the wrapper. Caveat emptor!
1876 virtual MXF::OP1aHeader& OP1aHeader();
1877 virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1878 virtual MXF::RIP& RIP();
1880 // Open the file for reading. The file must exist. Returns error if the
1881 // operation cannot be completed.
1882 Result_t OpenRead(const std::string& filename) const;
1884 // Returns RESULT_INIT if the file is not open.
1885 Result_t Close() const;
1887 // Fill an AtmosDescriptor struct with the values from the file's header.
1888 // Returns RESULT_INIT if the file is not open.
1889 Result_t FillAtmosDescriptor(AtmosDescriptor&) const;
1891 // Fill a WriterInfo struct with the values from the file's header.
1892 // Returns RESULT_INIT if the file is not open.
1893 Result_t FillWriterInfo(WriterInfo&) const;
1895 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1896 // argument is present, the essence is decrypted after reading. If the MXF
1897 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1898 // will contain the ciphertext frame data. If the HMACContext argument is
1899 // not NULL, the HMAC will be calculated (if the file supports it).
1900 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1901 // out of range, or if optional decrypt or HAMC operations fail.
1902 Result_t ReadFrame(ui32_t frame_number, DCData::FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1904 // Using the index table read from the footer partition, lookup the frame number
1905 // and return the offset into the file at which to read that frame of essence.
1906 // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1908 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1910 // Print debugging information to stream
1911 void DumpHeaderMetadata(FILE* = 0) const;
1912 void DumpIndex(FILE* = 0) const;
1915 } // namespace ATMOS
1919 } // namespace ASDCP
1922 #endif // _AS_DCP_H_