compile fixes
[asdcplib.git] / src / AS_02.h
1 /*
2 Copyright (c) 2011-2014, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
3 John Hurst
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16    derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 
29 /*! \file    AS_02.h
30     \version $Id$       
31     \brief   AS-02 library, public interface
32
33 This module implements MXF AS-02 is a set of file access objects that
34 offer simplified access to files conforming to the standards published
35 by the SMPTE Media and Packaging Technology Committee 35PM. The file
36 format, labeled IMF Essence Component (AKA "AS-02" for historical
37 reasons), is described in the following document:
38
39  o SMPTE 2067-5:2013 IMF Essence Component
40
41 The following use cases are supported by the module:
42
43  o Write essence to a plaintext or ciphertext AS-02 file:
44      JPEG 2000 codestreams
45      PCM audio streams
46
47  o Read essence from a plaintext or ciphertext AS-02 file:
48      JPEG 2000 codestreams
49      PCM audio streams
50
51  o Read header metadata from an AS-02 file
52
53 NOTE: ciphertext support for clip-wrapped PCM is not yet complete.
54 */
55
56 #ifndef _AS_02_H_
57 #define _AS_02_H_
58
59 #include "Metadata.h"
60
61
62 namespace AS_02
63 {
64   using Kumu::Result_t;
65
66   KM_DECLARE_RESULT(AS02_FORMAT,        -116, "The file format is not proper OP-1a/AS-02.");
67
68   namespace MXF {
69     //
70     // reads distributed index tables and provides a uniform lookup with
71     // translated StreamOffest values (that is, StreamOffest is adjusted
72     // to the actual file position
73     class AS02IndexReader : public ASDCP::MXF::Partition
74     {
75       Kumu::ByteString m_IndexSegmentData;
76       ui32_t m_Duration;
77       ui32_t m_BytesPerEditUnit;
78
79       Result_t InitFromBuffer(const byte_t* p, ui32_t l, const ui64_t& body_offset, const ui64_t& essence_container_offset);
80
81       ASDCP_NO_COPY_CONSTRUCT(AS02IndexReader);
82       AS02IndexReader();
83           
84     public:
85       const ASDCP::Dictionary*&   m_Dict;
86       ASDCP::IPrimerLookup *m_Lookup;
87     
88       AS02IndexReader(const ASDCP::Dictionary*&);
89       virtual ~AS02IndexReader();
90     
91       Result_t InitFromFile(const Kumu::FileReader& reader, const ASDCP::MXF::RIP& rip, const bool has_header_essence);
92       ui32_t GetDuration() const;
93       void     Dump(FILE* = 0);
94       Result_t GetMDObjectByID(const Kumu::UUID&, ASDCP::MXF::InterchangeObject** = 0);
95       Result_t GetMDObjectByType(const byte_t*, ASDCP::MXF::InterchangeObject** = 0);
96       Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<ASDCP::MXF::InterchangeObject*>& ObjectList);
97       Result_t Lookup(ui32_t frame_num, ASDCP::MXF::IndexTableSegment::IndexEntry&) const;
98     };
99
100     
101     // Returns size in bytes of a single sample of data described by ADesc
102     inline ui32_t CalcSampleSize(const ASDCP::MXF::WaveAudioDescriptor& d)
103     {
104       return (d.QuantizationBits / 8) * d.ChannelCount;
105     }
106
107       // Returns number of samples per frame of data described by ADesc
108     inline ui32_t CalcSamplesPerFrame(const ASDCP::MXF::WaveAudioDescriptor& d, const ASDCP::Rational& edit_rate)
109     {
110       double tmpd = d.AudioSamplingRate.Quotient() / edit_rate.Quotient();
111       return (ui32_t)ceil(tmpd);
112     }
113
114     // Returns the size in bytes of a frame of data described by ADesc
115     inline ui32_t CalcFrameBufferSize(const ASDCP::MXF::WaveAudioDescriptor& d, const ASDCP::Rational& edit_rate)
116     {
117       return CalcSampleSize(d) * CalcSamplesPerFrame(d, edit_rate);
118     }
119
120     // Returns number of frames for data described by ADesc, given a duration in samples and an edit rate
121     inline ui32_t CalcFramesFromDurationInSamples(const ui32_t duration_samples, const ASDCP::MXF::WaveAudioDescriptor& d,
122                                                   const ASDCP::Rational& edit_rate)
123     {
124       ui32_t spf = CalcSamplesPerFrame(d, edit_rate);
125       ui32_t frames = duration_samples / spf;
126       
127       if ( duration_samples % spf != 0 )
128         {
129           ++frames;
130         }
131
132       return frames;
133     }
134
135   } // namespace MXF
136
137
138   // IMF App 2 edit rates not already exposed in namespace ASDCP
139   const ASDCP::Rational EditRate_29_97 = ASDCP::Rational(30000, 1001);
140   const ASDCP::Rational EditRate_59_94 = ASDCP::Rational(60000, 1001);
141
142   //---------------------------------------------------------------------------------
143   // Accessors in the MXFReader and MXFWriter classes below return these types to
144   // provide direct access to MXF metadata structures declared in MXF.h and Metadata.h
145
146   // See ST 2067-5 Sec. x.y.z
147   enum IndexStrategy_t
148   {
149     IS_LEAD,
150     IS_FOLLOW,
151     IS_FILE_SPECIFIC,
152     IS_MAX
153   };
154  
155   namespace JP2K
156   { 
157     //
158     class MXFWriter
159     {
160       class h__Writer;
161       ASDCP::mem_ptr<h__Writer> m_Writer;
162       ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
163       
164     public:
165       MXFWriter();
166       virtual ~MXFWriter();
167
168       // Warning: direct manipulation of MXF structures can interfere
169       // with the normal operation of the wrapper.  Caveat emptor!
170       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
171       virtual ASDCP::MXF::RIP& RIP();
172
173       // Open the file for writing. The file must not exist. Returns error if
174       // the operation cannot be completed or if nonsensical data is discovered
175       // in the essence descriptor.
176       Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
177                          ASDCP::MXF::FileDescriptor* essence_descriptor,
178                          ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
179                          const ASDCP::Rational& edit_rate, const ui32_t& header_size = 16384,
180                          const IndexStrategy_t& strategy = IS_FOLLOW, const ui32_t& partition_space = 10);
181
182       // Writes a frame of essence to the MXF file. If the optional AESEncContext
183       // argument is present, the essence is encrypted prior to writing.
184       // Fails if the file is not open, is finalized, or an operating system
185       // error occurs.
186       Result_t WriteFrame(const ASDCP::JP2K::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
187
188       // Closes the MXF file, writing the index and revised header.
189       Result_t Finalize();
190     };
191
192     //
193     class MXFReader
194     {
195       class h__Reader;
196       ASDCP::mem_ptr<h__Reader> m_Reader;
197       ASDCP_NO_COPY_CONSTRUCT(MXFReader);
198
199     public:
200       MXFReader();
201       virtual ~MXFReader();
202
203       // Warning: direct manipulation of MXF structures can interfere
204       // with the normal operation of the wrapper.  Caveat emptor!
205       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
206       virtual AS_02::MXF::AS02IndexReader& AS02IndexReader();
207       virtual ASDCP::MXF::RIP& RIP();
208
209       // Open the file for reading. The file must exist. Returns error if the
210       // operation cannot be completed.
211       Result_t OpenRead(const std::string& filename) const;
212
213       // Returns RESULT_INIT if the file is not open.
214       Result_t Close() const;
215
216       // Fill a WriterInfo struct with the values from the file's header.
217       // Returns RESULT_INIT if the file is not open.
218       Result_t FillWriterInfo(ASDCP::WriterInfo&) const;
219
220       // Reads a frame of essence from the MXF file. If the optional AESEncContext
221       // argument is present, the essence is decrypted after reading. If the MXF
222       // file is encrypted and the AESDecContext argument is NULL, the frame buffer
223       // will contain the ciphertext frame data. If the HMACContext argument is
224       // not NULL, the HMAC will be calculated (if the file supports it).
225       // Returns RESULT_INIT if the file is not open, failure if the frame number is
226       // out of range, or if optional decrypt or HAMC operations fail.
227       Result_t ReadFrame(ui32_t frame_number, ASDCP::JP2K::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
228
229       // Print debugging information to stream
230       void     DumpHeaderMetadata(FILE* = 0) const;
231       void     DumpIndex(FILE* = 0) const;
232     };
233     
234   } //namespace JP2K
235   
236
237   //---------------------------------------------------------------------------------
238   //
239   namespace PCM
240   {
241     // see AS_DCP.h for related data types
242
243     // An AS-02 PCM file is clip-wrapped, but the interface defined below mimics that used
244     // for frame-wrapped essence elsewhere in this library.  The concept of frame rate
245     // therefore is only relevant to these classes and is not reflected in or affected by
246     // the contents of the MXF file.  The frame rate that is set on the writer is only
247     // for compatibility with the existing parsers, samples are packed contiguously into
248     // the same clip-wrapped packet.  Similarly, the edit rate must be set when initializing
249     // the reader to signal the number of samples to be read by each call to ReadFrame();
250
251     //
252       class MXFWriter
253     {
254       class h__Writer;
255       ASDCP::mem_ptr<h__Writer> m_Writer;
256       ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
257
258     public:
259       MXFWriter();
260       virtual ~MXFWriter();
261
262       // Warning: direct manipulation of MXF structures can interfere
263       // with the normal operation of the wrapper.  Caveat emptor!
264       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
265       virtual ASDCP::MXF::RIP& RIP();
266
267       // Open the file for writing. The file must not exist. Returns error if
268       // the operation cannot be completed or if nonsensical data is discovered
269       // in the essence descriptor.
270       Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
271                          ASDCP::MXF::FileDescriptor* essence_descriptor,
272                          ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
273                          const ASDCP::Rational& edit_rate, ui32_t HeaderSize = 16384);
274
275       // Writes a frame of essence to the MXF file. If the optional AESEncContext
276       // argument is present, the essence is encrypted prior to writing.
277       // Fails if the file is not open, is finalized, or an operating system
278       // error occurs.
279       Result_t WriteFrame(const ASDCP::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
280       
281       // Closes the MXF file, writing the index and revised header.
282       Result_t Finalize();
283     };
284
285     //
286     class MXFReader
287     {
288       class h__Reader;
289       ASDCP::mem_ptr<h__Reader> m_Reader;
290       ASDCP_NO_COPY_CONSTRUCT(MXFReader);
291
292     public:
293       MXFReader();
294       virtual ~MXFReader();
295
296       // Warning: direct manipulation of MXF structures can interfere
297       // with the normal operation of the wrapper.  Caveat emptor!
298       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
299       virtual AS_02::MXF::AS02IndexReader& AS02IndexReader();
300       virtual ASDCP::MXF::RIP& RIP();
301
302       // Open the file for reading. The file must exist. Returns error if the
303       // operation cannot be completed.
304       Result_t OpenRead(const std::string& filename, const ASDCP::Rational& EditRate);
305
306       // Returns RESULT_INIT if the file is not open.
307       Result_t Close() const;
308
309       // Fill a WriterInfo struct with the values from the file's header.
310       // Returns RESULT_INIT if the file is not open.
311       Result_t FillWriterInfo(ASDCP::WriterInfo&) const;
312
313       // Reads a frame of essence from the MXF file. If the optional AESEncContext
314       // argument is present, the essence is decrypted after reading. If the MXF
315       // file is encrypted and the AESDecContext argument is NULL, the frame buffer
316       // will contain the ciphertext frame data. If the HMACContext argument is
317       // not NULL, the HMAC will be calculated (if the file supports it).
318       // Returns RESULT_INIT if the file is not open, failure if the frame number is
319       // out of range, or if optional decrypt or HAMC operations fail.
320       Result_t ReadFrame(ui32_t frame_number, ASDCP::PCM::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
321       
322       // Print debugging information to stream
323       void     DumpHeaderMetadata(FILE* = 0) const;
324       void     DumpIndex(FILE* = 0) const;
325     };
326   } // namespace PCM
327
328   //---------------------------------------------------------------------------------
329   //
330   namespace TimedText
331     {
332       using ASDCP::TimedText::TimedTextDescriptor;
333       using ASDCP::TimedText::TimedTextResourceDescriptor;
334       using ASDCP::TimedText::ResourceList_t;
335
336       //
337       class Type5UUIDFilenameResolver : public ASDCP::TimedText::IResourceResolver
338         {
339           typedef std::map<Kumu::UUID, std::string> ResourceMap;
340             
341           ResourceMap m_ResourceMap;
342           std::string m_Dirname;
343           KM_NO_COPY_CONSTRUCT(Type5UUIDFilenameResolver);
344
345         public:
346           Type5UUIDFilenameResolver();
347           virtual ~Type5UUIDFilenameResolver();
348           Result_t OpenRead(const std::string& dirname);
349           Result_t ResolveRID(const byte_t* uuid, ASDCP::TimedText::FrameBuffer& FrameBuf) const;
350         };
351       
352       //
353       class ST2052_TextParser
354         {
355           class h__TextParser;
356           ASDCP::mem_ptr<h__TextParser> m_Parser;
357           ASDCP_NO_COPY_CONSTRUCT(ST2052_TextParser);
358
359         public:
360           ST2052_TextParser();
361           virtual ~ST2052_TextParser();
362
363           // Opens an XML file for reading, parses data to provide a complete
364           // set of stream metadata for the MXFWriter below.
365           Result_t OpenRead(const std::string& filename) const;
366
367           // Parse an XML string 
368           Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const;
369
370           // Fill a TimedTextDescriptor struct with the values from the file's contents.
371           // Returns RESULT_INIT if the file is not open.
372           Result_t FillTimedTextDescriptor(ASDCP::TimedText::TimedTextDescriptor&) const;
373
374           // Reads the complete Timed Text Resource into the given string.
375           Result_t ReadTimedTextResource(std::string&) const;
376
377           // Reads the Ancillary Resource having the given ID. Fails if the buffer
378           // is too small or the resource does not exist. The optional Resolver
379           // argument can be provided which will be used to retrieve the resource
380           // having a particulat UUID. If a Resolver is not supplied, the default
381           // internal resolver will return the contents of the file having the UUID
382           // as the filename. The filename must exist in the same directory as the
383           // XML file opened with OpenRead().
384           Result_t ReadAncillaryResource(const Kumu::UUID&, ASDCP::TimedText::FrameBuffer&,
385                                          const ASDCP::TimedText::IResourceResolver* Resolver = 0) const;
386         };
387
388       //
389       class MXFWriter
390         {
391           class h__Writer;
392           ASDCP::mem_ptr<h__Writer> m_Writer;
393           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
394
395         public:
396           MXFWriter();
397           virtual ~MXFWriter();
398
399           // Warning: direct manipulation of MXF structures can interfere
400           // with the normal operation of the wrapper.  Caveat emptor!
401           virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
402           virtual ASDCP::MXF::RIP& RIP();
403
404           // Open the file for writing. The file must not exist. Returns error if
405           // the operation cannot be completed or if nonsensical data is discovered
406           // in the essence descriptor.
407           Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
408                              const ASDCP::TimedText::TimedTextDescriptor&, ui32_t HeaderSize = 16384);
409
410           // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
411           // encoded. If the optional AESEncContext argument is present, the essence
412           // is encrypted prior to writing. Fails if the file is not open, is finalized,
413           // or an operating system error occurs.
414           // This method may only be called once, and it must be called before any
415           // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
416           // conditions are not met.
417           Result_t WriteTimedTextResource(const std::string& XMLDoc, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
418
419           // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
420           // argument is present, the essence is encrypted prior to writing.
421           // Fails if the file is not open, is finalized, or an operating system
422           // error occurs. RESULT_STATE will be returned if the method is called before
423           // WriteTimedTextResource()
424           Result_t WriteAncillaryResource(const ASDCP::TimedText::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
425
426           // Closes the MXF file, writing the index and revised header.
427           Result_t Finalize();
428         };
429
430       //
431       class MXFReader
432         {
433           class h__Reader;
434           ASDCP::mem_ptr<h__Reader> m_Reader;
435           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
436
437         public:
438           MXFReader();
439           virtual ~MXFReader();
440
441           // Warning: direct manipulation of MXF structures can interfere
442           // with the normal operation of the wrapper.  Caveat emptor!
443           virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
444           virtual AS_02::MXF::AS02IndexReader& AS02IndexReader();
445           virtual ASDCP::MXF::RIP& RIP();
446
447           // Open the file for reading. The file must exist. Returns error if the
448           // operation cannot be completed.
449           Result_t OpenRead(const std::string& filename) const;
450
451           // Returns RESULT_INIT if the file is not open.
452           Result_t Close() const;
453
454           // Fill a TimedTextDescriptor struct with the values from the file's header.
455           // Returns RESULT_INIT if the file is not open.
456           Result_t FillTimedTextDescriptor(ASDCP::TimedText::TimedTextDescriptor&) const;
457
458           // Fill a WriterInfo struct with the values from the file's header.
459           // Returns RESULT_INIT if the file is not open.
460           Result_t FillWriterInfo(ASDCP::WriterInfo&) const;
461
462           // Reads the complete Timed Text Resource into the given string. Fails if the resource
463           // is encrypted and AESDecContext is NULL (use the following method to retrieve the
464           // raw ciphertet block).
465           Result_t ReadTimedTextResource(std::string&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
466
467           // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
468           // argument is present, the resource is decrypted after reading. If the MXF
469           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
470           // will contain the ciphertext frame data. If the HMACContext argument is
471           // not NULL, the HMAC will be calculated (if the file supports it).
472           // Returns RESULT_INIT if the file is not open, failure if the frame number is
473           // out of range, or if optional decrypt or HAMC operations fail.
474           Result_t ReadTimedTextResource(ASDCP::TimedText::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
475
476           // Reads the timed-text resource having the given UUID from the MXF file. If the
477           // optional AESEncContext argument is present, the resource is decrypted after
478           // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
479           // the frame buffer will contain the ciphertext frame data. If the HMACContext
480           // argument is not NULL, the HMAC will be calculated (if the file supports it).
481           // Returns RESULT_INIT if the file is not open, failure if the frame number is
482           // out of range, or if optional decrypt or HAMC operations fail.
483           Result_t ReadAncillaryResource(const Kumu::UUID&, ASDCP::TimedText::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
484
485           // Print debugging information to stream
486           void     DumpHeaderMetadata(FILE* = 0) const;
487           void     DumpIndex(FILE* = 0) const;
488         };
489     } // namespace TimedText
490
491
492 } // namespace AS_02
493
494 #endif // _AS_02_H_
495
496 //
497 // end AS_02.h
498 //