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 ui32_t derive_timecode_rate_from_edit_rate(const ASDCP::Rational& edit_rate);
131 Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&);
132 Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&, const Dictionary&);
134 Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*);
135 Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*);
137 Result_t MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor& EssenceDescriptor,
138 const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
139 const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
140 ASDCP::JP2K::PictureDescriptor& PDesc);
142 Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
143 const ASDCP::Dictionary& dict,
144 ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
145 ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor);
147 Result_t MD_to_JP2K_PDesc(const ASDCP::MXF::CDCIEssenceDescriptor& EssenceDescriptor,
148 const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
149 const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
150 ASDCP::JP2K::PictureDescriptor& PDesc);
152 Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
153 const ASDCP::Dictionary& dict,
154 ASDCP::MXF::CDCIEssenceDescriptor *EssenceDescriptor,
155 ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor);
157 Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
158 Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc);
160 void AddDMScrypt(Partition& HeaderPart, SourcePackage& Package,
161 WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
163 Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict,
164 const ASDCP::WriterInfo& Info, Kumu::fpos_t& LastPosition, ASDCP::FrameBuffer& CtFrameBuf,
165 ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
166 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
168 Result_t Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
169 const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
170 ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
171 AESEncContext* Ctx, HMACContext* HMAC);
174 class KLReader : public ASDCP::KLVPacket
176 ASDCP_NO_COPY_CONSTRUCT(KLReader);
177 byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
183 inline const byte_t* Key() { return m_KeyBuf; }
184 inline const ui64_t Length() { return m_ValueLength; }
185 inline const ui64_t KLLength() { return m_KLLength; }
187 Result_t ReadKLFromFile(Kumu::FileReader& Reader);
192 //---------------------------------------------------------------------------------
195 /// void default_md_object_init();
197 template <class HeaderType, class IndexAccessType>
198 class TrackFileReader
200 KM_NO_COPY_CONSTRUCT(TrackFileReader);
204 const Dictionary* m_Dict;
205 Kumu::FileReader m_File;
206 HeaderType m_HeaderPart;
207 IndexAccessType m_IndexAccess;
210 ASDCP::FrameBuffer m_CtFrameBuf;
211 Kumu::fpos_t m_LastPosition;
213 TrackFileReader(const Dictionary& d) :
214 m_HeaderPart(m_Dict), m_IndexAccess(m_Dict), m_RIP(m_Dict), m_Dict(&d)
216 default_md_object_init();
219 virtual ~TrackFileReader() {
223 const MXF::RIP& GetRIP() const { return m_RIP; }
226 Result_t OpenMXFRead(const char* filename)
229 Result_t result = m_File.OpenRead(filename);
231 if ( ASDCP_SUCCESS(result) )
232 result = SeekToRIP(m_File);
234 if ( ASDCP_SUCCESS(result) )
236 result = m_RIP.InitFromFile(m_File);
237 ui32_t test_s = m_RIP.PairArray.size();
239 if ( ASDCP_FAILURE(result) )
241 DefaultLogSink().Error("File contains no RIP\n");
243 else if ( m_RIP.PairArray.empty() )
245 DefaultLogSink().Error("RIP contains no Pairs.\n");
250 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, SeekToRIP failed\n");
254 result = m_HeaderPart.InitFromFile(m_File);
256 if ( KM_FAILURE(result) )
258 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, header init failed\n");
268 InterchangeObject* Object;
271 Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object);
273 // Writer Info and SourcePackage
274 if ( KM_SUCCESS(result) )
276 MD_to_WriterInfo((Identification*)Object, m_Info);
277 result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(SourcePackage), &Object);
280 if ( KM_SUCCESS(result) )
282 SourcePackage* SP = (SourcePackage*)Object;
283 memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen);
286 // optional CryptographicContext
287 if ( KM_SUCCESS(result) )
289 Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object);
291 if ( KM_SUCCESS(cr_result) )
292 MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict);
298 // positions file before reading
299 // allows external control of index offset
300 Result_t ReadEKLVFrame(const ui64_t& body_offset,
301 ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
302 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
304 // look up frame index node
305 IndexTableSegment::IndexEntry TmpEntry;
307 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
309 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
313 // get relative frame position, apply offset and go read the frame's key and length
314 Kumu::fpos_t FilePosition = body_offset + TmpEntry.StreamOffset;
315 Result_t result = RESULT_OK;
317 if ( FilePosition != m_LastPosition )
319 m_LastPosition = FilePosition;
320 result = m_File.Seek(FilePosition);
323 if ( KM_SUCCESS(result) )
324 result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
329 // positions file before reading
330 // assumes "processed" index entries have absolute positions
331 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
332 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
334 // look up frame index node
335 IndexTableSegment::IndexEntry TmpEntry;
337 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
339 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
343 // get absolute frame position and go read the frame's key and length
344 Result_t result = RESULT_OK;
346 if ( TmpEntry.StreamOffset != m_LastPosition )
348 m_LastPosition = TmpEntry.StreamOffset;
349 result = m_File.Seek(TmpEntry.StreamOffset);
352 if ( KM_SUCCESS(result) )
353 result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
358 // reads from current position
359 Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
360 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
363 return Read_EKLV_Packet(m_File, *m_Dict, m_Info, m_LastPosition, m_CtFrameBuf,
364 FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC);
367 // Get the position of a frame from a track file
368 Result_t LocateFrame(const ui64_t& body_offset,
369 ui32_t FrameNum, Kumu::fpos_t& streamOffset,
370 i8_t& temporalOffset, i8_t& keyFrameOffset)
372 // look up frame index node
373 IndexTableSegment::IndexEntry TmpEntry;
375 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
377 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
381 // get frame position, temporal offset, and key frame ofset
382 streamOffset = body_offset + TmpEntry.StreamOffset;
383 temporalOffset = TmpEntry.TemporalOffset;
384 keyFrameOffset = TmpEntry.KeyFrameOffset;
396 //------------------------------------------------------------------------------------------
400 template <class ClipT>
404 MXF::Sequence* Sequence;
407 TrackSet() : Track(0), Sequence(0), Clip(0) {}
411 template <class PackageT, class ClipT>
413 CreateTrackAndSequence(OP1aHeader& Header, PackageT& Package, const std::string TrackName,
414 const MXF::Rational& clip_edit_rate, const UL& Definition, ui32_t TrackID, const Dictionary*& Dict)
416 TrackSet<ClipT> NewTrack;
418 NewTrack.Track = new Track(Dict);
419 Header.AddChildObject(NewTrack.Track);
420 NewTrack.Track->EditRate = clip_edit_rate;
421 Package.Tracks.push_back(NewTrack.Track->InstanceUID);
422 NewTrack.Track->TrackID = TrackID;
423 NewTrack.Track->TrackName = TrackName.c_str();
425 NewTrack.Sequence = new Sequence(Dict);
426 Header.AddChildObject(NewTrack.Sequence);
427 NewTrack.Track->Sequence = NewTrack.Sequence->InstanceUID;
428 NewTrack.Sequence->DataDefinition = Definition;
434 template <class PackageT>
435 TrackSet<TimecodeComponent>
436 CreateTimecodeTrack(OP1aHeader& Header, PackageT& Package,
437 const MXF::Rational& tc_edit_rate, ui32_t tc_frame_rate, ui64_t TCStart, const Dictionary*& Dict)
440 UL TCUL(Dict->ul(MDD_TimecodeDataDef));
442 TrackSet<TimecodeComponent> NewTrack =
443 CreateTrackAndSequence<PackageT, TimecodeComponent>(Header, Package, "Timecode Track",
444 tc_edit_rate, TCUL, 1, Dict);
446 NewTrack.Clip = new TimecodeComponent(Dict);
447 Header.AddChildObject(NewTrack.Clip);
448 NewTrack.Sequence->StructuralComponents.push_back(NewTrack.Clip->InstanceUID);
449 NewTrack.Clip->RoundedTimecodeBase = tc_frame_rate;
450 NewTrack.Clip->StartTimecode = TCStart;
451 NewTrack.Clip->DataDefinition = TCUL;
457 // state machine for mxf writer
459 ST_BEGIN, // waiting for Open()
460 ST_INIT, // waiting for SetSourceStream()
461 ST_READY, // ready to write frames
462 ST_RUNNING, // one or more frames written
463 ST_FINAL, // index written, file closed
467 // implementation of h__WriterState class Goto_* methods
468 #define Goto_body(s1,s2) \
469 if ( m_State != (s1) ) { \
470 return RESULT_STATE; \
477 ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
480 WriterState_t m_State;
481 h__WriterState() : m_State(ST_BEGIN) {}
484 inline bool Test_BEGIN() { return m_State == ST_BEGIN; }
485 inline bool Test_INIT() { return m_State == ST_INIT; }
486 inline bool Test_READY() { return m_State == ST_READY;}
487 inline bool Test_RUNNING() { return m_State == ST_RUNNING; }
488 inline bool Test_FINAL() { return m_State == ST_FINAL; }
489 inline Result_t Goto_INIT() { Goto_body(ST_BEGIN, ST_INIT); }
490 inline Result_t Goto_READY() { Goto_body(ST_INIT, ST_READY); }
491 inline Result_t Goto_RUNNING() { Goto_body(ST_READY, ST_RUNNING); }
492 inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); }
495 //------------------------------------------------------------------------------------------
499 template <class HeaderType>
500 class TrackFileWriter
502 KM_NO_COPY_CONSTRUCT(TrackFileWriter);
506 const Dictionary* m_Dict;
507 Kumu::FileWriter m_File;
509 HeaderType m_HeaderPart;
512 MaterialPackage* m_MaterialPackage;
513 SourcePackage* m_FilePackage;
515 FileDescriptor* m_EssenceDescriptor;
516 std::list<InterchangeObject*> m_EssenceSubDescriptorList;
518 ui32_t m_FramesWritten;
519 ui64_t m_StreamOffset;
520 ASDCP::FrameBuffer m_CtFrameBuf;
521 h__WriterState m_State;
524 typedef std::list<ui64_t*> DurationElementList_t;
525 DurationElementList_t m_DurationUpdateList;
527 TrackFileWriter(const Dictionary& d) :
528 m_Dict(&d), m_HeaderPart(m_Dict), m_RIP(m_Dict),
529 m_HeaderSize(0), m_EssenceDescriptor(0),
530 m_FramesWritten(0), m_StreamOffset(0)
532 default_md_object_init();
535 virtual ~TrackFileWriter() {
539 const MXF::RIP& GetRIP() const { return m_RIP; }
544 assert(m_EssenceDescriptor);
546 m_HeaderPart.m_Primer.ClearTagList();
547 m_HeaderPart.m_Preface = new Preface(m_Dict);
548 m_HeaderPart.AddChildObject(m_HeaderPart.m_Preface);
550 // Set the Operational Pattern label -- we're just starting and have no RIP or index,
551 // so we tell the world by using OP1a
552 m_HeaderPart.m_Preface->OperationalPattern = UL(m_Dict->ul(MDD_OP1a));
553 m_HeaderPart.OperationalPattern = m_HeaderPart.m_Preface->OperationalPattern;
556 Identification* Ident = new Identification(m_Dict);
557 m_HeaderPart.AddChildObject(Ident);
558 m_HeaderPart.m_Preface->Identifications.push_back(Ident->InstanceUID);
560 Kumu::GenRandomValue(Ident->ThisGenerationUID);
561 Ident->CompanyName = m_Info.CompanyName.c_str();
562 Ident->ProductName = m_Info.ProductName.c_str();
563 Ident->VersionString = m_Info.ProductVersion.c_str();
564 Ident->ProductUID.Set(m_Info.ProductUUID);
565 Ident->Platform = ASDCP_PLATFORM;
567 std::vector<int> version = version_split(Version());
569 Ident->ToolkitVersion.Major = version[0];
570 Ident->ToolkitVersion.Minor = version[1];
571 Ident->ToolkitVersion.Patch = version[2];
572 Ident->ToolkitVersion.Build = ASDCP_BUILD_NUMBER;
573 Ident->ToolkitVersion.Release = VersionType::RL_RELEASE;
577 void AddSourceClip(const MXF::Rational& clip_edit_rate,
578 const MXF::Rational& tc_edit_rate, ui32_t TCFrameRate,
579 const std::string& TrackName, const UL& EssenceUL,
580 const UL& DataDefinition, const std::string& PackageLabel)
583 ContentStorage* Storage = new ContentStorage(m_Dict);
584 m_HeaderPart.AddChildObject(Storage);
585 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
587 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
588 m_HeaderPart.AddChildObject(ECD);
589 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
593 UUID assetUUID(m_Info.AssetUUID);
594 UMID SourcePackageUMID, MaterialPackageUMID;
595 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
596 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
601 m_MaterialPackage = new MaterialPackage(m_Dict);
602 m_MaterialPackage->Name = "AS-DCP Material Package";
603 m_MaterialPackage->PackageUID = MaterialPackageUMID;
604 m_HeaderPart.AddChildObject(m_MaterialPackage);
605 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
607 TrackSet<TimecodeComponent> MPTCTrack =
608 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
609 tc_edit_rate, TCFrameRate, 0, m_Dict);
610 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration.get()));
611 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration.get()));
613 TrackSet<SourceClip> MPTrack =
614 CreateTrackAndSequence<MaterialPackage, SourceClip>(m_HeaderPart, *m_MaterialPackage,
615 TrackName, clip_edit_rate, DataDefinition,
617 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration.get()));
619 MPTrack.Clip = new SourceClip(m_Dict);
620 m_HeaderPart.AddChildObject(MPTrack.Clip);
621 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
622 MPTrack.Clip->DataDefinition = DataDefinition;
623 MPTrack.Clip->SourcePackageID = SourcePackageUMID;
624 MPTrack.Clip->SourceTrackID = 2;
625 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration.get()));
629 // File (Source) Package
631 m_FilePackage = new SourcePackage(m_Dict);
632 m_FilePackage->Name = PackageLabel.c_str();
633 m_FilePackage->PackageUID = SourcePackageUMID;
634 ECD->LinkedPackageUID = SourcePackageUMID;
636 m_HeaderPart.AddChildObject(m_FilePackage);
637 Storage->Packages.push_back(m_FilePackage->InstanceUID);
639 TrackSet<TimecodeComponent> FPTCTrack =
640 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
641 tc_edit_rate, TCFrameRate,
642 ui64_C(3600) * TCFrameRate, m_Dict);
643 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration.get()));
644 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration.get()));
645 TrackSet<SourceClip> FPTrack =
646 CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage,
647 TrackName, clip_edit_rate, DataDefinition,
649 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration.get()));
651 // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from.
652 FPTrack.Track->TrackNumber = KM_i32_BE(Kumu::cp2i<ui32_t>((EssenceUL.Value() + 12)));
654 FPTrack.Clip = new SourceClip(m_Dict);
655 m_HeaderPart.AddChildObject(FPTrack.Clip);
656 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
657 FPTrack.Clip->DataDefinition = DataDefinition;
659 // for now we do not allow setting this value, so all files will be 'original'
660 FPTrack.Clip->SourceTrackID = 0;
661 FPTrack.Clip->SourcePackageID = NilUMID;
662 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration.get()));
664 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
668 void AddDMSegment(const MXF::Rational& clip_edit_rate,
669 const MXF::Rational& tc_edit_rate, ui32_t tc_frame_rate,
670 const std::string& TrackName, const UL& DataDefinition,
671 const std::string& PackageLabel)
674 ContentStorage* Storage = new ContentStorage(m_Dict);
675 m_HeaderPart.AddChildObject(Storage);
676 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
678 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
679 m_HeaderPart.AddChildObject(ECD);
680 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
684 UUID assetUUID(m_Info.AssetUUID);
685 UMID SourcePackageUMID, MaterialPackageUMID;
686 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
687 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
692 m_MaterialPackage = new MaterialPackage(m_Dict);
693 m_MaterialPackage->Name = "AS-DCP Material Package";
694 m_MaterialPackage->PackageUID = MaterialPackageUMID;
695 m_HeaderPart.AddChildObject(m_MaterialPackage);
696 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
698 TrackSet<TimecodeComponent> MPTCTrack =
699 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
700 tc_edit_rate, tc_frame_rate, 0, m_Dict);
701 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration.get()));
702 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration.get()));
704 TrackSet<DMSegment> MPTrack =
705 CreateTrackAndSequence<MaterialPackage, DMSegment>(m_HeaderPart, *m_MaterialPackage,
706 TrackName, clip_edit_rate, DataDefinition,
708 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration.get()));
710 MPTrack.Clip = new DMSegment(m_Dict);
711 m_HeaderPart.AddChildObject(MPTrack.Clip);
712 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
713 MPTrack.Clip->DataDefinition = DataDefinition;
714 // MPTrack.Clip->SourcePackageID = SourcePackageUMID;
715 // MPTrack.Clip->SourceTrackID = 2;
716 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
720 // File (Source) Package
722 m_FilePackage = new SourcePackage(m_Dict);
723 m_FilePackage->Name = PackageLabel.c_str();
724 m_FilePackage->PackageUID = SourcePackageUMID;
725 ECD->LinkedPackageUID = SourcePackageUMID;
727 m_HeaderPart.AddChildObject(m_FilePackage);
728 Storage->Packages.push_back(m_FilePackage->InstanceUID);
730 TrackSet<TimecodeComponent> FPTCTrack =
731 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
732 clip_edit_rate, tc_frame_rate,
733 ui64_C(3600) * tc_frame_rate, m_Dict);
734 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration.get()));
735 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration.get()));
737 TrackSet<DMSegment> FPTrack =
738 CreateTrackAndSequence<SourcePackage, DMSegment>(m_HeaderPart, *m_FilePackage,
739 TrackName, clip_edit_rate, DataDefinition,
741 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration.get()));
743 FPTrack.Clip = new DMSegment(m_Dict);
744 m_HeaderPart.AddChildObject(FPTrack.Clip);
745 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
746 FPTrack.Clip->DataDefinition = DataDefinition;
747 FPTrack.Clip->EventComment = "ST 429-5 Timed Text";
749 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
750 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
754 void AddEssenceDescriptor(const UL& WrappingUL)
757 // Essence Descriptor
759 m_EssenceDescriptor->EssenceContainer = WrappingUL;
760 m_HeaderPart.m_Preface->PrimaryPackage = m_FilePackage->InstanceUID;
763 // Essence Descriptors
766 UL GenericContainerUL(m_Dict->ul(MDD_GCMulti));
767 m_HeaderPart.EssenceContainers.push_back(GenericContainerUL);
769 if ( m_Info.EncryptedEssence )
771 UL CryptEssenceUL(m_Dict->ul(MDD_EncryptedContainerLabel));
772 m_HeaderPart.EssenceContainers.push_back(CryptEssenceUL);
773 m_HeaderPart.m_Preface->DMSchemes.push_back(UL(m_Dict->ul(MDD_CryptographicFrameworkLabel)));
774 AddDMScrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL, m_Dict);
778 m_HeaderPart.EssenceContainers.push_back(WrappingUL);
781 m_HeaderPart.m_Preface->EssenceContainers = m_HeaderPart.EssenceContainers;
782 m_HeaderPart.AddChildObject(m_EssenceDescriptor);
784 std::list<InterchangeObject*>::iterator sdli = m_EssenceSubDescriptorList.begin();
785 for ( ; sdli != m_EssenceSubDescriptorList.end(); sdli++ )
786 m_HeaderPart.AddChildObject(*sdli);
788 m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
801 //------------------------------------------------------------------------------------------
805 class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
807 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPReader);
811 Partition m_BodyPart;
813 h__ASDCPReader(const Dictionary&);
814 virtual ~h__ASDCPReader();
816 Result_t OpenMXFRead(const char* filename);
817 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
818 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
819 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
820 i8_t& temporalOffset, i8_t& keyFrameOffset);
824 class h__ASDCPWriter : public MXF::TrackFileWriter<OP1aHeader>
826 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPWriter);
830 Partition m_BodyPart;
831 OPAtomIndexFooter m_FooterPart;
833 h__ASDCPWriter(const Dictionary&);
834 virtual ~h__ASDCPWriter();
836 // all the above for a single source clip
837 Result_t WriteASDCPHeader(const std::string& PackageLabel, const UL& WrappingUL,
838 const std::string& TrackName, const UL& EssenceUL,
839 const UL& DataDefinition, const MXF::Rational& EditRate,
840 ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
842 Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
843 Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
844 AESEncContext* Ctx, HMACContext* HMAC);
845 Result_t WriteASDCPFooter();
849 // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
854 byte_t Data[klv_intpack_size];
857 memset(Data, 0, klv_intpack_size);
862 Result_t CalcValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
863 Result_t TestValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
869 #endif // _AS_DCP_INTERNAL_H_
873 // end AS_DCP_internal.h