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&);
131 Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
132 Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
133 Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
134 Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc);
135 void AddDMScrypt(Partition& HeaderPart, SourcePackage& Package,
136 WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
138 Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
139 const ASDCP::WriterInfo& Info, Kumu::fpos_t& LastPosition, ASDCP::FrameBuffer& CtFrameBuf,
140 ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
141 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
143 Result_t Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
144 const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
145 ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
146 AESEncContext* Ctx, HMACContext* HMAC);
149 class KLReader : public ASDCP::KLVPacket
151 ASDCP_NO_COPY_CONSTRUCT(KLReader);
152 byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
158 inline const byte_t* Key() { return m_KeyBuf; }
159 inline const ui64_t Length() { return m_ValueLength; }
160 inline const ui64_t KLLength() { return m_KLLength; }
162 Result_t ReadKLFromFile(Kumu::FileReader& Reader);
167 //---------------------------------------------------------------------------------
170 /// void default_md_object_init();
172 template <class HeaderType, class IndexAccessType>
173 class TrackFileReader
175 KM_NO_COPY_CONSTRUCT(TrackFileReader);
179 const Dictionary* m_Dict;
180 Kumu::FileReader m_File;
181 HeaderType m_HeaderPart;
182 IndexAccessType m_IndexAccess;
185 ASDCP::FrameBuffer m_CtFrameBuf;
186 Kumu::fpos_t m_LastPosition;
188 TrackFileReader(const Dictionary& d) :
189 m_HeaderPart(m_Dict), m_IndexAccess(m_Dict), m_RIP(m_Dict), m_Dict(&d)
191 default_md_object_init();
194 virtual ~TrackFileReader() {
198 const MXF::RIP& GetRIP() const { return m_RIP; }
201 Result_t OpenMXFRead(const char* filename)
204 Result_t result = m_File.OpenRead(filename);
206 if ( ASDCP_SUCCESS(result) )
207 result = SeekToRIP(m_File);
209 if ( ASDCP_SUCCESS(result) )
211 result = m_RIP.InitFromFile(m_File);
212 ui32_t test_s = m_RIP.PairArray.size();
214 if ( ASDCP_FAILURE(result) )
216 DefaultLogSink().Error("File contains no RIP\n");
218 else if ( m_RIP.PairArray.empty() )
220 DefaultLogSink().Error("RIP contains no Pairs.\n");
225 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, SeekToRIP failed\n");
229 result = m_HeaderPart.InitFromFile(m_File);
231 if ( KM_FAILURE(result) )
233 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, header init failed\n");
243 InterchangeObject* Object;
246 Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object);
248 // Writer Info and SourcePackage
249 if ( KM_SUCCESS(result) )
251 MD_to_WriterInfo((Identification*)Object, m_Info);
252 result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(SourcePackage), &Object);
255 if ( KM_SUCCESS(result) )
257 SourcePackage* SP = (SourcePackage*)Object;
258 memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen);
261 // optional CryptographicContext
262 if ( KM_SUCCESS(result) )
264 Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object);
266 if ( KM_SUCCESS(cr_result) )
267 MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict);
273 // positions file before reading
274 Result_t ReadEKLVFrame(const ASDCP::MXF::Partition& CurrentPartition,
275 ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
276 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
278 // look up frame index node
279 IndexTableSegment::IndexEntry TmpEntry;
281 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
283 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
287 // get frame position and go read the frame's key and length
288 Kumu::fpos_t FilePosition = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
289 Result_t result = RESULT_OK;
291 if ( FilePosition != m_LastPosition )
293 m_LastPosition = FilePosition;
294 result = m_File.Seek(FilePosition);
297 if( KM_SUCCESS(result) )
298 result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
303 // reads from current position
304 Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
305 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
308 return Read_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_LastPosition, m_CtFrameBuf,
309 FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC);
312 // Get the position of a frame from a track file
313 Result_t LocateFrame(const ASDCP::MXF::Partition& CurrentPartition,
314 ui32_t FrameNum, Kumu::fpos_t& streamOffset,
315 i8_t& temporalOffset, i8_t& keyFrameOffset)
317 // look up frame index node
318 IndexTableSegment::IndexEntry TmpEntry;
320 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
322 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
326 // get frame position, temporal offset, and key frame ofset
327 streamOffset = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
328 temporalOffset = TmpEntry.TemporalOffset;
329 keyFrameOffset = TmpEntry.KeyFrameOffset;
344 template <class ClipT>
348 MXF::Sequence* Sequence;
351 TrackSet() : Track(0), Sequence(0), Clip(0) {}
355 template <class PackageT, class ClipT>
357 CreateTrackAndSequence(OP1aHeader& Header, PackageT& Package, const std::string TrackName,
358 const MXF::Rational& EditRate, const UL& Definition, ui32_t TrackID, const Dictionary*& Dict)
360 TrackSet<ClipT> NewTrack;
362 NewTrack.Track = new Track(Dict);
363 Header.AddChildObject(NewTrack.Track);
364 NewTrack.Track->EditRate = EditRate;
365 Package.Tracks.push_back(NewTrack.Track->InstanceUID);
366 NewTrack.Track->TrackID = TrackID;
367 NewTrack.Track->TrackName = TrackName.c_str();
369 NewTrack.Sequence = new Sequence(Dict);
370 Header.AddChildObject(NewTrack.Sequence);
371 NewTrack.Track->Sequence = NewTrack.Sequence->InstanceUID;
372 NewTrack.Sequence->DataDefinition = Definition;
378 template <class PackageT>
379 TrackSet<TimecodeComponent>
380 CreateTimecodeTrack(OP1aHeader& Header, PackageT& Package,
381 const MXF::Rational& EditRate, ui32_t TCFrameRate, ui64_t TCStart, const Dictionary*& Dict)
384 UL TCUL(Dict->ul(MDD_TimecodeDataDef));
386 TrackSet<TimecodeComponent> NewTrack = CreateTrackAndSequence<PackageT, TimecodeComponent>(Header, Package, "Timecode Track", EditRate, TCUL, 1, Dict);
388 NewTrack.Clip = new TimecodeComponent(Dict);
389 Header.AddChildObject(NewTrack.Clip);
390 NewTrack.Sequence->StructuralComponents.push_back(NewTrack.Clip->InstanceUID);
391 NewTrack.Clip->RoundedTimecodeBase = TCFrameRate;
392 NewTrack.Clip->StartTimecode = TCStart;
393 NewTrack.Clip->DataDefinition = TCUL;
399 // state machine for mxf writer
401 ST_BEGIN, // waiting for Open()
402 ST_INIT, // waiting for SetSourceStream()
403 ST_READY, // ready to write frames
404 ST_RUNNING, // one or more frames written
405 ST_FINAL, // index written, file closed
408 // implementation of h__WriterState class Goto_* methods
409 #define Goto_body(s1,s2) \
410 if ( m_State != (s1) ) { \
411 return RESULT_STATE; \
418 ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
421 WriterState_t m_State;
422 h__WriterState() : m_State(ST_BEGIN) {}
425 inline bool Test_BEGIN() { return m_State == ST_BEGIN; }
426 inline bool Test_INIT() { return m_State == ST_INIT; }
427 inline bool Test_READY() { return m_State == ST_READY;}
428 inline bool Test_RUNNING() { return m_State == ST_RUNNING; }
429 inline bool Test_FINAL() { return m_State == ST_FINAL; }
430 inline Result_t Goto_INIT() { Goto_body(ST_BEGIN, ST_INIT); }
431 inline Result_t Goto_READY() { Goto_body(ST_INIT, ST_READY); }
432 inline Result_t Goto_RUNNING() { Goto_body(ST_READY, ST_RUNNING); }
433 inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); }
438 template <class HeaderType>
439 class TrackFileWriter
441 KM_NO_COPY_CONSTRUCT(TrackFileWriter);
445 const Dictionary* m_Dict;
446 Kumu::FileWriter m_File;
448 HeaderType m_HeaderPart;
450 ui64_t m_EssenceStart;
452 MaterialPackage* m_MaterialPackage;
453 SourcePackage* m_FilePackage;
455 FileDescriptor* m_EssenceDescriptor;
456 std::list<InterchangeObject*> m_EssenceSubDescriptorList;
458 ui32_t m_FramesWritten;
459 ui64_t m_StreamOffset;
460 ASDCP::FrameBuffer m_CtFrameBuf;
461 h__WriterState m_State;
464 typedef std::list<ui64_t*> DurationElementList_t;
465 DurationElementList_t m_DurationUpdateList;
467 TrackFileWriter(const Dictionary& d) :
468 m_Dict(&d), m_HeaderPart(m_Dict), m_RIP(m_Dict),
469 m_HeaderSize(0), m_EssenceStart(0), m_EssenceDescriptor(0),
470 m_FramesWritten(0), m_StreamOffset(0)
472 default_md_object_init();
475 virtual ~TrackFileWriter() {}
477 const MXF::RIP& GetRIP() const { return m_RIP; }
482 assert(m_EssenceDescriptor);
484 m_HeaderPart.m_Primer.ClearTagList();
485 m_HeaderPart.m_Preface = new Preface(m_Dict);
486 m_HeaderPart.AddChildObject(m_HeaderPart.m_Preface);
488 // Set the Operational Pattern label -- we're just starting and have no RIP or index,
489 // so we tell the world by using OP1a
490 m_HeaderPart.m_Preface->OperationalPattern = UL(m_Dict->ul(MDD_OP1a));
491 m_HeaderPart.OperationalPattern = m_HeaderPart.m_Preface->OperationalPattern;
494 Identification* Ident = new Identification(m_Dict);
495 m_HeaderPart.AddChildObject(Ident);
496 m_HeaderPart.m_Preface->Identifications.push_back(Ident->InstanceUID);
498 Kumu::GenRandomValue(Ident->ThisGenerationUID);
499 Ident->CompanyName = m_Info.CompanyName.c_str();
500 Ident->ProductName = m_Info.ProductName.c_str();
501 Ident->VersionString = m_Info.ProductVersion.c_str();
502 Ident->ProductUID.Set(m_Info.ProductUUID);
503 Ident->Platform = ASDCP_PLATFORM;
505 std::vector<int> version = version_split(Version());
507 Ident->ToolkitVersion.Major = version[0];
508 Ident->ToolkitVersion.Minor = version[1];
509 Ident->ToolkitVersion.Patch = version[2];
510 Ident->ToolkitVersion.Build = ASDCP_BUILD_NUMBER;
511 Ident->ToolkitVersion.Release = VersionType::RL_RELEASE;
515 void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
516 const std::string& TrackName, const UL& EssenceUL,
517 const UL& DataDefinition, const std::string& PackageLabel)
520 ContentStorage* Storage = new ContentStorage(m_Dict);
521 m_HeaderPart.AddChildObject(Storage);
522 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
524 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
525 m_HeaderPart.AddChildObject(ECD);
526 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
530 UUID assetUUID(m_Info.AssetUUID);
531 UMID SourcePackageUMID, MaterialPackageUMID;
532 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
533 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
538 m_MaterialPackage = new MaterialPackage(m_Dict);
539 m_MaterialPackage->Name = "AS-DCP Material Package";
540 m_MaterialPackage->PackageUID = MaterialPackageUMID;
541 m_HeaderPart.AddChildObject(m_MaterialPackage);
542 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
544 TrackSet<TimecodeComponent> MPTCTrack =
545 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
546 EditRate, TCFrameRate, 0, m_Dict);
547 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration));
548 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration));
550 TrackSet<SourceClip> MPTrack =
551 CreateTrackAndSequence<MaterialPackage, SourceClip>(m_HeaderPart, *m_MaterialPackage,
552 TrackName, EditRate, DataDefinition,
554 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration));
556 MPTrack.Clip = new SourceClip(m_Dict);
557 m_HeaderPart.AddChildObject(MPTrack.Clip);
558 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
559 MPTrack.Clip->DataDefinition = DataDefinition;
560 MPTrack.Clip->SourcePackageID = SourcePackageUMID;
561 MPTrack.Clip->SourceTrackID = 2;
562 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
566 // File (Source) Package
568 m_FilePackage = new SourcePackage(m_Dict);
569 m_FilePackage->Name = PackageLabel.c_str();
570 m_FilePackage->PackageUID = SourcePackageUMID;
571 ECD->LinkedPackageUID = SourcePackageUMID;
573 m_HeaderPart.AddChildObject(m_FilePackage);
574 Storage->Packages.push_back(m_FilePackage->InstanceUID);
576 TrackSet<TimecodeComponent> FPTCTrack =
577 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
578 EditRate, TCFrameRate,
579 ui64_C(3600) * TCFrameRate, m_Dict);
580 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration));
581 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration));
582 TrackSet<SourceClip> FPTrack =
583 CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage,
584 TrackName, EditRate, DataDefinition,
586 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration));
588 // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from.
589 FPTrack.Track->TrackNumber = KM_i32_BE(Kumu::cp2i<ui32_t>((EssenceUL.Value() + 12)));
591 FPTrack.Clip = new SourceClip(m_Dict);
592 m_HeaderPart.AddChildObject(FPTrack.Clip);
593 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
594 FPTrack.Clip->DataDefinition = DataDefinition;
596 // for now we do not allow setting this value, so all files will be 'original'
597 FPTrack.Clip->SourceTrackID = 0;
598 FPTrack.Clip->SourcePackageID = NilUMID;
599 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
601 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
605 void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
606 const std::string& TrackName, const UL& DataDefinition,
607 const std::string& PackageLabel)
610 ContentStorage* Storage = new ContentStorage(m_Dict);
611 m_HeaderPart.AddChildObject(Storage);
612 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
614 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
615 m_HeaderPart.AddChildObject(ECD);
616 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
620 UUID assetUUID(m_Info.AssetUUID);
621 UMID SourcePackageUMID, MaterialPackageUMID;
622 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
623 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
628 m_MaterialPackage = new MaterialPackage(m_Dict);
629 m_MaterialPackage->Name = "AS-DCP Material Package";
630 m_MaterialPackage->PackageUID = MaterialPackageUMID;
631 m_HeaderPart.AddChildObject(m_MaterialPackage);
632 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
634 TrackSet<TimecodeComponent> MPTCTrack =
635 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
636 EditRate, TCFrameRate, 0, m_Dict);
637 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration));
638 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration));
640 TrackSet<DMSegment> MPTrack =
641 CreateTrackAndSequence<MaterialPackage, DMSegment>(m_HeaderPart, *m_MaterialPackage,
642 TrackName, EditRate, DataDefinition,
644 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration));
646 MPTrack.Clip = new DMSegment(m_Dict);
647 m_HeaderPart.AddChildObject(MPTrack.Clip);
648 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
649 MPTrack.Clip->DataDefinition = DataDefinition;
650 // MPTrack.Clip->SourcePackageID = SourcePackageUMID;
651 // MPTrack.Clip->SourceTrackID = 2;
652 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
656 // File (Source) Package
658 m_FilePackage = new SourcePackage(m_Dict);
659 m_FilePackage->Name = PackageLabel.c_str();
660 m_FilePackage->PackageUID = SourcePackageUMID;
661 ECD->LinkedPackageUID = SourcePackageUMID;
663 m_HeaderPart.AddChildObject(m_FilePackage);
664 Storage->Packages.push_back(m_FilePackage->InstanceUID);
666 TrackSet<TimecodeComponent> FPTCTrack =
667 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
668 EditRate, TCFrameRate,
669 ui64_C(3600) * TCFrameRate, m_Dict);
670 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration));
671 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration));
673 TrackSet<DMSegment> FPTrack =
674 CreateTrackAndSequence<SourcePackage, DMSegment>(m_HeaderPart, *m_FilePackage,
675 TrackName, EditRate, DataDefinition,
677 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration));
679 FPTrack.Clip = new DMSegment(m_Dict);
680 m_HeaderPart.AddChildObject(FPTrack.Clip);
681 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
682 FPTrack.Clip->DataDefinition = DataDefinition;
683 FPTrack.Clip->EventComment = "D-Cinema Timed Text";
685 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
686 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
690 void AddEssenceDescriptor(const UL& WrappingUL)
693 // Essence Descriptor
695 m_EssenceDescriptor->EssenceContainer = WrappingUL;
696 m_HeaderPart.m_Preface->PrimaryPackage = m_FilePackage->InstanceUID;
699 // Essence Descriptors
702 UL GenericContainerUL(m_Dict->ul(MDD_GCMulti));
703 m_HeaderPart.EssenceContainers.push_back(GenericContainerUL);
705 if ( m_Info.EncryptedEssence )
707 UL CryptEssenceUL(m_Dict->ul(MDD_EncryptedContainerLabel));
708 m_HeaderPart.EssenceContainers.push_back(CryptEssenceUL);
709 m_HeaderPart.m_Preface->DMSchemes.push_back(UL(m_Dict->ul(MDD_CryptographicFrameworkLabel)));
710 AddDMScrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL, m_Dict);
714 m_HeaderPart.EssenceContainers.push_back(WrappingUL);
717 m_HeaderPart.m_Preface->EssenceContainers = m_HeaderPart.EssenceContainers;
718 m_HeaderPart.AddChildObject(m_EssenceDescriptor);
720 std::list<InterchangeObject*>::iterator sdli = m_EssenceSubDescriptorList.begin();
721 for ( ; sdli != m_EssenceSubDescriptorList.end(); sdli++ )
722 m_HeaderPart.AddChildObject(*sdli);
724 m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
728 Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC)
730 return Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
731 m_StreamOffset, FrameBuf, EssenceUL, Ctx, HMAC);
745 class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
747 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPReader);
751 Partition m_BodyPart;
753 h__ASDCPReader(const Dictionary&);
754 virtual ~h__ASDCPReader();
756 Result_t OpenMXFRead(const char* filename);
757 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
758 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
759 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
760 i8_t& temporalOffset, i8_t& keyFrameOffset);
764 class h__ASDCPWriter : public MXF::TrackFileWriter<OP1aHeader>
766 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPWriter);
770 Partition m_BodyPart;
771 OPAtomIndexFooter m_FooterPart;
773 h__ASDCPWriter(const Dictionary&);
774 virtual ~h__ASDCPWriter();
776 Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
778 // all the above for a single source clip
779 Result_t WriteASDCPHeader(const std::string& PackageLabel, const UL& WrappingUL,
780 const std::string& TrackName, const UL& EssenceUL,
781 const UL& DataDefinition, const MXF::Rational& EditRate,
782 ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
784 Result_t WriteASDCPFooter();
788 // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
793 byte_t Data[klv_intpack_size];
796 memset(Data, 0, klv_intpack_size);
801 Result_t CalcValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
802 Result_t TestValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
808 #endif // _AS_DCP_INTERNAL_H_
812 // end AS_DCP_internal.h