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