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::GenericPictureEssenceDescriptor& 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::GenericPictureEssenceDescriptor& EssenceDescriptor,
145 ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor);
147 Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj);
148 Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc);
150 void AddDMScrypt(Partition& HeaderPart, SourcePackage& Package,
151 WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
153 Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict,
154 const ASDCP::WriterInfo& Info, Kumu::fpos_t& LastPosition, ASDCP::FrameBuffer& CtFrameBuf,
155 ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
156 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
158 Result_t Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart,
159 const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten,
160 ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL,
161 AESEncContext* Ctx, HMACContext* HMAC);
164 class KLReader : public ASDCP::KLVPacket
166 ASDCP_NO_COPY_CONSTRUCT(KLReader);
167 byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
173 inline const byte_t* Key() { return m_KeyBuf; }
174 inline const ui64_t Length() { return m_ValueLength; }
175 inline const ui64_t KLLength() { return m_KLLength; }
177 Result_t ReadKLFromFile(Kumu::FileReader& Reader);
182 //---------------------------------------------------------------------------------
185 /// void default_md_object_init();
187 template <class HeaderType, class IndexAccessType>
188 class TrackFileReader
190 KM_NO_COPY_CONSTRUCT(TrackFileReader);
194 const Dictionary* m_Dict;
195 Kumu::FileReader m_File;
196 HeaderType m_HeaderPart;
197 IndexAccessType m_IndexAccess;
200 ASDCP::FrameBuffer m_CtFrameBuf;
201 Kumu::fpos_t m_LastPosition;
203 TrackFileReader(const Dictionary& d) :
204 m_HeaderPart(m_Dict), m_IndexAccess(m_Dict), m_RIP(m_Dict), m_Dict(&d)
206 default_md_object_init();
209 virtual ~TrackFileReader() {
213 const MXF::RIP& GetRIP() const { return m_RIP; }
216 Result_t OpenMXFRead(const std::string& filename)
219 Result_t result = m_File.OpenRead(filename);
221 if ( ASDCP_SUCCESS(result) )
222 result = SeekToRIP(m_File);
224 if ( ASDCP_SUCCESS(result) )
226 result = m_RIP.InitFromFile(m_File);
227 ui32_t test_s = m_RIP.PairArray.size();
229 if ( ASDCP_FAILURE(result) )
231 DefaultLogSink().Error("File contains no RIP\n");
233 else if ( m_RIP.PairArray.empty() )
235 DefaultLogSink().Error("RIP contains no Pairs.\n");
240 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, SeekToRIP failed\n");
244 result = m_HeaderPart.InitFromFile(m_File);
246 if ( KM_FAILURE(result) )
248 DefaultLogSink().Error("TrackFileReader::OpenMXFRead, header init failed\n");
258 InterchangeObject* Object;
261 Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object);
263 // Writer Info and SourcePackage
264 if ( KM_SUCCESS(result) )
266 MD_to_WriterInfo((Identification*)Object, m_Info);
267 result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(SourcePackage), &Object);
270 if ( KM_SUCCESS(result) )
272 SourcePackage* SP = (SourcePackage*)Object;
273 memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen);
276 // optional CryptographicContext
277 if ( KM_SUCCESS(result) )
279 Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object);
281 if ( KM_SUCCESS(cr_result) )
282 MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict);
288 // positions file before reading
289 // allows external control of index offset
290 Result_t ReadEKLVFrame(const ui64_t& body_offset,
291 ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
292 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
294 // look up frame index node
295 IndexTableSegment::IndexEntry TmpEntry;
297 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
299 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
303 // get relative frame position, apply offset and go read the frame's key and length
304 Kumu::fpos_t FilePosition = body_offset + TmpEntry.StreamOffset;
305 Result_t result = RESULT_OK;
307 if ( FilePosition != m_LastPosition )
309 m_LastPosition = FilePosition;
310 result = m_File.Seek(FilePosition);
313 if ( KM_SUCCESS(result) )
314 result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
319 // positions file before reading
320 // assumes "processed" index entries have absolute positions
321 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
322 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
324 // look up frame index node
325 IndexTableSegment::IndexEntry TmpEntry;
327 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
329 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
333 // get absolute frame position and go read the frame's key and length
334 Result_t result = RESULT_OK;
336 if ( TmpEntry.StreamOffset != m_LastPosition )
338 m_LastPosition = TmpEntry.StreamOffset;
339 result = m_File.Seek(TmpEntry.StreamOffset);
342 if ( KM_SUCCESS(result) )
343 result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC);
348 // reads from current position
349 Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
350 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC)
353 return Read_EKLV_Packet(m_File, *m_Dict, m_Info, m_LastPosition, m_CtFrameBuf,
354 FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC);
357 // Get the position of a frame from a track file
358 Result_t LocateFrame(const ui64_t& body_offset,
359 ui32_t FrameNum, Kumu::fpos_t& streamOffset,
360 i8_t& temporalOffset, i8_t& keyFrameOffset)
362 // look up frame index node
363 IndexTableSegment::IndexEntry TmpEntry;
365 if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
367 DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
371 // get frame position, temporal offset, and key frame ofset
372 streamOffset = body_offset + TmpEntry.StreamOffset;
373 temporalOffset = TmpEntry.TemporalOffset;
374 keyFrameOffset = TmpEntry.KeyFrameOffset;
386 //------------------------------------------------------------------------------------------
390 template <class ClipT>
394 MXF::Sequence* Sequence;
397 TrackSet() : Track(0), Sequence(0), Clip(0) {}
401 template <class PackageT, class ClipT>
403 CreateTrackAndSequence(OP1aHeader& Header, PackageT& Package, const std::string TrackName,
404 const MXF::Rational& clip_edit_rate, const UL& Definition, ui32_t TrackID, const Dictionary*& Dict)
406 TrackSet<ClipT> NewTrack;
408 NewTrack.Track = new Track(Dict);
409 Header.AddChildObject(NewTrack.Track);
410 NewTrack.Track->EditRate = clip_edit_rate;
411 Package.Tracks.push_back(NewTrack.Track->InstanceUID);
412 NewTrack.Track->TrackID = TrackID;
413 NewTrack.Track->TrackName = TrackName.c_str();
415 NewTrack.Sequence = new Sequence(Dict);
416 Header.AddChildObject(NewTrack.Sequence);
417 NewTrack.Track->Sequence = NewTrack.Sequence->InstanceUID;
418 NewTrack.Sequence->DataDefinition = Definition;
424 template <class PackageT>
425 TrackSet<TimecodeComponent>
426 CreateTimecodeTrack(OP1aHeader& Header, PackageT& Package,
427 const MXF::Rational& tc_edit_rate, ui32_t tc_frame_rate, ui64_t TCStart, const Dictionary*& Dict)
430 UL TCUL(Dict->ul(MDD_TimecodeDataDef));
432 TrackSet<TimecodeComponent> NewTrack =
433 CreateTrackAndSequence<PackageT, TimecodeComponent>(Header, Package, "Timecode Track",
434 tc_edit_rate, TCUL, 1, Dict);
436 NewTrack.Clip = new TimecodeComponent(Dict);
437 Header.AddChildObject(NewTrack.Clip);
438 NewTrack.Sequence->StructuralComponents.push_back(NewTrack.Clip->InstanceUID);
439 NewTrack.Clip->RoundedTimecodeBase = tc_frame_rate;
440 NewTrack.Clip->StartTimecode = TCStart;
441 NewTrack.Clip->DataDefinition = TCUL;
447 // state machine for mxf writer
449 ST_BEGIN, // waiting for Open()
450 ST_INIT, // waiting for SetSourceStream()
451 ST_READY, // ready to write frames
452 ST_RUNNING, // one or more frames written
453 ST_FINAL, // index written, file closed
457 // implementation of h__WriterState class Goto_* methods
458 #define Goto_body(s1,s2) \
459 if ( m_State != (s1) ) { \
460 return RESULT_STATE; \
467 ASDCP_NO_COPY_CONSTRUCT(h__WriterState);
470 WriterState_t m_State;
471 h__WriterState() : m_State(ST_BEGIN) {}
474 inline bool Test_BEGIN() { return m_State == ST_BEGIN; }
475 inline bool Test_INIT() { return m_State == ST_INIT; }
476 inline bool Test_READY() { return m_State == ST_READY;}
477 inline bool Test_RUNNING() { return m_State == ST_RUNNING; }
478 inline bool Test_FINAL() { return m_State == ST_FINAL; }
479 inline Result_t Goto_INIT() { Goto_body(ST_BEGIN, ST_INIT); }
480 inline Result_t Goto_READY() { Goto_body(ST_INIT, ST_READY); }
481 inline Result_t Goto_RUNNING() { Goto_body(ST_READY, ST_RUNNING); }
482 inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); }
485 //------------------------------------------------------------------------------------------
489 template <class HeaderType>
490 class TrackFileWriter
492 KM_NO_COPY_CONSTRUCT(TrackFileWriter);
496 const Dictionary* m_Dict;
497 Kumu::FileWriter m_File;
499 HeaderType m_HeaderPart;
502 MaterialPackage* m_MaterialPackage;
503 SourcePackage* m_FilePackage;
505 FileDescriptor* m_EssenceDescriptor;
506 std::list<InterchangeObject*> m_EssenceSubDescriptorList;
508 ui32_t m_FramesWritten;
509 ui64_t m_StreamOffset;
510 ASDCP::FrameBuffer m_CtFrameBuf;
511 h__WriterState m_State;
514 typedef std::list<ui64_t*> DurationElementList_t;
515 DurationElementList_t m_DurationUpdateList;
517 TrackFileWriter(const Dictionary& d) :
518 m_Dict(&d), m_HeaderPart(m_Dict), m_RIP(m_Dict),
519 m_HeaderSize(0), m_EssenceDescriptor(0),
520 m_FramesWritten(0), m_StreamOffset(0)
522 default_md_object_init();
525 virtual ~TrackFileWriter() {
529 const MXF::RIP& GetRIP() const { return m_RIP; }
534 assert(m_EssenceDescriptor);
536 m_HeaderPart.m_Primer.ClearTagList();
537 m_HeaderPart.m_Preface = new Preface(m_Dict);
538 m_HeaderPart.AddChildObject(m_HeaderPart.m_Preface);
540 // Set the Operational Pattern label -- we're just starting and have no RIP or index,
541 // so we tell the world by using OP1a
542 m_HeaderPart.m_Preface->OperationalPattern = UL(m_Dict->ul(MDD_OP1a));
543 m_HeaderPart.OperationalPattern = m_HeaderPart.m_Preface->OperationalPattern;
546 Identification* Ident = new Identification(m_Dict);
547 m_HeaderPart.AddChildObject(Ident);
548 m_HeaderPart.m_Preface->Identifications.push_back(Ident->InstanceUID);
550 Kumu::GenRandomValue(Ident->ThisGenerationUID);
551 Ident->CompanyName = m_Info.CompanyName.c_str();
552 Ident->ProductName = m_Info.ProductName.c_str();
553 Ident->VersionString = m_Info.ProductVersion.c_str();
554 Ident->ProductUID.Set(m_Info.ProductUUID);
555 Ident->Platform = ASDCP_PLATFORM;
557 std::vector<int> version = version_split(Version());
559 Ident->ToolkitVersion.Major = version[0];
560 Ident->ToolkitVersion.Minor = version[1];
561 Ident->ToolkitVersion.Patch = version[2];
562 Ident->ToolkitVersion.Build = ASDCP_BUILD_NUMBER;
563 Ident->ToolkitVersion.Release = VersionType::RL_RELEASE;
567 void AddSourceClip(const MXF::Rational& clip_edit_rate,
568 const MXF::Rational& tc_edit_rate, ui32_t TCFrameRate,
569 const std::string& TrackName, const UL& EssenceUL,
570 const UL& DataDefinition, const std::string& PackageLabel)
573 ContentStorage* Storage = new ContentStorage(m_Dict);
574 m_HeaderPart.AddChildObject(Storage);
575 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
577 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
578 m_HeaderPart.AddChildObject(ECD);
579 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
583 UUID assetUUID(m_Info.AssetUUID);
584 UMID SourcePackageUMID, MaterialPackageUMID;
585 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
586 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
591 m_MaterialPackage = new MaterialPackage(m_Dict);
592 m_MaterialPackage->Name = "AS-DCP Material Package";
593 m_MaterialPackage->PackageUID = MaterialPackageUMID;
594 m_HeaderPart.AddChildObject(m_MaterialPackage);
595 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
597 TrackSet<TimecodeComponent> MPTCTrack =
598 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
599 tc_edit_rate, TCFrameRate, 0, m_Dict);
600 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration.get()));
601 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration.get()));
603 TrackSet<SourceClip> MPTrack =
604 CreateTrackAndSequence<MaterialPackage, SourceClip>(m_HeaderPart, *m_MaterialPackage,
605 TrackName, clip_edit_rate, DataDefinition,
607 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration.get()));
609 MPTrack.Clip = new SourceClip(m_Dict);
610 m_HeaderPart.AddChildObject(MPTrack.Clip);
611 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
612 MPTrack.Clip->DataDefinition = DataDefinition;
613 MPTrack.Clip->SourcePackageID = SourcePackageUMID;
614 MPTrack.Clip->SourceTrackID = 2;
615 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration.get()));
619 // File (Source) Package
621 m_FilePackage = new SourcePackage(m_Dict);
622 m_FilePackage->Name = PackageLabel.c_str();
623 m_FilePackage->PackageUID = SourcePackageUMID;
624 ECD->LinkedPackageUID = SourcePackageUMID;
626 m_HeaderPart.AddChildObject(m_FilePackage);
627 Storage->Packages.push_back(m_FilePackage->InstanceUID);
629 TrackSet<TimecodeComponent> FPTCTrack =
630 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
631 tc_edit_rate, TCFrameRate,
632 ui64_C(3600) * TCFrameRate, m_Dict);
633 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration.get()));
634 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration.get()));
635 TrackSet<SourceClip> FPTrack =
636 CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage,
637 TrackName, clip_edit_rate, DataDefinition,
639 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration.get()));
641 // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from.
642 FPTrack.Track->TrackNumber = KM_i32_BE(Kumu::cp2i<ui32_t>((EssenceUL.Value() + 12)));
644 FPTrack.Clip = new SourceClip(m_Dict);
645 m_HeaderPart.AddChildObject(FPTrack.Clip);
646 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
647 FPTrack.Clip->DataDefinition = DataDefinition;
649 // for now we do not allow setting this value, so all files will be 'original'
650 FPTrack.Clip->SourceTrackID = 0;
651 FPTrack.Clip->SourcePackageID = NilUMID;
652 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration.get()));
654 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
658 void AddDMSegment(const MXF::Rational& clip_edit_rate,
659 const MXF::Rational& tc_edit_rate, ui32_t tc_frame_rate,
660 const std::string& TrackName, const UL& DataDefinition,
661 const std::string& PackageLabel)
664 ContentStorage* Storage = new ContentStorage(m_Dict);
665 m_HeaderPart.AddChildObject(Storage);
666 m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID;
668 EssenceContainerData* ECD = new EssenceContainerData(m_Dict);
669 m_HeaderPart.AddChildObject(ECD);
670 Storage->EssenceContainerData.push_back(ECD->InstanceUID);
674 UUID assetUUID(m_Info.AssetUUID);
675 UMID SourcePackageUMID, MaterialPackageUMID;
676 SourcePackageUMID.MakeUMID(0x0f, assetUUID);
677 MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence
682 m_MaterialPackage = new MaterialPackage(m_Dict);
683 m_MaterialPackage->Name = "AS-DCP Material Package";
684 m_MaterialPackage->PackageUID = MaterialPackageUMID;
685 m_HeaderPart.AddChildObject(m_MaterialPackage);
686 Storage->Packages.push_back(m_MaterialPackage->InstanceUID);
688 TrackSet<TimecodeComponent> MPTCTrack =
689 CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage,
690 tc_edit_rate, tc_frame_rate, 0, m_Dict);
691 m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration.get()));
692 m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration.get()));
694 TrackSet<DMSegment> MPTrack =
695 CreateTrackAndSequence<MaterialPackage, DMSegment>(m_HeaderPart, *m_MaterialPackage,
696 TrackName, clip_edit_rate, DataDefinition,
698 m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration.get()));
700 MPTrack.Clip = new DMSegment(m_Dict);
701 m_HeaderPart.AddChildObject(MPTrack.Clip);
702 MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID);
703 MPTrack.Clip->DataDefinition = DataDefinition;
704 // MPTrack.Clip->SourcePackageID = SourcePackageUMID;
705 // MPTrack.Clip->SourceTrackID = 2;
706 m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration));
710 // File (Source) Package
712 m_FilePackage = new SourcePackage(m_Dict);
713 m_FilePackage->Name = PackageLabel.c_str();
714 m_FilePackage->PackageUID = SourcePackageUMID;
715 ECD->LinkedPackageUID = SourcePackageUMID;
717 m_HeaderPart.AddChildObject(m_FilePackage);
718 Storage->Packages.push_back(m_FilePackage->InstanceUID);
720 TrackSet<TimecodeComponent> FPTCTrack =
721 CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage,
722 clip_edit_rate, tc_frame_rate,
723 ui64_C(3600) * tc_frame_rate, m_Dict);
724 m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration.get()));
725 m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration.get()));
727 TrackSet<DMSegment> FPTrack =
728 CreateTrackAndSequence<SourcePackage, DMSegment>(m_HeaderPart, *m_FilePackage,
729 TrackName, clip_edit_rate, DataDefinition,
731 m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration.get()));
733 FPTrack.Clip = new DMSegment(m_Dict);
734 m_HeaderPart.AddChildObject(FPTrack.Clip);
735 FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID);
736 FPTrack.Clip->DataDefinition = DataDefinition;
737 FPTrack.Clip->EventComment = "ST 429-5 Timed Text";
739 m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration));
740 m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID;
744 void AddEssenceDescriptor(const UL& WrappingUL)
747 // Essence Descriptor
749 m_EssenceDescriptor->EssenceContainer = WrappingUL;
750 m_HeaderPart.m_Preface->PrimaryPackage = m_FilePackage->InstanceUID;
753 // Essence Descriptors
756 UL GenericContainerUL(m_Dict->ul(MDD_GCMulti));
757 m_HeaderPart.EssenceContainers.push_back(GenericContainerUL);
759 if ( m_Info.EncryptedEssence )
761 UL CryptEssenceUL(m_Dict->ul(MDD_EncryptedContainerLabel));
762 m_HeaderPart.EssenceContainers.push_back(CryptEssenceUL);
763 m_HeaderPart.m_Preface->DMSchemes.push_back(UL(m_Dict->ul(MDD_CryptographicFrameworkLabel)));
764 AddDMScrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL, m_Dict);
768 m_HeaderPart.EssenceContainers.push_back(WrappingUL);
771 m_HeaderPart.m_Preface->EssenceContainers = m_HeaderPart.EssenceContainers;
772 m_HeaderPart.AddChildObject(m_EssenceDescriptor);
774 std::list<InterchangeObject*>::iterator sdli = m_EssenceSubDescriptorList.begin();
775 for ( ; sdli != m_EssenceSubDescriptorList.end(); sdli++ )
776 m_HeaderPart.AddChildObject(*sdli);
778 m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID;
791 //------------------------------------------------------------------------------------------
795 class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
797 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPReader);
801 Partition m_BodyPart;
803 h__ASDCPReader(const Dictionary&);
804 virtual ~h__ASDCPReader();
806 Result_t OpenMXFRead(const std::string& filename);
807 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
808 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
809 Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset,
810 i8_t& temporalOffset, i8_t& keyFrameOffset);
814 class h__ASDCPWriter : public MXF::TrackFileWriter<OP1aHeader>
816 ASDCP_NO_COPY_CONSTRUCT(h__ASDCPWriter);
820 Partition m_BodyPart;
821 OPAtomIndexFooter m_FooterPart;
823 h__ASDCPWriter(const Dictionary&);
824 virtual ~h__ASDCPWriter();
826 // all the above for a single source clip
827 Result_t WriteASDCPHeader(const std::string& PackageLabel, const UL& WrappingUL,
828 const std::string& TrackName, const UL& EssenceUL,
829 const UL& DataDefinition, const MXF::Rational& EditRate,
830 ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
832 Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
833 Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
834 AESEncContext* Ctx, HMACContext* HMAC);
835 Result_t WriteASDCPFooter();
839 // helper class for calculating Integrity Packs, used by WriteEKLVPacket() below.
844 byte_t Data[klv_intpack_size];
847 memset(Data, 0, klv_intpack_size);
852 Result_t CalcValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
853 Result_t TestValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
859 #endif // _AS_DCP_INTERNAL_H_
863 // end AS_DCP_internal.h