2 Copyright (c) 2003-2006, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
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.
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.
29 \brief AS-DCP library, public interface
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:
37 o AS-DCP Track File Specification
38 o AS-DCP Track File Essence Encryption Specification
39 o AS-DCP Operational Constraints Specification
43 o SMPTE 390M - OP-Atom
44 o SMPTE 379M - Generic Container
45 o SMPTE 381M - MPEG2 picture
46 o SMPTE XXXM - JPEG 2000 picture
47 o SMPTE 382M - WAV/PCM sound
48 o IETF RFC 2104 - HMAC/SHA1
49 o NIST FIPS 197 - AES (Rijndael)
51 The following use cases are supported by the library:
53 o Write a plaintext MPEG2 Video Elementary Stream to a plaintext ASDCP file
54 o Write a plaintext MPEG2 Video Elementary Stream to a ciphertext ASDCP file
55 o Read a plaintext MPEG2 Video Elementary Stream from a plaintext ASDCP file
56 o Read a plaintext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
57 o Read a ciphertext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
58 o Write one or more plaintext JPEG 2000 codestreams to a plaintext ASDCP file
59 o Write one or more plaintext JPEG 2000 codestreams to a ciphertext ASDCP file
60 o Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file
61 o Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file
62 o Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file
63 o Write one or more plaintext PCM audio streams to a plaintext ASDCP file
64 o Write one or more plaintext PCM audio streams to a ciphertext ASDCP file
65 o Read one or more plaintext PCM audio streams from a plaintext ASDCP file
66 o Read one or more plaintext PCM audio streams from a ciphertext ASDCP file
67 o Read one or more ciphertext PCM audio streams from a ciphertext ASDCP file
68 o Read header metadata from an ASDCP file
70 This project depends upon the following library:
71 - OpenSSL http://www.openssl.org/
83 //--------------------------------------------------------------------------------
84 // common integer types
85 // supply your own by defining ASDCP_NO_BASE_TYPES
87 #ifndef ASDCP_NO_BASE_TYPES
88 typedef unsigned char byte_t;
90 typedef unsigned char ui8_t;
92 typedef unsigned short ui16_t;
94 typedef unsigned int ui32_t;
98 //--------------------------------------------------------------------------------
101 // Convenience macros for managing return values in predicates
102 #define ASDCP_SUCCESS(v) (((v) < 0) ? 0 : 1)
103 #define ASDCP_FAILURE(v) (((v) < 0) ? 1 : 0)
106 // Returns RESULT_PTR if the given argument is NULL.
107 // See Result_t below for an explanation of RESULT_* symbols.
108 #define ASDCP_TEST_NULL(p) \
110 return ASDCP::RESULT_PTR; \
113 // Returns RESULT_PTR if the given argument is NULL. See Result_t
114 // below for an explanation of RESULT_* symbols. It then assumes
115 // that the argument is a pointer to a string and returns
116 // RESULT_NULL_STR if the first character is '\0'.
118 #define ASDCP_TEST_NULL_STR(p) \
119 ASDCP_TEST_NULL(p); \
120 if ( (p)[0] == '\0' ) { \
121 return ASDCP::RESULT_NULL_STR; \
124 // Produces copy constructor boilerplate. Allows convenient private
125 // declatarion of copy constructors to prevent the compiler from
126 // silently manufacturing default methods.
127 #define ASDCP_NO_COPY_CONSTRUCT(T) \
129 T& operator=(const T&)
132 //--------------------------------------------------------------------------------
133 // All library components are defined in the namespace ASDCP
136 // The version number consists of three segments: major, API minor, and
137 // implementation minor. Whenever a change is made to AS_DCP.h, the API minor
138 // version will increment. Changes made to the internal implementation will
139 // result in the incrementing of the implementation minor version.
141 // For example, if asdcplib version 1.0.0 were modified to accomodate changes
142 // in file format, and if no changes were made to AS_DCP.h, the new version would be
143 // 1.0.1. If changes were also required in AS_DCP.h, the new version would be 1.1.1.
144 const ui32_t VERSION_MAJOR = 1;
145 const ui32_t VERSION_APIMINOR = 0;
146 const ui32_t VERSION_IMPMINOR = 4;
147 const char* Version();
149 // UUIDs are passed around as strings of UUIDlen bytes
150 const ui32_t UUIDlen = 16;
152 // Encryption keys are passed around as strings of KeyLen bytes
153 const ui32_t KeyLen = 16;
155 // Key IDs are really UUIDs, so it makes no sense to have this value
156 // // Encryption key IDs are passed around as strings of KeyIDlen bytes
157 // const ui32_t KeyIDlen = 16;
160 //---------------------------------------------------------------------------------
163 // Error and debug messages will be delivered to an object having this interface.
164 // The default implementation sends only LOG_ERROR and LOG_WARN messages to stderr.
165 // To receive LOG_INFO or LOG_DEBUG messages, or to send messages somewhere other
166 // than stderr, implement this interface and register an instance of your new class
167 // by calling SetDefaultLogSink().
171 enum LogType_t { LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG };
173 virtual ~ILogSink() {}
174 virtual void Error(const char*, ...) = 0; // receives error messges
175 virtual void Warn(const char*, ...) = 0; // receives warning messges
176 virtual void Info(const char*, ...) = 0; // receives info messages
177 virtual void Debug(const char*, ...) = 0; // receives debug messages
178 virtual void Logf(LogType_t, const char*, ...) = 0; // log a formatted string with positional parameters
179 virtual void vLogf(LogType_t, const char*, va_list*) = 0; // log a formatted string with a va_list struct
182 // Sets the internal default sink to the given receiver. If the given value
183 // is zero, sets the default sink to the internally allocated stderr sink.
184 void SetDefaultLogSink(ILogSink* = 0);
186 // Returns the internal default sink.
187 ILogSink& DefaultLogSink();
189 //---------------------------------------------------------------------------------
192 // Each method or subroutine in this library that is not void or does not directly
193 // return a value will instead return a result code from this enumeration.
195 RESULT_FALSE = 1, // successful but negative
196 RESULT_OK = 0, // No errors detected
197 RESULT_FAIL = -1, // An undefined error was detected
198 RESULT_PTR = -2, // An unexpected NULL pointer was given
199 RESULT_NULL_STR = -3, // An unexpected empty string was given
200 RESULT_SMALLBUF = -4, // The given frame buffer is too small
201 RESULT_INIT = -5, // The object is not yet initialized
202 RESULT_NOT_FOUND = -6, // The requested file does not exist on the system
203 RESULT_NO_PERM = -7, // Insufficient privilege exists to perform the operation
204 RESULT_FILEOPEN = -8, // Failure opening file
205 RESULT_FORMAT = -9, // The file format is not proper OP-Atom/AS-DCP
206 RESULT_BADSEEK = -10, // An invalid file location was requested
207 RESULT_READFAIL = -11, // File read error
208 RESULT_WRITEFAIL = -12, // File write error
209 RESULT_RAW_ESS = -13, // Unknown raw essence file type
210 RESULT_RAW_FORMAT = -14, // Raw essence format invalid
211 RESULT_STATE = -15, // Object state error
212 RESULT_ENDOFFILE = -16, // Attempt to read past end of file
213 RESULT_CONFIG = -17, // Invalid configuration option detected
214 RESULT_RANGE = -18, // Frame number out of range
215 RESULT_CRYPT_CTX = -19, // AESEncContext required when writing to encrypted file
216 RESULT_LARGE_PTO = -20, // Plaintext offset exceeds frame buffer size
217 RESULT_ALLOC = -21, // Error allocating memory
218 RESULT_CAPEXTMEM = -22, // Cannot resize externally allocated memory
219 RESULT_CHECKFAIL = -23, // The check value did not decrypt correctly
220 RESULT_HMACFAIL = -24, // HMAC authentication failure
221 RESULT_HMAC_CTX = -25, // HMAC context required
222 RESULT_CRYPT_INIT = -26, // Error initializing block cipher context
223 RESULT_EMPTY_FB = -27, // Attempted to write an empty frame buffer
226 // Returns a pointer to an English language string describing the given result code.
227 // If the result code is not a valid member of the Result_t enum, the string
228 // "**UNKNOWN**" will be returned.
229 const char* GetResultString(Result_t);
231 //---------------------------------------------------------------------------------
232 // file identification
234 // The file accessors in this library implement a bounded set of essence types.
235 // This list will be expanded when support for new types is added to the library.
237 ESS_UNKNOWN, // the file is not a supported AS-DCP essence container
238 ESS_MPEG2_VES, // the file contains an MPEG video elementary stream
239 ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams
240 ESS_PCM_24b_48k // the file contains one or more PCM audio pairs
244 // Determine the type of essence contained in the given MXF file. RESULT_OK
245 // is returned if the file is successfully opened and contains a valid MXF
246 // stream. If there is an error, the result code will indicate the reason.
247 Result_t EssenceType(const char* filename, EssenceType_t& type);
249 // Determine the type of essence contained in the given raw file. RESULT_OK
250 // is returned if the file is successfully opened and contains a known
251 // stream type. If there is an error, the result code will indicate the reason.
252 Result_t RawEssenceType(const char* filename, EssenceType_t& type);
254 // Locate the named object in the file header and dump it to the given stream.
255 // The default dump stream is stderr.
256 Result_t FindObject(const char* filename, const char* objname, FILE* = 0);
259 // A simple container for rational numbers.
266 Rational() : Numerator(0), Denominator(0) {}
267 Rational(i32_t n, i32_t d) : Numerator(n), Denominator(d) {}
269 inline double Quotient() const {
270 return (double)Numerator / (double)Denominator;
273 inline bool operator==(const Rational& rhs) const {
274 return ( rhs.Numerator == Numerator && rhs.Denominator == Denominator );
277 inline bool operator!=(const Rational& rhs) const {
278 return ( rhs.Numerator != Numerator || rhs.Denominator != Denominator );
282 // common edit rates, use these instead of hard coded constants
283 const Rational EditRate_24(24,1);
284 const Rational EditRate_23_98(24000,1001);
285 const Rational EditRate_48(48,1);
286 const Rational SampleRate_48k(48000,1);
288 // Non-reference counting container for internal member objects.
289 // Please do not use this class for any other purpose.
293 T* m_p; // the thing we point to
297 mem_ptr() : m_p(0) {}
298 mem_ptr(T* p) : m_p(p) {}
299 ~mem_ptr() { delete m_p; }
301 inline T& operator*() const { return *m_p; }
302 inline T* operator->() const { return m_p; }
303 inline operator T*()const { return m_p; }
304 inline const mem_ptr<T>& operator=(T* p) { set(p); return *this; }
305 inline T* set(T* p) { delete m_p; m_p = p; return m_p; }
306 inline T* get() const { return m_p; }
307 inline void release() { m_p = 0; }
308 inline bool empty() const { return m_p == 0; }
311 //---------------------------------------------------------------------------------
312 // cryptographic support
314 // The following classes define interfaces to Rijndael contexts having the following properties:
316 // o CBC mode with 16 byte block size
317 const ui32_t CBC_KEY_SIZE = 16;
318 const ui32_t CBC_BLOCK_SIZE = 16;
319 const ui32_t HMAC_SIZE = 20;
325 mem_ptr<h__AESContext> m_Context;
326 ASDCP_NO_COPY_CONSTRUCT(AESEncContext);
332 // Initializes Rijndael CBC encryption context.
333 // Returns error if the key argument is NULL.
334 Result_t InitKey(const byte_t* key);
336 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
337 // any number of times for a given key.
338 // Returns error if the i_vec argument is NULL.
339 Result_t SetIVec(const byte_t* i_vec);
340 Result_t GetIVec(byte_t* i_vec) const;
342 // Encrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
343 // Returns error if either argument is NULL.
344 Result_t EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size);
351 mem_ptr<h__AESContext> m_Context;
352 ASDCP_NO_COPY_CONSTRUCT(AESDecContext);
358 // Initializes Rijndael CBC decryption context.
359 // Returns error if the key argument is NULL.
360 Result_t InitKey(const byte_t* key);
362 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
363 // any number of times for a given key.
364 // Returns error if the i_vec argument is NULL.
365 Result_t SetIVec(const byte_t* i_vec);
367 // Decrypt a block of data. The block size must be a multiple of CBC_BLOCK_SIZE.
368 // Returns error if either argument is NULL.
369 Result_t DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size);
375 class h__HMACContext;
376 mem_ptr<h__HMACContext> m_Context;
377 ASDCP_NO_COPY_CONSTRUCT(HMACContext);
383 // Initializes HMAC context. The key argument must point to a binary
384 // key that is CBC_KEY_SIZE bytes in length. Returns error if the key
386 Result_t InitKey(const byte_t* key);
388 // Reset internal state, allows repeated cycles of Update -> Finalize
391 // Add data to the digest. Returns error if the key argument is NULL or
392 // if the digest has been finalized.
393 Result_t Update(const byte_t* buf, ui32_t buf_len);
395 // Finalize digest. Returns error if the digest has already been finalized.
398 // Writes HMAC value to given buffer. buf must point to a writable area of
399 // memory that is at least HMAC_SIZE bytes in length. Returns error if the
400 // buf argument is NULL or if the digest has not been finalized.
401 Result_t GetHMACValue(byte_t* buf) const;
403 // Tests the given value against the finalized value in the object. buf must
404 // point to a readable area of memory that is at least HMAC_SIZE bytes in length.
405 // Returns error if the buf argument is NULL or if the values do ot match.
406 Result_t TestHMACValue(const byte_t* buf) const;
409 //---------------------------------------------------------------------------------
410 // WriterInfo class - encapsulates writer identification details used for
411 // OpenWrite() calls. Replace these values at runtime to identify your product.
415 byte_t ProductUUID[UUIDlen];
416 byte_t AssetUUID[UUIDlen];
417 byte_t ContextID[UUIDlen];
418 byte_t CryptographicKeyID[UUIDlen];
419 bool EncryptedEssence; // true if essence data is (or is to be) encrypted
420 bool UsesHMAC; // true if HMAC exists or is to be calculated
421 std::string ProductVersion;
422 std::string CompanyName;
423 std::string ProductName;
425 WriterInfo() : EncryptedEssence(false), UsesHMAC(false) {
426 static byte_t default_ProductUUID_Data[UUIDlen] = { 0x43, 0x05, 0x9a, 0x1d, 0x04, 0x32, 0x41, 0x01,
427 0xb8, 0x3f, 0x73, 0x68, 0x15, 0xac, 0xf3, 0x1d };
429 memcpy(ProductUUID, default_ProductUUID_Data, UUIDlen);
430 memset(AssetUUID, 0, UUIDlen);
431 memset(ContextID, 0, UUIDlen);
432 memset(CryptographicKeyID, 0, UUIDlen);
434 ProductVersion = "Unreleased ";
435 ProductVersion += Version();
437 ProductName = "asdcplib";
441 // Print WriterInfo to stream, stderr by default.
442 void WriterInfoDump(const WriterInfo&, FILE* = 0);
444 //---------------------------------------------------------------------------------
445 // frame buffer base class
447 // The supported essence types are stored using per-frame KLV packetization. The
448 // following class implements essence-neutral functionality for managing a buffer
449 // containing a frame of essence.
453 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer);
456 byte_t* m_Data; // pointer to memory area containing frame data
457 ui32_t m_Capacity; // size of memory area pointed to by m_Data
458 bool m_OwnMem; // if false, m_Data points to externally allocated memory
459 ui32_t m_Size; // size of frame data in memory area pointed to by m_Data
460 ui32_t m_FrameNumber; // delivery-order frame number
462 // It is possible to read raw ciphertext from an encrypted AS-DCP file.
463 // After reading an encrypted AS-DCP file in raw mode, the frame buffer will
464 // contain the encrypted source value portion of the Encrypted Triplet, followed
465 // by the integrity pack, if it exists.
466 // The buffer will begin with the IV and CheckValue, followed by encrypted essence
467 // and optional integrity pack
468 // The SourceLength and PlaintextOffset values from the packet will be held in the
469 // following variables:
470 ui32_t m_SourceLength; // plaintext length (delivered plaintext+decrypted ciphertext)
471 ui32_t m_PlaintextOffset; // offset to first byte of ciphertext
475 virtual ~FrameBuffer();
477 // Instructs the object to use an externally allocated buffer. The external
478 // buffer will not be cleaned up by the frame buffer when it exits.
479 // Call with (0,0) to revert to internally allocated buffer.
480 // Returns error if the buf_addr argument is NULL and buf_size is non-zero.
481 Result_t SetData(byte_t* buf_addr, ui32_t buf_size);
483 // Sets the size of the internally allocate buffer. Returns RESULT_CAPEXTMEM
484 // if the object is using an externally allocated buffer via SetData();
485 // Resets content size to zero.
486 Result_t Capacity(ui32_t cap);
488 // returns the size of the buffer
489 inline ui32_t Capacity() const { return m_Capacity; }
491 // returns a const pointer to the essence data
492 inline const byte_t* RoData() const { return m_Data; }
494 // returns a non-const pointer to the essence data
495 inline byte_t* Data() { return m_Data; }
497 // set the size of the buffer's contents
498 inline ui32_t Size(ui32_t size) { return m_Size = size; }
500 // returns the size of the buffer's contents
501 inline ui32_t Size() const { return m_Size; }
503 // Sets the absolute frame number of this frame in the file in delivery order.
504 inline void FrameNumber(ui32_t num) { m_FrameNumber = num; }
506 // Returns the absolute frame number of this frame in the file in delivery order.
507 inline ui32_t FrameNumber() const { return m_FrameNumber; }
509 // Sets the length of the plaintext essence data
510 inline void SourceLength(ui32_t len) { m_SourceLength = len; }
512 // When this value is 0 (zero), the buffer contains only plaintext. When it is
513 // non-zero, the buffer contains raw ciphertext and the return value is the length
514 // of the original plaintext.
515 inline ui32_t SourceLength() const { return m_SourceLength; }
517 // Sets the offset into the buffer at which encrypted data begins
518 inline void PlaintextOffset(ui32_t ofst) { m_PlaintextOffset = ofst; }
520 // Returns offset into buffer of first byte of ciphertext.
521 inline ui32_t PlaintextOffset() const { return m_PlaintextOffset; }
525 //---------------------------------------------------------------------------------
526 // MPEG2 video elementary stream support
531 // MPEG picture coding type
533 FRAME_U = 0x00, // Unknown
534 FRAME_I = 0x01, // I-Frame
535 FRAME_P = 0x02, // P-Frame
536 FRAME_B = 0x03 // B-Frame
539 // convert FrameType_t to char
540 inline char FrameTypeChar(FrameType_t type)
544 case FRAME_I: return 'I';
545 case FRAME_B: return 'B';
546 case FRAME_P: return 'P';
551 // Structure represents the metadata elements in the file header's
552 // MPEG2VideoDescriptor object.
553 struct VideoDescriptor
555 Rational EditRate; //
557 Rational SampleRate; //
558 ui8_t FrameLayout; //
559 ui32_t StoredWidth; //
560 ui32_t StoredHeight; //
561 Rational AspectRatio; //
562 ui32_t ComponentDepth; //
563 ui32_t HorizontalSubsampling; //
564 ui32_t VerticalSubsampling; //
565 ui8_t ColorSiting; //
566 ui8_t CodedContentType; //
569 ui8_t ProfileAndLevel; //
570 ui32_t ContainerDuration; //
573 // Print VideoDescriptor to stream, stderr by default.
574 void VideoDescriptorDump(const VideoDescriptor&, FILE* = 0);
576 // A container for MPEG frame data.
577 class FrameBuffer : public ASDCP::FrameBuffer
579 ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct
582 FrameType_t m_FrameType;
583 ui8_t m_TemporalOffset;
589 m_FrameType(FRAME_U), m_TemporalOffset(0),
590 m_ClosedGOP(false), m_GOPStart(false) {}
592 FrameBuffer(ui32_t size) :
593 m_FrameType(FRAME_U), m_TemporalOffset(0),
594 m_ClosedGOP(false), m_GOPStart(false)
599 virtual ~FrameBuffer() {}
601 // Sets the MPEG frame type of the picture data in the frame buffer.
602 inline void FrameType(FrameType_t type) { m_FrameType = type; }
604 // Returns the MPEG frame type of the picture data in the frame buffer.
605 inline FrameType_t FrameType() const { return m_FrameType; }
607 // Sets the MPEG temporal offset of the picture data in the frame buffer.
608 inline void TemporalOffset(ui8_t offset) { m_TemporalOffset = offset; }
610 // Returns the MPEG temporal offset of the picture data in the frame buffer.
611 inline ui8_t TemporalOffset() const { return m_TemporalOffset; }
613 // Sets the MPEG GOP 'start' attribute for the frame buffer.
614 inline void GOPStart(bool start) { m_GOPStart = start; }
616 // True if the frame in the buffer is the first in the GOP (in transport order)
617 inline bool GOPStart() const { return m_GOPStart; }
619 // Sets the MPEG GOP 'closed' attribute for the frame buffer.
620 inline void ClosedGOP(bool closed) { m_ClosedGOP = closed; }
622 // Returns true if the frame in the buffer is from a closed GOP, false if
623 // the frame is from an open GOP. Always returns false unless GOPStart()
625 inline bool ClosedGOP() const { return m_ClosedGOP; }
627 // Print object state to stream, include n bytes of frame data if indicated.
628 // Default stream is stderr.
629 void Dump(FILE* = 0, ui32_t dump_len = 0) const;
633 // An object which opens and reads an MPEG2 Video Elementary Stream file. The call to
634 // OpenRead() reads metadata from the file and populates an internal VideoDescriptor object.
635 // Each subsequent call to ReadFrame() reads exactly one frame from the stream into the
636 // given FrameBuffer object.
640 mem_ptr<h__Parser> m_Parser;
641 ASDCP_NO_COPY_CONSTRUCT(Parser);
647 // Opens the stream for reading, parses enough data to provide a complete
648 // set of stream metadata for the MXFWriter below.
649 Result_t OpenRead(const char* filename) const;
651 // Fill a VideoDescriptor struct with the values from the file's header.
652 // Returns RESULT_INIT if the file is not open.
653 Result_t FillVideoDescriptor(VideoDescriptor&) const;
655 // Rewind the stream to the beginning.
656 Result_t Reset() const;
658 // Reads the next sequential frame in the input file and places it in the
659 // frame buffer. Fails if the buffer is too small or the stream is empty.
660 // The frame buffer's PlaintextOffset parameter will be set to the first
661 // data byte of the first slice. Set this value to zero if you want
662 // encrypted headers.
663 Result_t ReadFrame(FrameBuffer&) const;
666 // A class which creates and writes MPEG frame data to an AS-DCP format MXF file.
667 // Not yet implemented
671 mem_ptr<h__Writer> m_Writer;
672 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
676 virtual ~MXFWriter();
678 // Open the file for writing. The file must not exist. Returns error if
679 // the operation cannot be completed or if nonsensical data is discovered
680 // in the essence descriptor.
681 Result_t OpenWrite(const char* filename, const WriterInfo&,
682 const VideoDescriptor&, ui32_t HeaderSize = 16384);
684 // Writes a frame of essence to the MXF file. If the optional AESEncContext
685 // argument is present, the essence is encrypted prior to writing.
686 // Fails if the file is not open, is finalized, or an operating system
688 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
690 // Closes the MXF file, writing the index and revised header.
694 // A class which reads MPEG frame data from an AS-DCP format MXF file.
698 mem_ptr<h__Reader> m_Reader;
699 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
703 virtual ~MXFReader();
705 // Open the file for reading. The file must exist. Returns error if the
706 // operation cannot be completed.
707 Result_t OpenRead(const char* filename) const;
709 // Returns RESULT_INIT if the file is not open.
710 Result_t Close() const;
712 // Fill a VideoDescriptor struct with the values from the file's header.
713 // Returns RESULT_INIT if the file is not open.
714 Result_t FillVideoDescriptor(VideoDescriptor&) const;
716 // Fill a WriterInfo struct with the values from the file's header.
717 // Returns RESULT_INIT if the file is not open.
718 Result_t FillWriterInfo(WriterInfo&) const;
720 // Reads a frame of essence from the MXF file. If the optional AESEncContext
721 // argument is present, the essence is decrypted after reading. If the MXF
722 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
723 // will contain the ciphertext frame data. If the HMACContext argument is
724 // not NULL, the HMAC will be calculated (if the file supports it).
725 // Returns RESULT_INIT if the file is not open, failure if the frame number is
726 // out of range, or if optional decrypt or HAMC operations fail.
727 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
729 // Calculates the first frame in transport order of the GOP in which the requested
730 // frame is located. Calls ReadFrame() to fetch the frame at the calculated position.
731 // Returns RESULT_INIT if the file is not open.
732 Result_t ReadFrameGOPStart(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
734 // Calculates the first frame in transport order of the GOP in which the requested
735 // frame is located. Sets key_frame_number to the number of the frame at the calculated position.
736 // Returns RESULT_INIT if the file is not open.
737 Result_t FindFrameGOPStart(ui32_t frame_number, ui32_t& key_frame_number) const;
739 // Returns the type of the frame at the given position.
740 // Returns RESULT_INIT if the file is not open or RESULT_RANGE if the index is out of range.
741 Result_t FrameType(ui32_t frame_number, FrameType_t&) const;
743 // Print debugging information to stream
744 void DumpHeaderMetadata(FILE* = 0) const;
745 void DumpIndex(FILE* = 0) const;
752 struct AudioDescriptor
754 Rational SampleRate; // rate of frame wrapping
755 Rational AudioSamplingRate; // rate of audio sample
757 ui32_t ChannelCount; // number of channels
758 ui32_t QuantizationBits; // number of bits per single-channel sample
759 ui32_t BlockAlign; // number of bytes ber sample, all channels
761 ui32_t LinkedTrackID; //
762 ui32_t ContainerDuration; // number of frames
765 // Print debugging information to stream (stderr default)
766 void AudioDescriptorDump(const AudioDescriptor&, FILE* = 0);
768 // Returns size in bytes of a single sample of data described by ADesc
769 inline ui32_t CalcSampleSize(const AudioDescriptor& ADesc)
771 return (ADesc.QuantizationBits / 8) * ADesc.ChannelCount;
774 // Returns number of samples per frame of data described by ADesc
775 inline ui32_t CalcSamplesPerFrame(const AudioDescriptor& ADesc)
777 double tmpd = ADesc.AudioSamplingRate.Quotient() / ADesc.SampleRate.Quotient();
778 return (ui32_t)ceil(tmpd);
781 // Returns the size in bytes of a frame of data described by ADesc
782 inline ui32_t CalcFrameBufferSize(const AudioDescriptor& ADesc)
784 return CalcSampleSize(ADesc) * CalcSamplesPerFrame(ADesc);
788 class FrameBuffer : public ASDCP::FrameBuffer
792 FrameBuffer(ui32_t size) { Capacity(size); }
793 virtual ~FrameBuffer() {}
795 // Print debugging information to stream (stderr default)
796 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
799 // An object which opens and reads a WAV file. The call to OpenRead() reads metadata from
800 // the file and populates an internal AudioDescriptor object. Each subsequent call to
801 // ReadFrame() reads exactly one frame from the stream into the given FrameBuffer object.
802 // A "frame" is either 2000 or 2002 samples, depending upon the value of PictureRate.
806 mem_ptr<h__WAVParser> m_Parser;
807 ASDCP_NO_COPY_CONSTRUCT(WAVParser);
811 virtual ~WAVParser();
813 // Opens the stream for reading, parses enough data to provide a complete
814 // set of stream metadata for the MXFWriter below. PictureRate controls
815 // ther frame rate for the MXF frame wrapping option.
816 Result_t OpenRead(const char* filename, const Rational& PictureRate) const;
818 // Fill an AudioDescriptor struct with the values from the file's header.
819 // Returns RESULT_INIT if the file is not open.
820 Result_t FillAudioDescriptor(AudioDescriptor&) const;
822 // Rewind the stream to the beginning.
823 Result_t Reset() const;
825 // Reads the next sequential frame in the input file and places it in the
826 // frame buffer. Fails if the buffer is too small or the stream is empty.
827 Result_t ReadFrame(FrameBuffer&) const;
835 mem_ptr<h__Writer> m_Writer;
836 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
840 virtual ~MXFWriter();
842 // Open the file for writing. The file must not exist. Returns error if
843 // the operation cannot be completed or if nonsensical data is discovered
844 // in the essence descriptor.
845 Result_t OpenWrite(const char* filename, const WriterInfo&,
846 const AudioDescriptor&, ui32_t HeaderSize = 16384);
848 // Writes a frame of essence to the MXF file. If the optional AESEncContext
849 // argument is present, the essence is encrypted prior to writing.
850 // Fails if the file is not open, is finalized, or an operating system
852 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
854 // Closes the MXF file, writing the index and revised header.
862 mem_ptr<h__Reader> m_Reader;
863 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
867 virtual ~MXFReader();
869 // Open the file for reading. The file must exist. Returns error if the
870 // operation cannot be completed.
871 Result_t OpenRead(const char* filename) const;
873 // Returns RESULT_INIT if the file is not open.
874 Result_t Close() const;
876 // Fill an AudioDescriptor struct with the values from the file's header.
877 // Returns RESULT_INIT if the file is not open.
878 Result_t FillAudioDescriptor(AudioDescriptor&) const;
880 // Fill a WriterInfo struct with the values from the file's header.
881 // Returns RESULT_INIT if the file is not open.
882 Result_t FillWriterInfo(WriterInfo&) const;
884 // Reads a frame of essence from the MXF file. If the optional AESEncContext
885 // argument is present, the essence is decrypted after reading. If the MXF
886 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
887 // will contain the ciphertext frame data. If the HMACContext argument is
888 // not NULL, the HMAC will be calculated (if the file supports it).
889 // Returns RESULT_INIT if the file is not open, failure if the frame number is
890 // out of range, or if optional decrypt or HAMC operations fail.
891 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
893 // Print debugging information to stream
894 void DumpHeaderMetadata(FILE* = 0) const;
895 void DumpIndex(FILE* = 0) const;
902 const ui32_t MaxComponents = 3;
903 const ui32_t DefaultCodingDataLength = 64;
905 struct ImageComponent
912 struct PictureDescriptor
915 ui32_t ContainerDuration;
919 Rational AspectRatio;
930 ImageComponent ImageComponents[MaxComponents];
931 byte_t CodingStyle[DefaultCodingDataLength];
932 ui32_t CodingStyleLength;
933 byte_t QuantDefault[DefaultCodingDataLength];
934 ui32_t QuantDefaultLength;
937 // Print debugging information to stream (stderr default)
938 void PictureDescriptorDump(const PictureDescriptor&, FILE* = 0);
941 class FrameBuffer : public ASDCP::FrameBuffer
945 FrameBuffer(ui32_t size) { Capacity(size); }
946 virtual ~FrameBuffer() {}
948 // Print debugging information to stream (stderr default)
949 void Dump(FILE* = 0, ui32_t dump_bytes = 0) const;
953 // An object which opens and reads a JPEG 2000 codestream file. The file is expected
954 // to contain exactly one complete frame of picture essence as an unwrapped (raw)
955 // ISO/IEC 15444 codestream.
956 class CodestreamParser
958 class h__CodestreamParser;
959 mem_ptr<h__CodestreamParser> m_Parser;
960 ASDCP_NO_COPY_CONSTRUCT(CodestreamParser);
964 virtual ~CodestreamParser();
966 // Opens a file for reading, parses enough data to provide a complete
967 // set of stream metadata for the MXFWriter below.
968 // The frame buffer's PlaintextOffset parameter will be set to the first
969 // byte of the data segment. Set this value to zero if you want
970 // encrypted headers.
971 Result_t OpenReadFrame(const char* filename, FrameBuffer&) const;
973 // Fill a PictureDescriptor struct with the values from the file's codestream.
974 // Returns RESULT_INIT if the file is not open.
975 Result_t FillPictureDescriptor(PictureDescriptor&) const;
978 // An object which reads a sequence of files containing JPEG 2000 pictures.
981 class h__SequenceParser;
982 mem_ptr<h__SequenceParser> m_Parser;
983 ASDCP_NO_COPY_CONSTRUCT(SequenceParser);
987 virtual ~SequenceParser();
989 // Opens a directory for reading. The directory is expected to contain one or
990 // more files, each containing the codestream for exactly one picture. The
991 // files must be named such that the frames are in temporal order when sorted
992 // alphabetically by filename. The parser will automatically parse enough data
993 // from the first file to provide a complete set of stream metadata for the
994 // MXFWriter below. If the "pedantic" parameter is given and is true, the
995 // parser will check the metadata for each codestream and fail if a
996 // mismatch is detected.
997 Result_t OpenRead(const char* filename, bool pedantic = false) const;
999 // Fill a PictureDescriptor struct with the values from the first file's codestream.
1000 // Returns RESULT_INIT if the directory is not open.
1001 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1003 // Rewind the directory to the beginning.
1004 Result_t Reset() const;
1006 // Reads the next sequential frame in the directory and places it in the
1007 // frame buffer. Fails if the buffer is too small or the direcdtory
1008 // contains no more files.
1009 // The frame buffer's PlaintextOffset parameter will be set to the first
1010 // byte of the data segment. Set this value to zero if you want
1011 // encrypted headers.
1012 Result_t ReadFrame(FrameBuffer&) const;
1020 mem_ptr<h__Writer> m_Writer;
1021 ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
1025 virtual ~MXFWriter();
1027 // Open the file for writing. The file must not exist. Returns error if
1028 // the operation cannot be completed or if nonsensical data is discovered
1029 // in the essence descriptor.
1030 Result_t OpenWrite(const char* filename, const WriterInfo&,
1031 const PictureDescriptor&, ui32_t HeaderSize = 16384);
1033 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1034 // argument is present, the essence is encrypted prior to writing.
1035 // Fails if the file is not open, is finalized, or an operating system
1037 Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
1039 // Closes the MXF file, writing the index and revised header.
1040 Result_t Finalize();
1047 mem_ptr<h__Reader> m_Reader;
1048 ASDCP_NO_COPY_CONSTRUCT(MXFReader);
1052 virtual ~MXFReader();
1054 // Open the file for reading. The file must exist. Returns error if the
1055 // operation cannot be completed.
1056 Result_t OpenRead(const char* filename) const;
1058 // Returns RESULT_INIT if the file is not open.
1059 Result_t Close() const;
1061 // Fill an AudioDescriptor struct with the values from the file's header.
1062 // Returns RESULT_INIT if the file is not open.
1063 Result_t FillPictureDescriptor(PictureDescriptor&) const;
1065 // Fill a WriterInfo struct with the values from the file's header.
1066 // Returns RESULT_INIT if the file is not open.
1067 Result_t FillWriterInfo(WriterInfo&) const;
1069 // Reads a frame of essence from the MXF file. If the optional AESEncContext
1070 // argument is present, the essence is decrypted after reading. If the MXF
1071 // file is encrypted and the AESDecContext argument is NULL, the frame buffer
1072 // will contain the ciphertext frame data. If the HMACContext argument is
1073 // not NULL, the HMAC will be calculated (if the file supports it).
1074 // Returns RESULT_INIT if the file is not open, failure if the frame number is
1075 // out of range, or if optional decrypt or HAMC operations fail.
1076 Result_t ReadFrame(ui32_t frame_number, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const;
1078 // Print debugging information to stream
1079 void DumpHeaderMetadata(FILE* = 0) const;
1080 void DumpIndex(FILE* = 0) const;
1083 } // namespace ASDCP
1086 #endif // _AS_DCP_H__