15890a77917f6f82adb79a906976d7a8d2727e99
[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
49   static const ui32_t klv_cryptinfo_size =
50     MXF_BER_LENGTH
51     + UUIDlen /* ContextID */
52     + MXF_BER_LENGTH
53     + sizeof(ui64_t) /* PlaintextOffset */
54     + MXF_BER_LENGTH
55     + SMPTE_UL_LENGTH /* SourceKey */
56     + MXF_BER_LENGTH
57     + sizeof(ui64_t) /* SourceLength */
58     + MXF_BER_LENGTH /* ESV length */ ;
59
60   static const ui32_t klv_intpack_size =
61     MXF_BER_LENGTH
62     + UUIDlen /* TrackFileID */
63     + MXF_BER_LENGTH
64     + sizeof(ui64_t) /* SequenceNumber */
65     + MXF_BER_LENGTH
66     + 20; /* HMAC length*/
67
68   // calculate size of encrypted essence with IV, CheckValue, and padding
69   inline ui32_t
70     calc_esv_length(ui32_t source_length, ui32_t plaintext_offset)
71     {
72       ui32_t ct_size = source_length - plaintext_offset;
73       ui32_t diff = ct_size % CBC_BLOCK_SIZE;
74       ui32_t block_size = ct_size - diff;
75       return plaintext_offset + block_size + (CBC_BLOCK_SIZE * 3);
76     }
77
78   // Interop labels
79
80   static byte_t OPAtom_Data[SMPTE_UL_LENGTH] =
81   { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01,
82     0x0d, 0x01, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00 };
83   static UL OPAtomUL(OPAtom_Data);
84
85   static const byte_t CryptEssenceUL_Data[SMPTE_UL_LENGTH] =
86   { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x04, 0x01, 0x07,
87     0x0d, 0x01, 0x03, 0x01, 0x02, 0x7e, 0x01, 0x00 };
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&);
100   Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
101   Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
102
103   //
104   class h__Reader
105     {
106       ASDCP_NO_COPY_CONSTRUCT(h__Reader);
107
108     public:
109       FileReader         m_File;
110       OPAtomHeader       m_HeaderPart;
111       Partition          m_BodyPart;
112       OPAtomIndexFooter  m_FooterPart;
113       ui64_t             m_EssenceStart;
114       WriterInfo         m_Info;
115       ASDCP::FrameBuffer m_CtFrameBuf;
116       fpos_t             m_LastPosition;
117
118       h__Reader();
119       virtual ~h__Reader();
120
121       Result_t InitInfo(WriterInfo& Info);
122       Result_t OpenMXFRead(const char* filename);
123       Result_t InitMXFIndex();
124       Result_t ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
125                               const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
126       void     Close();
127     };
128
129
130   // state machine for mxf writer
131   enum WriterState_t {
132     ST_BEGIN,   // waiting for Open()
133     ST_INIT,    // waiting for SetSourceStream()
134     ST_READY,   // ready to write frames
135     ST_RUNNING, // one or more frames written
136     ST_FINAL,   // index written, file closed
137   };
138
139   // implementation of h__WriterState class Goto_* methods
140 #define Goto_body(s1,s2) if ( m_State != (s1) ) \
141                            return RESULT_STATE; \
142                          m_State = (s2); \
143                          return RESULT_OK
144   //
145   class h__WriterState
146     {
147       ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
148
149     public:
150       WriterState_t m_State;
151       h__WriterState() : m_State(ST_BEGIN) {}
152       ~h__WriterState() {}
153
154       inline bool     Test_BEGIN()   { return m_State == ST_BEGIN; }
155       inline bool     Test_INIT()    { return m_State == ST_INIT; }
156       inline bool     Test_READY()   { return m_State == ST_READY;}
157       inline bool     Test_RUNNING() { return m_State == ST_RUNNING; }
158       inline bool     Test_FINAL()   { return m_State == ST_FINAL; }
159       inline Result_t Goto_INIT()    { Goto_body(ST_BEGIN,   ST_INIT); }
160       inline Result_t Goto_READY()   { Goto_body(ST_INIT,    ST_READY); }
161       inline Result_t Goto_RUNNING() { Goto_body(ST_READY,   ST_RUNNING); }
162       inline Result_t Goto_FINAL()   { Goto_body(ST_RUNNING, ST_FINAL); }
163     };
164
165   //
166   class h__Writer
167     {
168       ASDCP_NO_COPY_CONSTRUCT(h__Writer);
169
170     public:
171       FileWriter         m_File;
172       ui32_t             m_HeaderSize;
173       OPAtomHeader       m_HeaderPart;
174       Partition          m_BodyPart;
175       OPAtomIndexFooter  m_FooterPart;
176       ui64_t             m_EssenceStart;
177
178       MaterialPackage*   m_MaterialPackage;
179       Sequence*          m_MPTCSequence;
180       TimecodeComponent* m_MPTimecode;
181       Sequence*          m_MPClSequence;
182       SourceClip*        m_MPClip;                      //! Material Package SourceClip for each essence stream 
183
184       SourcePackage*     m_FilePackage;
185       Sequence*          m_FPTCSequence;
186       TimecodeComponent* m_FPTimecode;
187       Sequence*          m_FPClSequence;
188       SourceClip*        m_FPClip;                      //! File Package SourceClip for each essence stream 
189
190       FileDescriptor*    m_EssenceDescriptor;
191
192       ui32_t             m_FramesWritten;
193       ui64_t             m_StreamOffset;
194       ASDCP::FrameBuffer m_CtFrameBuf;
195       h__WriterState     m_State;
196       WriterInfo         m_Info;
197
198       h__Writer();
199       virtual ~h__Writer();
200
201       Result_t WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL,
202                               const std::string& TrackName, const UL& DataDefinition,
203                               const MXF::Rational& EditRate,
204                               ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
205
206       Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
207                                const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
208
209       Result_t WriteMXFFooter();
210
211    };
212
213
214   // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
215   //
216   class IntegrityPack
217     {
218     public:
219       byte_t Data[klv_intpack_size];
220   
221       IntegrityPack() {
222         memset(Data, 0, klv_intpack_size);
223       }
224
225       ~IntegrityPack() {}
226   
227       Result_t CalcValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
228       Result_t TestValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
229     };
230
231   //
232   class KLVReader
233     {
234       byte_t m_Key[32];
235       ui64_t m_Length;
236       ui32_t m_BERLength;
237       ui32_t m_HeaderLength;
238
239       ASDCP_NO_COPY_CONSTRUCT(KLVReader);
240
241     public:
242       KLVReader() : m_Length(0), m_BERLength(0), m_HeaderLength(0) {}
243       ~KLVReader() {}
244
245       inline const byte_t* Key() { return m_Key; }
246       inline const ui64_t  Length() { return m_Length; }
247       inline const ui64_t  KLLength() { return m_BERLength + SMPTE_UL_LENGTH; }
248       Result_t ReadKLFromFile(ASDCP::FileReader& Reader);
249     };
250
251 } // namespace ASDCP
252
253 #endif // _AS_DCP_INTERNAL_H__
254
255
256 //
257 // end AS_DCP_internal.h
258 //