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