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 MD_to_JP2K_PDesc(const ASDCP::MXF::CDCIEssenceDescriptor& EssenceDescriptor,
146 const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
147 const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
148 ASDCP::JP2K::PictureDescriptor& PDesc);
150 Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
151 const ASDCP::Dictionary& dict,
152 ASDCP::MXF::CDCIEssenceDescriptor *EssenceDescriptor,
153 ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor);
155 Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
156 Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc);
158 void AddDMScrypt(Partition& HeaderPart, SourcePackage& Package,
159 WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
161 Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
162 const ASDCP::WriterInfo& Info, Kumu::fpos_t& LastPosition, ASDCP::FrameBuffer& CtFrameBuf,
163 ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
164 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
166 Result_t Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
167 const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
168 ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
169 AESEncContext* Ctx, HMACContext* HMAC);
173 class KLReader : public ASDCP::KLVPacket
175 ASDCP_NO_COPY_CONSTRUCT(KLReader);
176 byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
182 inline const byte_t* Key() { return m_KeyBuf; }
183 inline const ui64_t Length() { return m_ValueLength; }
184 inline const ui64_t KLLength() { return m_KLLength; }
186 Result_t ReadKLFromFile(Kumu::FileReader& Reader);
191 //---------------------------------------------------------------------------------
194 /// void default_md_object_init();
196 template <class HeaderType, class IndexAccessType>
197 class TrackFileReader
199 KM_NO_COPY_CONSTRUCT(TrackFileReader);
203 const Dictionary* m_Dict;
204 Kumu::FileReader m_File;
205 HeaderType m_HeaderPart;
206 IndexAccessType m_IndexAccess;
209 ASDCP::FrameBuffer m_CtFrameBuf;
210 Kumu::fpos_t m_LastPosition;
212 TrackFileReader(const Dictionary& d) :
213 m_HeaderPart(m_Dict), m_IndexAccess(m_Dict), m_RIP(m_Dict), m_Dict(&d)
215 default_md_object_init();
218 virtual ~TrackFileReader() {
222 const MXF::RIP& GetRIP() const { return m_RIP; }
225 Result_t OpenMXFRead(const char* filename)
228 Result_t result = m_File.OpenRead(filename);
230 if ( ASDCP_SUCCESS(result) )
231 result = SeekToRIP(m_File);
233 if ( ASDCP_SUCCESS(result) )
235 result = m_RIP.InitFromFile(m_File);
236 ui32_t test_s = m_RIP.PairArray.size();
238 if ( ASDCP_FAILURE(result) )
240 DefaultLogSink().Error("File contains no RIP\n");
242 else if ( m_RIP.PairArray.empty() )
244 DefaultLogSink().Error("RIP contains no Pairs.\n");
249 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, SeekToRIP failed\n");
253 result = m_HeaderPart.InitFromFile(m_File);
255 if ( KM_FAILURE(result) )
257 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, header init failed\n");
267 InterchangeObject* Object;
270 Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object);
272 // Writer Info and SourcePackage
273 if ( KM_SUCCESS(result) )
275 MD_to_WriterInfo((Identification*)Object, m_Info);
276 result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(SourcePackage), &Object);
279 if ( KM_SUCCESS(result) )
281 SourcePackage* SP = (SourcePackage*)Object;
282 memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen);
285 // optional CryptographicContext
286 if ( KM_SUCCESS(result) )
288 Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object);
290 if ( KM_SUCCESS(cr_result) )
291 MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict);
297 // positions file before reading
298 Result_t ReadEKLVFrame(const ASDCP::MXF::Partition& CurrentPartition,
299 ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
300 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
302 // look up frame index node
303 IndexTableSegment::IndexEntry TmpEntry;
305 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
307 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
311 // get frame position and go read the frame's key and length
312 Kumu::fpos_t FilePosition = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
313 Result_t result = RESULT_OK;
315 if ( FilePosition != m_LastPosition )
317 m_LastPosition = FilePosition;
318 result = m_File.Seek(FilePosition);
321 if ( KM_SUCCESS(result) )
322 result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
327 // reads from current position
328 Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
329 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
332 return Read_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_LastPosition, m_CtFrameBuf,
333 FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC);
336 // Get the position of a frame from a track file
337 Result_t LocateFrame(const ASDCP::MXF::Partition& CurrentPartition,
338 ui32_t FrameNum, Kumu::fpos_t& streamOffset,
339 i8_t& temporalOffset, i8_t& keyFrameOffset)
341 // look up frame index node
342 IndexTableSegment::IndexEntry TmpEntry;
344 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
346 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
350 // get frame position, temporal offset, and key frame ofset
351 streamOffset = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
352 temporalOffset = TmpEntry.TemporalOffset;
353 keyFrameOffset = TmpEntry.KeyFrameOffset;
365 //------------------------------------------------------------------------------------------
369 template <class ClipT>
373 MXF::Sequence* Sequence;
376 TrackSet() : Track(0), Sequence(0), Clip(0) {}
380 template <class PackageT, class ClipT>
382 CreateTrackAndSequence(OP1aHeader& Header, PackageT& Package, const std::string TrackName,
383 const MXF::Rational& EditRate, const UL& Definition, ui32_t TrackID, const Dictionary*& Dict)
385 TrackSet<ClipT> NewTrack;
387 NewTrack.Track = new Track(Dict);
388 Header.AddChildObject(NewTrack.Track);
389 NewTrack.Track->EditRate = EditRate;
390 Package.Tracks.push_back(NewTrack.Track->InstanceUID);
391 NewTrack.Track->TrackID = TrackID;
392 NewTrack.Track->TrackName = TrackName.c_str();
394 NewTrack.Sequence = new Sequence(Dict);
395 Header.AddChildObject(NewTrack.Sequence);
396 NewTrack.Track->Sequence = NewTrack.Sequence->InstanceUID;
397 NewTrack.Sequence->DataDefinition = Definition;
403 template <class PackageT>
404 TrackSet<TimecodeComponent>
405 CreateTimecodeTrack(OP1aHeader& Header, PackageT& Package,
406 const MXF::Rational& EditRate, ui32_t TCFrameRate, ui64_t TCStart, const Dictionary*& Dict)
409 UL TCUL(Dict->ul(MDD_TimecodeDataDef));
411 TrackSet<TimecodeComponent> NewTrack = CreateTrackAndSequence<PackageT, TimecodeComponent>(Header, Package, "Timecode Track", EditRate, TCUL, 1, Dict);
413 NewTrack.Clip = new TimecodeComponent(Dict);
414 Header.AddChildObject(NewTrack.Clip);
415 NewTrack.Sequence->StructuralComponents.push_back(NewTrack.Clip->InstanceUID);
416 NewTrack.Clip->RoundedTimecodeBase = TCFrameRate;
417 NewTrack.Clip->StartTimecode = TCStart;
418 NewTrack.Clip->DataDefinition = TCUL;
424 // state machine for mxf writer
426 ST_BEGIN, // waiting for Open()
427 ST_INIT, // waiting for SetSourceStream()
428 ST_READY, // ready to write frames
429 ST_RUNNING, // one or more frames written
430 ST_FINAL, // index written, file closed
433 // implementation of h__WriterState class Goto_* methods
434 #define Goto_body(s1,s2) \
435 if ( m_State != (s1) ) { \
436 return RESULT_STATE; \
443 ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
446 WriterState_t m_State;
447 h__WriterState() : m_State(ST_BEGIN) {}
450 inline bool Test_BEGIN() { return m_State == ST_BEGIN; }
451 inline bool Test_INIT() { return m_State == ST_INIT; }
452 inline bool Test_READY() { return m_State == ST_READY;}
453 inline bool Test_RUNNING() { return m_State == ST_RUNNING; }
454 inline bool Test_FINAL() { return m_State == ST_FINAL; }
455 inline Result_t Goto_INIT() { Goto_body(ST_BEGIN, ST_INIT); }
456 inline Result_t Goto_READY() { Goto_body(ST_INIT, ST_READY); }
457 inline Result_t Goto_RUNNING() { Goto_body(ST_READY, ST_RUNNING); }
458 inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); }
461 //------------------------------------------------------------------------------------------
465 template <class HeaderType>
466 class TrackFileWriter
468 KM_NO_COPY_CONSTRUCT(TrackFileWriter);
472 const Dictionary* m_Dict;
473 Kumu::FileWriter m_File;
475 HeaderType m_HeaderPart;
478 MaterialPackage* m_MaterialPackage;
479 SourcePackage* m_FilePackage;
481 FileDescriptor* m_EssenceDescriptor;
482 std::list<InterchangeObject*> m_EssenceSubDescriptorList;
484 ui32_t m_FramesWritten;
485 ui64_t m_StreamOffset;
486 ASDCP::FrameBuffer m_CtFrameBuf;
487 h__WriterState m_State;
490 typedef std::list<ui64_t*> DurationElementList_t;
491 DurationElementList_t m_DurationUpdateList;
493 TrackFileWriter(const Dictionary& d) :
494 m_Dict(&d), m_HeaderPart(m_Dict), m_RIP(m_Dict),
495 m_HeaderSize(0), m_EssenceDescriptor(0),
496 m_FramesWritten(0), m_StreamOffset(0)
498 default_md_object_init();
501 virtual ~TrackFileWriter() {
505 const MXF::RIP& GetRIP() const { return m_RIP; }
510 assert(m_EssenceDescriptor);
512 m_HeaderPart.m_Primer.ClearTagList();
513 m_HeaderPart.m_Preface = new Preface(m_Dict);
514 m_HeaderPart.AddChildObject(m_HeaderPart.m_Preface);
516 // Set the Operational Pattern label -- we're just starting and have no RIP or index,
517 // so we tell the world by using OP1a
518 m_HeaderPart.m_Preface->OperationalPattern = UL(m_Dict->ul(MDD_OP1a));
519 m_HeaderPart.OperationalPattern = m_HeaderPart.m_Preface->OperationalPattern;
522 Identification* Ident = new Identification(m_Dict);
523 m_HeaderPart.AddChildObject(Ident);
524 m_HeaderPart.m_Preface->Identifications.push_back(Ident->InstanceUID);
526 Kumu::GenRandomValue(Ident->ThisGenerationUID);
527 Ident->CompanyName = m_Info.CompanyName.c_str();
528 Ident->ProductName = m_Info.ProductName.c_str();
529 Ident->VersionString = m_Info.ProductVersion.c_str();
530 Ident->ProductUID.Set(m_Info.ProductUUID);
531 Ident->Platform = ASDCP_PLATFORM;
533 std::vector<int> version = version_split(Version());
535 Ident->ToolkitVersion.Major = version[0];
536 Ident->ToolkitVersion.Minor = version[1];
537 Ident->ToolkitVersion.Patch = version[2];
538 Ident->ToolkitVersion.Build = ASDCP_BUILD_NUMBER;
539 Ident->ToolkitVersion.Release = VersionType::RL_RELEASE;
543 void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
544 const std::string& TrackName, const UL& EssenceUL,
545 const UL& DataDefinition, const std::string& PackageLabel)
548 ContentStorage* Storage = new ContentStorage(m_Dict);
549 m_HeaderPart.AddChildObject(Storage);
550 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
552 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
553 m_HeaderPart.AddChildObject(ECD);
554 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
558 UUID assetUUID(m_Info.AssetUUID);
559 UMID SourcePackageUMID, MaterialPackageUMID;
560 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
561 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
566 m_MaterialPackage = new MaterialPackage(m_Dict);
567 m_MaterialPackage->Name = "AS-DCP Material Package";
568 m_MaterialPackage->PackageUID = MaterialPackageUMID;
569 m_HeaderPart.AddChildObject(m_MaterialPackage);
570 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
572 TrackSet<TimecodeComponent> MPTCTrack =
573 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
574 EditRate, TCFrameRate, 0, m_Dict);
575 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration));
576 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration));
578 TrackSet<SourceClip> MPTrack =
579 CreateTrackAndSequence<MaterialPackage, SourceClip>(m_HeaderPart, *m_MaterialPackage,
580 TrackName, EditRate, DataDefinition,
582 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration));
584 MPTrack.Clip = new SourceClip(m_Dict);
585 m_HeaderPart.AddChildObject(MPTrack.Clip);
586 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
587 MPTrack.Clip->DataDefinition = DataDefinition;
588 MPTrack.Clip->SourcePackageID = SourcePackageUMID;
589 MPTrack.Clip->SourceTrackID = 2;
590 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
594 // File (Source) Package
596 m_FilePackage = new SourcePackage(m_Dict);
597 m_FilePackage->Name = PackageLabel.c_str();
598 m_FilePackage->PackageUID = SourcePackageUMID;
599 ECD->LinkedPackageUID = SourcePackageUMID;
601 m_HeaderPart.AddChildObject(m_FilePackage);
602 Storage->Packages.push_back(m_FilePackage->InstanceUID);
604 TrackSet<TimecodeComponent> FPTCTrack =
605 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
606 EditRate, TCFrameRate,
607 ui64_C(3600) * TCFrameRate, m_Dict);
608 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration));
609 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration));
610 TrackSet<SourceClip> FPTrack =
611 CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage,
612 TrackName, EditRate, DataDefinition,
614 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration));
616 // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from.
617 FPTrack.Track->TrackNumber = KM_i32_BE(Kumu::cp2i<ui32_t>((EssenceUL.Value() + 12)));
619 FPTrack.Clip = new SourceClip(m_Dict);
620 m_HeaderPart.AddChildObject(FPTrack.Clip);
621 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
622 FPTrack.Clip->DataDefinition = DataDefinition;
624 // for now we do not allow setting this value, so all files will be 'original'
625 FPTrack.Clip->SourceTrackID = 0;
626 FPTrack.Clip->SourcePackageID = NilUMID;
627 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
629 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
633 void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
634 const std::string& TrackName, const UL& DataDefinition,
635 const std::string& PackageLabel)
638 ContentStorage* Storage = new ContentStorage(m_Dict);
639 m_HeaderPart.AddChildObject(Storage);
640 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
642 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
643 m_HeaderPart.AddChildObject(ECD);
644 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
648 UUID assetUUID(m_Info.AssetUUID);
649 UMID SourcePackageUMID, MaterialPackageUMID;
650 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
651 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
656 m_MaterialPackage = new MaterialPackage(m_Dict);
657 m_MaterialPackage->Name = "AS-DCP Material Package";
658 m_MaterialPackage->PackageUID = MaterialPackageUMID;
659 m_HeaderPart.AddChildObject(m_MaterialPackage);
660 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
662 TrackSet<TimecodeComponent> MPTCTrack =
663 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
664 EditRate, TCFrameRate, 0, m_Dict);
665 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration));
666 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration));
668 TrackSet<DMSegment> MPTrack =
669 CreateTrackAndSequence<MaterialPackage, DMSegment>(m_HeaderPart, *m_MaterialPackage,
670 TrackName, EditRate, DataDefinition,
672 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration));
674 MPTrack.Clip = new DMSegment(m_Dict);
675 m_HeaderPart.AddChildObject(MPTrack.Clip);
676 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
677 MPTrack.Clip->DataDefinition = DataDefinition;
678 // MPTrack.Clip->SourcePackageID = SourcePackageUMID;
679 // MPTrack.Clip->SourceTrackID = 2;
680 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
684 // File (Source) Package
686 m_FilePackage = new SourcePackage(m_Dict);
687 m_FilePackage->Name = PackageLabel.c_str();
688 m_FilePackage->PackageUID = SourcePackageUMID;
689 ECD->LinkedPackageUID = SourcePackageUMID;
691 m_HeaderPart.AddChildObject(m_FilePackage);
692 Storage->Packages.push_back(m_FilePackage->InstanceUID);
694 TrackSet<TimecodeComponent> FPTCTrack =
695 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
696 EditRate, TCFrameRate,
697 ui64_C(3600) * TCFrameRate, m_Dict);
698 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration));
699 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration));
701 TrackSet<DMSegment> FPTrack =
702 CreateTrackAndSequence<SourcePackage, DMSegment>(m_HeaderPart, *m_FilePackage,
703 TrackName, EditRate, DataDefinition,
705 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration));
707 FPTrack.Clip = new DMSegment(m_Dict);
708 m_HeaderPart.AddChildObject(FPTrack.Clip);
709 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
710 FPTrack.Clip->DataDefinition = DataDefinition;
711 FPTrack.Clip->EventComment = "D-Cinema Timed Text";
713 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
714 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
718 void AddEssenceDescriptor(const UL& WrappingUL)
721 // Essence Descriptor
723 m_EssenceDescriptor->EssenceContainer = WrappingUL;
724 m_HeaderPart.m_Preface->PrimaryPackage = m_FilePackage->InstanceUID;
727 // Essence Descriptors
730 UL GenericContainerUL(m_Dict->ul(MDD_GCMulti));
731 m_HeaderPart.EssenceContainers.push_back(GenericContainerUL);
733 if ( m_Info.EncryptedEssence )
735 UL CryptEssenceUL(m_Dict->ul(MDD_EncryptedContainerLabel));
736 m_HeaderPart.EssenceContainers.push_back(CryptEssenceUL);
737 m_HeaderPart.m_Preface->DMSchemes.push_back(UL(m_Dict->ul(MDD_CryptographicFrameworkLabel)));
738 AddDMScrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL, m_Dict);
742 m_HeaderPart.EssenceContainers.push_back(WrappingUL);
745 m_HeaderPart.m_Preface->EssenceContainers = m_HeaderPart.EssenceContainers;
746 m_HeaderPart.AddChildObject(m_EssenceDescriptor);
748 std::list<InterchangeObject*>::iterator sdli = m_EssenceSubDescriptorList.begin();
749 for ( ; sdli != m_EssenceSubDescriptorList.end(); sdli++ )
750 m_HeaderPart.AddChildObject(*sdli);
752 m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
765 //------------------------------------------------------------------------------------------
769 class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
771 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPReader);
775 Partition m_BodyPart;
777 h__ASDCPReader(const Dictionary&);
778 virtual ~h__ASDCPReader();
780 Result_t OpenMXFRead(const char* filename);
781 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
782 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
783 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
784 i8_t& temporalOffset, i8_t& keyFrameOffset);
788 class h__ASDCPWriter : public MXF::TrackFileWriter<OP1aHeader>
790 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPWriter);
794 Partition m_BodyPart;
795 OPAtomIndexFooter m_FooterPart;
797 h__ASDCPWriter(const Dictionary&);
798 virtual ~h__ASDCPWriter();
800 // all the above for a single source clip
801 Result_t WriteASDCPHeader(const std::string& PackageLabel, const UL& WrappingUL,
802 const std::string& TrackName, const UL& EssenceUL,
803 const UL& DataDefinition, const MXF::Rational& EditRate,
804 ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
806 Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
807 Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
808 AESEncContext* Ctx, HMACContext* HMAC);
809 Result_t WriteASDCPFooter();
813 // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
818 byte_t Data[klv_intpack_size];
821 memset(Data, 0, klv_intpack_size);
826 Result_t CalcValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
827 Result_t TestValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
833 #endif // _AS_DCP_INTERNAL_H_
837 // end AS_DCP_internal.h