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