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