version bump
[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 durationInSamples, const ASDCP::MXF::WaveAudioDescriptor& d,
122                                                   const ASDCP::Rational& edit_rate)
123     {
124       return static_cast<ui32_t>(static_cast<ui64_t>(durationInSamples) *
125                                  static_cast<ui64_t>(d.AudioSamplingRate.Denominator * edit_rate.Numerator) /
126                                  static_cast<ui64_t>(d.AudioSamplingRate.Numerator * edit_rate.Denominator));
127     }
128
129   } // namespace MXF
130
131
132   // IMF App 2 edit rates not already exposed in namespace ASDCP
133   const ASDCP::Rational EditRate_29_97 = ASDCP::Rational(30000, 1001);
134   const ASDCP::Rational EditRate_59_94 = ASDCP::Rational(60000, 1001);
135
136   //---------------------------------------------------------------------------------
137   // Accessors in the MXFReader and MXFWriter classes below return these types to
138   // provide direct access to MXF metadata structures declared in MXF.h and Metadata.h
139
140   // See ST 2067-5 Sec. x.y.z
141   enum IndexStrategy_t
142   {
143     IS_LEAD,
144     IS_FOLLOW,
145     IS_FILE_SPECIFIC,
146     IS_MAX
147   };
148  
149   namespace JP2K
150   { 
151     //
152     class MXFWriter
153     {
154       class h__Writer;
155       ASDCP::mem_ptr<h__Writer> m_Writer;
156       ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
157       
158     public:
159       MXFWriter();
160       virtual ~MXFWriter();
161
162       // Warning: direct manipulation of MXF structures can interfere
163       // with the normal operation of the wrapper.  Caveat emptor!
164       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
165       virtual ASDCP::MXF::RIP& RIP();
166
167       // Open the file for writing. The file must not exist. Returns error if
168       // the operation cannot be completed or if nonsensical data is discovered
169       // in the essence descriptor.
170       Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
171                          ASDCP::MXF::FileDescriptor* essence_descriptor,
172                          ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
173                          const ASDCP::Rational& edit_rate, const ui32_t& header_size = 16384,
174                          const IndexStrategy_t& strategy = IS_FOLLOW, const ui32_t& partition_space = 10);
175
176       // Writes a frame of essence to the MXF file. If the optional AESEncContext
177       // argument is present, the essence is encrypted prior to writing.
178       // Fails if the file is not open, is finalized, or an operating system
179       // error occurs.
180       Result_t WriteFrame(const ASDCP::JP2K::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
181
182       // Closes the MXF file, writing the index and revised header.
183       Result_t Finalize();
184     };
185
186     //
187     class MXFReader
188     {
189       class h__Reader;
190       ASDCP::mem_ptr<h__Reader> m_Reader;
191       ASDCP_NO_COPY_CONSTRUCT(MXFReader);
192
193     public:
194       MXFReader();
195       virtual ~MXFReader();
196
197       // Warning: direct manipulation of MXF structures can interfere
198       // with the normal operation of the wrapper.  Caveat emptor!
199       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
200       virtual AS_02::MXF::AS02IndexReader& AS02IndexReader();
201       virtual ASDCP::MXF::RIP& RIP();
202
203       // Open the file for reading. The file must exist. Returns error if the
204       // operation cannot be completed.
205       Result_t OpenRead(const std::string& filename) const;
206
207       // Returns RESULT_INIT if the file is not open.
208       Result_t Close() const;
209
210       // Fill a WriterInfo struct with the values from the file's header.
211       // Returns RESULT_INIT if the file is not open.
212       Result_t FillWriterInfo(ASDCP::WriterInfo&) const;
213
214       // Reads a frame of essence from the MXF file. If the optional AESEncContext
215       // argument is present, the essence is decrypted after reading. If the MXF
216       // file is encrypted and the AESDecContext argument is NULL, the frame buffer
217       // will contain the ciphertext frame data. If the HMACContext argument is
218       // not NULL, the HMAC will be calculated (if the file supports it).
219       // Returns RESULT_INIT if the file is not open, failure if the frame number is
220       // out of range, or if optional decrypt or HAMC operations fail.
221       Result_t ReadFrame(ui32_t frame_number, ASDCP::JP2K::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
222
223       // Print debugging information to stream
224       void     DumpHeaderMetadata(FILE* = 0) const;
225       void     DumpIndex(FILE* = 0) const;
226     };
227     
228   } //namespace JP2K
229   
230
231   //---------------------------------------------------------------------------------
232   //
233   namespace PCM
234   {
235     // see AS_DCP.h for related data types
236
237     // An AS-02 PCM file is clip-wrapped, but the interface defined below mimics that used
238     // for frame-wrapped essence elsewhere in this library.  The concept of frame rate
239     // therefore is only relevant to these classes and is not reflected in or affected by
240     // the contents of the MXF file.  The frame rate that is set on the writer is only
241     // for compatibility with the existing parsers, samples are packed contiguously into
242     // the same clip-wrapped packet.  Similarly, the edit rate must be set when initializing
243     // the reader to signal the number of samples to be read by each call to ReadFrame();
244
245     //
246       class MXFWriter
247     {
248       class h__Writer;
249       ASDCP::mem_ptr<h__Writer> m_Writer;
250       ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
251
252     public:
253       MXFWriter();
254       virtual ~MXFWriter();
255
256       // Warning: direct manipulation of MXF structures can interfere
257       // with the normal operation of the wrapper.  Caveat emptor!
258       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
259       virtual ASDCP::MXF::RIP& RIP();
260
261       // Open the file for writing. The file must not exist. Returns error if
262       // the operation cannot be completed or if nonsensical data is discovered
263       // in the essence descriptor.
264       Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
265                          ASDCP::MXF::FileDescriptor* essence_descriptor,
266                          ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
267                          const ASDCP::Rational& edit_rate, ui32_t HeaderSize = 16384);
268
269       // Writes a frame of essence to the MXF file. If the optional AESEncContext
270       // argument is present, the essence is encrypted prior to writing.
271       // Fails if the file is not open, is finalized, or an operating system
272       // error occurs.
273       Result_t WriteFrame(const ASDCP::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
274       
275       // Closes the MXF file, writing the index and revised header.
276       Result_t Finalize();
277     };
278
279     //
280     class MXFReader
281     {
282       class h__Reader;
283       ASDCP::mem_ptr<h__Reader> m_Reader;
284       ASDCP_NO_COPY_CONSTRUCT(MXFReader);
285
286     public:
287       MXFReader();
288       virtual ~MXFReader();
289
290       // Warning: direct manipulation of MXF structures can interfere
291       // with the normal operation of the wrapper.  Caveat emptor!
292       virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
293       virtual AS_02::MXF::AS02IndexReader& AS02IndexReader();
294       virtual ASDCP::MXF::RIP& RIP();
295
296       // Open the file for reading. The file must exist. Returns error if the
297       // operation cannot be completed.
298       Result_t OpenRead(const std::string& filename, const ASDCP::Rational& EditRate);
299
300       // Returns RESULT_INIT if the file is not open.
301       Result_t Close() const;
302
303       // Fill a WriterInfo struct with the values from the file's header.
304       // Returns RESULT_INIT if the file is not open.
305       Result_t FillWriterInfo(ASDCP::WriterInfo&) const;
306
307       // Reads a frame of essence from the MXF file. If the optional AESEncContext
308       // argument is present, the essence is decrypted after reading. If the MXF
309       // file is encrypted and the AESDecContext argument is NULL, the frame buffer
310       // will contain the ciphertext frame data. If the HMACContext argument is
311       // not NULL, the HMAC will be calculated (if the file supports it).
312       // Returns RESULT_INIT if the file is not open, failure if the frame number is
313       // out of range, or if optional decrypt or HAMC operations fail.
314       Result_t ReadFrame(ui32_t frame_number, ASDCP::PCM::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
315       
316       // Print debugging information to stream
317       void     DumpHeaderMetadata(FILE* = 0) const;
318       void     DumpIndex(FILE* = 0) const;
319     };
320   } // namespace PCM
321
322   //---------------------------------------------------------------------------------
323   //
324   namespace TimedText
325     {
326       using ASDCP::TimedText::TimedTextDescriptor;
327       using ASDCP::TimedText::TimedTextResourceDescriptor;
328       using ASDCP::TimedText::ResourceList_t;
329
330       //
331       class ST2052_TextParser
332         {
333           class h__TextParser;
334           ASDCP::mem_ptr<h__TextParser> m_Parser;
335           ASDCP_NO_COPY_CONSTRUCT(ST2052_TextParser);
336
337         public:
338           ST2052_TextParser();
339           virtual ~ST2052_TextParser();
340
341           // Opens an XML file for reading, parses data to provide a complete
342           // set of stream metadata for the MXFWriter below.
343           Result_t OpenRead(const std::string& filename) const;
344
345           // Parse an XML string 
346           Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const;
347
348           // Fill a TimedTextDescriptor struct with the values from the file's contents.
349           // Returns RESULT_INIT if the file is not open.
350           Result_t FillTimedTextDescriptor(ASDCP::TimedText::TimedTextDescriptor&) const;
351
352           // Reads the complete Timed Text Resource into the given string.
353           Result_t ReadTimedTextResource(std::string&) const;
354
355           // Reads the Ancillary Resource having the given ID. Fails if the buffer
356           // is too small or the resource does not exist. The optional Resolver
357           // argument can be provided which will be used to retrieve the resource
358           // having a particulat UUID. If a Resolver is not supplied, the default
359           // internal resolver will return the contents of the file having the UUID
360           // as the filename. The filename must exist in the same directory as the
361           // XML file opened with OpenRead().
362           Result_t ReadAncillaryResource(const Kumu::UUID&, ASDCP::TimedText::FrameBuffer&,
363                                          const ASDCP::TimedText::IResourceResolver* Resolver = 0) const;
364         };
365
366       //
367       class MXFWriter
368         {
369           class h__Writer;
370           ASDCP::mem_ptr<h__Writer> m_Writer;
371           ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
372
373         public:
374           MXFWriter();
375           virtual ~MXFWriter();
376
377           // Warning: direct manipulation of MXF structures can interfere
378           // with the normal operation of the wrapper.  Caveat emptor!
379           virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
380           virtual ASDCP::MXF::RIP& RIP();
381
382           // Open the file for writing. The file must not exist. Returns error if
383           // the operation cannot be completed or if nonsensical data is discovered
384           // in the essence descriptor.
385           Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&,
386                              const ASDCP::TimedText::TimedTextDescriptor&, ui32_t HeaderSize = 16384);
387
388           // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8
389           // encoded. If the optional AESEncContext argument is present, the essence
390           // is encrypted prior to writing. Fails if the file is not open, is finalized,
391           // or an operating system error occurs.
392           // This method may only be called once, and it must be called before any
393           // call to WriteAncillaryResource(). RESULT_STATE will be returned if these
394           // conditions are not met.
395           Result_t WriteTimedTextResource(const std::string& XMLDoc, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
396
397           // Writes an Ancillary Resource to the MXF file. If the optional AESEncContext
398           // argument is present, the essence is encrypted prior to writing.
399           // Fails if the file is not open, is finalized, or an operating system
400           // error occurs. RESULT_STATE will be returned if the method is called before
401           // WriteTimedTextResource()
402           Result_t WriteAncillaryResource(const ASDCP::TimedText::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0);
403
404           // Closes the MXF file, writing the index and revised header.
405           Result_t Finalize();
406         };
407
408       //
409       class MXFReader
410         {
411           class h__Reader;
412           ASDCP::mem_ptr<h__Reader> m_Reader;
413           ASDCP_NO_COPY_CONSTRUCT(MXFReader);
414
415         public:
416           MXFReader();
417           virtual ~MXFReader();
418
419           // Warning: direct manipulation of MXF structures can interfere
420           // with the normal operation of the wrapper.  Caveat emptor!
421           virtual ASDCP::MXF::OP1aHeader& OP1aHeader();
422           virtual AS_02::MXF::AS02IndexReader& AS02IndexReader();
423           virtual ASDCP::MXF::RIP& RIP();
424
425           // Open the file for reading. The file must exist. Returns error if the
426           // operation cannot be completed.
427           Result_t OpenRead(const std::string& filename) const;
428
429           // Returns RESULT_INIT if the file is not open.
430           Result_t Close() const;
431
432           // Fill a TimedTextDescriptor struct with the values from the file's header.
433           // Returns RESULT_INIT if the file is not open.
434           Result_t FillTimedTextDescriptor(ASDCP::TimedText::TimedTextDescriptor&) const;
435
436           // Fill a WriterInfo struct with the values from the file's header.
437           // Returns RESULT_INIT if the file is not open.
438           Result_t FillWriterInfo(ASDCP::WriterInfo&) const;
439
440           // Reads the complete Timed Text Resource into the given string. Fails if the resource
441           // is encrypted and AESDecContext is NULL (use the following method to retrieve the
442           // raw ciphertet block).
443           Result_t ReadTimedTextResource(std::string&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
444
445           // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext
446           // argument is present, the resource is decrypted after reading. If the MXF
447           // file is encrypted and the AESDecContext argument is NULL, the frame buffer
448           // will contain the ciphertext frame data. If the HMACContext argument is
449           // not NULL, the HMAC will be calculated (if the file supports it).
450           // Returns RESULT_INIT if the file is not open, failure if the frame number is
451           // out of range, or if optional decrypt or HAMC operations fail.
452           Result_t ReadTimedTextResource(ASDCP::TimedText::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
453
454           // Reads the timed-text resource having the given UUID from the MXF file. If the
455           // optional AESEncContext argument is present, the resource is decrypted after
456           // reading. If the MXF file is encrypted and the AESDecContext argument is NULL,
457           // the frame buffer will contain the ciphertext frame data. If the HMACContext
458           // argument is not NULL, the HMAC will be calculated (if the file supports it).
459           // Returns RESULT_INIT if the file is not open, failure if the frame number is
460           // out of range, or if optional decrypt or HAMC operations fail.
461           Result_t ReadAncillaryResource(const Kumu::UUID&, ASDCP::TimedText::FrameBuffer&, ASDCP::AESDecContext* = 0, ASDCP::HMACContext* = 0) const;
462
463           // Print debugging information to stream
464           void     DumpHeaderMetadata(FILE* = 0) const;
465           void     DumpIndex(FILE* = 0) const;
466         };
467     } // namespace TimedText
468
469
470 } // namespace AS_02
471
472 #endif // _AS_02_H_
473
474 //
475 // end AS_02.h
476 //