release candidate
[asdcplib.git] / src / AS_DCP.h
1 /*
2 Copyright (c) 2003-2010, 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 429-2-2009 DCP Operational Constraints
38  o SMPTE 429-3-2006 Track File Specification
39  o SMPTE 429-4-2006 JPEG 2000 for D-Cinema
40  o SMPTE 429-5-2009 Timed Text Track File
41  o SMPTE 429-6-2006 Essence Encryption Specification
42  o SMPTE 429-10-2008 Stereoscopic Image Track File
43  o SMPTE 330M - UMID
44  o SMPTE 336M - KLV
45  o SMPTE 377M - MXF
46  o SMPTE 390M - OP-Atom
47  o SMPTE 379M - Generic Container
48  o SMPTE 381M - MPEG2 picture
49  o SMPTE 422M - JPEG 2000 picture
50  o SMPTE 382M - WAV/PCM sound
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 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   const Kumu::Result_t RESULT_FORMAT     (-101, "The file format is not proper OP-Atom/AS-DCP.");
184   const Kumu::Result_t RESULT_RAW_ESS    (-102, "Unknown raw essence file type.");
185   const Kumu::Result_t RESULT_RAW_FORMAT (-103, "Raw essence format invalid.");
186   const Kumu::Result_t RESULT_RANGE      (-104, "Frame number out of range.");
187   const Kumu::Result_t RESULT_CRYPT_CTX  (-105, "AESEncContext required when writing to encrypted file.");
188   const Kumu::Result_t RESULT_LARGE_PTO  (-106, "Plaintext offset exceeds frame buffer size.");
189   const Kumu::Result_t RESULT_CAPEXTMEM  (-107, "Cannot resize externally allocated memory.");
190   const Kumu::Result_t RESULT_CHECKFAIL  (-108, "The check value did not decrypt correctly.");
191   const Kumu::Result_t RESULT_HMACFAIL   (-109, "HMAC authentication failure.");
192   const Kumu::Result_t RESULT_HMAC_CTX   (-110, "HMAC context required.");
193   const Kumu::Result_t RESULT_CRYPT_INIT (-111, "Error initializing block cipher context.");
194   const Kumu::Result_t RESULT_EMPTY_FB   (-112, "Empty frame buffer.");
195   const Kumu::Result_t RESULT_KLV_CODING (-113, "KLV coding error.");
196   const Kumu::Result_t RESULT_SPHASE     (-114, "Stereoscopic phase mismatch.");
197   const Kumu::Result_t 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(24,1);
265   const Rational EditRate_23_98(24000,1001); // Not a DCI-compliant value!
266   const Rational EditRate_48(48,1);
267   const Rational SampleRate_48k(48000,1);
268   const Rational SampleRate_96k(96000,1);
269
270   // Additional frame rates, see ST 428-11
271   // These rates are new and not supported by all systems. Do not assume that
272   // a package made using on of these rates will work just anywhere!
273   const Rational EditRate_25(25,1);
274   const Rational EditRate_30(30,1);
275   const Rational EditRate_50(50,1);
276   const Rational EditRate_60(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 with optional HI/VI
796       };
797
798       struct AudioDescriptor
799         {
800           Rational EditRate;         // rate of frame wrapping
801           Rational AudioSamplingRate;  // rate of audio sample
802           ui32_t   Locked;             // 
803           ui32_t   ChannelCount;       // number of channels
804           ui32_t   QuantizationBits;   // number of bits per single-channel sample
805           ui32_t   BlockAlign;         // number of bytes ber sample, all channels
806           ui32_t   AvgBps;             // 
807           ui32_t   LinkedTrackID;      // 
808           ui32_t   ContainerDuration;  // number of frames
809           ChannelFormat_t ChannelFormat; // audio channel arrangement
810       };
811
812       // Print AudioDescriptor to std::ostream
813       std::ostream& operator << (std::ostream& strm, const AudioDescriptor& adesc);
814       // Print debugging information to stream (stderr default)
815       void   AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
816
817       // Returns size in bytes of a single sample of data described by ADesc
818       inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
819         {
820           return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
821         }
822
823       // Returns number of samples per frame of data described by ADesc
824       inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
825         {
826           double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.EditRate.Quotient();
827           return (ui32_t)ceil(tmpd);
828         }
829
830       // Returns the size in bytes of a frame of data described by ADesc
831       inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
832         {
833           return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
834         }
835
836       //
837       class FrameBuffer : public ASDCP::FrameBuffer
838         {
839         public:
840           FrameBuffer() {}
841           FrameBuffer(ui32_t size) { Capacity(size); }
842           virtual ~FrameBuffer() {}
843         
844           // Print debugging information to stream (stderr default)
845           void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
846         };
847
848       // An object which opens and reads a WAV file.  The call to OpenRead() reads metadata from
849       // the file and populates an internal AudioDescriptor object. Each subsequent call to
850       // ReadFrame() reads exactly one frame from the stream into the given FrameBuffer object.
851       // A "frame" is either 2000 or 2002 samples, depending upon the value of PictureRate.
852       class WAVParser
853         {
854           class h__WAVParser;
855           mem_ptr<h__WAVParser> m_Parser;
856           ASDCP_NO_COPY_CONSTRUCT(WAVParser);
857
858         public:
859           WAVParser();
860           virtual ~WAVParser();
861
862           // Opens the stream for reading, parses enough data to provide a complete
863           // set of stream metadata for the MXFWriter below. PictureRate controls
864           // ther frame rate for the MXF frame wrapping option.
865           Result_t OpenRead(const char* filename, const Rational& PictureRate) const;
866
867           // Fill an AudioDescriptor struct with the values from the file's header.
868           // Returns RESULT_INIT if the file is not open.
869           Result_t FillAudioDescriptor(AudioDescriptor&) const;
870
871           // Rewind the stream to the beginning.
872           Result_t Reset() const;
873
874           // Reads the next sequential frame in the input file and places it in the
875           // frame buffer. Fails if the buffer is too small or the stream is empty.
876           Result_t ReadFrame(FrameBuffer&) const;
877         };
878
879
880       //
881       class MXFWriter
882         {
883           class h__Writer;
884           mem_ptr<h__Writer> m_Writer;
885           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
886
887         public:
888           MXFWriter();
889           virtual ~MXFWriter();
890
891           // Open the file for writing. The file must not exist. Returns error if
892           // the operation cannot be completed or if nonsensical data is discovered
893           // in the essence descriptor.
894           Result_t OpenWrite(const char* filename, const WriterInfo&,
895                              const AudioDescriptor&, ui32_t HeaderSize = 16384);
896
897           // Writes a frame of essence to the MXF file. If the optional AESEncContext
898           // argument is present, the essence is encrypted prior to writing.
899           // Fails if the file is not open, is finalized, or an operating system
900           // error occurs.
901           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
902
903           // Closes the MXF file, writing the index and revised header.
904           Result_t Finalize();
905         };
906
907       //
908       class MXFReader
909         {
910           class h__Reader;
911           mem_ptr<h__Reader> m_Reader;
912           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
913
914         public:
915           MXFReader();
916           virtual ~MXFReader();
917
918           // Open the file for reading. The file must exist. Returns error if the
919           // operation cannot be completed.
920           Result_t OpenRead(const char* filename) const;
921
922           // Returns RESULT_INIT if the file is not open.
923           Result_t Close() const;
924
925           // Fill an AudioDescriptor struct with the values from the file's header.
926           // Returns RESULT_INIT if the file is not open.
927           Result_t FillAudioDescriptor(AudioDescriptor&) const;
928
929           // Fill a WriterInfo struct with the values from the file's header.
930           // Returns RESULT_INIT if the file is not open.
931           Result_t FillWriterInfo(WriterInfo&) const;
932
933           // Reads a frame of essence from the MXF file. If the optional AESEncContext
934           // argument is present, the essence is decrypted after reading. If the MXF
935           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
936           // will contain the ciphertext frame data. If the HMACContext argument is
937           // not NULL, the HMAC will be calculated (if the file supports it).
938           // Returns RESULT_INIT if the file is not open, failure if the frame number is
939           // out of range, or if optional decrypt or HAMC operations fail.
940           Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
941
942           // Print debugging information to stream
943           void     DumpHeaderMetadata(FILE* = 0) const;
944           void     DumpIndex(FILE* = 0) const;
945         };
946     } // namespace PCM
947
948   //---------------------------------------------------------------------------------
949   //
950   namespace JP2K
951     {
952       const ui32_t MaxComponents = 3;
953       const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
954       const ui32_t MaxDefaults = 256; // made up
955
956 #pragma pack(1)
957       struct ImageComponent_t  // ISO 15444-1 Annex A.5.1
958       {
959         ui8_t Ssize;
960         ui8_t XRsize;
961         ui8_t YRsize;
962       };
963
964       struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1
965       {
966         ui8_t   Scod;
967
968         struct
969         {
970           ui8_t  ProgressionOrder;
971           ui8_t  NumberOfLayers[sizeof(ui16_t)];
972           ui8_t  MultiCompTransform;
973         } SGcod;
974         
975         struct
976         {
977           ui8_t  DecompositionLevels;
978           ui8_t  CodeblockWidth;
979           ui8_t  CodeblockHeight;
980           ui8_t  CodeblockStyle;
981           ui8_t  Transformation;
982           ui8_t  PrecinctSize[MaxPrecincts];
983         } SPcod;
984       };
985
986       struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4
987       {
988         ui8_t  Sqcd;
989         ui8_t  SPqcd[MaxDefaults];
990         ui8_t  SPqcdLength;
991       };
992 #pragma pack()
993
994       struct PictureDescriptor
995       {
996         Rational       EditRate;
997         ui32_t         ContainerDuration;
998         Rational       SampleRate;
999         ui32_t         StoredWidth;
1000         ui32_t         StoredHeight;
1001         Rational       AspectRatio;
1002         ui16_t         Rsize;
1003         ui32_t         Xsize;
1004         ui32_t         Ysize;
1005         ui32_t         XOsize;
1006         ui32_t         YOsize;
1007         ui32_t         XTsize;
1008         ui32_t         YTsize;
1009         ui32_t         XTOsize;
1010         ui32_t         YTOsize;
1011         ui16_t         Csize;
1012         ImageComponent_t      ImageComponents[MaxComponents];
1013         CodingStyleDefault_t  CodingStyleDefault;
1014         QuantizationDefault_t QuantizationDefault;
1015       };
1016
1017       // Print debugging information to std::ostream
1018       std::ostream& operator << (std::ostream& strm, const PictureDescriptor& pdesc);
1019       // Print debugging information to stream (stderr default)
1020       void   PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
1021
1022       //
1023       class FrameBuffer : public ASDCP::FrameBuffer
1024         {
1025         public:
1026           FrameBuffer() {}
1027           FrameBuffer(ui32_t size) { Capacity(size); }
1028           virtual ~FrameBuffer() {}
1029         
1030           // Print debugging information to stream (stderr default)
1031           void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1032         };
1033
1034
1035       // An object which opens and reads a JPEG 2000 codestream file.  The file is expected
1036       // to contain exactly one complete frame of picture essence as an unwrapped (raw)
1037       // ISO/IEC 15444 codestream.
1038       class CodestreamParser
1039         {
1040           class h__CodestreamParser;
1041           mem_ptr<h__CodestreamParser> m_Parser;
1042           ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
1043
1044         public:
1045           CodestreamParser();
1046           virtual ~CodestreamParser();
1047
1048           // Opens a file for reading, parses enough data to provide a complete
1049           // set of stream metadata for the MXFWriter below.
1050           // The frame buffer's PlaintextOffset parameter will be set to the first
1051           // byte of the data segment. Set this value to zero if you want
1052           // encrypted headers.
1053           Result_t OpenReadFrame(const char* filename, FrameBuffer&) const;
1054
1055           // Fill a PictureDescriptor struct with the values from the file's codestream.
1056           // Returns RESULT_INIT if the file is not open.
1057           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1058         };
1059
1060       // Parses the data in the frame buffer to fill in the picture descriptor. Copies
1061       // the offset of the image data into start_of_data. Returns error if the parser fails.
1062       Result_t ParseMetadataIntoDesc(const FrameBuffer&, PictureDescriptor&, byte_t* start_of_data = 0);
1063
1064       // An object which reads a sequence of files containing JPEG 2000 pictures.
1065       class SequenceParser
1066         {
1067           class h__SequenceParser;
1068           mem_ptr<h__SequenceParser> m_Parser;
1069           ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
1070
1071         public:
1072           SequenceParser();
1073           virtual ~SequenceParser();
1074
1075           // Opens a directory for reading.  The directory is expected to contain one or
1076           // more files, each containing the codestream for exactly one picture. The
1077           // files must be named such that the frames are in temporal order when sorted
1078           // alphabetically by filename. The parser will automatically parse enough data
1079           // from the first file to provide a complete set of stream metadata for the
1080           // MXFWriter below.  If the "pedantic" parameter is given and is true, the
1081           // parser will check the metadata for each codestream and fail if a 
1082           // mismatch is detected.
1083           Result_t OpenRead(const char* filename, bool pedantic = false) const;
1084
1085           // Opens a file sequence for reading.  The sequence is expected to contain one or
1086           // more filenames, each naming a file containing the codestream for exactly one
1087           // picture. The parser will automatically parse enough data
1088           // from the first file to provide a complete set of stream metadata for the
1089           // MXFWriter below.  If the "pedantic" parameter is given and is true, the
1090           // parser will check the metadata for each codestream and fail if a 
1091           // mismatch is detected.
1092           Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic = false) const;
1093
1094           // Fill a PictureDescriptor struct with the values from the first file's codestream.
1095           // Returns RESULT_INIT if the directory is not open.
1096           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1097
1098           // Rewind the directory to the beginning.
1099           Result_t Reset() const;
1100
1101           // Reads the next sequential frame in the directory and places it in the
1102           // frame buffer. Fails if the buffer is too small or the direcdtory
1103           // contains no more files.
1104           // The frame buffer's PlaintextOffset parameter will be set to the first
1105           // byte of the data segment. Set this value to zero if you want
1106           // encrypted headers.
1107           Result_t ReadFrame(FrameBuffer&) const;
1108         };
1109
1110
1111       //
1112       class MXFWriter
1113         {
1114           class h__Writer;
1115           mem_ptr<h__Writer> m_Writer;
1116           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1117
1118         public:
1119           MXFWriter();
1120           virtual ~MXFWriter();
1121
1122           // Open the file for writing. The file must not exist. Returns error if
1123           // the operation cannot be completed or if nonsensical data is discovered
1124           // in the essence descriptor.
1125           Result_t OpenWrite(const char* filename, const WriterInfo&,
1126                              const PictureDescriptor&, ui32_t HeaderSize = 16384);
1127
1128           // Writes a frame of essence to the MXF file. If the optional AESEncContext
1129           // argument is present, the essence is encrypted prior to writing.
1130           // Fails if the file is not open, is finalized, or an operating system
1131           // error occurs.
1132           Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1133
1134           // Closes the MXF file, writing the index and revised header.
1135           Result_t Finalize();
1136         };
1137
1138       //
1139       class MXFReader
1140         {
1141           class h__Reader;
1142           mem_ptr<h__Reader> m_Reader;
1143           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1144
1145         public:
1146           MXFReader();
1147           virtual ~MXFReader();
1148
1149           // Open the file for reading. The file must exist. Returns error if the
1150           // operation cannot be completed.
1151           Result_t OpenRead(const char* filename) const;
1152
1153           // Returns RESULT_INIT if the file is not open.
1154           Result_t Close() const;
1155
1156           // Fill an AudioDescriptor struct with the values from the file's header.
1157           // Returns RESULT_INIT if the file is not open.
1158           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1159
1160           // Fill a WriterInfo struct with the values from the file's header.
1161           // Returns RESULT_INIT if the file is not open.
1162           Result_t FillWriterInfo(WriterInfo&) const;
1163
1164           // Reads a frame of essence from the MXF file. If the optional AESEncContext
1165           // argument is present, the essence is decrypted after reading. If the MXF
1166           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1167           // will contain the ciphertext frame data. If the HMACContext argument is
1168           // not NULL, the HMAC will be calculated (if the file supports it).
1169           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1170           // out of range, or if optional decrypt or HAMC operations fail.
1171           Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1172
1173           // Print debugging information to stream
1174           void     DumpHeaderMetadata(FILE* = 0) const;
1175           void     DumpIndex(FILE* = 0) const;
1176         };
1177
1178
1179       // Stereoscopic Image support
1180       //
1181
1182       enum StereoscopicPhase_t
1183       {
1184         SP_LEFT,
1185         SP_RIGHT
1186       };
1187       
1188       struct SFrameBuffer
1189       {
1190         JP2K::FrameBuffer Left;
1191         JP2K::FrameBuffer Right;
1192
1193         SFrameBuffer(ui32_t size) {
1194           Left.Capacity(size);
1195           Right.Capacity(size);
1196         }
1197       };
1198
1199       class MXFSWriter
1200       {
1201           class h__SWriter;
1202           mem_ptr<h__SWriter> m_Writer;
1203           ASDCP_NO_COPY_CONSTRUCT(MXFSWriter);
1204
1205         public:
1206           MXFSWriter();
1207           virtual ~MXFSWriter();
1208
1209           // Open the file for writing. The file must not exist. Returns error if
1210           // the operation cannot be completed or if nonsensical data is discovered
1211           // in the essence descriptor.
1212           Result_t OpenWrite(const char* filename, const WriterInfo&,
1213                              const PictureDescriptor&, ui32_t HeaderSize = 16384);
1214
1215           // Writes a pair of frames of essence to the MXF file. If the optional AESEncContext
1216           // argument is present, the essence is encrypted prior to writing.
1217           // Fails if the file is not open, is finalized, or an operating system
1218           // error occurs.
1219           Result_t WriteFrame(const SFrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1220
1221           // Writes a frame of essence to the MXF file. If the optional AESEncContext
1222           // argument is present, the essence is encrypted prior to writing.
1223           // Fails if the file is not open, is finalized, or an operating system
1224           // error occurs. Frames must be written in the proper phase (L-R-L-R),
1225           // RESULT_SPHASE will be returned if phase is reversed. The first frame
1226           // written must be left eye.
1227           Result_t WriteFrame(const FrameBuffer&, StereoscopicPhase_t phase,
1228                               AESEncContext* = 0, HMACContext* = 0);
1229
1230           // Closes the MXF file, writing the index and revised header.  Returns
1231           // RESULT_SPHASE if WriteFrame was called an odd number of times.
1232           Result_t Finalize();
1233         };
1234
1235       //
1236       class MXFSReader
1237         {
1238           class h__SReader;
1239           mem_ptr<h__SReader> m_Reader;
1240           ASDCP_NO_COPY_CONSTRUCT(MXFSReader);
1241
1242         public:
1243           MXFSReader();
1244           virtual ~MXFSReader();
1245
1246           // Open the file for reading. The file must exist. Returns error if the
1247           // operation cannot be completed.
1248           Result_t OpenRead(const char* filename) const;
1249
1250           // Returns RESULT_INIT if the file is not open.
1251           Result_t Close() const;
1252
1253           // Fill an AudioDescriptor struct with the values from the file's header.
1254           // Returns RESULT_INIT if the file is not open.
1255           Result_t FillPictureDescriptor(PictureDescriptor&) const;
1256
1257           // Fill a WriterInfo struct with the values from the file's header.
1258           // Returns RESULT_INIT if the file is not open.
1259           Result_t FillWriterInfo(WriterInfo&) const;
1260
1261           // Reads a pair of frames of essence from the MXF file. If the optional AESEncContext
1262           // argument is present, the essence is decrypted after reading. If the MXF
1263           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1264           // will contain the ciphertext frame data. If the HMACContext argument is
1265           // not NULL, the HMAC will be calculated (if the file supports it).
1266           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1267           // out of range, or if optional decrypt or HAMC operations fail.
1268           Result_t ReadFrame(ui32_t frame_number, SFrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1269
1270           // Reads a frame of essence from the MXF file. If the optional AESEncContext
1271           // argument is present, the essence is decrypted after reading. If the MXF
1272           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1273           // will contain the ciphertext frame data. If the HMACContext argument is
1274           // not NULL, the HMAC will be calculated (if the file supports it).
1275           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1276           // out of range, or if optional decrypt or HAMC operations fail.
1277           Result_t ReadFrame(ui32_t frame_number, StereoscopicPhase_t phase,
1278                              FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1279
1280           // Print debugging information to stream
1281           void     DumpHeaderMetadata(FILE* = 0) const;
1282           void     DumpIndex(FILE* = 0) const;
1283         };
1284     } // namespace JP2K
1285
1286   //---------------------------------------------------------------------------------
1287   //
1288   namespace TimedText
1289     {
1290       enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE };
1291
1292       struct TimedTextResourceDescriptor
1293       {
1294         byte_t      ResourceID[UUIDlen];
1295         MIMEType_t  Type;
1296
1297         TimedTextResourceDescriptor() : Type(MT_BIN) {}
1298       };
1299
1300       typedef std::list<TimedTextResourceDescriptor> ResourceList_t;
1301
1302       struct TimedTextDescriptor
1303       {
1304         Rational       EditRate;                // 
1305         ui32_t         ContainerDuration;
1306         byte_t         AssetID[UUIDlen];
1307         std::string    NamespaceName;
1308         std::string    EncodingName;
1309         ResourceList_t ResourceList;
1310
1311       TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8
1312       };
1313
1314       // Print debugging information to std::ostream
1315       std::ostream& operator << (std::ostream& strm, const TimedTextDescriptor& tinfo);
1316       // Print debugging information to stream (stderr default)
1317       void   DescriptorDump(const TimedTextDescriptor&, FILE* = 0);
1318
1319       //
1320       class FrameBuffer : public ASDCP::FrameBuffer
1321       {
1322         ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
1323
1324       protected:
1325         byte_t      m_AssetID[UUIDlen];
1326         std::string m_MIMEType;
1327
1328       public:
1329         FrameBuffer() { memset(m_AssetID, 0, UUIDlen); }
1330         FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); }
1331         virtual ~FrameBuffer() {}
1332         
1333         inline const byte_t* AssetID() const { return m_AssetID; }
1334         inline void          AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); }
1335         inline const char*   MIMEType() const { return m_MIMEType.c_str(); }
1336         inline void          MIMEType(const std::string& s) { m_MIMEType = s; }
1337
1338         // Print debugging information to stream (stderr default)
1339         void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
1340       };
1341
1342       //
1343       class IResourceResolver
1344       {
1345       public:
1346         virtual ~IResourceResolver() {}
1347         virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID
1348       };
1349
1350       //
1351       class DCSubtitleParser
1352         {
1353           class h__SubtitleParser;
1354           mem_ptr<h__SubtitleParser> m_Parser;
1355           ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser);
1356
1357         public:
1358           DCSubtitleParser();
1359           virtual ~DCSubtitleParser();
1360
1361           // Opens an XML file for reading, parses data to provide a complete
1362           // set of stream metadata for the MXFWriter below.
1363           Result_t OpenRead(const char* filename) const;
1364
1365           // Parses an XML document to provide a complete set of stream metadata
1366           // for the MXFWriter below. The optional filename argument is used to
1367           // initialize the default resource resolver (see ReadAncillaryResource).
1368           Result_t OpenRead(const std::string& xml_doc, const char* filename = 0) const;
1369
1370           // Fill a TimedTextDescriptor struct with the values from the file's contents.
1371           // Returns RESULT_INIT if the file is not open.
1372           Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1373
1374           // Reads the complete Timed Text Resource into the given string.
1375           Result_t ReadTimedTextResource(std::string&) const;
1376
1377           // Reads the Ancillary Resource having the given ID. Fails if the buffer
1378           // is too small or the resource does not exist. The optional Resolver
1379           // argument can be provided which will be used to retrieve the resource
1380           // having a particulat UUID. If a Resolver is not supplied, the default
1381           // internal resolver will return the contents of the file having the UUID
1382           // as the filename. The filename must exist in the same directory as the
1383           // XML file opened with OpenRead().
1384           Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&,
1385                                          const IResourceResolver* Resolver = 0) const;
1386         };
1387
1388       //
1389       class MXFWriter
1390         {
1391           class h__Writer;
1392           mem_ptr<h__Writer> m_Writer;
1393           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1394
1395         public:
1396           MXFWriter();
1397           virtual ~MXFWriter();
1398
1399           // Open the file for writing. The file must not exist. Returns error if
1400           // the operation cannot be completed or if nonsensical data is discovered
1401           // in the essence descriptor.
1402           Result_t OpenWrite(const char* filename, const WriterInfo&,
1403                              const TimedTextDescriptor&, ui32_t HeaderSize = 16384);
1404
1405           // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
1406           // encoded. If the optional AESEncContext argument is present, the essence
1407           // is encrypted prior to writing. Fails if the file is not open, is finalized,
1408           // or an operating system error occurs.
1409           // This method may only be called once, and it must be called before any
1410           // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
1411           // conditions are not met.
1412           Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0);
1413
1414           // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
1415           // argument is present, the essence is encrypted prior to writing.
1416           // Fails if the file is not open, is finalized, or an operating system
1417           // error occurs. RESULT_STATE will be returned if the method is called before
1418           // WriteTimedTextResource()
1419           Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1420
1421           // Closes the MXF file, writing the index and revised header.
1422           Result_t Finalize();
1423         };
1424
1425       //
1426       class MXFReader
1427         {
1428           class h__Reader;
1429           mem_ptr<h__Reader> m_Reader;
1430           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1431
1432         public:
1433           MXFReader();
1434           virtual ~MXFReader();
1435
1436           // Open the file for reading. The file must exist. Returns error if the
1437           // operation cannot be completed.
1438           Result_t OpenRead(const char* filename) const;
1439
1440           // Returns RESULT_INIT if the file is not open.
1441           Result_t Close() const;
1442
1443           // Fill a TimedTextDescriptor struct with the values from the file's header.
1444           // Returns RESULT_INIT if the file is not open.
1445           Result_t FillTimedTextDescriptor(TimedTextDescriptor&) const;
1446
1447           // Fill a WriterInfo struct with the values from the file's header.
1448           // Returns RESULT_INIT if the file is not open.
1449           Result_t FillWriterInfo(WriterInfo&) const;
1450
1451           // Reads the complete Timed Text Resource into the given string. Fails if the resource
1452           // is encrypted and AESDecContext is NULL (use the following method to retrieve the
1453           // raw ciphertet block).
1454           Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const;
1455
1456           // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
1457           // argument is present, the resource is decrypted after reading. If the MXF
1458           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1459           // will contain the ciphertext frame data. If the HMACContext argument is
1460           // not NULL, the HMAC will be calculated (if the file supports it).
1461           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1462           // out of range, or if optional decrypt or HAMC operations fail.
1463           Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1464
1465           // Reads the timed-text resource having the given UUID from the MXF file. If the
1466           // optional AESEncContext argument is present, the resource is decrypted after
1467           // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
1468           // the frame buffer will contain the ciphertext frame data. If the HMACContext
1469           // argument is not NULL, the HMAC will be calculated (if the file supports it).
1470           // Returns RESULT_INIT if the file is not open, failure if the frame number is
1471           // out of range, or if optional decrypt or HAMC operations fail.
1472           Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1473
1474           // Print debugging information to stream
1475           void     DumpHeaderMetadata(FILE* = 0) const;
1476           void     DumpIndex(FILE* = 0) const;
1477         };
1478     } // namespace TimedText
1479
1480
1481 } // namespace ASDCP
1482
1483
1484 #endif // _AS_DCP_H_
1485
1486 //
1487 // end AS_DCP.h
1488 //