2 Copyright (c) 2004-2013, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
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.
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.
27 /*! \file AS_DCP_internal.h
29 \brief AS-DCP library, non-public common elements
32 #ifndef _AS_DCP_INTERNAL_H_
33 #define _AS_DCP_INTERNAL_H_
35 #include <KM_platform.h>
40 using Kumu::DefaultLogSink;
41 using namespace ASDCP;
42 using namespace ASDCP::MXF;
44 // a magic number identifying asdcplib
45 #ifndef ASDCP_BUILD_NUMBER
46 #define ASDCP_BUILD_NUMBER 0x6A68
50 #ifdef DEFAULT_MD_DECL
51 ASDCP::MXF::OP1aHeader *g_OP1aHeader;
52 ASDCP::MXF::OPAtomIndexFooter *g_OPAtomIndexFooter;
53 ASDCP::MXF::RIP *g_RIP;
55 extern MXF::OP1aHeader *g_OP1aHeader;
56 extern MXF::OPAtomIndexFooter *g_OPAtomIndexFooter;
57 extern MXF::RIP *g_RIP;
63 void default_md_object_init();
66 static std::vector<int>
67 version_split(const char* str)
69 std::vector<int> result;
70 const char* pstr = str;
71 const char* r = strchr(pstr, '.');
77 result.push_back(atoi(pstr));
80 r = strchr(pstr, '.');
83 if( strlen(pstr) > 0 )
84 result.push_back(atoi(pstr));
86 assert(result.size() == 3);
90 // constant values used to calculate KLV and EKLV packet sizes
91 static const ui32_t klv_cryptinfo_size =
93 + UUIDlen /* ContextID */
95 + sizeof(ui64_t) /* PlaintextOffset */
97 + SMPTE_UL_LENGTH /* SourceKey */
99 + sizeof(ui64_t) /* SourceLength */
100 + MXF_BER_LENGTH /* ESV length */ ;
102 static const ui32_t klv_intpack_size =
104 + UUIDlen /* TrackFileID */
106 + sizeof(ui64_t) /* SequenceNumber */
108 + 20; /* HMAC length*/
110 // calculate size of encrypted essence with IV, CheckValue, and padding
112 calc_esv_length(ui32_t source_length, ui32_t plaintext_offset)
114 ui32_t ct_size = source_length - plaintext_offset;
115 ui32_t diff = ct_size % CBC_BLOCK_SIZE;
116 ui32_t block_size = ct_size - diff;
117 return plaintext_offset + block_size + (CBC_BLOCK_SIZE * 3);
120 // the check value for EKLV packets
122 static const byte_t ESV_CheckValue[CBC_BLOCK_SIZE] =
123 { 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b,
124 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b };
126 //------------------------------------------------------------------------------------------
129 Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&);
130 Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&, const Dictionary&);
132 Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
133 Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
135 Result_t MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor& EssenceDescriptor,
136 const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
137 const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
138 ASDCP::JP2K::PictureDescriptor& PDesc);
140 Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
141 const ASDCP::Dictionary& dict,
142 ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
143 ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor);
145 Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
146 Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc);
148 void AddDMScrypt(Partition& HeaderPart, SourcePackage& Package,
149 WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
151 Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
152 const ASDCP::WriterInfo& Info, Kumu::fpos_t& LastPosition, ASDCP::FrameBuffer& CtFrameBuf,
153 ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
154 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
156 Result_t Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
157 const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
158 ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
159 AESEncContext* Ctx, HMACContext* HMAC);
163 class KLReader : public ASDCP::KLVPacket
165 ASDCP_NO_COPY_CONSTRUCT(KLReader);
166 byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
172 inline const byte_t* Key() { return m_KeyBuf; }
173 inline const ui64_t Length() { return m_ValueLength; }
174 inline const ui64_t KLLength() { return m_KLLength; }
176 Result_t ReadKLFromFile(Kumu::FileReader& Reader);
181 //---------------------------------------------------------------------------------
184 /// void default_md_object_init();
186 template <class HeaderType, class IndexAccessType>
187 class TrackFileReader
189 KM_NO_COPY_CONSTRUCT(TrackFileReader);
193 const Dictionary* m_Dict;
194 Kumu::FileReader m_File;
195 HeaderType m_HeaderPart;
196 IndexAccessType m_IndexAccess;
199 ASDCP::FrameBuffer m_CtFrameBuf;
200 Kumu::fpos_t m_LastPosition;
202 TrackFileReader(const Dictionary& d) :
203 m_HeaderPart(m_Dict), m_IndexAccess(m_Dict), m_RIP(m_Dict), m_Dict(&d)
205 default_md_object_init();
208 virtual ~TrackFileReader() {
212 const MXF::RIP& GetRIP() const { return m_RIP; }
215 Result_t OpenMXFRead(const char* filename)
218 Result_t result = m_File.OpenRead(filename);
220 if ( ASDCP_SUCCESS(result) )
221 result = SeekToRIP(m_File);
223 if ( ASDCP_SUCCESS(result) )
225 result = m_RIP.InitFromFile(m_File);
226 ui32_t test_s = m_RIP.PairArray.size();
228 if ( ASDCP_FAILURE(result) )
230 DefaultLogSink().Error("File contains no RIP\n");
232 else if ( m_RIP.PairArray.empty() )
234 DefaultLogSink().Error("RIP contains no Pairs.\n");
239 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, SeekToRIP failed\n");
243 result = m_HeaderPart.InitFromFile(m_File);
245 if ( KM_FAILURE(result) )
247 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, header init failed\n");
257 InterchangeObject* Object;
260 Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object);
262 // Writer Info and SourcePackage
263 if ( KM_SUCCESS(result) )
265 MD_to_WriterInfo((Identification*)Object, m_Info);
266 result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(SourcePackage), &Object);
269 if ( KM_SUCCESS(result) )
271 SourcePackage* SP = (SourcePackage*)Object;
272 memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen);
275 // optional CryptographicContext
276 if ( KM_SUCCESS(result) )
278 Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object);
280 if ( KM_SUCCESS(cr_result) )
281 MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict);
287 // positions file before reading
288 Result_t ReadEKLVFrame(const ASDCP::MXF::Partition& CurrentPartition,
289 ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
290 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
292 // look up frame index node
293 IndexTableSegment::IndexEntry TmpEntry;
295 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
297 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
301 // get frame position and go read the frame's key and length
302 Kumu::fpos_t FilePosition = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
303 Result_t result = RESULT_OK;
305 if ( FilePosition != m_LastPosition )
307 m_LastPosition = FilePosition;
308 result = m_File.Seek(FilePosition);
311 if( KM_SUCCESS(result) )
312 result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
317 // reads from current position
318 Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
319 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
322 return Read_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_LastPosition, m_CtFrameBuf,
323 FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC);
326 // Get the position of a frame from a track file
327 Result_t LocateFrame(const ASDCP::MXF::Partition& CurrentPartition,
328 ui32_t FrameNum, Kumu::fpos_t& streamOffset,
329 i8_t& temporalOffset, i8_t& keyFrameOffset)
331 // look up frame index node
332 IndexTableSegment::IndexEntry TmpEntry;
334 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
336 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
340 // get frame position, temporal offset, and key frame ofset
341 streamOffset = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
342 temporalOffset = TmpEntry.TemporalOffset;
343 keyFrameOffset = TmpEntry.KeyFrameOffset;
355 //------------------------------------------------------------------------------------------
359 template <class ClipT>
363 MXF::Sequence* Sequence;
366 TrackSet() : Track(0), Sequence(0), Clip(0) {}
370 template <class PackageT, class ClipT>
372 CreateTrackAndSequence(OP1aHeader& Header, PackageT& Package, const std::string TrackName,
373 const MXF::Rational& EditRate, const UL& Definition, ui32_t TrackID, const Dictionary*& Dict)
375 TrackSet<ClipT> NewTrack;
377 NewTrack.Track = new Track(Dict);
378 Header.AddChildObject(NewTrack.Track);
379 NewTrack.Track->EditRate = EditRate;
380 Package.Tracks.push_back(NewTrack.Track->InstanceUID);
381 NewTrack.Track->TrackID = TrackID;
382 NewTrack.Track->TrackName = TrackName.c_str();
384 NewTrack.Sequence = new Sequence(Dict);
385 Header.AddChildObject(NewTrack.Sequence);
386 NewTrack.Track->Sequence = NewTrack.Sequence->InstanceUID;
387 NewTrack.Sequence->DataDefinition = Definition;
393 template <class PackageT>
394 TrackSet<TimecodeComponent>
395 CreateTimecodeTrack(OP1aHeader& Header, PackageT& Package,
396 const MXF::Rational& EditRate, ui32_t TCFrameRate, ui64_t TCStart, const Dictionary*& Dict)
399 UL TCUL(Dict->ul(MDD_TimecodeDataDef));
401 TrackSet<TimecodeComponent> NewTrack = CreateTrackAndSequence<PackageT, TimecodeComponent>(Header, Package, "Timecode Track", EditRate, TCUL, 1, Dict);
403 NewTrack.Clip = new TimecodeComponent(Dict);
404 Header.AddChildObject(NewTrack.Clip);
405 NewTrack.Sequence->StructuralComponents.push_back(NewTrack.Clip->InstanceUID);
406 NewTrack.Clip->RoundedTimecodeBase = TCFrameRate;
407 NewTrack.Clip->StartTimecode = TCStart;
408 NewTrack.Clip->DataDefinition = TCUL;
414 // state machine for mxf writer
416 ST_BEGIN, // waiting for Open()
417 ST_INIT, // waiting for SetSourceStream()
418 ST_READY, // ready to write frames
419 ST_RUNNING, // one or more frames written
420 ST_FINAL, // index written, file closed
423 // implementation of h__WriterState class Goto_* methods
424 #define Goto_body(s1,s2) \
425 if ( m_State != (s1) ) { \
426 return RESULT_STATE; \
433 ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
436 WriterState_t m_State;
437 h__WriterState() : m_State(ST_BEGIN) {}
440 inline bool Test_BEGIN() { return m_State == ST_BEGIN; }
441 inline bool Test_INIT() { return m_State == ST_INIT; }
442 inline bool Test_READY() { return m_State == ST_READY;}
443 inline bool Test_RUNNING() { return m_State == ST_RUNNING; }
444 inline bool Test_FINAL() { return m_State == ST_FINAL; }
445 inline Result_t Goto_INIT() { Goto_body(ST_BEGIN, ST_INIT); }
446 inline Result_t Goto_READY() { Goto_body(ST_INIT, ST_READY); }
447 inline Result_t Goto_RUNNING() { Goto_body(ST_READY, ST_RUNNING); }
448 inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); }
451 //------------------------------------------------------------------------------------------
455 template <class HeaderType>
456 class TrackFileWriter
458 KM_NO_COPY_CONSTRUCT(TrackFileWriter);
462 const Dictionary* m_Dict;
463 Kumu::FileWriter m_File;
465 HeaderType m_HeaderPart;
467 ui64_t m_EssenceStart;
469 MaterialPackage* m_MaterialPackage;
470 SourcePackage* m_FilePackage;
472 FileDescriptor* m_EssenceDescriptor;
473 std::list<InterchangeObject*> m_EssenceSubDescriptorList;
475 ui32_t m_FramesWritten;
476 ui64_t m_StreamOffset;
477 ASDCP::FrameBuffer m_CtFrameBuf;
478 h__WriterState m_State;
481 typedef std::list<ui64_t*> DurationElementList_t;
482 DurationElementList_t m_DurationUpdateList;
484 TrackFileWriter(const Dictionary& d) :
485 m_Dict(&d), m_HeaderPart(m_Dict), m_RIP(m_Dict),
486 m_HeaderSize(0), m_EssenceStart(0), m_EssenceDescriptor(0),
487 m_FramesWritten(0), m_StreamOffset(0)
489 default_md_object_init();
492 virtual ~TrackFileWriter() {
496 const MXF::RIP& GetRIP() const { return m_RIP; }
501 assert(m_EssenceDescriptor);
503 m_HeaderPart.m_Primer.ClearTagList();
504 m_HeaderPart.m_Preface = new Preface(m_Dict);
505 m_HeaderPart.AddChildObject(m_HeaderPart.m_Preface);
507 // Set the Operational Pattern label -- we're just starting and have no RIP or index,
508 // so we tell the world by using OP1a
509 m_HeaderPart.m_Preface->OperationalPattern = UL(m_Dict->ul(MDD_OP1a));
510 m_HeaderPart.OperationalPattern = m_HeaderPart.m_Preface->OperationalPattern;
513 Identification* Ident = new Identification(m_Dict);
514 m_HeaderPart.AddChildObject(Ident);
515 m_HeaderPart.m_Preface->Identifications.push_back(Ident->InstanceUID);
517 Kumu::GenRandomValue(Ident->ThisGenerationUID);
518 Ident->CompanyName = m_Info.CompanyName.c_str();
519 Ident->ProductName = m_Info.ProductName.c_str();
520 Ident->VersionString = m_Info.ProductVersion.c_str();
521 Ident->ProductUID.Set(m_Info.ProductUUID);
522 Ident->Platform = ASDCP_PLATFORM;
524 std::vector<int> version = version_split(Version());
526 Ident->ToolkitVersion.Major = version[0];
527 Ident->ToolkitVersion.Minor = version[1];
528 Ident->ToolkitVersion.Patch = version[2];
529 Ident->ToolkitVersion.Build = ASDCP_BUILD_NUMBER;
530 Ident->ToolkitVersion.Release = VersionType::RL_RELEASE;
534 void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
535 const std::string& TrackName, const UL& EssenceUL,
536 const UL& DataDefinition, const std::string& PackageLabel)
539 ContentStorage* Storage = new ContentStorage(m_Dict);
540 m_HeaderPart.AddChildObject(Storage);
541 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
543 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
544 m_HeaderPart.AddChildObject(ECD);
545 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
549 UUID assetUUID(m_Info.AssetUUID);
550 UMID SourcePackageUMID, MaterialPackageUMID;
551 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
552 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
557 m_MaterialPackage = new MaterialPackage(m_Dict);
558 m_MaterialPackage->Name = "AS-DCP Material Package";
559 m_MaterialPackage->PackageUID = MaterialPackageUMID;
560 m_HeaderPart.AddChildObject(m_MaterialPackage);
561 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
563 TrackSet<TimecodeComponent> MPTCTrack =
564 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
565 EditRate, TCFrameRate, 0, m_Dict);
566 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration));
567 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration));
569 TrackSet<SourceClip> MPTrack =
570 CreateTrackAndSequence<MaterialPackage, SourceClip>(m_HeaderPart, *m_MaterialPackage,
571 TrackName, EditRate, DataDefinition,
573 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration));
575 MPTrack.Clip = new SourceClip(m_Dict);
576 m_HeaderPart.AddChildObject(MPTrack.Clip);
577 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
578 MPTrack.Clip->DataDefinition = DataDefinition;
579 MPTrack.Clip->SourcePackageID = SourcePackageUMID;
580 MPTrack.Clip->SourceTrackID = 2;
581 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
585 // File (Source) Package
587 m_FilePackage = new SourcePackage(m_Dict);
588 m_FilePackage->Name = PackageLabel.c_str();
589 m_FilePackage->PackageUID = SourcePackageUMID;
590 ECD->LinkedPackageUID = SourcePackageUMID;
592 m_HeaderPart.AddChildObject(m_FilePackage);
593 Storage->Packages.push_back(m_FilePackage->InstanceUID);
595 TrackSet<TimecodeComponent> FPTCTrack =
596 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
597 EditRate, TCFrameRate,
598 ui64_C(3600) * TCFrameRate, m_Dict);
599 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration));
600 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration));
601 TrackSet<SourceClip> FPTrack =
602 CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage,
603 TrackName, EditRate, DataDefinition,
605 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration));
607 // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from.
608 FPTrack.Track->TrackNumber = KM_i32_BE(Kumu::cp2i<ui32_t>((EssenceUL.Value() + 12)));
610 FPTrack.Clip = new SourceClip(m_Dict);
611 m_HeaderPart.AddChildObject(FPTrack.Clip);
612 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
613 FPTrack.Clip->DataDefinition = DataDefinition;
615 // for now we do not allow setting this value, so all files will be 'original'
616 FPTrack.Clip->SourceTrackID = 0;
617 FPTrack.Clip->SourcePackageID = NilUMID;
618 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
620 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
624 void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
625 const std::string& TrackName, const UL& DataDefinition,
626 const std::string& PackageLabel)
629 ContentStorage* Storage = new ContentStorage(m_Dict);
630 m_HeaderPart.AddChildObject(Storage);
631 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
633 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
634 m_HeaderPart.AddChildObject(ECD);
635 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
639 UUID assetUUID(m_Info.AssetUUID);
640 UMID SourcePackageUMID, MaterialPackageUMID;
641 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
642 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
647 m_MaterialPackage = new MaterialPackage(m_Dict);
648 m_MaterialPackage->Name = "AS-DCP Material Package";
649 m_MaterialPackage->PackageUID = MaterialPackageUMID;
650 m_HeaderPart.AddChildObject(m_MaterialPackage);
651 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
653 TrackSet<TimecodeComponent> MPTCTrack =
654 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
655 EditRate, TCFrameRate, 0, m_Dict);
656 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration));
657 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration));
659 TrackSet<DMSegment> MPTrack =
660 CreateTrackAndSequence<MaterialPackage, DMSegment>(m_HeaderPart, *m_MaterialPackage,
661 TrackName, EditRate, DataDefinition,
663 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration));
665 MPTrack.Clip = new DMSegment(m_Dict);
666 m_HeaderPart.AddChildObject(MPTrack.Clip);
667 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
668 MPTrack.Clip->DataDefinition = DataDefinition;
669 // MPTrack.Clip->SourcePackageID = SourcePackageUMID;
670 // MPTrack.Clip->SourceTrackID = 2;
671 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
675 // File (Source) Package
677 m_FilePackage = new SourcePackage(m_Dict);
678 m_FilePackage->Name = PackageLabel.c_str();
679 m_FilePackage->PackageUID = SourcePackageUMID;
680 ECD->LinkedPackageUID = SourcePackageUMID;
682 m_HeaderPart.AddChildObject(m_FilePackage);
683 Storage->Packages.push_back(m_FilePackage->InstanceUID);
685 TrackSet<TimecodeComponent> FPTCTrack =
686 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
687 EditRate, TCFrameRate,
688 ui64_C(3600) * TCFrameRate, m_Dict);
689 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration));
690 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration));
692 TrackSet<DMSegment> FPTrack =
693 CreateTrackAndSequence<SourcePackage, DMSegment>(m_HeaderPart, *m_FilePackage,
694 TrackName, EditRate, DataDefinition,
696 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration));
698 FPTrack.Clip = new DMSegment(m_Dict);
699 m_HeaderPart.AddChildObject(FPTrack.Clip);
700 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
701 FPTrack.Clip->DataDefinition = DataDefinition;
702 FPTrack.Clip->EventComment = "D-Cinema Timed Text";
704 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
705 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
709 void AddEssenceDescriptor(const UL& WrappingUL)
712 // Essence Descriptor
714 m_EssenceDescriptor->EssenceContainer = WrappingUL;
715 m_HeaderPart.m_Preface->PrimaryPackage = m_FilePackage->InstanceUID;
718 // Essence Descriptors
721 UL GenericContainerUL(m_Dict->ul(MDD_GCMulti));
722 m_HeaderPart.EssenceContainers.push_back(GenericContainerUL);
724 if ( m_Info.EncryptedEssence )
726 UL CryptEssenceUL(m_Dict->ul(MDD_EncryptedContainerLabel));
727 m_HeaderPart.EssenceContainers.push_back(CryptEssenceUL);
728 m_HeaderPart.m_Preface->DMSchemes.push_back(UL(m_Dict->ul(MDD_CryptographicFrameworkLabel)));
729 AddDMScrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL, m_Dict);
733 m_HeaderPart.EssenceContainers.push_back(WrappingUL);
736 m_HeaderPart.m_Preface->EssenceContainers = m_HeaderPart.EssenceContainers;
737 m_HeaderPart.AddChildObject(m_EssenceDescriptor);
739 std::list<InterchangeObject*>::iterator sdli = m_EssenceSubDescriptorList.begin();
740 for ( ; sdli != m_EssenceSubDescriptorList.end(); sdli++ )
741 m_HeaderPart.AddChildObject(*sdli);
743 m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
756 //------------------------------------------------------------------------------------------
760 class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
762 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPReader);
766 Partition m_BodyPart;
768 h__ASDCPReader(const Dictionary&);
769 virtual ~h__ASDCPReader();
771 Result_t OpenMXFRead(const char* filename);
772 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
773 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
774 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
775 i8_t& temporalOffset, i8_t& keyFrameOffset);
779 class h__ASDCPWriter : public MXF::TrackFileWriter<OP1aHeader>
781 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPWriter);
785 Partition m_BodyPart;
786 OPAtomIndexFooter m_FooterPart;
788 h__ASDCPWriter(const Dictionary&);
789 virtual ~h__ASDCPWriter();
791 // all the above for a single source clip
792 Result_t WriteASDCPHeader(const std::string& PackageLabel, const UL& WrappingUL,
793 const std::string& TrackName, const UL& EssenceUL,
794 const UL& DataDefinition, const MXF::Rational& EditRate,
795 ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
797 Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
798 Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
799 AESEncContext* Ctx, HMACContext* HMAC);
800 Result_t WriteASDCPFooter();
804 // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
809 byte_t Data[klv_intpack_size];
812 memset(Data, 0, klv_intpack_size);
817 Result_t CalcValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
818 Result_t TestValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
824 #endif // _AS_DCP_INTERNAL_H_
828 // end AS_DCP_internal.h