massive dictionary re-factoring
[asdcplib.git] / src / AS_DCP_internal.h
1 /*
2 Copyright (c) 2004-2009, 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 <KM_platform.h>
36 #include <KM_util.h>
37 #include <KM_log.h>
38 #include "Metadata.h"
39
40 using Kumu::DefaultLogSink;
41 // using namespace std;
42 using namespace ASDCP;
43 using namespace ASDCP::MXF;
44
45
46
47 namespace ASDCP
48 {
49   // constant values used to calculate KLV and EKLV packet sizes
50   static const ui32_t klv_cryptinfo_size =
51     MXF_BER_LENGTH
52     + UUIDlen /* ContextID */
53     + MXF_BER_LENGTH
54     + sizeof(ui64_t) /* PlaintextOffset */
55     + MXF_BER_LENGTH
56     + SMPTE_UL_LENGTH /* SourceKey */
57     + MXF_BER_LENGTH
58     + sizeof(ui64_t) /* SourceLength */
59     + MXF_BER_LENGTH /* ESV length */ ;
60
61   static const ui32_t klv_intpack_size =
62     MXF_BER_LENGTH
63     + UUIDlen /* TrackFileID */
64     + MXF_BER_LENGTH
65     + sizeof(ui64_t) /* SequenceNumber */
66     + MXF_BER_LENGTH
67     + 20; /* HMAC length*/
68
69   // calculate size of encrypted essence with IV, CheckValue, and padding
70   inline ui32_t
71     calc_esv_length(ui32_t source_length, ui32_t plaintext_offset)
72     {
73       ui32_t ct_size = source_length - plaintext_offset;
74       ui32_t diff = ct_size % CBC_BLOCK_SIZE;
75       ui32_t block_size = ct_size - diff;
76       return plaintext_offset + block_size + (CBC_BLOCK_SIZE * 3);
77     }
78
79   // the check value for EKLV packets
80   // CHUKCHUKCHUKCHUK
81   static const byte_t ESV_CheckValue[CBC_BLOCK_SIZE] =
82   { 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b,
83     0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b };
84
85   //------------------------------------------------------------------------------------------
86   //
87
88   Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&);
89   Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&, const Dictionary&);
90   Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
91   Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
92
93   //
94  class KLReader : public ASDCP::KLVPacket
95     {
96       ASDCP_NO_COPY_CONSTRUCT(KLReader);
97       byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
98
99     public:
100       KLReader() {}
101       ~KLReader() {}
102
103       inline const byte_t* Key() { return m_KeyBuf; }
104       inline const ui64_t  Length() { return m_ValueLength; }
105       inline const ui64_t  KLLength() { return m_KLLength; }
106       
107       Result_t ReadKLFromFile(Kumu::FileReader& Reader);
108     };
109
110   //
111   class h__Reader
112     {
113       ASDCP_NO_COPY_CONSTRUCT(h__Reader);
114       h__Reader();
115
116     public:
117       const Dictionary&  m_Dict;
118       Kumu::FileReader   m_File;
119       OPAtomHeader       m_HeaderPart;
120       Partition          m_BodyPart;
121       OPAtomIndexFooter  m_FooterPart;
122       ui64_t             m_EssenceStart;
123       WriterInfo         m_Info;
124       ASDCP::FrameBuffer m_CtFrameBuf;
125       Kumu::fpos_t       m_LastPosition;
126
127       h__Reader(const Dictionary&);
128       virtual ~h__Reader();
129
130       Result_t InitInfo();
131       Result_t OpenMXFRead(const char* filename);
132       Result_t InitMXFIndex();
133
134       // positions file before reading
135       Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
136                              const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
137
138       // reads from current position
139       Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
140                               const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
141       void     Close();
142     };
143
144
145   // state machine for mxf writer
146   enum WriterState_t {
147     ST_BEGIN,   // waiting for Open()
148     ST_INIT,    // waiting for SetSourceStream()
149     ST_READY,   // ready to write frames
150     ST_RUNNING, // one or more frames written
151     ST_FINAL,   // index written, file closed
152   };
153
154   // implementation of h__WriterState class Goto_* methods
155 #define Goto_body(s1,s2) if ( m_State != (s1) ) \
156                            return RESULT_STATE; \
157                          m_State = (s2); \
158                          return RESULT_OK
159   //
160   class h__WriterState
161     {
162       ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
163
164     public:
165       WriterState_t m_State;
166       h__WriterState() : m_State(ST_BEGIN) {}
167       ~h__WriterState() {}
168
169       inline bool     Test_BEGIN()   { return m_State == ST_BEGIN; }
170       inline bool     Test_INIT()    { return m_State == ST_INIT; }
171       inline bool     Test_READY()   { return m_State == ST_READY;}
172       inline bool     Test_RUNNING() { return m_State == ST_RUNNING; }
173       inline bool     Test_FINAL()   { return m_State == ST_FINAL; }
174       inline Result_t Goto_INIT()    { Goto_body(ST_BEGIN,   ST_INIT); }
175       inline Result_t Goto_READY()   { Goto_body(ST_INIT,    ST_READY); }
176       inline Result_t Goto_RUNNING() { Goto_body(ST_READY,   ST_RUNNING); }
177       inline Result_t Goto_FINAL()   { Goto_body(ST_RUNNING, ST_FINAL); }
178     };
179
180   typedef std::list<ui64_t*> DurationElementList_t;
181
182   //
183   class h__Writer
184     {
185       ASDCP_NO_COPY_CONSTRUCT(h__Writer);
186       h__Writer();
187
188     public:
189       const Dictionary&  m_Dict;
190       Kumu::FileWriter   m_File;
191       ui32_t             m_HeaderSize;
192       OPAtomHeader       m_HeaderPart;
193       Partition          m_BodyPart;
194       OPAtomIndexFooter  m_FooterPart;
195       ui64_t             m_EssenceStart;
196
197       MaterialPackage*   m_MaterialPackage;
198       SourcePackage*     m_FilePackage;
199
200       FileDescriptor*    m_EssenceDescriptor;
201       std::list<InterchangeObject*> m_EssenceSubDescriptorList;
202
203       ui32_t             m_FramesWritten;
204       ui64_t             m_StreamOffset;
205       ASDCP::FrameBuffer m_CtFrameBuf;
206       h__WriterState     m_State;
207       WriterInfo         m_Info;
208       DurationElementList_t m_DurationUpdateList;
209
210       h__Writer(const Dictionary&);
211       virtual ~h__Writer();
212
213       void InitHeader();
214       void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
215                          const std::string& TrackName, const UL& DataDefinition,
216                          const std::string& PackageLabel);
217       void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
218                          const std::string& TrackName, const UL& DataDefinition,
219                         const std::string& PackageLabel);
220       void AddEssenceDescriptor(const UL& WrappingUL);
221       Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
222
223       // all the above for a single source clip
224       Result_t WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL,
225                               const std::string& TrackName, const UL& DataDefinition,
226                               const MXF::Rational& EditRate,
227                               ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
228
229       Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
230                                const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
231
232       Result_t WriteMXFFooter();
233
234    };
235
236
237   // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
238   //
239   class IntegrityPack
240     {
241     public:
242       byte_t Data[klv_intpack_size];
243   
244       IntegrityPack() {
245         memset(Data, 0, klv_intpack_size);
246       }
247
248       ~IntegrityPack() {}
249   
250       Result_t CalcValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
251       Result_t TestValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
252     };
253
254
255 } // namespace ASDCP
256
257 #endif // _AS_DCP_INTERNAL_H_
258
259
260 //
261 // end AS_DCP_internal.h
262 //