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