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