oops
[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 <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&);
90   Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
91   Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
92
93   //
94   class h__Reader
95     {
96       ASDCP_NO_COPY_CONSTRUCT(h__Reader);
97
98     public:
99       Kumu::FileReader   m_File;
100       OPAtomHeader       m_HeaderPart;
101       Partition          m_BodyPart;
102       OPAtomIndexFooter  m_FooterPart;
103       ui64_t             m_EssenceStart;
104       WriterInfo         m_Info;
105       ASDCP::FrameBuffer m_CtFrameBuf;
106       Kumu::fpos_t       m_LastPosition;
107
108       h__Reader();
109       virtual ~h__Reader();
110
111       Result_t InitInfo();
112       Result_t OpenMXFRead(const char* filename);
113       Result_t InitMXFIndex();
114
115       // positions file before reading
116       Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
117                              const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
118
119       // reads from current position
120       Result_t ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
121                               const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
122       void     Close();
123     };
124
125
126   // state machine for mxf writer
127   enum WriterState_t {
128     ST_BEGIN,   // waiting for Open()
129     ST_INIT,    // waiting for SetSourceStream()
130     ST_READY,   // ready to write frames
131     ST_RUNNING, // one or more frames written
132     ST_FINAL,   // index written, file closed
133   };
134
135   // implementation of h__WriterState class Goto_* methods
136 #define Goto_body(s1,s2) if ( m_State != (s1) ) \
137                            return RESULT_STATE; \
138                          m_State = (s2); \
139                          return RESULT_OK
140   //
141   class h__WriterState
142     {
143       ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
144
145     public:
146       WriterState_t m_State;
147       h__WriterState() : m_State(ST_BEGIN) {}
148       ~h__WriterState() {}
149
150       inline bool     Test_BEGIN()   { return m_State == ST_BEGIN; }
151       inline bool     Test_INIT()    { return m_State == ST_INIT; }
152       inline bool     Test_READY()   { return m_State == ST_READY;}
153       inline bool     Test_RUNNING() { return m_State == ST_RUNNING; }
154       inline bool     Test_FINAL()   { return m_State == ST_FINAL; }
155       inline Result_t Goto_INIT()    { Goto_body(ST_BEGIN,   ST_INIT); }
156       inline Result_t Goto_READY()   { Goto_body(ST_INIT,    ST_READY); }
157       inline Result_t Goto_RUNNING() { Goto_body(ST_READY,   ST_RUNNING); }
158       inline Result_t Goto_FINAL()   { Goto_body(ST_RUNNING, ST_FINAL); }
159     };
160
161   typedef std::list<ui64_t*> DurationElementList_t;
162
163   //
164   class h__Writer
165     {
166       ASDCP_NO_COPY_CONSTRUCT(h__Writer);
167
168     public:
169       Kumu::FileWriter   m_File;
170       ui32_t             m_HeaderSize;
171       OPAtomHeader       m_HeaderPart;
172       Partition          m_BodyPart;
173       OPAtomIndexFooter  m_FooterPart;
174       ui64_t             m_EssenceStart;
175
176       MaterialPackage*   m_MaterialPackage;
177       SourcePackage*     m_FilePackage;
178
179       FileDescriptor*    m_EssenceDescriptor;
180       std::list<FileDescriptor*> m_EssenceSubDescriptorList;
181
182       ui32_t             m_FramesWritten;
183       ui64_t             m_StreamOffset;
184       ASDCP::FrameBuffer m_CtFrameBuf;
185       h__WriterState     m_State;
186       WriterInfo         m_Info;
187       DurationElementList_t m_DurationUpdateList;
188
189       h__Writer();
190       virtual ~h__Writer();
191
192       void InitHeader();
193       void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
194                          const std::string& TrackName, const UL& DataDefinition,
195                          const std::string& PackageLabel);
196       void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
197                          const std::string& TrackName, const UL& DataDefinition,
198                         const std::string& PackageLabel, const UMID& PackageUID);
199       void AddEssenceDescriptor(const UL& WrappingUL);
200       Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
201
202       // all the above for a single source clip
203       Result_t WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL,
204                               const std::string& TrackName, const UL& DataDefinition,
205                               const MXF::Rational& EditRate,
206                               ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
207
208       Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
209                                const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
210
211       Result_t WriteMXFFooter();
212
213    };
214
215
216   // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
217   //
218   class IntegrityPack
219     {
220     public:
221       byte_t Data[klv_intpack_size];
222   
223       IntegrityPack() {
224         memset(Data, 0, klv_intpack_size);
225       }
226
227       ~IntegrityPack() {}
228   
229       Result_t CalcValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
230       Result_t TestValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
231     };
232
233
234 } // namespace ASDCP
235
236 #endif // _AS_DCP_INTERNAL_H_
237
238
239 //
240 // end AS_DCP_internal.h
241 //