banner updates to 2015
[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 ST2052_TextParser
338         {
339           class h__TextParser;
340           ASDCP::mem_ptr<h__TextParser> m_Parser;
341           ASDCP_NO_COPY_CONSTRUCT(ST2052_TextParser);
342
343         public:
344           ST2052_TextParser();
345           virtual ~ST2052_TextParser();
346
347           // Opens an XML file for reading, parses data to provide a complete
348           // set of stream metadata for the MXFWriter below.
349           Result_t OpenRead(const std::string& filename) const;
350
351           // Parse an XML string 
352           Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const;
353
354           // Fill a TimedTextDescriptor struct with the values from the file's contents.
355           // Returns RESULT_INIT if the file is not open.
356           Result_t FillTimedTextDescriptor(ASDCP::TimedText::TimedTextDescriptor&) const;
357
358           // Reads the complete Timed Text Resource into the given string.
359           Result_t ReadTimedTextResource(std::string&) const;
360
361           // Reads the Ancillary Resource having the given ID. Fails if the buffer
362           // is too small or the resource does not exist. The optional Resolver
363           // argument can be provided which will be used to retrieve the resource
364           // having a particulat UUID. If a Resolver is not supplied, the default
365           // internal resolver will return the contents of the file having the UUID
366           // as the filename. The filename must exist in the same directory as the
367           // XML file opened with OpenRead().
368           Result_t ReadAncillaryResource(const Kumu::UUID&, ASDCP::TimedText::FrameBuffer&,
369                                          const ASDCP::TimedText::IResourceResolver* Resolver = 0) const;
370         };
371
372       //
373       class MXFWriter
374         {
375           class h__Writer;
376           ASDCP::mem_ptr<h__Writer> m_Writer;
377           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
378
379         public:
380           MXFWriter();
381           virtual ~MXFWriter();
382
383           // Warning: direct manipulation of MXF structures can interfere
384           // with the normal operation of the wrapper.  Caveat emptor!
385           virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
386           virtual ASDCP::MXF::RIP& RIP();
387
388           // Open the file for writing. The file must not exist. Returns error if
389           // the operation cannot be completed or if nonsensical data is discovered
390           // in the essence descriptor.
391           Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
392                              const ASDCP::TimedText::TimedTextDescriptor&, ui32_t HeaderSize = 16384);
393
394           // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
395           // encoded. If the optional AESEncContext argument is present, the essence
396           // is encrypted prior to writing. Fails if the file is not open, is finalized,
397           // or an operating system error occurs.
398           // This method may only be called once, and it must be called before any
399           // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
400           // conditions are not met.
401           Result_t WriteTimedTextResource(const std::string& XMLDoc, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
402
403           // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
404           // argument is present, the essence is encrypted prior to writing.
405           // Fails if the file is not open, is finalized, or an operating system
406           // error occurs. RESULT_STATE will be returned if the method is called before
407           // WriteTimedTextResource()
408           Result_t WriteAncillaryResource(const ASDCP::TimedText::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
409
410           // Closes the MXF file, writing the index and revised header.
411           Result_t Finalize();
412         };
413
414       //
415       class MXFReader
416         {
417           class h__Reader;
418           ASDCP::mem_ptr<h__Reader> m_Reader;
419           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
420
421         public:
422           MXFReader();
423           virtual ~MXFReader();
424
425           // Warning: direct manipulation of MXF structures can interfere
426           // with the normal operation of the wrapper.  Caveat emptor!
427           virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
428           virtual AS_02::MXF::AS02IndexReader& AS02IndexReader();
429           virtual ASDCP::MXF::RIP& RIP();
430
431           // Open the file for reading. The file must exist. Returns error if the
432           // operation cannot be completed.
433           Result_t OpenRead(const std::string& filename) const;
434
435           // Returns RESULT_INIT if the file is not open.
436           Result_t Close() const;
437
438           // Fill a TimedTextDescriptor struct with the values from the file's header.
439           // Returns RESULT_INIT if the file is not open.
440           Result_t FillTimedTextDescriptor(ASDCP::TimedText::TimedTextDescriptor&) const;
441
442           // Fill a WriterInfo struct with the values from the file's header.
443           // Returns RESULT_INIT if the file is not open.
444           Result_t FillWriterInfo(ASDCP::WriterInfo&) const;
445
446           // Reads the complete Timed Text Resource into the given string. Fails if the resource
447           // is encrypted and AESDecContext is NULL (use the following method to retrieve the
448           // raw ciphertet block).
449           Result_t ReadTimedTextResource(std::string&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
450
451           // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
452           // argument is present, the resource is decrypted after reading. If the MXF
453           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
454           // will contain the ciphertext frame data. If the HMACContext argument is
455           // not NULL, the HMAC will be calculated (if the file supports it).
456           // Returns RESULT_INIT if the file is not open, failure if the frame number is
457           // out of range, or if optional decrypt or HAMC operations fail.
458           Result_t ReadTimedTextResource(ASDCP::TimedText::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
459
460           // Reads the timed-text resource having the given UUID from the MXF file. If the
461           // optional AESEncContext argument is present, the resource is decrypted after
462           // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
463           // the frame buffer will contain the ciphertext frame data. If the HMACContext
464           // argument is not NULL, the HMAC will be calculated (if the file supports it).
465           // Returns RESULT_INIT if the file is not open, failure if the frame number is
466           // out of range, or if optional decrypt or HAMC operations fail.
467           Result_t ReadAncillaryResource(const Kumu::UUID&, ASDCP::TimedText::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
468
469           // Print debugging information to stream
470           void     DumpHeaderMetadata(FILE* = 0) const;
471           void     DumpIndex(FILE* = 0) const;
472         };
473     } // namespace TimedText
474
475
476 } // namespace AS_02
477
478 #endif // _AS_02_H_
479
480 //
481 // end AS_02.h
482 //