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