big change rollup
[asdcplib.git] / src / AS_DCP.h
1 /*
2 Copyright (c) 2003-2012, 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
70  o Read essence from a plaintext or ciphertext AS-DCP file:
71      MPEG2 Video Elementary Stream
72      JPEG 2000 codestreams
73      JPEG 2000 stereoscopic codestream pairs
74      PCM audio streams
75      SMPTE 429-7 Timed Text XML with font and image resources
76
77  o Read header metadata from an AS-DCP file
78
79 This project depends upon the following libraries:
80  - OpenSSL http://www.openssl.org/
81  - Expat http://expat.sourceforge.net/  or
82      Xerces-C http://xerces.apache.org/xerces-c/
83    An XML library is not needed if you don't need support for SMPTE ST 429-5:2009.
84 */
85
86 #ifndef _AS_DCP_H_
87 #define _AS_DCP_H_
88
89 #include <KM_error.h>
90 #include <stdio.h>
91 #include <stdarg.h>
92 #include <math.h>
93 #include <iosfwd>
94 #include <string>
95 #include <cstring>
96 #include <list>
97
98 //--------------------------------------------------------------------------------
99 // common integer types
100 // supply your own by defining ASDCP_NO_BASE_TYPES
101
102 #ifndef ASDCP_NO_BASE_TYPES
103 typedef unsigned char  byte_t;
104 typedef char           i8_t;
105 typedef unsigned char  ui8_t;
106 typedef short          i16_t;
107 typedef unsigned short ui16_t;
108 typedef int            i32_t;
109 typedef unsigned int   ui32_t;
110 #endif
111
112
113 //--------------------------------------------------------------------------------
114 // convenience macros
115
116 // Convenience macros for managing return values in predicates
117 #define ASDCP_SUCCESS(v) (((v) < 0) ? 0 : 1)
118 #define ASDCP_FAILURE(v) (((v) < 0) ? 1 : 0)
119
120
121 // Returns RESULT_PTR if the given argument is NULL.
122 // See Result_t below for an explanation of RESULT_* symbols.
123 #define ASDCP_TEST_NULL(p) \
124   if ( (p) == 0  ) { \
125     return ASDCP::RESULT_PTR; \
126   }
127
128 // Returns RESULT_PTR if the given argument is NULL. See Result_t
129 // below for an explanation of RESULT_* symbols. It then assumes
130 // that the argument is a pointer to a string and returns
131 // RESULT_NULL_STR if the first character is '\0'.
132 //
133 #define ASDCP_TEST_NULL_STR(p) \
134   ASDCP_TEST_NULL(p); \
135   if ( (p)[0] == '\0' ) { \
136     return ASDCP::RESULT_NULL_STR; \
137   }
138
139 // Produces copy constructor boilerplate. Allows convenient private
140 // declatarion of copy constructors to prevent the compiler from
141 // silently manufacturing default methods.
142 #define ASDCP_NO_COPY_CONSTRUCT(T)   \
143           T(const T&); \
144           T& operator=(const T&)
145
146 //--------------------------------------------------------------------------------
147 // All library components are defined in the namespace ASDCP
148 //
149 namespace ASDCP {
150   //
151   // The version number declaration and explanation have moved to ../configure.ac
152   const char* Version();
153
154   // UUIDs are passed around as strings of UUIDlen bytes
155   const ui32_t UUIDlen = 16;
156
157   // Encryption keys are passed around as strings of KeyLen bytes
158   const ui32_t KeyLen = 16;
159
160   //---------------------------------------------------------------------------------
161   // return values
162
163   using Kumu::Result_t;
164
165   using Kumu::RESULT_FALSE;
166   using Kumu::RESULT_OK;
167   using Kumu::RESULT_FAIL;
168   using Kumu::RESULT_PTR;
169   using Kumu::RESULT_NULL_STR;
170   using Kumu::RESULT_ALLOC;
171   using Kumu::RESULT_PARAM;
172   using Kumu::RESULT_SMALLBUF;
173   using Kumu::RESULT_INIT;
174   using Kumu::RESULT_NOT_FOUND;
175   using Kumu::RESULT_NO_PERM;
176   using Kumu::RESULT_FILEOPEN;
177   using Kumu::RESULT_BADSEEK;
178   using Kumu::RESULT_READFAIL;
179   using Kumu::RESULT_WRITEFAIL;
180   using Kumu::RESULT_STATE;
181   using Kumu::RESULT_ENDOFFILE;
182   using Kumu::RESULT_CONFIG;
183
184   KM_DECLARE_RESULT(FORMAT,     -101, "The file format is not proper OP-Atom/AS-DCP.");
185   KM_DECLARE_RESULT(RAW_ESS,    -102, "Unknown raw essence file type.");
186   KM_DECLARE_RESULT(RAW_FORMAT, -103, "Raw essence format invalid.");
187   KM_DECLARE_RESULT(RANGE,      -104, "Frame number out of range.");
188   KM_DECLARE_RESULT(CRYPT_CTX,  -105, "AESEncContext required when writing to encrypted file.");
189   KM_DECLARE_RESULT(LARGE_PTO,  -106, "Plaintext offset exceeds frame buffer size.");
190   KM_DECLARE_RESULT(CAPEXTMEM,  -107, "Cannot resize externally allocated memory.");
191   KM_DECLARE_RESULT(CHECKFAIL,  -108, "The check value did not decrypt correctly.");
192   KM_DECLARE_RESULT(HMACFAIL,   -109, "HMAC authentication failure.");
193   KM_DECLARE_RESULT(HMAC_CTX,   -110, "HMAC context required.");
194   KM_DECLARE_RESULT(CRYPT_INIT, -111, "Error initializing block cipher context.");
195   KM_DECLARE_RESULT(EMPTY_FB,   -112, "Empty frame buffer.");
196   KM_DECLARE_RESULT(KLV_CODING, -113, "KLV coding error.");
197   KM_DECLARE_RESULT(SPHASE,     -114, "Stereoscopic phase mismatch.");
198   KM_DECLARE_RESULT(SFORMAT,    -115, "Rate mismatch, file may contain stereoscopic essence.");
199
200   //---------------------------------------------------------------------------------
201   // file identification
202
203   // The file accessors in this library implement a bounded set of essence types.
204   // This list will be expanded when support for new types is added to the library.
205   enum EssenceType_t {
206     ESS_UNKNOWN,     // the file is not a supported AS-DCP essence container
207     ESS_MPEG2_VES,   // the file contains an MPEG video elementary stream
208     ESS_JPEG_2000,   // the file contains one or more JPEG 2000 codestreams
209     ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs
210     ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs
211     ESS_TIMED_TEXT,  // the file contains an XML timed text document and one or more resources
212     ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic)
213   };
214
215   // Determine the type of essence contained in the given MXF file. RESULT_OK
216   // is returned if the file is successfully opened and contains a valid MXF
217   // stream. If there is an error, the result code will indicate the reason.
218   Result_t EssenceType(const char* filename, EssenceType_t& type);
219
220   // Determine the type of essence contained in the given raw file. RESULT_OK
221   // is returned if the file is successfully opened and contains a known
222   // stream type. If there is an error, the result code will indicate the reason.
223   Result_t RawEssenceType(const char* filename, EssenceType_t& type);
224
225
226   //---------------------------------------------------------------------------------
227   // base types
228
229   // A simple container for rational numbers.
230   class Rational
231   {
232   public:
233     i32_t Numerator;
234     i32_t Denominator;
235
236     Rational() : Numerator(0), Denominator(0) {}
237     Rational(i32_t n, i32_t d) : Numerator(n), Denominator(d) {}
238
239     inline double Quotient() const {
240       return (double)Numerator / (double)Denominator;
241     }
242
243     inline bool operator==(const Rational& rhs) const {
244       return ( rhs.Numerator == Numerator && rhs.Denominator == Denominator );
245     }
246
247     inline bool operator!=(const Rational& rhs) const {
248       return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
249     }
250
251     inline bool operator<(const Rational& rhs) {
252       if ( Numerator < rhs.Numerator )     return true;
253       if ( Numerator == rhs.Numerator && Denominator < rhs.Denominator )    return true;
254       return false;
255     }
256  
257     inline bool operator>(const Rational& rhs) {
258       if ( Numerator > rhs.Numerator )     return true;
259       if ( Numerator == rhs.Numerator && Denominator > rhs.Denominator )     return true;
260       return false;
261     }
262   };
263
264   // common edit rates, use these instead of hard coded constants
265   const Rational EditRate_24 = Rational(24,1);
266   const Rational EditRate_23_98 = Rational(24000,1001); // Not a DCI-compliant value!
267   const Rational EditRate_48 = Rational(48,1);
268   const Rational SampleRate_48k = Rational(48000,1);
269   const Rational SampleRate_96k = Rational(96000,1);
270
271   // Additional frame rates, see ST 428-11, ST 429-13
272   // These rates are new and not supported by all systems. Do not assume that
273   // a package made using one of these rates will work just anywhere!
274   const Rational EditRate_25 = Rational(25,1);
275   const Rational EditRate_30 = Rational(30,1);
276   const Rational EditRate_50 = Rational(50,1);
277   const Rational EditRate_60 = Rational(60,1);
278   const Rational EditRate_96 = Rational(96,1);
279   const Rational EditRate_100 = Rational(100,1);
280   const Rational EditRate_120 = Rational(120,1);
281
282   // Archival frame rates, see ST 428-21
283   // These rates are new and not supported by all systems. Do not assume that
284   // a package made using one of these rates will work just anywhere!
285   const Rational EditRate_16 = Rational(16,1);
286   const Rational EditRate_18 = Rational(200,11); // 18.182
287   const Rational EditRate_20 = Rational(20,1);
288   const Rational EditRate_22 = Rational(240,11); // 21.818
289
290
291   // Non-reference counting container for internal member objects.
292   // Please do not use this class for any other purpose.
293   template <class T>
294     class mem_ptr
295     {
296       T* m_p; // the thing we point to
297       mem_ptr(T&);
298
299     public:
300       mem_ptr() : m_p(0) {}
301       mem_ptr(T* p) : m_p(p) {}
302       ~mem_ptr() { delete m_p; }
303
304       inline T&   operator*()  const { return *m_p; }
305       inline T*   operator->() const { return m_p; }
306       inline      operator T*()const { return m_p; }
307       inline const mem_ptr<T>& operator=(T* p) { set(p); return *this; }
308       inline T*   set(T* p)          { delete m_p; m_p = p; return m_p; }
309       inline T*   get()        const { return m_p; }
310       inline void release()          { m_p = 0; }
311       inline bool empty()      const { return m_p == 0; }
312     };
313
314
315   //---------------------------------------------------------------------------------
316   // WriterInfo class - encapsulates writer identification details used for
317   // OpenWrite() calls.  Replace these values at runtime to identify your product.
318   //
319   // MXF files use SMPTE Universal Labels to identify data items. The set of Labels
320   // in a file is determined by the MXF Operational Pattern and any constraining
321   // documentation. There are currently two flavors of AS-DCP file in use: MXF Interop
322   // (AKA JPEG Interop) and SMPTE. The two differ in the values of three labels:
323   //
324   //   OPAtom
325   //      Interop : 06 0e 2b 34 04 01 01 01  0d 01 02 01 10 00 00 00
326   //      SMPTE   : 06 0e 2b 34 04 01 01 02  0d 01 02 01 10 00 00 00
327   //
328   //   EKLV Packet:
329   //      Interop : 06 0e 2b 34 02 04 01 07  0d 01 03 01 02 7e 01 00
330   //      SMPTE   : 06 0e 2b 34 02 04 01 01  0d 01 03 01 02 7e 01 00
331   //
332   //   GenericDescriptor/SubDescriptors:
333   //      Interop : 06 0e 2b 34 01 01 01 02  06 01 01 04 06 10 00 00
334   //      SMPTE   : 06 0e 2b 34 01 01 01 09  06 01 01 04 06 10 00 00
335   //
336   // asdcplib will read any (otherwise valid) file which has any combination of the
337   // above values. When writing files, MXF Interop labels are used by default. To
338   // write a file containing SMPTE labels, replace the default label set value in
339   // the WriterInfo before calling OpenWrite()
340   //
341   //
342   enum LabelSet_t
343   {
344     LS_MXF_UNKNOWN,
345     LS_MXF_INTEROP,
346     LS_MXF_SMPTE
347   };
348
349   //
350   struct WriterInfo
351   {
352     byte_t      ProductUUID[UUIDlen];
353     byte_t      AssetUUID[UUIDlen];
354     byte_t      ContextID[UUIDlen];
355     byte_t      CryptographicKeyID[UUIDlen];
356     bool        EncryptedEssence; // true if essence data is (or is going to be) encrypted
357     bool        UsesHMAC;         // true if HMAC exists or is to be calculated
358     std::string ProductVersion;
359     std::string CompanyName;
360     std::string ProductName;
361     LabelSet_t  LabelSetType;
362
363     WriterInfo() : EncryptedEssence(false), UsesHMAC(false), LabelSetType(LS_MXF_INTEROP)
364     {
365       static byte_t default_ProductUUID_Data[UUIDlen] = {
366         0x43, 0x05, 0x9a, 0x1d, 0x04, 0x32, 0x41, 0x01,
367         0xb8, 0x3f, 0x73, 0x68, 0x15, 0xac, 0xf3, 0x1d };
368       
369       memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
370       memset(AssetUUID, 0, UUIDlen);
371       memset(ContextID, 0, UUIDlen);
372       memset(CryptographicKeyID, 0, UUIDlen);
373
374       ProductVersion = "Unreleased ";
375       ProductVersion += Version();
376       CompanyName = "DCI";
377       ProductName = "asdcplib";
378     }
379   };
380
381   // Print WriterInfo to std::ostream
382   std::ostream& operator << (std::ostream& strm, const WriterInfo& winfo);
383   // Print WriterInfo to stream, stderr by default.
384   void WriterInfoDump(const WriterInfo&, FILE* = 0);
385
386   //---------------------------------------------------------------------------------
387   // cryptographic support
388
389   // The following classes define interfaces to Rijndael contexts having the following properties:
390   //  o 16 byte key
391   //  o CBC mode with 16 byte block size
392   const ui32_t CBC_KEY_SIZE = 16;
393   const ui32_t CBC_BLOCK_SIZE = 16;
394   const ui32_t HMAC_SIZE = 20;
395
396   //
397   class AESEncContext
398     {
399       class h__AESContext;
400       mem_ptr<h__AESContext> m_Context;
401       ASDCP_NO_COPY_CONSTRUCT(AESEncContext);
402
403     public:
404       AESEncContext();
405       ~AESEncContext();
406
407       // Initializes Rijndael CBC encryption context.
408       // Returns error if the key argument is NULL.
409       Result_t InitKey(const byte_t* key);
410       
411       // Initializes 16 byte CBC Initialization Vector. This operation may be performed
412       // any number of times for a given key.
413       // Returns error if the i_vec argument is NULL.
414       Result_t SetIVec(const byte_t* i_vec);
415       Result_t GetIVec(byte_t* i_vec) const;
416
417       // Encrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
418       // Returns error if either argument is NULL.
419       Result_t EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size);
420     };
421
422   //
423   class AESDecContext
424     {
425       class h__AESContext;
426       mem_ptr<h__AESContext> m_Context;
427       ASDCP_NO_COPY_CONSTRUCT(AESDecContext);
428
429     public:
430       AESDecContext();
431       ~AESDecContext();
432
433       // Initializes Rijndael CBC decryption context.
434       // Returns error if the key argument is NULL.
435       Result_t InitKey(const byte_t* key);
436
437       // Initializes 16 byte CBC Initialization Vector. This operation may be performed
438       // any number of times for a given key.
439       // Returns error if the i_vec argument is NULL.
440       Result_t SetIVec(const byte_t* i_vec);
441
442       // Decrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
443       // Returns error if either argument is NULL.
444       Result_t DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size);
445     };
446
447   //
448   class HMACContext
449     {
450       class h__HMACContext;
451       mem_ptr<h__HMACContext> m_Context;
452       ASDCP_NO_COPY_CONSTRUCT(HMACContext);
453
454     public:
455       HMACContext();
456       ~HMACContext();
457
458       // Initializes HMAC context. The key argument must point to a binary
459       // key that is CBC_KEY_SIZE bytes in length. Returns error if the key
460       // argument is NULL.
461       Result_t InitKey(const byte_t* key, LabelSet_t);
462
463       // Reset internal state, allows repeated cycles of Update -> Finalize
464       void Reset();
465
466       // Add data to the digest. Returns error if the key argument is NULL or
467       // if the digest has been finalized.
468       Result_t Update(const byte_t* buf, ui32_t buf_len);
469
470       // Finalize digest.  Returns error if the digest has already been finalized.
471       Result_t Finalize();
472
473       // Writes HMAC value to given buffer. buf must point to a writable area of
474       // memory that is at least HMAC_SIZE bytes in length. Returns error if the
475       // buf argument is NULL or if the digest has not been finalized.
476       Result_t GetHMACValue(byte_t* buf) const;
477
478       // Tests the given value against the finalized value in the object. buf must
479       // point to a readable area of memory that is at least HMAC_SIZE bytes in length.
480       // Returns error if the buf argument is NULL or if the values do ot match.
481       Result_t TestHMACValue(const byte_t* buf) const;
482     };
483
484   //---------------------------------------------------------------------------------
485   // frame buffer base class
486   //
487   // The supported essence types are stored using per-frame KLV packetization. The
488   // following class implements essence-neutral functionality for managing a buffer
489   // containing a frame of essence.
490
491   class FrameBuffer
492     {
493       ASDCP_NO_COPY_CONSTRUCT(FrameBuffer);
494
495     protected:
496       byte_t* m_Data;          // pointer to memory area containing frame data
497       ui32_t  m_Capacity;      // size of memory area pointed to by m_Data
498       bool    m_OwnMem;        // if false, m_Data points to externally allocated memory
499       ui32_t  m_Size;          // size of frame data in memory area pointed to by m_Data
500       ui32_t  m_FrameNumber;   // delivery-order frame number
501
502       // It is possible to read raw ciphertext from an encrypted AS-DCP file.
503       // After reading an encrypted AS-DCP file in raw mode, the frame buffer will
504       // contain the encrypted source value portion of the Encrypted Triplet, followed
505       // by the integrity pack, if it exists.
506       // The buffer will begin with the IV and CheckValue, followed by encrypted essence
507       // and optional integrity pack
508       // The SourceLength and PlaintextOffset values from the packet will be held in the
509       // following variables:
510       ui32_t  m_SourceLength;       // plaintext length (delivered plaintext+decrypted ciphertext)
511       ui32_t  m_PlaintextOffset;    // offset to first byte of ciphertext
512
513      public:
514       FrameBuffer();
515       virtual ~FrameBuffer();
516
517       // Instructs the object to use an externally allocated buffer. The external
518       // buffer will not be cleaned up by the frame buffer when it exits.
519       // Call with (0,0) to revert to internally allocated buffer.
520       // Returns error if the buf_addr argument is NULL and buf_size is non-zero.
521       Result_t SetData(byte_t* buf_addr, ui32_t buf_size);
522
523       // Sets the size of the internally allocate buffer. Returns RESULT_CAPEXTMEM
524       // if the object is using an externally allocated buffer via SetData();
525       // Resets content size to zero.
526       Result_t Capacity(ui32_t cap);
527
528       // returns the size of the buffer
529       inline ui32_t  Capacity() const { return m_Capacity; }
530
531       // returns a const pointer to the essence data
532       inline const byte_t* RoData() const { return m_Data; }
533
534       // returns a non-const pointer to the essence data
535       inline byte_t* Data() { return m_Data; }
536
537       // set the size of the buffer's contents
538       inline ui32_t  Size(ui32_t size) { return m_Size = size; }
539
540       // returns the size of the buffer's contents
541       inline ui32_t  Size() const { return m_Size; }
542
543       // Sets the absolute frame number of this frame in the file in delivery order.
544       inline void    FrameNumber(ui32_t num) { m_FrameNumber = num; }
545
546       // Returns the absolute frame number of this frame in the file in delivery order.
547       inline ui32_t  FrameNumber() const { return m_FrameNumber; }
548
549       // Sets the length of the plaintext essence data
550       inline void    SourceLength(ui32_t len) { m_SourceLength = len; }
551
552       // When this value is 0 (zero), the buffer contains only plaintext. When it is
553       // non-zero, the buffer contains raw ciphertext and the return value is the length
554       // of the original plaintext.
555       inline ui32_t  SourceLength() const { return m_SourceLength; }
556
557       // Sets the offset into the buffer at which encrypted data begins
558       inline void    PlaintextOffset(ui32_t ofst) { m_PlaintextOffset = ofst; }
559
560       // Returns offset into buffer of first byte of ciphertext.
561       inline ui32_t  PlaintextOffset() const { return m_PlaintextOffset; }
562     };
563
564   //---------------------------------------------------------------------------------
565   // Accessors in the MXFReader and MXFWriter classes below return these types to
566   // provide direct access to MXF metadata structures declared in MXF.h and Metadata.h
567
568   namespace MXF {
569     // #include<Metadata.h> to use these
570     class OPAtomHeader;
571     class OPAtomIndexFooter;
572   };
573
574   //---------------------------------------------------------------------------------
575   // MPEG2 video elementary stream support
576
577   //
578   namespace MPEG2
579     {
580       // MPEG picture coding type
581       enum FrameType_t {
582         FRAME_U = 0x00, // Unknown
583         FRAME_I = 0x01, // I-Frame
584         FRAME_P = 0x02, // P-Frame
585         FRAME_B = 0x03  // B-Frame
586       };
587
588       // convert FrameType_t to char
589       inline char FrameTypeChar(FrameType_t type)
590         {
591           switch ( type )
592             {
593             case FRAME_I: return 'I';
594             case FRAME_B: return 'B';
595             case FRAME_P: return 'P';
596             default: return 'U';
597             }
598         }
599
600       // Structure represents the metadata elements in the file header's
601       // MPEG2VideoDescriptor object.
602       struct VideoDescriptor
603         {
604           Rational EditRate;                // 
605           ui32_t   FrameRate;               // 
606           Rational SampleRate;              // 
607           ui8_t    FrameLayout;             // 
608           ui32_t   StoredWidth;             // 
609           ui32_t   StoredHeight;            // 
610           Rational AspectRatio;             // 
611           ui32_t   ComponentDepth;          // 
612           ui32_t   HorizontalSubsampling;   // 
613           ui32_t   VerticalSubsampling;     // 
614           ui8_t    ColorSiting;             // 
615           ui8_t    CodedContentType;        // 
616           bool     LowDelay;                // 
617           ui32_t   BitRate;                 // 
618           ui8_t    ProfileAndLevel;         // 
619           ui32_t   ContainerDuration;       // 
620       };
621
622       // Print VideoDescriptor to std::ostream
623       std::ostream& operator << (std::ostream& strm, const VideoDescriptor& vdesc);
624       // Print VideoDescriptor to stream, stderr by default.
625       void VideoDescriptorDump(const VideoDescriptor&, FILE* = 0);
626
627       // A container for MPEG frame data.
628       class FrameBuffer : public ASDCP::FrameBuffer
629         {
630           ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
631
632         protected:
633           FrameType_t m_FrameType;
634           ui8_t       m_TemporalOffset;
635           bool        m_ClosedGOP;
636           bool        m_GOPStart;
637
638         public:
639           FrameBuffer() :
640             m_FrameType(FRAME_U), m_TemporalOffset(0),
641             m_ClosedGOP(false), m_GOPStart(false) {}
642
643           FrameBuffer(ui32_t size) :
644             m_FrameType(FRAME_U), m_TemporalOffset(0),
645             m_ClosedGOP(false), m_GOPStart(false)
646             {
647               Capacity(size);
648             }
649             
650           virtual ~FrameBuffer() {}
651
652           // Sets the MPEG frame type of the picture data in the frame buffer.
653           inline void FrameType(FrameType_t type) { m_FrameType = type; }
654
655           // Returns the MPEG frame type of the picture data in the frame buffer.
656           inline FrameType_t FrameType() const { return m_FrameType; }
657
658           // Sets the MPEG temporal offset of the picture data in the frame buffer.
659           inline void TemporalOffset(ui8_t offset) { m_TemporalOffset = offset; }
660
661           // Returns the MPEG temporal offset of the picture data in the frame buffer.
662           inline ui8_t TemporalOffset() const { return m_TemporalOffset; }
663
664           // Sets the MPEG GOP 'start' attribute for the frame buffer.
665           inline void GOPStart(bool start) { m_GOPStart = start; }
666
667           // True if the frame in the buffer is the first in the GOP (in transport order)
668           inline bool GOPStart() const { return m_GOPStart; }
669
670           // Sets the MPEG GOP 'closed' attribute for the frame buffer.
671           inline void ClosedGOP(bool closed) { m_ClosedGOP = closed; }
672
673           // Returns true if the frame in the buffer is from a closed GOP, false if
674           // the frame is from an open GOP.  Always returns false unless GOPStart()
675           // returns true.
676           inline bool ClosedGOP() const { return m_ClosedGOP; }
677
678           // Print object state to stream, include n bytes of frame data if indicated.
679           // Default stream is stderr.
680           void    Dump(FILE* = 0, ui32_t dump_len = 0) const;
681         };
682
683
684       // An object which opens and reads an MPEG2 Video Elementary Stream file.  The call to
685       // OpenRead() reads metadata from the file and populates an internal VideoDescriptor object.
686       // Each subsequent call to ReadFrame() reads exactly one frame from the stream into the
687       // given FrameBuffer object.
688       class Parser
689         {
690           class h__Parser;
691           mem_ptr<h__Parser> m_Parser;
692           ASDCP_NO_COPY_CONSTRUCT(Parser);
693
694         public:
695           Parser();
696           virtual ~Parser();
697
698           // Opens the stream for reading, parses enough data to provide a complete
699           // set of stream metadata for the MXFWriter below.
700           Result_t OpenRead(const char* filename) const;
701
702           // Fill a VideoDescriptor struct with the values from the file's header.
703           // Returns RESULT_INIT if the file is not open.
704           Result_t FillVideoDescriptor(VideoDescriptor&) const;
705
706           // Rewind the stream to the beginning.
707           Result_t Reset() const;
708
709           // Reads the next sequential frame in the input file and places it in the
710           // frame buffer. Fails if the buffer is too small or the stream is empty.
711           // The frame buffer's PlaintextOffset parameter will be set to the first
712           // data byte of the first slice. Set this value to zero if you want
713           // encrypted headers.
714           Result_t ReadFrame(FrameBuffer&) const;
715         };
716
717       // A class which creates and writes MPEG frame data to an AS-DCP format MXF file.
718       // Not yet implemented
719       class MXFWriter
720         {
721           class h__Writer;
722           mem_ptr<h__Writer> m_Writer;
723           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
724
725         public:
726           MXFWriter();
727           virtual ~MXFWriter();
728
729           // Warning: direct manipulation of MXF structures can interfere
730           // with the normal operation of the wrapper.  Caveat emptor!
731           virtual MXF::OPAtomHeader& OPAtomHeader();
732           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
733
734           // Open the file for writing. The file must not exist. Returns error if
735           // the operation cannot be completed or if nonsensical data is discovered
736           // in the essence descriptor.
737           Result_t OpenWrite(const char* filename, const WriterInfo&,
738                              const VideoDescriptor&, ui32_t HeaderSize = 16384);
739
740           // Writes a frame of essence to the MXF file. If the optional AESEncContext
741           // argument is present, the essence is encrypted prior to writing.
742           // Fails if the file is not open, is finalized, or an operating system
743           // error occurs.
744           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
745
746           // Closes the MXF file, writing the index and revised header.
747           Result_t Finalize();
748         };
749
750       // A class which reads MPEG frame data from an AS-DCP format MXF file.
751       class MXFReader
752         {
753           class h__Reader;
754           mem_ptr<h__Reader> m_Reader;
755           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
756
757         public:
758           MXFReader();
759           virtual ~MXFReader();
760
761           // Warning: direct manipulation of MXF structures can interfere
762           // with the normal operation of the wrapper.  Caveat emptor!
763           virtual MXF::OPAtomHeader& OPAtomHeader();
764           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
765
766           // Open the file for reading. The file must exist. Returns error if the
767           // operation cannot be completed.
768           Result_t OpenRead(const char* filename) const;
769
770           // Returns RESULT_INIT if the file is not open.
771           Result_t Close() const;
772
773           // Fill a VideoDescriptor struct with the values from the file's header.
774           // Returns RESULT_INIT if the file is not open.
775           Result_t FillVideoDescriptor(VideoDescriptor&) const;
776
777           // Fill a WriterInfo struct with the values from the file's header.
778           // Returns RESULT_INIT if the file is not open.
779           Result_t FillWriterInfo(WriterInfo&) const;
780
781           // Reads a frame of essence from the MXF file. If the optional AESEncContext
782           // argument is present, the essence is decrypted after reading. If the MXF
783           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
784           // will contain the ciphertext frame data. If the HMACContext argument is
785           // not NULL, the HMAC will be calculated (if the file supports it).
786           // Returns RESULT_INIT if the file is not open, failure if the frame number is
787           // out of range, or if optional decrypt or HAMC operations fail.
788           Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
789
790           // Calculates the first frame in transport order of the GOP in which the requested
791           // frame is located.  Calls ReadFrame() to fetch the frame at the calculated position.
792           // Returns RESULT_INIT if the file is not open.
793           Result_t ReadFrameGOPStart(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
794
795           // Calculates the first frame in transport order of the GOP in which the requested
796           // frame is located.  Sets key_frame_number to the number of the frame at the calculated position.
797           // Returns RESULT_INIT if the file is not open.
798           Result_t FindFrameGOPStart(ui32_t frame_number, ui32_t& key_frame_number) const;
799
800           // Returns the type of the frame at the given position.
801           // Returns RESULT_INIT if the file is not open or RESULT_RANGE if the index is out of range.
802           Result_t FrameType(ui32_t frame_number, FrameType_t&) const;
803
804           // Print debugging information to stream
805           void     DumpHeaderMetadata(FILE* = 0) const;
806           void     DumpIndex(FILE* = 0) const;
807         };
808     } // namespace MPEG2
809
810   //---------------------------------------------------------------------------------
811   //
812
813
814
815   namespace PCM
816     {
817       // The default value of the ChannelFormat element of the AudioDescriptor struct
818       // is CF_NONE. If the value is set to one of the other ChannelFormat_t enum
819       // values, the file's Wave Audio Descriptor will contain a Channel Assignment
820       // element.
821       //
822       // The channel format should be one of (CF_CFG_1, CF_CFG_2, or CF_CFG_3) for
823       // SMPTE 429-2 files. It should normally be CF_NONE for JPEG Interop files, but
824       // the 429-2 may also be used.
825       //
826       enum ChannelFormat_t {
827         CF_NONE,
828         CF_CFG_1, // 5.1 with optional HI/VI
829         CF_CFG_2, // 6.1 (5.1 + center surround) with optional HI/VI
830         CF_CFG_3, // 7.1 (SDDS) with optional HI/VI
831         CF_CFG_4, // Wild Track Format
832         CF_CFG_5, // 7.1 DS with optional HI/VI
833       };
834
835       struct AudioDescriptor
836         {
837           Rational EditRate;         // rate of frame wrapping
838           Rational AudioSamplingRate;  // rate of audio sample
839           ui32_t   Locked;             // 
840           ui32_t   ChannelCount;       // number of channels
841           ui32_t   QuantizationBits;   // number of bits per single-channel sample
842           ui32_t   BlockAlign;         // number of bytes ber sample, all channels
843           ui32_t   AvgBps;             // 
844           ui32_t   LinkedTrackID;      // 
845           ui32_t   ContainerDuration;  // number of frames
846           ChannelFormat_t ChannelFormat; // audio channel arrangement
847       };
848
849       // Print AudioDescriptor to std::ostream
850       std::ostream& operator << (std::ostream& strm, const AudioDescriptor& adesc);
851       // Print debugging information to stream (stderr default)
852       void   AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
853
854       // Returns size in bytes of a single sample of data described by ADesc
855       inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
856         {
857           return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
858         }
859
860       // Returns number of samples per frame of data described by ADesc
861       inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
862         {
863           double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
864           return (ui32_t)ceil(tmpd);
865         }
866
867       // Returns the size in bytes of a frame of data described by ADesc
868       inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
869         {
870           return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
871         }
872
873       //
874       class FrameBuffer : public ASDCP::FrameBuffer
875         {
876         public:
877           FrameBuffer() {}
878           FrameBuffer(ui32_t size) { Capacity(size); }
879           virtual ~FrameBuffer() {}
880         
881           // Print debugging information to stream (stderr default)
882           void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
883         };
884
885       // An object which opens and reads a WAV file.  The call to OpenRead() reads metadata from
886       // the file and populates an internal AudioDescriptor object. Each subsequent call to
887       // ReadFrame() reads exactly one frame from the stream into the given FrameBuffer object.
888       // A "frame" is either 2000 or 2002 samples, depending upon the value of PictureRate.
889       class WAVParser
890         {
891           class h__WAVParser;
892           mem_ptr<h__WAVParser> m_Parser;
893           ASDCP_NO_COPY_CONSTRUCT(WAVParser);
894
895         public:
896           WAVParser();
897           virtual ~WAVParser();
898
899           // Opens the stream for reading, parses enough data to provide a complete
900           // set of stream metadata for the MXFWriter below. PictureRate controls
901           // ther frame rate for the MXF frame wrapping option.
902           Result_t OpenRead(const char* filename, const Rational& PictureRate) const;
903
904           // Fill an AudioDescriptor struct with the values from the file's header.
905           // Returns RESULT_INIT if the file is not open.
906           Result_t FillAudioDescriptor(AudioDescriptor&) const;
907
908           // Rewind the stream to the beginning.
909           Result_t Reset() const;
910
911           // Reads the next sequential frame in the input file and places it in the
912           // frame buffer. Fails if the buffer is too small or the stream is empty.
913           Result_t ReadFrame(FrameBuffer&) const;
914         };
915
916
917       //
918       class MXFWriter
919         {
920           class h__Writer;
921           mem_ptr<h__Writer> m_Writer;
922           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
923
924         public:
925           MXFWriter();
926           virtual ~MXFWriter();
927
928           // Warning: direct manipulation of MXF structures can interfere
929           // with the normal operation of the wrapper.  Caveat emptor!
930           virtual MXF::OPAtomHeader& OPAtomHeader();
931           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
932
933           // Open the file for writing. The file must not exist. Returns error if
934           // the operation cannot be completed or if nonsensical data is discovered
935           // in the essence descriptor.
936           Result_t OpenWrite(const char* filename, const WriterInfo&,
937                              const AudioDescriptor&, ui32_t HeaderSize = 16384);
938
939           // Writes a frame of essence to the MXF file. If the optional AESEncContext
940           // argument is present, the essence is encrypted prior to writing.
941           // Fails if the file is not open, is finalized, or an operating system
942           // error occurs.
943           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
944
945           // Closes the MXF file, writing the index and revised header.
946           Result_t Finalize();
947         };
948
949       //
950       class MXFReader
951         {
952           class h__Reader;
953           mem_ptr<h__Reader> m_Reader;
954           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
955
956         public:
957           MXFReader();
958           virtual ~MXFReader();
959
960           // Warning: direct manipulation of MXF structures can interfere
961           // with the normal operation of the wrapper.  Caveat emptor!
962           virtual MXF::OPAtomHeader& OPAtomHeader();
963           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
964
965           // Open the file for reading. The file must exist. Returns error if the
966           // operation cannot be completed.
967           Result_t OpenRead(const char* filename) const;
968
969           // Returns RESULT_INIT if the file is not open.
970           Result_t Close() const;
971
972           // Fill an AudioDescriptor struct with the values from the file's header.
973           // Returns RESULT_INIT if the file is not open.
974           Result_t FillAudioDescriptor(AudioDescriptor&) const;
975
976           // Fill a WriterInfo struct with the values from the file's header.
977           // Returns RESULT_INIT if the file is not open.
978           Result_t FillWriterInfo(WriterInfo&) const;
979
980           // Reads a frame of essence from the MXF file. If the optional AESEncContext
981           // argument is present, the essence is decrypted after reading. If the MXF
982           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
983           // will contain the ciphertext frame data. If the HMACContext argument is
984           // not NULL, the HMAC will be calculated (if the file supports it).
985           // Returns RESULT_INIT if the file is not open, failure if the frame number is
986           // out of range, or if optional decrypt or HAMC operations fail.
987           Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
988
989           // Print debugging information to stream
990           void     DumpHeaderMetadata(FILE* = 0) const;
991           void     DumpIndex(FILE* = 0) const;
992         };
993     } // namespace PCM
994
995   //---------------------------------------------------------------------------------
996   //
997   namespace JP2K
998     {
999       const ui32_t MaxComponents = 3;
1000       const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
1001       const ui32_t MaxDefaults = 256; // made up
1002
1003 #pragma pack(1)
1004       struct ImageComponent_t  // ISO 15444-1 Annex A.5.1
1005       {
1006         ui8_t Ssize;
1007         ui8_t XRsize;
1008         ui8_t YRsize;
1009       };
1010
1011       struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
1012       {
1013         ui8_t   Scod;
1014
1015         struct
1016         {
1017           ui8_t  ProgressionOrder;
1018           ui8_t  NumberOfLayers[sizeof(ui16_t)];
1019           ui8_t  MultiCompTransform;
1020         } SGcod;
1021         
1022         struct
1023         {
1024           ui8_t  DecompositionLevels;
1025           ui8_t  CodeblockWidth;
1026           ui8_t  CodeblockHeight;
1027           ui8_t  CodeblockStyle;
1028           ui8_t  Transformation;
1029           ui8_t  PrecinctSize[MaxPrecincts];
1030         } SPcod;
1031       };
1032
1033       struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
1034       {
1035         ui8_t  Sqcd;
1036         ui8_t  SPqcd[MaxDefaults];
1037         ui8_t  SPqcdLength;
1038       };
1039 #pragma pack()
1040
1041       struct PictureDescriptor
1042       {
1043         Rational       EditRate;
1044         ui32_t         ContainerDuration;
1045         Rational       SampleRate;
1046         ui32_t         StoredWidth;
1047         ui32_t         StoredHeight;
1048         Rational       AspectRatio;
1049         ui16_t         Rsize;
1050         ui32_t         Xsize;
1051         ui32_t         Ysize;
1052         ui32_t         XOsize;
1053         ui32_t         YOsize;
1054         ui32_t         XTsize;
1055         ui32_t         YTsize;
1056         ui32_t         XTOsize;
1057         ui32_t         YTOsize;
1058         ui16_t         Csize;
1059         ImageComponent_t      ImageComponents[MaxComponents];
1060         CodingStyleDefault_t  CodingStyleDefault;
1061         QuantizationDefault_t QuantizationDefault;
1062       };
1063
1064       // Print debugging information to std::ostream
1065       std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
1066       // Print debugging information to stream (stderr default)
1067       void   PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
1068
1069       //
1070       class FrameBuffer : public ASDCP::FrameBuffer
1071         {
1072         public:
1073           FrameBuffer() {}
1074           FrameBuffer(ui32_t size) { Capacity(size); }
1075           virtual ~FrameBuffer() {}
1076         
1077           // Print debugging information to stream (stderr default)
1078           void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1079         };
1080
1081
1082       // An object which opens and reads a JPEG 2000 codestream file.  The file is expected
1083       // to contain exactly one complete frame of picture essence as an unwrapped (raw)
1084       // ISO/IEC 15444 codestream.
1085       class CodestreamParser
1086         {
1087           class h__CodestreamParser;
1088           mem_ptr<h__CodestreamParser> m_Parser;
1089           ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
1090
1091         public:
1092           CodestreamParser();
1093           virtual ~CodestreamParser();
1094
1095           // Opens a file for reading, parses enough data to provide a complete
1096           // set of stream metadata for the MXFWriter below.
1097           // The frame buffer's PlaintextOffset parameter will be set to the first
1098           // byte of the data segment. Set this value to zero if you want
1099           // encrypted headers.
1100           Result_t OpenReadFrame(const char* filename, FrameBuffer&) const;
1101
1102           // Fill a PictureDescriptor struct with the values from the file's codestream.
1103           // Returns RESULT_INIT if the file is not open.
1104           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1105         };
1106
1107       // Parses the data in the frame buffer to fill in the picture descriptor. Copies
1108       // the offset of the image data into start_of_data. Returns error if the parser fails.
1109       Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
1110
1111       // An object which reads a sequence of files containing JPEG 2000 pictures.
1112       class SequenceParser
1113         {
1114           class h__SequenceParser;
1115           mem_ptr<h__SequenceParser> m_Parser;
1116           ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1117
1118         public:
1119           SequenceParser();
1120           virtual ~SequenceParser();
1121
1122           // Opens a directory for reading.  The directory is expected to contain one or
1123           // more files, each containing the codestream for exactly one picture. The
1124           // files must be named such that the frames are in temporal order when sorted
1125           // alphabetically by filename. The parser will automatically parse enough data
1126           // from the first file to provide a complete set of stream metadata for the
1127           // MXFWriter below.  If the "pedantic" parameter is given and is true, the
1128           // parser will check the metadata for each codestream and fail if a 
1129           // mismatch is detected.
1130           Result_t OpenRead(const char* filename, bool pedantic = false) const;
1131
1132           // Opens a file sequence for reading.  The sequence is expected to contain one or
1133           // more filenames, each naming a file containing the codestream for exactly one
1134           // picture. The parser will automatically parse enough data
1135           // from the first file to provide a complete set of stream metadata for the
1136           // MXFWriter below.  If the "pedantic" parameter is given and is true, the
1137           // parser will check the metadata for each codestream and fail if a 
1138           // mismatch is detected.
1139           Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic = false) const;
1140
1141           // Fill a PictureDescriptor struct with the values from the first file's codestream.
1142           // Returns RESULT_INIT if the directory is not open.
1143           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1144
1145           // Rewind the directory to the beginning.
1146           Result_t Reset() const;
1147
1148           // Reads the next sequential frame in the directory and places it in the
1149           // frame buffer. Fails if the buffer is too small or the direcdtory
1150           // contains no more files.
1151           // The frame buffer's PlaintextOffset parameter will be set to the first
1152           // byte of the data segment. Set this value to zero if you want
1153           // encrypted headers.
1154           Result_t ReadFrame(FrameBuffer&) const;
1155         };
1156
1157
1158       //
1159       class MXFWriter
1160         {
1161           class h__Writer;
1162           mem_ptr<h__Writer> m_Writer;
1163           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1164
1165         public:
1166           MXFWriter();
1167           virtual ~MXFWriter();
1168
1169           // Warning: direct manipulation of MXF structures can interfere
1170           // with the normal operation of the wrapper.  Caveat emptor!
1171           virtual MXF::OPAtomHeader& OPAtomHeader();
1172           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1173
1174           // Open the file for writing. The file must not exist. Returns error if
1175           // the operation cannot be completed or if nonsensical data is discovered
1176           // in the essence descriptor.
1177           Result_t OpenWrite(const char* filename, const WriterInfo&,
1178                              const PictureDescriptor&, ui32_t HeaderSize = 16384);
1179
1180           // Writes a frame of essence to the MXF file. If the optional AESEncContext
1181           // argument is present, the essence is encrypted prior to writing.
1182           // Fails if the file is not open, is finalized, or an operating system
1183           // error occurs.
1184           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1185
1186           // Closes the MXF file, writing the index and revised header.
1187           Result_t Finalize();
1188         };
1189
1190       //
1191       class MXFReader
1192         {
1193           class h__Reader;
1194           mem_ptr<h__Reader> m_Reader;
1195           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1196
1197         public:
1198           MXFReader();
1199           virtual ~MXFReader();
1200
1201           // Warning: direct manipulation of MXF structures can interfere
1202           // with the normal operation of the wrapper.  Caveat emptor!
1203           virtual MXF::OPAtomHeader& OPAtomHeader();
1204           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1205
1206           // Open the file for reading. The file must exist. Returns error if the
1207           // operation cannot be completed.
1208           Result_t OpenRead(const char* filename) const;
1209
1210           // Returns RESULT_INIT if the file is not open.
1211           Result_t Close() const;
1212
1213           // Fill an AudioDescriptor struct with the values from the file's header.
1214           // Returns RESULT_INIT if the file is not open.
1215           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1216
1217           // Fill a WriterInfo struct with the values from the file's header.
1218           // Returns RESULT_INIT if the file is not open.
1219           Result_t FillWriterInfo(WriterInfo&) const;
1220
1221           // Reads a frame of essence from the MXF file. If the optional AESEncContext
1222           // argument is present, the essence is decrypted after reading. If the MXF
1223           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1224           // will contain the ciphertext frame data. If the HMACContext argument is
1225           // not NULL, the HMAC will be calculated (if the file supports it).
1226           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1227           // out of range, or if optional decrypt or HAMC operations fail.
1228           Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1229
1230           // Print debugging information to stream
1231           void     DumpHeaderMetadata(FILE* = 0) const;
1232           void     DumpIndex(FILE* = 0) const;
1233         };
1234
1235
1236       // Stereoscopic Image support
1237       //
1238
1239       enum StereoscopicPhase_t
1240       {
1241         SP_LEFT,
1242         SP_RIGHT
1243       };
1244       
1245       struct SFrameBuffer
1246       {
1247         JP2K::FrameBuffer Left;
1248         JP2K::FrameBuffer Right;
1249
1250         SFrameBuffer(ui32_t size) {
1251           Left.Capacity(size);
1252           Right.Capacity(size);
1253         }
1254       };
1255
1256       class MXFSWriter
1257       {
1258           class h__SWriter;
1259           mem_ptr<h__SWriter> m_Writer;
1260           ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
1261
1262         public:
1263           MXFSWriter();
1264           virtual ~MXFSWriter();
1265
1266           // Warning: direct manipulation of MXF structures can interfere
1267           // with the normal operation of the wrapper.  Caveat emptor!
1268           virtual MXF::OPAtomHeader& OPAtomHeader();
1269           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1270
1271           // Open the file for writing. The file must not exist. Returns error if
1272           // the operation cannot be completed or if nonsensical data is discovered
1273           // in the essence descriptor.
1274           Result_t OpenWrite(const char* filename, const WriterInfo&,
1275                              const PictureDescriptor&, ui32_t HeaderSize = 16384);
1276
1277           // Writes a pair of frames of essence to the MXF file. If the optional AESEncContext
1278           // argument is present, the essence is encrypted prior to writing.
1279           // Fails if the file is not open, is finalized, or an operating system
1280           // error occurs.
1281           Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1282
1283           // Writes a frame of essence to the MXF file. If the optional AESEncContext
1284           // argument is present, the essence is encrypted prior to writing.
1285           // Fails if the file is not open, is finalized, or an operating system
1286           // error occurs. Frames must be written in the proper phase (L-R-L-R),
1287           // RESULT_SPHASE will be returned if phase is reversed. The first frame
1288           // written must be left eye.
1289           Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
1290                               AESEncContext* = 0, HMACContext* = 0);
1291
1292           // Closes the MXF file, writing the index and revised header.  Returns
1293           // RESULT_SPHASE if WriteFrame was called an odd number of times.
1294           Result_t Finalize();
1295         };
1296
1297       //
1298       class MXFSReader
1299         {
1300           class h__SReader;
1301           mem_ptr<h__SReader> m_Reader;
1302           ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
1303
1304         public:
1305           MXFSReader();
1306           virtual ~MXFSReader();
1307
1308           // Warning: direct manipulation of MXF structures can interfere
1309           // with the normal operation of the wrapper.  Caveat emptor!
1310           virtual MXF::OPAtomHeader& OPAtomHeader();
1311           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1312
1313           // Open the file for reading. The file must exist. Returns error if the
1314           // operation cannot be completed.
1315           Result_t OpenRead(const char* filename) const;
1316
1317           // Returns RESULT_INIT if the file is not open.
1318           Result_t Close() const;
1319
1320           // Fill an AudioDescriptor struct with the values from the file's header.
1321           // Returns RESULT_INIT if the file is not open.
1322           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1323
1324           // Fill a WriterInfo struct with the values from the file's header.
1325           // Returns RESULT_INIT if the file is not open.
1326           Result_t FillWriterInfo(WriterInfo&) const;
1327
1328           // Reads a pair of frames of essence from the MXF file. If the optional AESEncContext
1329           // argument is present, the essence is decrypted after reading. If the MXF
1330           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1331           // will contain the ciphertext frame data. If the HMACContext argument is
1332           // not NULL, the HMAC will be calculated (if the file supports it).
1333           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1334           // out of range, or if optional decrypt or HAMC operations fail.
1335           Result_t ReadFrame(ui32_t frame_number, SFrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1336
1337           // Reads a frame of essence from the MXF file. If the optional AESEncContext
1338           // argument is present, the essence is decrypted after reading. If the MXF
1339           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1340           // will contain the ciphertext frame data. If the HMACContext argument is
1341           // not NULL, the HMAC will be calculated (if the file supports it).
1342           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1343           // out of range, or if optional decrypt or HAMC operations fail.
1344           Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
1345                              FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1346
1347           // Print debugging information to stream
1348           void     DumpHeaderMetadata(FILE* = 0) const;
1349           void     DumpIndex(FILE* = 0) const;
1350         };
1351     } // namespace JP2K
1352
1353   //---------------------------------------------------------------------------------
1354   //
1355   namespace TimedText
1356     {
1357       enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
1358
1359       struct TimedTextResourceDescriptor
1360       {
1361         byte_t      ResourceID[UUIDlen];
1362         MIMEType_t  Type;
1363
1364         TimedTextResourceDescriptor() : Type(MT_BIN) {}
1365       };
1366
1367       typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
1368
1369       struct TimedTextDescriptor
1370       {
1371         Rational       EditRate;                // 
1372         ui32_t         ContainerDuration;
1373         byte_t         AssetID[UUIDlen];
1374         std::string    NamespaceName;
1375         std::string    EncodingName;
1376         ResourceList_t ResourceList;
1377
1378       TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8
1379       };
1380
1381       // Print debugging information to std::ostream
1382       std::ostream& operator << (std::ostream& strm, const TimedTextDescriptor& tinfo);
1383       // Print debugging information to stream (stderr default)
1384       void   DescriptorDump(const TimedTextDescriptor&, FILE* = 0);
1385
1386       //
1387       class FrameBuffer : public ASDCP::FrameBuffer
1388       {
1389         ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
1390
1391       protected:
1392         byte_t      m_AssetID[UUIDlen];
1393         std::string m_MIMEType;
1394
1395       public:
1396         FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
1397         FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
1398         virtual ~FrameBuffer() {}
1399         
1400         inline const byte_t* AssetID() const { return m_AssetID; }
1401         inline void          AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); }
1402         inline const char*   MIMEType() const { return m_MIMEType.c_str(); }
1403         inline void          MIMEType(const std::string& s) { m_MIMEType = s; }
1404
1405         // Print debugging information to stream (stderr default)
1406         void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1407       };
1408
1409       //
1410       class IResourceResolver
1411       {
1412       public:
1413         virtual ~IResourceResolver() {}
1414         virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
1415       };
1416
1417       //
1418       class DCSubtitleParser
1419         {
1420           class h__SubtitleParser;
1421           mem_ptr<h__SubtitleParser> m_Parser;
1422           ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
1423
1424         public:
1425           DCSubtitleParser();
1426           virtual ~DCSubtitleParser();
1427
1428           // Opens an XML file for reading, parses data to provide a complete
1429           // set of stream metadata for the MXFWriter below.
1430           Result_t OpenRead(const char* filename) const;
1431
1432           // Parses an XML document to provide a complete set of stream metadata
1433           // for the MXFWriter below. The optional filename argument is used to
1434           // initialize the default resource resolver (see ReadAncillaryResource).
1435           Result_t OpenRead(const std::string& xml_doc, const char* filename = 0) const;
1436
1437           // Fill a TimedTextDescriptor struct with the values from the file's contents.
1438           // Returns RESULT_INIT if the file is not open.
1439           Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1440
1441           // Reads the complete Timed Text Resource into the given string.
1442           Result_t ReadTimedTextResource(std::string&) const;
1443
1444           // Reads the Ancillary Resource having the given ID. Fails if the buffer
1445           // is too small or the resource does not exist. The optional Resolver
1446           // argument can be provided which will be used to retrieve the resource
1447           // having a particulat UUID. If a Resolver is not supplied, the default
1448           // internal resolver will return the contents of the file having the UUID
1449           // as the filename. The filename must exist in the same directory as the
1450           // XML file opened with OpenRead().
1451           Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
1452                                          const IResourceResolver* Resolver = 0) const;
1453         };
1454
1455       //
1456       class MXFWriter
1457         {
1458           class h__Writer;
1459           mem_ptr<h__Writer> m_Writer;
1460           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1461
1462         public:
1463           MXFWriter();
1464           virtual ~MXFWriter();
1465
1466           // Warning: direct manipulation of MXF structures can interfere
1467           // with the normal operation of the wrapper.  Caveat emptor!
1468           virtual MXF::OPAtomHeader& OPAtomHeader();
1469           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1470
1471           // Open the file for writing. The file must not exist. Returns error if
1472           // the operation cannot be completed or if nonsensical data is discovered
1473           // in the essence descriptor.
1474           Result_t OpenWrite(const char* filename, const WriterInfo&,
1475                              const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
1476
1477           // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
1478           // encoded. If the optional AESEncContext argument is present, the essence
1479           // is encrypted prior to writing. Fails if the file is not open, is finalized,
1480           // or an operating system error occurs.
1481           // This method may only be called once, and it must be called before any
1482           // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
1483           // conditions are not met.
1484           Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
1485
1486           // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
1487           // argument is present, the essence is encrypted prior to writing.
1488           // Fails if the file is not open, is finalized, or an operating system
1489           // error occurs. RESULT_STATE will be returned if the method is called before
1490           // WriteTimedTextResource()
1491           Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1492
1493           // Closes the MXF file, writing the index and revised header.
1494           Result_t Finalize();
1495         };
1496
1497       //
1498       class MXFReader
1499         {
1500           class h__Reader;
1501           mem_ptr<h__Reader> m_Reader;
1502           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1503
1504         public:
1505           MXFReader();
1506           virtual ~MXFReader();
1507
1508           // Warning: direct manipulation of MXF structures can interfere
1509           // with the normal operation of the wrapper.  Caveat emptor!
1510           virtual MXF::OPAtomHeader& OPAtomHeader();
1511           virtual MXF::OPAtomIndexFooter& OPAtomIndexFooter();
1512
1513           // Open the file for reading. The file must exist. Returns error if the
1514           // operation cannot be completed.
1515           Result_t OpenRead(const char* filename) const;
1516
1517           // Returns RESULT_INIT if the file is not open.
1518           Result_t Close() const;
1519
1520           // Fill a TimedTextDescriptor struct with the values from the file's header.
1521           // Returns RESULT_INIT if the file is not open.
1522           Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1523
1524           // Fill a WriterInfo struct with the values from the file's header.
1525           // Returns RESULT_INIT if the file is not open.
1526           Result_t FillWriterInfo(WriterInfo&) const;
1527
1528           // Reads the complete Timed Text Resource into the given string. Fails if the resource
1529           // is encrypted and AESDecContext is NULL (use the following method to retrieve the
1530           // raw ciphertet block).
1531           Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
1532
1533           // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
1534           // argument is present, the resource is decrypted after reading. If the MXF
1535           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1536           // will contain the ciphertext frame data. If the HMACContext argument is
1537           // not NULL, the HMAC will be calculated (if the file supports it).
1538           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1539           // out of range, or if optional decrypt or HAMC operations fail.
1540           Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1541
1542           // Reads the timed-text resource having the given UUID from the MXF file. If the
1543           // optional AESEncContext argument is present, the resource is decrypted after
1544           // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
1545           // the frame buffer will contain the ciphertext frame data. If the HMACContext
1546           // argument is not NULL, the HMAC will be calculated (if the file supports it).
1547           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1548           // out of range, or if optional decrypt or HAMC operations fail.
1549           Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1550
1551           // Print debugging information to stream
1552           void     DumpHeaderMetadata(FILE* = 0) const;
1553           void     DumpIndex(FILE* = 0) const;
1554         };
1555     } // namespace TimedText
1556
1557
1558 } // namespace ASDCP
1559
1560
1561 #endif // _AS_DCP_H_
1562
1563 //
1564 // end AS_DCP.h
1565 //