o Added preliminary support for timed-text wrapping for AS-02. This
[asdcplib.git] / src / AS_DCP.h
1 /*
2 Copyright (c) 2003-2013, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27 /*! \file    AS_DCP.h
28     \version $Id$
29     \brief   AS-DCP library, public interface
30
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
35 be be limited to:
36
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)
54
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.
60
61 The following use cases are supported by the library:
62
63  o Write essence to a plaintext or ciphertext AS-DCP file:
64      MPEG2 Video Elementary Stream
65      JPEG 2000 codestreams
66      JPEG 2000 stereoscopic codestream pairs
67      PCM audio streams
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
71
72  o Read essence from a plaintext or ciphertext AS-DCP file:
73      MPEG2 Video Elementary Stream
74      JPEG 2000 codestreams
75      JPEG 2000 stereoscopic codestream pairs
76      PCM audio streams
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
80
81  o Read header metadata from an AS-DCP file
82
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.
88 */
89
90 #ifndef _AS_DCP_H_
91 #define _AS_DCP_H_
92
93 #include <KM_error.h>
94 #include <KM_fileio.h>
95 #include <stdio.h>
96 #include <stdarg.h>
97 #include <math.h>
98 #include <iosfwd>
99 #include <string>
100 #include <cstring>
101 #include <list>
102
103 //--------------------------------------------------------------------------------
104 // common integer types
105 // supply your own by defining ASDCP_NO_BASE_TYPES
106
107 #ifndef ASDCP_NO_BASE_TYPES
108 typedef unsigned char  byte_t;
109 typedef char           i8_t;
110 typedef unsigned char  ui8_t;
111 typedef short          i16_t;
112 typedef unsigned short ui16_t;
113 typedef int            i32_t;
114 typedef unsigned int   ui32_t;
115 #endif
116
117
118 //--------------------------------------------------------------------------------
119 // convenience macros
120
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)
124
125
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) \
129   if ( (p) == 0  ) { \
130     return ASDCP::RESULT_PTR; \
131   }
132
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'.
137 //
138 #define ASDCP_TEST_NULL_STR(p) \
139   ASDCP_TEST_NULL(p); \
140   if ( (p)[0] == '\0' ) { \
141     return ASDCP::RESULT_NULL_STR; \
142   }
143
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)   \
148           T(const T&); \
149           T& operator=(const T&)
150
151 //--------------------------------------------------------------------------------
152 // All library components are defined in the namespace ASDCP
153 //
154 namespace ASDCP {
155   //
156   // The version number declaration and explanation have moved to ../configure.ac
157   const char* Version();
158
159   // UUIDs are passed around as strings of UUIDlen bytes
160   const ui32_t UUIDlen = 16;
161
162   // Encryption keys are passed around as strings of KeyLen bytes
163   const ui32_t KeyLen = 16;
164
165   //---------------------------------------------------------------------------------
166   // return values
167
168   using Kumu::Result_t;
169
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;
188
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.");
204
205   //---------------------------------------------------------------------------------
206   // file identification
207
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.
210   enum EssenceType_t {
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
220     ESS_MAX
221   };
222
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);
227
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);
232
233
234   //---------------------------------------------------------------------------------
235   // base types
236
237   // A simple container for rational numbers.
238   class Rational
239   {
240   public:
241     i32_t Numerator;
242     i32_t Denominator;
243
244     Rational() : Numerator(0), Denominator(0) {}
245     Rational(i32_t n, i32_t d) : Numerator(n), Denominator(d) {}
246
247     inline double Quotient() const {
248       return (double)Numerator / (double)Denominator;
249     }
250
251     inline bool operator==(const Rational& rhs) const {
252       return ( rhs.Numerator == Numerator && rhs.Denominator == Denominator );
253     }
254
255     inline bool operator!=(const Rational& rhs) const {
256       return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
257     }
258
259     inline bool operator<(const Rational& rhs) {
260       if ( Numerator < rhs.Numerator )     return true;
261       if ( Numerator == rhs.Numerator && Denominator < rhs.Denominator )    return true;
262       return false;
263     }
264
265     inline bool operator>(const Rational& rhs) {
266       if ( Numerator > rhs.Numerator )     return true;
267       if ( Numerator == rhs.Numerator && Denominator > rhs.Denominator )     return true;
268       return false;
269     }
270   };
271
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);
278
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);
289
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
297
298
299   // Non-reference counting container for internal member objects.
300   // Please do not use this class for any other purpose.
301   template <class T>
302     class mem_ptr
303     {
304       T* m_p; // the thing we point to
305       mem_ptr(T&);
306
307     public:
308       mem_ptr() : m_p(0) {}
309       mem_ptr(T* p) : m_p(p) {}
310       ~mem_ptr() { delete m_p; }
311
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; }
320     };
321
322
323   //---------------------------------------------------------------------------------
324   // WriterInfo class - encapsulates writer identification details used for
325   // OpenWrite() calls.  Replace these values at runtime to identify your product.
326   //
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:
331   //
332   //   OPAtom
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
335   //
336   //   EKLV Packet:
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
339   //
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
343   //
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()
348   //
349   //
350   enum LabelSet_t
351   {
352     LS_MXF_UNKNOWN,
353     LS_MXF_INTEROP,
354     LS_MXF_SMPTE,
355     LS_MAX
356   };
357
358   //
359   struct WriterInfo
360   {
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;
371
372     WriterInfo() : EncryptedEssence(false), UsesHMAC(false), LabelSetType(LS_MXF_INTEROP)
373     {
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 };
377
378       memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
379       memset(AssetUUID, 0, UUIDlen);
380       memset(ContextID, 0, UUIDlen);
381       memset(CryptographicKeyID, 0, UUIDlen);
382
383       ProductVersion = "Unreleased ";
384       ProductVersion += Version();
385       CompanyName = "DCI";
386       ProductName = "asdcplib";
387     }
388   };
389
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);
394
395   //---------------------------------------------------------------------------------
396   // cryptographic support
397
398   // The following classes define interfaces to Rijndael contexts having the following properties:
399   //  o 16 byte key
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;
404
405   //
406   class AESEncContext
407     {
408       class h__AESContext;
409       mem_ptr<h__AESContext> m_Context;
410       ASDCP_NO_COPY_CONSTRUCT(AESEncContext);
411
412     public:
413       AESEncContext();
414       ~AESEncContext();
415
416       // Initializes Rijndael CBC encryption context.
417       // Returns error if the key argument is NULL.
418       Result_t InitKey(const byte_t* key);
419
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;
425
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);
429     };
430
431   //
432   class AESDecContext
433     {
434       class h__AESContext;
435       mem_ptr<h__AESContext> m_Context;
436       ASDCP_NO_COPY_CONSTRUCT(AESDecContext);
437
438     public:
439       AESDecContext();
440       ~AESDecContext();
441
442       // Initializes Rijndael CBC decryption context.
443       // Returns error if the key argument is NULL.
444       Result_t InitKey(const byte_t* key);
445
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);
450
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);
454     };
455
456   //
457   class HMACContext
458     {
459       class h__HMACContext;
460       mem_ptr<h__HMACContext> m_Context;
461       ASDCP_NO_COPY_CONSTRUCT(HMACContext);
462
463     public:
464       HMACContext();
465       ~HMACContext();
466
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
469       // argument is NULL.
470       Result_t InitKey(const byte_t* key, LabelSet_t);
471
472       // Reset internal state, allows repeated cycles of Update -> Finalize
473       void Reset();
474
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);
478
479       // Finalize digest.  Returns error if the digest has already been finalized.
480       Result_t Finalize();
481
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;
486
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;
491     };
492
493   //---------------------------------------------------------------------------------
494   // frame buffer base class
495   //
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.
499
500   class FrameBuffer
501     {
502       ASDCP_NO_COPY_CONSTRUCT(FrameBuffer);
503
504     protected:
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
510
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
521
522      public:
523       FrameBuffer();
524       virtual ~FrameBuffer();
525
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);
531
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);
536
537       // returns the size of the buffer
538       inline ui32_t  Capacity() const { return m_Capacity; }
539
540       // returns a const pointer to the essence data
541       inline const byte_t* RoData() const { return m_Data; }
542
543       // returns a non-const pointer to the essence data
544       inline byte_t* Data() { return m_Data; }
545
546       // set the size of the buffer's contents
547       inline ui32_t  Size(ui32_t size) { return m_Size = size; }
548
549       // returns the size of the buffer's contents
550       inline ui32_t  Size() const { return m_Size; }
551
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; }
554
555       // Returns the absolute frame number of this frame in the file in delivery order.
556       inline ui32_t  FrameNumber() const { return m_FrameNumber; }
557
558       // Sets the length of the plaintext essence data
559       inline void    SourceLength(ui32_t len) { m_SourceLength = len; }
560
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; }
565
566       // Sets the offset into the buffer at which encrypted data begins
567       inline void    PlaintextOffset(ui32_t ofst) { m_PlaintextOffset = ofst; }
568
569       // Returns offset into buffer of first byte of ciphertext.
570       inline ui32_t  PlaintextOffset() const { return m_PlaintextOffset; }
571     };
572
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
576
577   namespace MXF {
578     // #include<Metadata.h> to use these
579     class OP1aHeader;
580     class OPAtomIndexFooter;
581     class RIP;
582   };
583
584   //---------------------------------------------------------------------------------
585   // MPEG2 video elementary stream support
586
587   //
588   namespace MPEG2
589     {
590       // MPEG picture coding type
591       enum FrameType_t {
592         FRAME_U = 0x00, // Unknown
593         FRAME_I = 0x01, // I-Frame
594         FRAME_P = 0x02, // P-Frame
595         FRAME_B = 0x03  // B-Frame
596       };
597
598       // convert FrameType_t to char
599       inline char FrameTypeChar(FrameType_t type)
600         {
601           switch ( type )
602             {
603             case FRAME_I: return 'I';
604             case FRAME_B: return 'B';
605             case FRAME_P: return 'P';
606             default: return 'U';
607             }
608         }
609
610       // Structure represents the metadata elements in the file header's
611       // MPEG2VideoDescriptor object.
612       struct VideoDescriptor
613         {
614           Rational EditRate;                //
615           ui32_t   FrameRate;               //
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;        //
626           bool     LowDelay;                //
627           ui32_t   BitRate;                 //
628           ui8_t    ProfileAndLevel;         //
629           ui32_t   ContainerDuration;       //
630       };
631
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);
636
637       // A container for MPEG frame data.
638       class FrameBuffer : public ASDCP::FrameBuffer
639         {
640           ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
641
642         protected:
643           FrameType_t m_FrameType;
644           ui8_t       m_TemporalOffset;
645           bool        m_ClosedGOP;
646           bool        m_GOPStart;
647
648         public:
649           FrameBuffer() :
650             m_FrameType(FRAME_U), m_TemporalOffset(0),
651             m_ClosedGOP(false), m_GOPStart(false) {}
652
653           FrameBuffer(ui32_t size) :
654             m_FrameType(FRAME_U), m_TemporalOffset(0),
655             m_ClosedGOP(false), m_GOPStart(false)
656             {
657               Capacity(size);
658             }
659
660           virtual ~FrameBuffer() {}
661
662           // Sets the MPEG frame type of the picture data in the frame buffer.
663           inline void FrameType(FrameType_t type) { m_FrameType = type; }
664
665           // Returns the MPEG frame type of the picture data in the frame buffer.
666           inline FrameType_t FrameType() const { return m_FrameType; }
667
668           // Sets the MPEG temporal offset of the picture data in the frame buffer.
669           inline void TemporalOffset(ui8_t offset) { m_TemporalOffset = offset; }
670
671           // Returns the MPEG temporal offset of the picture data in the frame buffer.
672           inline ui8_t TemporalOffset() const { return m_TemporalOffset; }
673
674           // Sets the MPEG GOP 'start' attribute for the frame buffer.
675           inline void GOPStart(bool start) { m_GOPStart = start; }
676
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; }
679
680           // Sets the MPEG GOP 'closed' attribute for the frame buffer.
681           inline void ClosedGOP(bool closed) { m_ClosedGOP = closed; }
682
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()
685           // returns true.
686           inline bool ClosedGOP() const { return m_ClosedGOP; }
687
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;
691         };
692
693
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.
698       class Parser
699         {
700           class h__Parser;
701           mem_ptr<h__Parser> m_Parser;
702           ASDCP_NO_COPY_CONSTRUCT(Parser);
703
704         public:
705           Parser();
706           virtual ~Parser();
707
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;
711
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;
715
716           // Rewind the stream to the beginning.
717           Result_t Reset() const;
718
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;
725         };
726
727       // A class which creates and writes MPEG frame data to an AS-DCP format MXF file.
728       // Not yet implemented
729       class MXFWriter
730         {
731           class h__Writer;
732           mem_ptr<h__Writer> m_Writer;
733           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
734
735         public:
736           MXFWriter();
737           virtual ~MXFWriter();
738
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();
744
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);
750
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
754           // error occurs.
755           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
756
757           // Closes the MXF file, writing the index and revised header.
758           Result_t Finalize();
759         };
760
761       // A class which reads MPEG frame data from an AS-DCP format MXF file.
762       class MXFReader
763         {
764           class h__Reader;
765           mem_ptr<h__Reader> m_Reader;
766           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
767
768         public:
769           MXFReader();
770           virtual ~MXFReader();
771
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();
777
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;
781
782           // Returns RESULT_INIT if the file is not open.
783           Result_t Close() const;
784
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;
788
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;
792
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;
801
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
805           // out of range.
806           Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
807
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;
812
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;
817
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;
821
822           // Print debugging information to stream
823           void     DumpHeaderMetadata(FILE* = 0) const;
824           void     DumpIndex(FILE* = 0) const;
825         };
826     } // namespace MPEG2
827
828   //---------------------------------------------------------------------------------
829   //
830
831
832
833   namespace PCM
834     {
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
838       // element.
839       //
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.
843       //
844       enum ChannelFormat_t {
845         CF_NONE,
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
851         CF_MAXIMUM
852       };
853
854       struct AudioDescriptor
855         {
856           Rational EditRate;         // rate of frame wrapping
857           Rational AudioSamplingRate;  // rate of audio sample
858           ui32_t   Locked;             //
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
862           ui32_t   AvgBps;             //
863           ui32_t   LinkedTrackID;      //
864           ui32_t   ContainerDuration;  // number of frames
865           ChannelFormat_t ChannelFormat; // audio channel arrangement
866       };
867
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);
872
873       // Returns size in bytes of a single sample of data described by ADesc
874       inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
875         {
876           return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
877         }
878
879       // Returns number of samples per frame of data described by ADesc
880       inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
881         {
882           double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
883           return (ui32_t)ceil(tmpd);
884         }
885
886       // Returns the size in bytes of a frame of data described by ADesc
887       inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
888         {
889           return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
890         }
891
892       //
893       class FrameBuffer : public ASDCP::FrameBuffer
894         {
895         public:
896           FrameBuffer() {}
897           FrameBuffer(ui32_t size) { Capacity(size); }
898           virtual ~FrameBuffer() {}
899
900           // Print debugging information to stream (stderr default)
901           void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
902         };
903
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.
908       class WAVParser
909         {
910           class h__WAVParser;
911           mem_ptr<h__WAVParser> m_Parser;
912           ASDCP_NO_COPY_CONSTRUCT(WAVParser);
913
914         public:
915           WAVParser();
916           virtual ~WAVParser();
917
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;
922
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;
926
927           // Rewind the stream to the beginning.
928           Result_t Reset() const;
929
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;
933         };
934
935
936       //
937       class MXFWriter
938         {
939           class h__Writer;
940           mem_ptr<h__Writer> m_Writer;
941           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
942
943         public:
944           MXFWriter();
945           virtual ~MXFWriter();
946
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();
952
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);
958
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
962           // error occurs.
963           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
964
965           // Closes the MXF file, writing the index and revised header.
966           Result_t Finalize();
967         };
968
969       //
970       class MXFReader
971         {
972           class h__Reader;
973           mem_ptr<h__Reader> m_Reader;
974           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
975
976         public:
977           MXFReader();
978           virtual ~MXFReader();
979
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();
985
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;
989
990           // Returns RESULT_INIT if the file is not open.
991           Result_t Close() const;
992
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;
996
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;
1000
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;
1009
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
1013           // out of range.
1014           Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1015
1016           // Print debugging information to stream
1017           void     DumpHeaderMetadata(FILE* = 0) const;
1018           void     DumpIndex(FILE* = 0) const;
1019         };
1020     } // namespace PCM
1021
1022   //---------------------------------------------------------------------------------
1023   //
1024   namespace JP2K
1025     {
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
1029
1030 #pragma pack(1)
1031       struct ImageComponent_t  // ISO 15444-1 Annex A.5.1
1032       {
1033         ui8_t Ssize;
1034         ui8_t XRsize;
1035         ui8_t YRsize;
1036       };
1037
1038       struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
1039       {
1040         ui8_t   Scod;
1041
1042         struct
1043         {
1044           ui8_t  ProgressionOrder;
1045           ui8_t  NumberOfLayers[sizeof(ui16_t)];
1046           ui8_t  MultiCompTransform;
1047         } SGcod;
1048
1049         struct
1050         {
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];
1057         } SPcod;
1058       };
1059
1060       struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
1061       {
1062         ui8_t  Sqcd;
1063         ui8_t  SPqcd[MaxDefaults];
1064         ui8_t  SPqcdLength;
1065       };
1066 #pragma pack()
1067
1068       struct PictureDescriptor
1069       {
1070         Rational       EditRate;
1071         ui32_t         ContainerDuration;
1072         Rational       SampleRate;
1073         ui32_t         StoredWidth;
1074         ui32_t         StoredHeight;
1075         Rational       AspectRatio;
1076         ui16_t         Rsize;
1077         ui32_t         Xsize;
1078         ui32_t         Ysize;
1079         ui32_t         XOsize;
1080         ui32_t         YOsize;
1081         ui32_t         XTsize;
1082         ui32_t         YTsize;
1083         ui32_t         XTOsize;
1084         ui32_t         YTOsize;
1085         ui16_t         Csize;
1086         ImageComponent_t      ImageComponents[MaxComponents];
1087         CodingStyleDefault_t  CodingStyleDefault;
1088         QuantizationDefault_t QuantizationDefault;
1089       };
1090
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);
1095
1096       //
1097       class FrameBuffer : public ASDCP::FrameBuffer
1098         {
1099         public:
1100           FrameBuffer() {}
1101           FrameBuffer(ui32_t size) { Capacity(size); }
1102           virtual ~FrameBuffer() {}
1103
1104           // Print debugging information to stream (stderr default)
1105           void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1106         };
1107
1108
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
1113         {
1114           class h__CodestreamParser;
1115           mem_ptr<h__CodestreamParser> m_Parser;
1116           ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
1117
1118         public:
1119           CodestreamParser();
1120           virtual ~CodestreamParser();
1121
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;
1128
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;
1132         };
1133
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);
1137
1138       // An object which reads a sequence of files containing JPEG 2000 pictures.
1139       class SequenceParser
1140         {
1141           class h__SequenceParser;
1142           mem_ptr<h__SequenceParser> m_Parser;
1143           ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1144
1145         public:
1146           SequenceParser();
1147           virtual ~SequenceParser();
1148
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;
1158
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;
1167
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;
1171
1172           // Rewind the directory to the beginning.
1173           Result_t Reset() const;
1174
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;
1182         };
1183
1184
1185       //
1186       class MXFWriter
1187         {
1188           class h__Writer;
1189           mem_ptr<h__Writer> m_Writer;
1190           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1191
1192         public:
1193           MXFWriter();
1194           virtual ~MXFWriter();
1195
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();
1201
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);
1207
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
1211           // error occurs.
1212           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1213
1214           // Closes the MXF file, writing the index and revised header.
1215           Result_t Finalize();
1216         };
1217
1218       //
1219       class MXFReader
1220         {
1221           class h__Reader;
1222           mem_ptr<h__Reader> m_Reader;
1223           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1224
1225         public:
1226           MXFReader();
1227           virtual ~MXFReader();
1228
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();
1234
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;
1238
1239           // Returns RESULT_INIT if the file is not open.
1240           Result_t Close() const;
1241
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;
1245
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;
1249
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;
1258
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
1262           // out of range.
1263           Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1264
1265           // Print debugging information to stream
1266           void     DumpHeaderMetadata(FILE* = 0) const;
1267           void     DumpIndex(FILE* = 0) const;
1268         };
1269
1270
1271       // Stereoscopic Image support
1272       //
1273
1274       enum StereoscopicPhase_t
1275       {
1276         SP_LEFT,
1277         SP_RIGHT
1278       };
1279
1280       struct SFrameBuffer
1281       {
1282         JP2K::FrameBuffer Left;
1283         JP2K::FrameBuffer Right;
1284
1285         SFrameBuffer(ui32_t size) {
1286           Left.Capacity(size);
1287           Right.Capacity(size);
1288         }
1289       };
1290
1291       class MXFSWriter
1292       {
1293           class h__SWriter;
1294           mem_ptr<h__SWriter> m_Writer;
1295           ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
1296
1297         public:
1298           MXFSWriter();
1299           virtual ~MXFSWriter();
1300
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();
1306
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);
1312
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
1316           // error occurs.
1317           Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1318
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);
1327
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();
1331         };
1332
1333       //
1334       class MXFSReader
1335         {
1336           class h__SReader;
1337           mem_ptr<h__SReader> m_Reader;
1338           ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
1339
1340         public:
1341           MXFSReader();
1342           virtual ~MXFSReader();
1343
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();
1349
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;
1353
1354           // Returns RESULT_INIT if the file is not open.
1355           Result_t Close() const;
1356
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;
1360
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;
1364
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;
1373
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;
1383
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
1387           // out of range.
1388           Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1389
1390           // Print debugging information to stream
1391           void     DumpHeaderMetadata(FILE* = 0) const;
1392           void     DumpIndex(FILE* = 0) const;
1393         };
1394     } // namespace JP2K
1395
1396   //---------------------------------------------------------------------------------
1397   //
1398   namespace TimedText
1399     {
1400       enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
1401
1402       struct TimedTextResourceDescriptor
1403       {
1404         byte_t      ResourceID[UUIDlen];
1405           MIMEType_t  Type;
1406
1407         TimedTextResourceDescriptor() : Type(MT_BIN) {}
1408       };
1409
1410       typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
1411
1412       struct TimedTextDescriptor
1413       {
1414         Rational       EditRate;                //
1415         ui32_t         ContainerDuration;
1416         byte_t         AssetID[UUIDlen];
1417         std::string    NamespaceName;
1418         std::string    EncodingName;
1419         ResourceList_t ResourceList;
1420
1421       TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8
1422       };
1423
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);
1428
1429       //
1430       class FrameBuffer : public ASDCP::FrameBuffer
1431       {
1432         ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
1433
1434       protected:
1435         byte_t      m_AssetID[UUIDlen];
1436         std::string m_MIMEType;
1437
1438       public:
1439         FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
1440         FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
1441         virtual ~FrameBuffer() {}
1442
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; }
1447
1448         // Print debugging information to stream (stderr default)
1449         void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1450       };
1451
1452       // An abstract base for a lookup service that returns the resource data
1453       // identified by the given ancillary resource id.
1454       //
1455       class IResourceResolver
1456       {
1457       public:
1458         virtual ~IResourceResolver() {}
1459         virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
1460       };
1461
1462       // Resolves resource references by testing the named directory for file names containing
1463       // the respective UUID.
1464       //
1465       class LocalFilenameResolver : public ASDCP::TimedText::IResourceResolver
1466         {
1467           std::string m_Dirname;
1468           ASDCP_NO_COPY_CONSTRUCT(LocalFilenameResolver);
1469
1470         public:
1471           LocalFilenameResolver();
1472           Result_t OpenRead(const std::string& dirname);
1473           Result_t ResolveRID(const byte_t* uuid, FrameBuffer& FrameBuf) const;
1474         };
1475
1476       //
1477       class DCSubtitleParser
1478         {
1479           class h__SubtitleParser;
1480           mem_ptr<h__SubtitleParser> m_Parser;
1481           ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
1482
1483         public:
1484           DCSubtitleParser();
1485           virtual ~DCSubtitleParser();
1486
1487           // Opens an XML file for reading, parses data to provide a complete
1488           // set of stream metadata for the MXFWriter below.
1489           Result_t OpenRead(const char* filename) const;
1490
1491           // Parses an XML document to provide a complete set of stream metadata
1492           // for the MXFWriter below. The optional filename argument is used to
1493           // initialize the default resource resolver (see ReadAncillaryResource).
1494           Result_t OpenRead(const std::string& xml_doc, const char* filename = 0) const;
1495
1496           // Fill a TimedTextDescriptor struct with the values from the file's contents.
1497           // Returns RESULT_INIT if the file is not open.
1498           Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1499
1500           // Reads the complete Timed Text Resource into the given string.
1501           Result_t ReadTimedTextResource(std::string&) const;
1502
1503           // Reads the Ancillary Resource having the given ID. Fails if the buffer
1504           // is too small or the resource does not exist. The optional Resolver
1505           // argument can be provided which will be used to retrieve the resource
1506           // having a particulat UUID. If a Resolver is not supplied, the default
1507           // internal resolver will return the contents of the file having the UUID
1508           // as the filename. The filename must exist in the same directory as the
1509           // XML file opened with OpenRead().
1510           Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
1511                                          const IResourceResolver* Resolver = 0) const;
1512         };
1513
1514       //
1515       class MXFWriter
1516         {
1517           class h__Writer;
1518           mem_ptr<h__Writer> m_Writer;
1519           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1520
1521         public:
1522           MXFWriter();
1523           virtual ~MXFWriter();
1524
1525           // Warning: direct manipulation of MXF structures can interfere
1526           // with the normal operation of the wrapper.  Caveat emptor!
1527           virtual MXF::OP1aHeader& OP1aHeader();
1528           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1529           virtual MXF::RIP& RIP();
1530
1531           // Open the file for writing. The file must not exist. Returns error if
1532           // the operation cannot be completed or if nonsensical data is discovered
1533           // in the essence descriptor.
1534           Result_t OpenWrite(const char* filename, const WriterInfo&,
1535                              const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
1536
1537           // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
1538           // encoded. If the optional AESEncContext argument is present, the essence
1539           // is encrypted prior to writing. Fails if the file is not open, is finalized,
1540           // or an operating system error occurs.
1541           // This method may only be called once, and it must be called before any
1542           // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
1543           // conditions are not met.
1544           Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
1545
1546           // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
1547           // argument is present, the essence is encrypted prior to writing.
1548           // Fails if the file is not open, is finalized, or an operating system
1549           // error occurs. RESULT_STATE will be returned if the method is called before
1550           // WriteTimedTextResource()
1551           Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1552
1553           // Closes the MXF file, writing the index and revised header.
1554           Result_t Finalize();
1555         };
1556
1557       //
1558       class MXFReader
1559         {
1560           class h__Reader;
1561           mem_ptr<h__Reader> m_Reader;
1562           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1563
1564         public:
1565           MXFReader();
1566           virtual ~MXFReader();
1567
1568           // Warning: direct manipulation of MXF structures can interfere
1569           // with the normal operation of the wrapper.  Caveat emptor!
1570           virtual MXF::OP1aHeader& OP1aHeader();
1571           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1572           virtual MXF::RIP& RIP();
1573
1574           // Open the file for reading. The file must exist. Returns error if the
1575           // operation cannot be completed.
1576           Result_t OpenRead(const char* filename) const;
1577
1578           // Returns RESULT_INIT if the file is not open.
1579           Result_t Close() const;
1580
1581           // Fill a TimedTextDescriptor struct with the values from the file's header.
1582           // Returns RESULT_INIT if the file is not open.
1583           Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1584
1585           // Fill a WriterInfo struct with the values from the file's header.
1586           // Returns RESULT_INIT if the file is not open.
1587           Result_t FillWriterInfo(WriterInfo&) const;
1588
1589           // Reads the complete Timed Text Resource into the given string. Fails if the resource
1590           // is encrypted and AESDecContext is NULL (use the following method to retrieve the
1591           // raw ciphertet block).
1592           Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
1593
1594           // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
1595           // argument is present, the resource is decrypted after reading. If the MXF
1596           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1597           // will contain the ciphertext frame data. If the HMACContext argument is
1598           // not NULL, the HMAC will be calculated (if the file supports it).
1599           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1600           // out of range, or if optional decrypt or HAMC operations fail.
1601           Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1602
1603           // Reads the timed-text resource having the given UUID from the MXF file. If the
1604           // optional AESEncContext argument is present, the resource is decrypted after
1605           // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
1606           // the frame buffer will contain the ciphertext frame data. If the HMACContext
1607           // argument is not NULL, the HMAC will be calculated (if the file supports it).
1608           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1609           // out of range, or if optional decrypt or HAMC operations fail.
1610           Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1611
1612           // Print debugging information to stream
1613           void     DumpHeaderMetadata(FILE* = 0) const;
1614           void     DumpIndex(FILE* = 0) const;
1615         };
1616     } // namespace TimedText
1617
1618   //---------------------------------------------------------------------------------
1619   //
1620   namespace DCData
1621   {
1622     struct DCDataDescriptor
1623     {
1624       Rational EditRate;                 // Sample rate
1625       ui32_t   ContainerDuration;          // number of frames
1626       byte_t   AssetID[UUIDlen];           // The UUID for the DCData track
1627       byte_t   DataEssenceCoding[UUIDlen]; // The coding for the data carried
1628     };
1629
1630     // Print DCDataDescriptor to std::ostream
1631     std::ostream& operator << (std::ostream& strm, const DCDataDescriptor& ddesc);
1632     // Print debugging information to stream (stderr default)
1633     void DCDataDescriptorDump(const DCDataDescriptor&, FILE* = 0);
1634
1635     //
1636     class FrameBuffer : public ASDCP::FrameBuffer
1637         {
1638      public:
1639           FrameBuffer() {}
1640           FrameBuffer(ui32_t size) { Capacity(size); }
1641           virtual ~FrameBuffer() {}
1642
1643           // Print debugging information to stream (stderr default)
1644           void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1645         };
1646
1647     // An object which opens and reads a DC Data file.  The file is expected
1648     // to contain exactly one complete frame of DC data essence as an unwrapped (raw)
1649     // byte stream.
1650     class BytestreamParser
1651         {
1652           class h__BytestreamParser;
1653           mem_ptr<h__BytestreamParser> m_Parser;
1654           ASDCP_NO_COPY_CONSTRUCT(BytestreamParser);
1655
1656      public:
1657           BytestreamParser();
1658           virtual ~BytestreamParser();
1659
1660           // Opens a file for reading, parses enough data to provide a complete
1661       // set of stream metadata for the MXFWriter below.
1662           // The frame buffer's PlaintextOffset parameter will be set to the first
1663           // byte of the data segment. Set this value to zero if you want
1664           // encrypted headers.
1665           Result_t OpenReadFrame(const char* filename, FrameBuffer&) const;
1666
1667           // Fill a DCDataDescriptor struct with the values from the file's bytestream.
1668           // Returns RESULT_INIT if the file is not open.
1669           Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1670         };
1671
1672     // An object which reads a sequence of files containing DC Data.
1673     class SequenceParser
1674         {
1675           class h__SequenceParser;
1676           mem_ptr<h__SequenceParser> m_Parser;
1677           ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1678
1679      public:
1680           SequenceParser();
1681           virtual ~SequenceParser();
1682
1683           // Opens a directory for reading.  The directory is expected to contain one or
1684           // more files, each containing the bytestream for exactly one frame. The files
1685       // must be named such that the frames are in temporal order when sorted
1686           // alphabetically by filename.
1687           Result_t OpenRead(const char* filename) const;
1688
1689           // Opens a file sequence for reading.  The sequence is expected to contain one or
1690           // more filenames, each naming a file containing the bytestream for exactly one
1691           // frame.
1692           Result_t OpenRead(const std::list<std::string>& file_list) const;
1693
1694           // Fill a DCDataDescriptor struct with default values.
1695           // Returns RESULT_INIT if the directory is not open.
1696           Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1697
1698           // Rewind the directory to the beginning.
1699           Result_t Reset() const;
1700
1701           // Reads the next sequential frame in the directory and places it in the
1702           // frame buffer. Fails if the buffer is too small or the direcdtory
1703           // contains no more files.
1704           // The frame buffer's PlaintextOffset parameter will be set to the first
1705           // byte of the data segment. Set this value to zero if you want
1706           // encrypted headers.
1707           Result_t ReadFrame(FrameBuffer&) const;
1708         };
1709
1710     //
1711     class MXFWriter
1712         {
1713           class h__Writer;
1714           mem_ptr<h__Writer> m_Writer;
1715           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1716
1717      public:
1718           MXFWriter();
1719           virtual ~MXFWriter();
1720
1721           // Warning: direct manipulation of MXF structures can interfere
1722           // with the normal operation of the wrapper.  Caveat emptor!
1723           virtual MXF::OP1aHeader& OP1aHeader();
1724           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1725           virtual MXF::RIP& RIP();
1726
1727           // Open the file for writing. The file must not exist. Returns error if
1728           // the operation cannot be completed or if nonsensical data is discovered
1729           // in the essence descriptor.
1730           Result_t OpenWrite(const char* filename, const WriterInfo&,
1731                              const DCDataDescriptor&, ui32_t HeaderSize = 16384);
1732
1733           // Writes a frame of essence to the MXF file. If the optional AESEncContext
1734           // argument is present, the essence is encrypted prior to writing.
1735           // Fails if the file is not open, is finalized, or an operating system
1736           // error occurs.
1737           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1738
1739           // Closes the MXF file, writing the index and revised header.
1740           Result_t Finalize();
1741         };
1742
1743     //
1744     class MXFReader
1745         {
1746           class h__Reader;
1747           mem_ptr<h__Reader> m_Reader;
1748           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1749
1750      public:
1751           MXFReader();
1752           virtual ~MXFReader();
1753
1754           // Warning: direct manipulation of MXF structures can interfere
1755           // with the normal operation of the wrapper.  Caveat emptor!
1756           virtual MXF::OP1aHeader& OP1aHeader();
1757           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1758           virtual MXF::RIP& RIP();
1759
1760           // Open the file for reading. The file must exist. Returns error if the
1761           // operation cannot be completed.
1762           Result_t OpenRead(const char* filename) const;
1763
1764           // Returns RESULT_INIT if the file is not open.
1765           Result_t Close() const;
1766
1767           // Fill a DCDataDescriptor struct with the values from the file's header.
1768           // Returns RESULT_INIT if the file is not open.
1769           Result_t FillDCDataDescriptor(DCDataDescriptor&) const;
1770
1771           // Fill a WriterInfo struct with the values from the file's header.
1772           // Returns RESULT_INIT if the file is not open.
1773           Result_t FillWriterInfo(WriterInfo&) const;
1774
1775           // Reads a frame of essence from the MXF file. If the optional AESEncContext
1776           // argument is present, the essence is decrypted after reading. If the MXF
1777           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1778           // will contain the ciphertext frame data. If the HMACContext argument is
1779           // not NULL, the HMAC will be calculated (if the file supports it).
1780           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1781           // out of range, or if optional decrypt or HAMC operations fail.
1782           Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1783
1784           // Using the index table read from the footer partition, lookup the frame number
1785           // and return the offset into the file at which to read that frame of essence.
1786           // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1787           // out of range.
1788           Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1789
1790           // Print debugging information to stream
1791           void     DumpHeaderMetadata(FILE* = 0) const;
1792           void     DumpIndex(FILE* = 0) const;
1793         };
1794
1795   } // namespace DCData
1796
1797   //---------------------------------------------------------------------------------
1798   //
1799   namespace ATMOS
1800   {
1801     struct AtmosDescriptor : public DCData::DCDataDescriptor
1802     {
1803       ui32_t FirstFrame;       // Frame number of the frame to align with the FFOA of the picture track
1804       ui16_t MaxChannelCount;  // Max number of channels in bitstream
1805       ui16_t MaxObjectCount;   // Max number of objects in bitstream
1806       byte_t AtmosID[UUIDlen]; // UUID of Atmos Project
1807       ui8_t  AtmosVersion;     // ATMOS Coder Version used to create bitstream
1808     };
1809
1810     // Print AtmosDescriptor to std::ostream
1811     std::ostream& operator << (std::ostream& strm, const AtmosDescriptor& adesc);
1812     // Print debugging information to stream (stderr default)
1813     void AtmosDescriptorDump(const AtmosDescriptor&, FILE* = 0);
1814     // Determine if a file is a raw atmos file
1815     bool IsDolbyAtmos(const char* filename);
1816
1817     //
1818     class MXFWriter
1819         {
1820
1821       class h__Writer;
1822           mem_ptr<h__Writer> m_Writer;
1823           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1824
1825      public:
1826           MXFWriter();
1827           virtual ~MXFWriter();
1828
1829           // Warning: direct manipulation of MXF structures can interfere
1830           // with the normal operation of the wrapper.  Caveat emptor!
1831           virtual MXF::OP1aHeader& OP1aHeader();
1832           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1833           virtual MXF::RIP& RIP();
1834
1835           // Open the file for writing. The file must not exist. Returns error if
1836           // the operation cannot be completed or if nonsensical data is discovered
1837           // in the essence descriptor.
1838           Result_t OpenWrite(const char* filename, const WriterInfo&,
1839                              const AtmosDescriptor&, ui32_t HeaderSize = 16384);
1840
1841           // Writes a frame of essence to the MXF file. If the optional AESEncContext
1842           // argument is present, the essence is encrypted prior to writing.
1843           // Fails if the file is not open, is finalized, or an operating system
1844           // error occurs.
1845       Result_t WriteFrame(const DCData::FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1846
1847           // Closes the MXF file, writing the index and revised header.
1848           Result_t Finalize();
1849         };
1850
1851     //
1852     class MXFReader
1853         {
1854       class h__Reader;
1855           mem_ptr<h__Reader> m_Reader;
1856           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1857
1858      public:
1859           MXFReader();
1860           virtual ~MXFReader();
1861
1862           // Warning: direct manipulation of MXF structures can interfere
1863           // with the normal operation of the wrapper.  Caveat emptor!
1864           virtual MXF::OP1aHeader& OP1aHeader();
1865           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1866           virtual MXF::RIP& RIP();
1867
1868           // Open the file for reading. The file must exist. Returns error if the
1869           // operation cannot be completed.
1870           Result_t OpenRead(const char* filename) const;
1871
1872           // Returns RESULT_INIT if the file is not open.
1873           Result_t Close() const;
1874
1875           // Fill an AtmosDescriptor struct with the values from the file's header.
1876           // Returns RESULT_INIT if the file is not open.
1877           Result_t FillAtmosDescriptor(AtmosDescriptor&) const;
1878
1879           // Fill a WriterInfo struct with the values from the file's header.
1880           // Returns RESULT_INIT if the file is not open.
1881           Result_t FillWriterInfo(WriterInfo&) const;
1882
1883           // Reads a frame of essence from the MXF file. If the optional AESEncContext
1884           // argument is present, the essence is decrypted after reading. If the MXF
1885           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1886           // will contain the ciphertext frame data. If the HMACContext argument is
1887           // not NULL, the HMAC will be calculated (if the file supports it).
1888           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1889           // out of range, or if optional decrypt or HAMC operations fail.
1890           Result_t ReadFrame(ui32_t frame_number, DCData::FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1891
1892           // Using the index table read from the footer partition, lookup the frame number
1893           // and return the offset into the file at which to read that frame of essence.
1894           // Returns RESULT_INIT if the file is not open, and RESULT_RANGE if the frame number is
1895           // out of range.
1896           Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const;
1897
1898           // Print debugging information to stream
1899           void     DumpHeaderMetadata(FILE* = 0) const;
1900           void     DumpIndex(FILE* = 0) const;
1901         };
1902
1903   } // namespace ATMOS
1904
1905
1906
1907 } // namespace ASDCP
1908
1909
1910 #endif // _AS_DCP_H_
1911
1912 //
1913 // end AS_DCP.h
1914 //