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