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