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