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