ca3d9bbb9c76792a46073200409b87db65ae3de2
[asdcplib.git] / src / AS_DCP_internal.h
1 /*
2 Copyright (c) 2004-2006, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27 /*! \file    AS_DCP_internal.h
28     \version $Id$       
29     \brief   AS-DCP library, non-public common elements
30 */
31
32 #ifndef _AS_DCP_INTERNAL_H__
33 #define _AS_DCP_INTERNAL_H__
34
35 #include "AS_DCP_system.h"
36 #include "Metadata.h"
37 #include "hex_utils.h"
38
39 using namespace std;
40 using namespace ASDCP;
41 using namespace ASDCP::MXF;
42
43
44
45 namespace ASDCP
46 {
47   // constant values used to calculate KLV and EKLV packet sizes
48   static const ui32_t klv_key_size = 16;
49   static const ui32_t klv_length_size = 4;
50
51   static const ui32_t klv_cryptinfo_size =
52     klv_length_size
53     + UUIDlen /* ContextID */
54     + klv_length_size
55     + sizeof(ui64_t) /* PlaintextOffset */
56     + klv_length_size
57     + klv_key_size /* SourceKey */
58     + klv_length_size
59     + sizeof(ui64_t) /* SourceLength */
60     + klv_length_size /* ESV length */ ;
61
62   static const ui32_t klv_intpack_size =
63     klv_length_size
64     + UUIDlen /* TrackFileID */
65     + klv_length_size
66     + sizeof(ui64_t) /* SequenceNumber */
67     + klv_length_size
68     + 20; /* HMAC length*/
69
70   // why this value? i dunno. it was peeled from mxflib.
71   static const ui32_t HeaderPadding = 16384;
72   
73   const byte_t GCMulti_Data[16] =
74   { 0x06, 0x0E, 0x2B, 0x34, 0x04, 0x01, 0x01, 0x03,
75     0x0d, 0x01, 0x03, 0x01, 0x02, 0x7F, 0x01, 0x00 };
76
77   static const byte_t CipherAlgorithm_AES[klv_key_size] =
78   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x07,
79     0x02, 0x09, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00 };
80
81   static const byte_t MICAlgorithm_NONE[klv_key_size] = {0};
82   static const byte_t MICAlgorithm_HMAC_SHA1[klv_key_size] = 
83   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x07,
84     0x02, 0x09, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00 };
85
86 #ifdef SMPTE_LABELS
87   static byte_t OPAtom_Data[klv_key_size] =
88   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x02,
89     0x0d, 0x01, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00 };
90   static UL OPAtomUL(OPAtom_Data);
91 #else
92   static byte_t OPAtom_Data[klv_key_size] =
93   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
94     0x0d, 0x01, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00 };
95   static UL OPAtomUL(OPAtom_Data);
96 #endif
97
98   static const byte_t OP1a_Data[klv_key_size] =
99   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
100     0x0d, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00 };
101   static UL OP1aUL(OP1a_Data);
102   
103   // Essence element labels
104   static const byte_t WAVEssenceUL_Data[klv_key_size] =
105   { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01, 0x01,
106     0x0d, 0x01, 0x03, 0x01, 0x16, 0x01, 0x01, 0x00 };
107
108   static const byte_t MPEGEssenceUL_Data[klv_key_size] =
109   { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01, 0x01,
110     0x0d, 0x01, 0x03, 0x01, 0x15, 0x01, 0x05, 0x00 };
111
112   static const byte_t JP2KEssenceUL_Data[klv_key_size] =
113   { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01, 0x01,
114     0x0d, 0x01, 0x03, 0x01, 0x15, 0x01, 0x08, 0x01 };
115
116 #ifdef SMPTE_LABELS
117   static const byte_t CryptEssenceUL_Data[klv_key_size] =
118   { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x04, 0x01, 0x01,
119     0x0d, 0x01, 0x03, 0x01, 0x02, 0x7e, 0x01, 0x00 };
120 #else
121   static const byte_t CryptEssenceUL_Data[klv_key_size] =
122   { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x04, 0x01, 0x07,
123     0x0d, 0x01, 0x03, 0x01, 0x02, 0x7e, 0x01, 0x00 };
124 #endif
125
126   // Essence Container Labels
127   static const byte_t WrappingUL_Data_PCM_24b_48k[klv_key_size] =
128   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
129     0x0d, 0x01, 0x03, 0x01, 0x02, 0x06, 0x01, 0x00 };
130
131   static const byte_t WrappingUL_Data_MPEG2_VES[klv_key_size] =
132   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x02,
133     0x0d, 0x01, 0x03, 0x01, 0x02, 0x04, 0x60, 0x01 };
134
135   static const byte_t WrappingUL_Data_JPEG_2000[klv_key_size] =
136   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x07,
137     0x0d, 0x01, 0x03, 0x01, 0x02, 0x0c, 0x01, 0x00 };
138
139   static const byte_t WrappingUL_Data_Crypt[klv_key_size] =
140   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x07,
141     0x0d, 0x01, 0x03, 0x01, 0x02, 0x0b, 0x01, 0x00 };
142
143
144   // the label for the Cryptographic Framework DM scheme
145   static const byte_t CryptoFrameworkUL_Data[klv_key_size] =
146   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x07,
147     0x0d, 0x01, 0x04, 0x01, 0x02, 0x01, 0x01, 0x00 };
148
149   // the check value for EKLV packets
150   // CHUKCHUKCHUKCHUK
151   static const byte_t ESV_CheckValue[CBC_BLOCK_SIZE] =
152   { 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b,
153     0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b };
154
155   // labels used for FilePackages
156   static std::string MPEG_PACKAGE_LABEL = "File Package: SMPTE 381M frame wrapping of MPEG2 video elementary stream";
157   static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE XXXM frame wrapping of JPEG 2000 codestreams";
158   static std::string PCM_PACKAGE_LABEL = "File Package: SMPTE 382M frame wrapping of wave audio";
159
160   // GetMDObjectByPath() allows searching for metadata object by pathname
161   // This character separates the path elements.
162   static const char OBJECT_PATH_SEPARATOR = '.';
163
164   //------------------------------------------------------------------------------------------
165   //
166
167   Result_t MD_to_MPEG2_VDesc(MXF::MPEG2VideoDescriptor*, MPEG2::VideoDescriptor&);
168   Result_t MD_to_JP2K_PDesc(MXF::RGBAEssenceDescriptor*, JP2K::PictureDescriptor&);
169   Result_t MD_to_PCM_ADesc(MXF::WaveAudioDescriptor*, PCM::AudioDescriptor&);
170   Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&);
171   Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&);
172   Result_t MPEG2_VDesc_to_MD(MPEG2::VideoDescriptor&, MXF::MPEG2VideoDescriptor*);
173   Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor&, MXF::RGBAEssenceDescriptor*);
174   Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor&, MXF::WaveAudioDescriptor*);
175   Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
176   Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
177
178   // calculate size of encrypted essence with IV, CheckValue, and padding
179   inline ui32_t
180     calc_esv_length(ui32_t source_length, ui32_t plaintext_offset)
181     {
182       ui32_t ct_size = source_length - plaintext_offset;
183       ui32_t diff = ct_size % CBC_BLOCK_SIZE;
184       ui32_t block_size = ct_size - diff;
185       return plaintext_offset + block_size + (CBC_BLOCK_SIZE * 3);
186     }
187
188   //
189   class h__Reader
190     {
191       ASDCP_NO_COPY_CONSTRUCT(h__Reader);
192
193     public:
194       FileReader         m_File;
195       OPAtomHeader       m_HeaderPart;
196       Partition          m_BodyPart;
197       OPAtomIndexFooter  m_FooterPart;
198       ui64_t             m_EssenceStart;
199       WriterInfo         m_Info;
200       ASDCP::FrameBuffer m_CtFrameBuf;
201       fpos_t             m_LastPosition;
202
203       h__Reader();
204       virtual ~h__Reader();
205
206       Result_t InitInfo(WriterInfo& Info);
207       Result_t OpenMXFRead(const char* filename);
208       Result_t InitMXFIndex();
209       Result_t ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
210                               const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
211       void     Close();
212     };
213
214
215   // state machine for mxf writer
216   enum WriterState_t {
217     ST_BEGIN,   // waiting for Open()
218     ST_INIT,    // waiting for SetSourceStream()
219     ST_READY,   // ready to write frames
220     ST_RUNNING, // one or more frames written
221     ST_FINAL,   // index written, file closed
222   };
223
224   // implementation of h__WriterState class Goto_* methods
225 #define Goto_body(s1,s2) if ( m_State != (s1) ) \
226                            return RESULT_STATE; \
227                          m_State = (s2); \
228                          return RESULT_OK
229   //
230   class h__WriterState
231     {
232       ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
233
234     public:
235       WriterState_t m_State;
236       h__WriterState() : m_State(ST_BEGIN) {}
237       ~h__WriterState() {}
238
239       inline bool     Test_BEGIN()   { return m_State == ST_BEGIN; }
240       inline bool     Test_INIT()    { return m_State == ST_INIT; }
241       inline bool     Test_READY()   { return m_State == ST_READY;}
242       inline bool     Test_RUNNING() { return m_State == ST_RUNNING; }
243       inline bool     Test_FINAL()   { return m_State == ST_FINAL; }
244       inline Result_t Goto_INIT()    { Goto_body(ST_BEGIN,   ST_INIT); }
245       inline Result_t Goto_READY()   { Goto_body(ST_INIT,    ST_READY); }
246       inline Result_t Goto_RUNNING() { Goto_body(ST_READY,   ST_RUNNING); }
247       inline Result_t Goto_FINAL()   { Goto_body(ST_RUNNING, ST_FINAL); }
248     };
249
250   //
251   class h__Writer
252     {
253       ASDCP_NO_COPY_CONSTRUCT(h__Writer);
254
255     public:
256       FileWriter         m_File;
257       OPAtomHeader       m_HeaderPart;
258       Partition          m_BodyPart;
259       OPAtomIndexFooter  m_FooterPart;
260       ui64_t             m_EssenceStart;
261
262       MaterialPackage*   m_MaterialPackage;
263       TimecodeComponent* m_MPTimecode;
264       SourceClip*        m_MPClip;                      //! Material Package SourceClip for each essence stream 
265
266       SourcePackage*     m_FilePackage;
267       TimecodeComponent* m_FPTimecode;
268       SourceClip*        m_FPClip;                      //! File Package SourceClip for each essence stream 
269
270       FileDescriptor*    m_EssenceDescriptor;
271
272       ui32_t             m_FramesWritten;
273       ui64_t             m_StreamOffset;
274       ASDCP::FrameBuffer m_CtFrameBuf;
275       h__WriterState     m_State;
276       WriterInfo         m_Info;
277
278       h__Writer();
279       virtual ~h__Writer();
280
281       Result_t WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL,
282                               const MXF::Rational& EditRate,
283                               ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
284
285       Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
286                                const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
287
288       Result_t WriteMXFFooter();
289
290    };
291
292
293   // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
294   //
295   class IntegrityPack
296     {
297     public:
298       byte_t Data[klv_intpack_size];
299   
300       IntegrityPack() {
301         memset(Data, 0, klv_intpack_size);
302       }
303
304       ~IntegrityPack() {}
305   
306       Result_t CalcValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
307       Result_t TestValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
308     };
309
310   //
311   class KLVReader
312     {
313       byte_t m_Key[32];
314       ui64_t m_Length;
315       ui32_t m_BERLength;
316       ui32_t m_HeaderLength;
317
318       ASDCP_NO_COPY_CONSTRUCT(KLVReader);
319
320     public:
321       KLVReader() : m_Length(0), m_BERLength(0), m_HeaderLength(0) {}
322       ~KLVReader() {}
323
324       inline const byte_t* Key() { return m_Key; }
325       inline const ui64_t  Length() { return m_Length; }
326       inline const ui64_t  KLLength() { return m_BERLength + klv_key_size; }
327       Result_t ReadKLFromFile(ASDCP::FileReader& Reader);
328     };
329
330 } // namespace ASDCP
331
332 #endif // _AS_DCP_INTERNAL_H__
333
334
335 //
336 // end AS_DCP_internal.h
337 //